diff --git a/.Rbuildignore b/.Rbuildignore new file mode 100644 index 00000000..91114bf2 --- /dev/null +++ b/.Rbuildignore @@ -0,0 +1,2 @@ +^.*\.Rproj$ +^\.Rproj\.user$ diff --git a/DESCRIPTION b/DESCRIPTION new file mode 100644 index 00000000..88e77b17 --- /dev/null +++ b/DESCRIPTION @@ -0,0 +1,41 @@ +Package: magclass +Type: Package +Title: Data Class and Tools for Handling Spatial-Temporal Data +Version: 4.39 +Date: 2017-05-23 +Author: Jan Philipp Dietrich, + Benjamin Bodirsky, + Misko Stevanovic, + Lavinia Baumstark, + Christoph Bertram, + Markus Bonsch, + Anastasis Giannousakis, + Florian Humpenoeder, + David Klein, + Ina Neher, + Michaja Pehl, + Anselm Schultes, + Xiaoxi Wang +Maintainer: Jan Philipp Dietrich +Description: Data class for increased interoperability working with spatial- + temporal data together with corresponding functions and methods (conversions, + basic calculations and basic data manipulation). The class distinguishes + between spatial, temporal and other dimensions to facilitate the development + and interoperability of tools build for it. Additional features are name-based + addressing of data and internal consistency checks (e.g. checking for the right + data order in calculations). +Depends: + R(>= 2.10.0), + methods +Imports: + sp, + maptools, + abind, + ncdf4, + reshape2 +Suggests: + testthat +License: LGPL-3 | file LICENSE +LazyData: no +RoxygenNote: 6.0.1 +Suggests: testthat diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/NAMESPACE b/NAMESPACE new file mode 100644 index 00000000..9fb754b7 --- /dev/null +++ b/NAMESPACE @@ -0,0 +1,106 @@ +# Generated by roxygen2: do not edit by hand + +S3method(head,magpie) +S3method(print,magpie) +S3method(tail,magpie) +export("copy.attributes<-") +export("getCells<-") +export("getComment<-") +export("getNames<-") +export("getRegionList<-") +export("getRegions<-") +export("getSets<-") +export("getYears<-") +export("mselect<-") +export(add_columns) +export(add_dimension) +export(calibrate_it) +export(clean_magpie) +export(collapseNames) +export(complete_magpie) +export(convergence) +export(convert.report) +export(copy.attributes) +export(copy.magpie) +export(dimCode) +export(dimOrder) +export(dimSums) +export(fulldim) +export(getCPR) +export(getCells) +export(getComment) +export(getNames) +export(getRegionList) +export(getRegions) +export(getSets) +export(getYears) +export(is.magpie) +export(is.spatial) +export(is.temporal) +export(isYear) +export(lin.convergence) +export(lowpass) +export(magpieComp) +export(magpieResolution) +export(magpie_expand) +export(magpiesort) +export(mbind) +export(mbind2) +export(mcalc) +export(mselect) +export(ncells) +export(ndata) +export(new.magpie) +export(nregions) +export(nyears) +export(old_dim_convention) +export(place_x_in_y) +export(read.magpie) +export(read.report) +export(remind2magpie) +export(setCells) +export(setComment) +export(setYears) +export(time_interpolate) +export(unwrap) +export(where) +export(wrap) +export(write.magpie) +export(write.report) +export(write.report2) +export(write.reportProject) +exportClasses(magpie) +exportMethods("[") +exportMethods("[<-") +exportMethods(Ops) +exportMethods(as.array) +exportMethods(as.data.frame) +exportMethods(as.magpie) +exportMethods(colMeans) +exportMethods(colSums) +exportMethods(round) +exportMethods(rowMeans) +exportMethods(rowSums) +exportMethods(setNames) +importFrom(methods,Ops) +importFrom(methods,as) +importFrom(methods,callGeneric) +importFrom(methods,is) +importFrom(methods,new) +importFrom(methods,setClass) +importFrom(methods,setGeneric) +importFrom(methods,setMethod) +importFrom(methods,signature) +importFrom(reshape2,dcast) +importFrom(reshape2,melt) +importFrom(stats,as.formula) +importFrom(utils,head) +importFrom(utils,read.csv) +importFrom(utils,read.csv2) +importFrom(utils,read.table) +importFrom(utils,setTxtProgressBar) +importFrom(utils,tail) +importFrom(utils,txtProgressBar) +importFrom(utils,type.convert) +importFrom(utils,write.csv) +importFrom(utils,write.table) diff --git a/R/add_columns.R b/R/add_columns.R new file mode 100644 index 00000000..1a815b2f --- /dev/null +++ b/R/add_columns.R @@ -0,0 +1,43 @@ +#' add_columns +#' +#' Function adds new columns to the existing magpie object. The new columns are +#' filled with NAs. +#' +#' +#' @param x MAgPIE object which should be extended. +#' @param dim The number of the dimension that should be extended +#' @param addnm The new columns within dimension "dim" +#' @return The extended MAgPIE object +#' @author Benjamin Bodirsky +#' @seealso \code{\link{add_dimension}},\code{\link{mbind}} +#' @examples +#' +#' data(population_magpie) +#' a <- add_columns(population_magpie) +#' str(a) +#' fulldim(a) +#' +#' @export add_columns +add_columns<-function(x,addnm=c("new"),dim=3.1){ + dim=old_dim_convention(dim) + if (dim==1) { + new_columns<-x[rep(1,length(addnm)),,] + new_columns<-setCells(new_columns,paste(substr(addnm,1,3),".",(dim(x)[dim]+1):(dim(x)[dim]+length(addnm)),sep="")) + new_columns[,,]<-NA + } else if (dim==2) { + new_columns<-x[,rep(1,length(addnm)),] + new_columns<-setYears(new_columns,addnm) + new_columns[,,]<-NA + } else if (dim>2) { + new_columns<-x[,,fulldim(x)[[2]][[dim]][[1]]] + getNames(new_columns,dim=dim-2)<-addnm[1] + if(length(addnm)>1){ + single_column_x<-new_columns + for (i in 2:length(addnm)){ + getNames(single_column_x,dim=dim-2)<-addnm[i] + new_columns<-mbind(new_columns,as.magpie(single_column_x)) + }} + new_columns[,,]<-NA + } + return(mbind(x,new_columns)) +} diff --git a/R/add_dimension.R b/R/add_dimension.R new file mode 100644 index 00000000..45df2272 --- /dev/null +++ b/R/add_dimension.R @@ -0,0 +1,48 @@ +#' add_dimension +#' +#' Function adds a name dimension as dimension number "dim" with the name "add" +#' with an empty data column with the name "nm". +#' +#' +#' @param x MAgPIE object which should be extended. +#' @param dim The dimension number of the new dimension. 4 stands for the +#' second name dimension. +#' @param add The name of the new dimension +#' @param nm The name of the first entry in dimension "add". +#' @return The extended MAgPIE object +#' @author Benjamin Bodirsky +#' @seealso \code{\link{add_columns}},\code{\link{mbind}} +#' @examples +#' +#' data(population_magpie) +#' a <- add_dimension(population_magpie) +#' str(a) +#' fulldim(a) +#' +#' @export add_dimension +add_dimension<-function(x,dim=3.1,add="new", nm="dummy"){ + x<-clean_magpie(x) + dim<-as.numeric(dim) + olddim<-old_dim_convention(dim) + if (olddim<3) stop("Dimensions below 3 are currently not supported by add_dimensions.") + if (is.null(getNames(x))){getNames(x)<-"NA"} + firstnm<-nm[1] + + separate<-strsplit(dimnames(x)[[3]],split = "\\.") + newnm<-NULL + for (i in 1:length(separate)) { + newnm<-c(newnm,paste(append(separate[[i]],firstnm,after=olddim-3),collapse=".")) + } + dimnames(x)[[3]]<-newnm + names(dimnames(x))[3] <- paste(append( + strsplit(names(dimnames(x))[3],split="\\.")[[1]] + ,add,after=olddim-3),collapse=".") + + if (length(nm)>1) { + x<-add_columns(x,addnm = nm[2:length(nm)],dim=dim) + tmp<-list(neu=nm[1]) + names(tmp)<-add + x[,,]<-mselect(x,tmp) + } + return(x) +} diff --git a/R/as.array.R b/R/as.array.R new file mode 100644 index 00000000..cd8cf320 --- /dev/null +++ b/R/as.array.R @@ -0,0 +1,27 @@ + +#' ~~ Methods for Function as.array ~~ +#' +#' ~~ Methods for function \code{as.array} ~~ +#' +#' +#' @name as.array-methods +#' @aliases as.array-methods as.array,ANY-method as.array,magpie-method +#' @param x object which should be converted to an array +#' @docType methods +#' @section Methods: \describe{ +#' +#' \item{list("signature(x = \"ANY\")")}{ standard as.array-method } +#' +#' \item{list("signature(x = \"magpie\")")}{ Conversion takes place just by +#' removing MAgPIE-object specific elements } } +#' @keywords methods +#' @importFrom methods as setMethod signature +#' @exportMethod as.array + +setMethod("as.array", + signature(x = "magpie"), + function (x) + { + return(as(x,"array")) + } +) \ No newline at end of file diff --git a/R/as.data.frame.R b/R/as.data.frame.R new file mode 100644 index 00000000..c1011342 --- /dev/null +++ b/R/as.data.frame.R @@ -0,0 +1,95 @@ +#' ~~ Methods for Function as.data.frame ~~ +#' +#' ~~ Methods for function \code{as.data.frame} ~~ +#' +#' +#' @name as.data.frame-methods +#' @aliases as.data.frame as.data.frame-methods as.data.frame,ANY-method +#' as.data.frame,magpie-method +#' @docType methods +#' @param x A MAgPIE-object +#' @param rev The revision of the algorithm that should be used for conversion. +#' rev=1 creates columns with the predefined names Cell, Region, Year, Data1, +#' Data2,... and Value, rev=2 uses the set names of the MAgPIE object for +#' naming and adds an attribute "dimtype" to the data.frame which contains +#' information about the types of the different columns (spatial, temporal, +#' data or value). +#' @section Methods: \describe{ +#' +#' \item{list("signature(x = \"magpie\")")}{ Conversion creates columns for +#' Cell, Region, Year, Data1, Data2,... and Value } } +#' @keywords methods +#' @examples +#' +#' data(population_magpie) +#' head(as.data.frame(population_magpie)) +#' head(as.data.frame(population_magpie,rev=2)) +#' +#' @importFrom utils type.convert +#' @exportMethod as.data.frame + +setMethod("as.data.frame", + signature(x="magpie"), + function(x,rev=1) + { + if(rev==1) { + dimnames(x)[[2]] <- getYears(x,as.integer=TRUE) + if(is.null(dimnames(x)[[2]])) dimnames(x)[[2]] <- 0 + if(is.null(dimnames(x)[[3]])) dimnames(x)[[3]] <- "NA" + if(any(dim(x)==0)) { + return(data.frame()) + } else { + x <- as.data.frame(as.table(x)) + } + if(all(grepl(".",x[[3]],fixed=TRUE))) { + levels(x[[3]]) <- gsub("\\.$","\\.STRINGTORESETAG",levels(x[[3]])) + tmp <- data.frame(t(matrix(unlist(strsplit(as.character(x[[3]]),split="\\.")),ncol=nrow(x))),stringsAsFactors=FALSE) + for(i in 1:ncol(tmp)) { + tmp[[i]] <- factor(tmp[[i]],unique(tmp[[i]])) + levels(tmp[[i]]) <- gsub("STRINGTORESETAG","",levels(tmp[[i]])) + } + x <- cbind(x[,1:2],tmp,x[4]) + } + colnames(x) <- c("Region","Year",paste("Data",1:(dim(x)[2]-3),sep=""),"Value") + x <- cbind(Cell=suppressWarnings(as.integer(gsub("^[^\\.]*\\.","",x$Region))),x) + x$Region <- gsub("\\..*$","",x$Region) + return(x) + } else if(rev==2) { + x <- clean_magpie(x,what="sets") + dimnames(x)[[2]] <- getYears(x,as.integer=TRUE) + if(any(dim(x)==0)) { + return(data.frame()) + } else { + x <- as.data.frame(as.table(x), stringsAsFactors=FALSE) + } + names(x)[4] <- ".value" + what <- ".value" + types <- c(".spat",".temp",".data") + for(i in 3:1) { + if(grepl(".",names(x)[i],fixed=TRUE)) { + tmp <- data.frame(t(matrix(unlist(strsplit(as.character(x[[i]]),split="\\.")),ncol=nrow(x))),stringsAsFactors=FALSE) + names(tmp) <- strsplit(names(x)[i],split="\\.")[[1]] + if(i==1) { + x <- cbind(tmp,x[2:length(x)]) + } else { + x <- cbind(x[1:(i-1)],tmp,x[(i+1):length(x)]) + } + what <- c(paste0(types[i],1:dim(tmp)[2]),what) + } else { + what <- c(paste0(types[i],1),what) + } + } + #use other types than character if possible + for(i in 1:ncol(x)) { + if(is.character(x[[i]])) { + x[[i]] <- type.convert(x[[i]],as.is=TRUE) + if(is.character(x[[i]])) x[[i]] <- factor(x[[i]],unique(x[[i]])) + } + } + attr(x,"dimtype") <- what + return(x) + } else { + stop('Unknown revision "',rev,'"!') + } + } +) \ No newline at end of file diff --git a/R/as.magpie.R b/R/as.magpie.R new file mode 100644 index 00000000..665fc844 --- /dev/null +++ b/R/as.magpie.R @@ -0,0 +1,258 @@ +#' @importFrom methods new setGeneric +#' @importFrom reshape2 melt +#' @exportMethod as.magpie +setGeneric("as.magpie", function(x,...)standardGeneric("as.magpie")) + +setMethod("as.magpie",signature(x = "magpie"),function (x) return(x)) + +setMethod("as.magpie", + signature(x = "lpj"), + function (x, ...) + { + 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)) + } +) + +setMethod("as.magpie", + signature(x = "array"), + function (x, spatial=NULL, temporal=NULL, ...) + { + store_attributes <- copy.attributes(x,0) + + # Add the sets as name to the dimnames, if existent + if(is.null(names(dimnames(x))) & !is.null(attr(x,"sets"))){ + tmp<-dimnames(x) + names(tmp)<-attr(x,"sets") + dimnames(x)<-tmp + } + #This part of the function analyses what structure the input has + d <- list() #list of dimension types found in the array + if(!is.null(temporal)) d$temporal <- temporal + if(!is.null(spatial)) d$regiospatial <- spatial + for(i in 1:length(dim(x))) { + if(!is.null(dimnames(x)[[i]])) { + if(is.null(spatial)) { + if(length(grep("^(([A-Z]{3})|(glob))$",dimnames(x)[[i]]))==dim(x)[i]) d$regional <- c(d$regional,i) #regional information + if(length(grep("^[A-Z]+[\\._][0-9]+$",dimnames(x)[[i]]))==dim(x)[i]) d$regiospatial <- c(d$regiospatial,i) #regio-spatial information + } + if(is.null(temporal)) { + if(is.temporal(dimnames(x)[[i]])) d$temporal <- c(d$temporal,i) #temporal information + } + } else if(dim(x)[i]==1) d$nothing <- c(d$nothing,i) #dimension with no content + } + + if(!is.null(spatial)) { + if(spatial==0) { + d$regiospatial <- NULL + d$regional <- NULL + } + } + + if(!is.null(temporal)) { + if(temporal==0) { + d$temporal <- NULL + } + } + + #Write warning when any type (except type "nothing") is found more than once + tmp <- lapply(d,length)>1; tmp <- tmp[names(tmp)!="nothing"] + if(any(tmp)==TRUE) warning("No clear mapping of dimensions to dimension types. First detected possibility is used! Please use arguments temporal and spatial to specify which dimensions are what!") + for(i in which(tmp)) { + d[[i]] <- d[[i]][1] + } + + #If a regional dimension exists, test whether "glob" appears in the dimnames and rename it with "GLO" + if(!is.null(d$regional)) { + for(i in d$regional) { + dimnames(x)[[i]] <- sub("^glob$","GLO",dimnames(x)[[i]]) + } + } + + #make sure that temporal dimension uses dimnames of the form y0000 + if(!is.null(d$temporal)) { + for(i in d$temporal) { + dimnames(x)[[i]] <- sub("^[a-z]?([0-9]{4})$","y\\1",dimnames(x)[[i]]) + } + } + + #make sure that spatial dimension uses dimnames of the form XXX.123 + if(!is.null(d$regiospatial)) { + for(i in d$regiospatial) { + ntmp <- names(dimnames(x))[1] + if(!is.null(ntmp)) if(!is.na(ntmp)) if(names(dimnames(x))[1] == "j") names(dimnames(x))[1] <- "i.j" + dimnames(x)[[i]] <- sub("_","\\.",dimnames(x)[[i]]) + } + } + + + #If no temporal dimension is defined, but a dimension of type nothing exists, use this dimension as temporal dimension + if(is.null(d$temporal)) { + if(length(d$nothing)>0) { + d$temporal <- d$nothing[1] + d$nothing <- d$nothing[-1] + if(length(d$nothing)==0) d$nothing <- NULL + } else { + d$temporal <- 0 + } + } + + #try to create regiospatial dimension if possible + if(is.null(d[["regiospatial"]])) { + #regional dimension exists + if(!is.null(d$regional)) { + #dimnames(x)[[d$regional]] <- paste(dimnames(x)[[d$regional]],1:dim(x)[d$regional],sep=".") + d$regiospatial <- d$regional + } else { + d$regiospatial <- 0 + } + } + d$regional <- NULL + + #Starting from here d$temporal and d$regiospatial should be defined both + #If any of these two could neither be found nor created the value should be 0 + + if(d$regiospatial==0) { + if(is.null(dimnames(x))) { + x <- array(x,c(dim(x),1)) + dimnames(x)[[length(dim(x))]] <- list("GLO") + } else { + x <- array(x,c(dim(x),1),c(dimnames(x),"GLO")) + } + d$regiospatial <- length(dim(x)) + } + + if(d$temporal==0) { + x <- array(x,c(dim(x),1),c(dimnames(x),NULL)) + d$temporal <- length(dim(x)) + } + + #Check if third dimension exists. If not, create it + if(length(dim(x))==2) { + x <- array(x,c(dim(x),1),c(dimnames(x),NULL)) + } + + #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))))) + } +) + +setMethod("as.magpie", + signature(x = "numeric"), + function(x,...) + { + return(copy.attributes(x,as.magpie(as.array(x),...))) + } +) + +setMethod("as.magpie", + signature(x = "NULL"), + function (x) + { + return(NULL) + } +) + +setMethod("as.magpie", + signature(x = "data.frame"), + function (x, datacol=NULL, tidy=FALSE, ...) + { + if(tidy) return(tidy2magpie(x,...)) + if(dim(x)[1]==0) return(copy.attributes(x,new.magpie(NULL))) + if(is.null(datacol)) { + for(i in dim(x)[2]:1) { + if(all(!is.na(suppressWarnings(as.numeric(x[,i])))) & !is.temporal(x[,i])) { + datacol <- i + } else { + break + } + } + } + if(!is.null(datacol)) { + if(datacol==1) return(copy.attributes(x,as.magpie(as.matrix(x),...))) + 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)),...))) + } +) + +setMethod("as.magpie", + signature(x = "quitte"), + function(x, ...) + { + is.quitte <- function(x, warn=FALSE) { + # object is not formally defined as quitte class + if(!methods::is(x,"quitte")) return(FALSE) + + # object is formally defined as quitte but it has to + # be checked whether it follows all structural + # rules of a quitte object + + # are all mandatory columns included? + mandatory_columns <- c("model","scenario","region","variable","unit","period","value") + if(!all(mandatory_columns %in% names(x))) { + if(warn) warning("Object formally defined as quitte object, but it does not contain all required columns (missing: ",paste(mandatory_columns[!(mandatory_columns %in% names(x))],collapse=", "),")!") + return(FALSE) + } + + # are all columns factors which have to be factors? + factor_columns <- sapply(x[c("model","scenario","region","variable","unit")],is.factor) + if(!all(factor_columns)) { + if(warn) warning("Object formally defined as quitte object, but there are columns not stored as factor which actually have to be stored that way (no factor: ",paste(names(factor_columns)[!factor_columns],collapse=", "),")!") + return(FALSE) + } + + #is the value column of type numeric? + if(!is.numeric(x$value)) { + if(warn) warning("Object formally defined as quitte object, but value column is not of type numeric!") + return(FALSE) + } + + #is period column of type POSIXct? + if(!methods::is(x$period,"POSIXct") && !is.integer(x$period)) { + if(warn) warning("Object formally defined as quitte object, but period column is neither integer nor of type POSIXct!") + return(FALSE) + } + + return(TRUE) + } + + if(!is.quitte(x)) { + warning("Input does not follow the full quitte class definition! Fallback to data.frame conversion.") + class(x) <- "data.frame" + return(as.magpie(x,...)) + } + x$period <- format(x$period, format = "y%Y") + if(length(grep("^cell$",names(x),ignore.case=TRUE)) > 0) { + i <- grep("^cell$",names(x),ignore.case=TRUE,value=TRUE) + x$region <- paste(x$region,x[[i]],sep=".") + x <- x[names(x)!=i] + } + #remove NA columns + x <- x[colSums(!is.na(x))!=0] + + #put value column as last column + x <- x[c(which(names(x)!="value"),which(names(x)=="value"))] + return(tidy2magpie(x,spatial="region",temporal="period")) + } +) + +setMethod("as.magpie", + signature(x = "tbl_df"), + function(x, ...) + { + if("quitte" %in% class(x)) { + class(x) <- c("quitte","data.frame") + } else { + class(x) <- "data.frame" + } + return(as.magpie(x,...)) + } +) diff --git a/R/calibrate_it.R b/R/calibrate_it.R new file mode 100644 index 00000000..c4359be7 --- /dev/null +++ b/R/calibrate_it.R @@ -0,0 +1,84 @@ +#' calibrate_it +#' +#' Standardized functions to calibrate values to a certain baseyear. +#' +#' +#' @param origin Original Values (MAgPIE object) +#' @param cal_to Values to calibrate to (MAgPIE object). +#' @param cal_type "none" leaves the values as they are, "convergence" starts +#' from the aim values and then linearily converges towards the values of +#' origin, "growth_rate" uses the growth-rates of origin and applies them on +#' aim. +#' @param cal_year year on which the dataset should be calibrated. +#' @param end_year only for cal_type="convergence". Year in which the +#' calibration shall be faded out. +#' @param report_calibration_factors prints out the multipliers which are used +#' for calibration. +#' @return Calibrated dataset. +#' @author Benjamin Bodirsky +#' @seealso \code{\link{convergence}},\code{\link{lin.convergence}} +#' @examples +#' +#' data(population_magpie) +#' test<-as.magpie(array(1000,dim(population_magpie[,,"A2"]),dimnames(population_magpie[,,"A2"]))) +#' calibrate_it(origin=population_magpie,cal_to=test[,"y1995",],cal_type="growth_rate") +#' calibrate_it(origin=population_magpie,cal_to=test[,"y1995",],cal_type="convergence", +#' cal_year="y1995", end_year="y2055") +#' calibrate_it(origin=population_magpie,cal_to=test[,"y1995",],cal_type="none") +#' +#' @export calibrate_it +calibrate_it<-function(origin, cal_to, cal_type="convergence", cal_year=NULL, end_year=NULL, report_calibration_factors=FALSE) { +#data(population_magpie) +#origin = population_magpie[,,"A2"] +#cal_to= population_magpie[,,"B1"] +#cal_year="y1995" +#end_year="y2155" +#cal_type="convergence" +#origin=population_country_inputdata[,names_years_sres,definition_population_x] +#cal_to=population_calibrate_to_country[,,c("worldbank")] +#cal_type=definition_population_calib_x +#cal_year=definition_calib_year +#end_year=calibration_convergence_year + if(cal_type=="convergence"&(is.null(cal_year) | is.null(end_year))){stop("for convergence, cal_year and end_year is required")} + if(!is.magpie(origin)){stop("origin is no magpie object")} + if(!is.magpie(cal_to)){stop("cal_to is no magpie object")} + if(!is.null(cal_year)){ + if (cal_year %in% getYears(cal_to)) {cal_to<-cal_to[,cal_year,]} + } + if (dim(cal_to)[[2]]!=1){stop("cal_to has more timesteps than one.")} + if ((is.null(cal_year))&(dim(cal_to)[2]==1)) { + cal_year<-getYears(cal_to) + cal_to<-setNames(cal_to,NULL) + } + if ((!is.null(cal_year))&(cal_year==getYears(cal_to))) {cal_to<-setNames(cal_to,NULL)} + if (!is.null(getYears(cal_to))&(cal_year!=getYears(cal_to))) {stop("cal_year has to be in cal_to, or cal_to has to be NULL")} + if (!is.null(getNames(cal_to))&(!identical(getNames(origin),getNames(cal_to)))) {stop("names of cal_to has to be identical with origin or NULL")} + calibration_factor<-as.magpie(array(NA,dim(origin),dimnames(origin))) + calibration_factor[,,]<-1 + calibrated <-as.magpie(array(NA,dim(origin),dimnames(origin))) + + cal_to <- setYears(cal_to[,cal_year,],NULL) + + if (cal_type=="none") { + calibrated<-origin + if(report_calibration_factors==TRUE){ + print(1) + } + } else if (cal_type=="convergence") { + calibration_factor[,,]<-cal_to[,,]/setYears(origin[,cal_year,],NULL) + calibration_factor<-convergence(origin=calibration_factor, aim=1, start_year=cal_year, end_year=end_year, direction=NULL, type="linear") +# calibration_factor<-lin.convergence(origin=calibration_factor, aim=1, start_year=cal_year, end_year=end_year,before=before, after=after) + calibrated<-origin*calibration_factor + if(report_calibration_factors==TRUE){ + print(calibration_factor) + } + } else if (cal_type=="growth_rate") { + cal_origin <- setYears(origin[,cal_year,],NULL) + calibrated[,,] <- origin[,,]/cal_origin[,,]*cal_to[,,] + if(report_calibration_factors==TRUE){ + print(cal_origin[,,]*cal_to[,,]) + } + } else {stop("unknown cal_type")} + return(calibrated) +} + diff --git a/R/clean_magpie.R b/R/clean_magpie.R new file mode 100644 index 00000000..6a5a4013 --- /dev/null +++ b/R/clean_magpie.R @@ -0,0 +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) +} diff --git a/R/colMeans-method.R b/R/colMeans-method.R new file mode 100644 index 00000000..f2e1434f --- /dev/null +++ b/R/colMeans-method.R @@ -0,0 +1,13 @@ +#' @importFrom methods new +#' @exportMethod colMeans +setMethod("colMeans", + signature(x = "magpie"), + function (x, na.rm = FALSE, dims = 1, ...) + { + x_array<-as.array(x) + x_glo<-colMeans(x_array,na.rm=na.rm,...) + x<-new("magpie",array(x_glo,dim=c(1,dim(x_glo)),dimnames=c("GLO",dimnames(x_glo)))) + return(x) + } + ) + diff --git a/R/colSums-method.R b/R/colSums-method.R new file mode 100644 index 00000000..695f2ded --- /dev/null +++ b/R/colSums-method.R @@ -0,0 +1,35 @@ +#' ~~ Methods for Function colSums and colMeans ~~ +#' +#' ~~ Methods for function \code{colSums} and \code{colMeans} ~~ +#' +#' +#' @name colSums-methods +#' @aliases colSums-methods colSums,ANY-method colSums,magpie-method +#' colMeans-methods colMeans,ANY-method colMeans,magpie-method +#' @param x object on which calculation should be performed +#' @param na.rm logical. Should missing values (including NaN) be omitted from the calculations? +#' @param dims integer: Which dimensions are regarded as "rows" or "columns" to sum over. For row*, +#' the sum or mean is over dimensions dims+1, ...; for col* it is over dimensions 1:dims. +#' @param ... further arguments passed to other colSums/colMeans methods +#' @docType methods +#' @section Methods: \describe{ +#' +#' \item{list("signature(x = \"ANY\")")}{ normal colSums and colMeans method } +#' +#' \item{list("signature(x = \"magpie\")")}{ classical method prepared to +#' handle MAgPIE objects } } +#' @keywords methods ~~ other possible keyword(s) ~~ +#' @importFrom methods new +#' @exportMethod colSums +#' +setMethod("colSums", + signature(x = "magpie"), + function (x, na.rm = FALSE, dims = 1, ...) + { + x_array<-as.array(x) + x_glo<-colSums(x_array,na.rm=na.rm,...) + x<-new("magpie",array(x_glo,dim=c(1,dim(x_glo)),dimnames=c("GLO",dimnames(x_glo)))) + return(x) + } + ) + diff --git a/R/collapseNames.R b/R/collapseNames.R new file mode 100644 index 00000000..0ad49708 --- /dev/null +++ b/R/collapseNames.R @@ -0,0 +1,75 @@ +#' Collapse dataset names +#' +#' This function will remove names in the data dimension which are the same for +#' each element (meaning that this data dimension contains exactly one element) +#' +#' +#' @param x MAgPIE object +#' @param collapsedim If you want to remove the names of particular dimensions +#' provide the dimensions here. Since the function only works in the third dimension, +#' you have to count from there on (e.g. dim = 3.2 refers to collapsedim = 2). Default: NULL. +#' CAUTION with parameter collapsedim! You could also force him to remove dimnames, +#' which are NOT the same for each element and so create duplicates in dimnames. +#' @return The provided MAgPIE object with collapsed names +#' @author Jan Philipp Dietrich, David Klein, Xiaoxi Wang +#' @seealso \code{\link{getNames}}, \code{\link{setNames}}, +#' \code{"\linkS4class{magpie}"} +#' @examples +#' +#' x <- new.magpie("GLO",2000,c("bla.a","bla.b")) +#' print(x) +#' # An object of class "magpie" +#' # , , bla.a +#' # y2000 +#' # GLO.1 NA +#' # , , bla.b +#' # y2000 +#' # GLO.1 NA +#' +#' print(collapseNames(x)) +#' # An object of class "magpie" +#' # , , a +#' # y2000 +#' # GLO.1 NA +#' # , , b +#' # y2000 +#' # GLO.1 NA +#' +#' print(collapseNames(x), collapseNames = 2) +#' # An object of class "magpie" +#' # , , bla +#' # y2000 +#' # GLO.1 NA +#' # , , bla +#' # y2000 +#' # GLO.1 NA +#' +#' @export collapseNames +collapseNames <- function(x,collapsedim=NULL) { + if(is.null(x)) return(NULL) + if(is.null(getNames(x))) return(x) + f <- fulldim(x) + if (is.null(collapsedim)) { + collapsedim <- which(f[[1]][-1:-2]==1) + } + maxdim <- length(f[[1]])-2 + tmp <- getNames(x) + tmp2 <- names(dimnames(x))[3] + for(i in collapsedim) { + searchstring <- paste("^(",paste(rep(".*\\.",i-1),collapse=""),")[^\\.]*(",paste(rep("\\..*",maxdim-i),collapse=""),")$",sep="") + tmp <- sub(searchstring,"\\1\\2",tmp) + tmp2 <- sub(searchstring,"\\1\\2",tmp2) + } + tmp <- gsub("\\.+","\\.",tmp) + tmp <- sub("^\\.","",tmp) + tmp <- sub("\\.$","",tmp) + tmp2 <- gsub("\\.+","\\.",tmp2) + tmp2 <- sub("^\\.","",tmp2) + tmp2 <- sub("\\.$","",tmp2) + if(length(tmp)==1) if(tmp=="") tmp <- NULL + if(length(tmp2)==0) tmp2 <- "data" + getNames(x) <- tmp + names(dimnames(x))[3] <- tmp2 + x <- clean_magpie(x,what="sets") + return(x) +} diff --git a/R/complete_magpie.R b/R/complete_magpie.R new file mode 100644 index 00000000..e6af1133 --- /dev/null +++ b/R/complete_magpie.R @@ -0,0 +1,39 @@ +#' complete_magpie +#' +#' MAgPIE objects can be incomplete to reduce memory. This function blows up a +#' magpie object to its real dimensions, so you can apply unwrap. +#' +#' +#' @param x MAgPIE object which should be completed. +#' @param fill Value that shall be written into the missing entries +#' @return The completed MAgPIE object +#' @author Benjamin Bodirsky +#' @seealso \code{\link{add_dimension}},\code{\link{clean_magpie}} +#' @examples +#' +#' data(population_magpie) +#' a <- complete_magpie(population_magpie) +#' b <- add_dimension(a) +#' c <- add_dimension(a,nm="dummy2") +#' incomplete<-mbind(b[,,1],c) +#' d<-complete_magpie(incomplete) +#' +#' @export complete_magpie +complete_magpie<-function(x,fill=NA) { + full<-fulldim(x)[[2]] + permute<-full[[3]] + repeatit<-length(permute) + if (length(full)>3) { + for (i in 4:length(full)) { + permute<-paste(rep(permute,each=length(full[[i]])),full[[i]],sep=".") + repeatit<-length(permute) + } + } + missing<-permute[!(permute%in%dimnames(x)[[3]])] + if(length(missing)>0){ + add<-new.magpie(cells_and_regions = full[[1]],years = full[[2]],names = missing,fill=fill) + out<-mbind(x,add) + } else {out<-x} + out<-out[,,order(getNames(out))] + return(out) +} diff --git a/R/convergence.R b/R/convergence.R new file mode 100644 index 00000000..0677813f --- /dev/null +++ b/R/convergence.R @@ -0,0 +1,106 @@ +#' convergence +#' +#' Cross-Fades the values of one MAGPIE object into the values of another over +#' a certain time +#' +#' +#' @param origin an object with one name-column +#' @param aim Can be twofold: An magpie object or a numeric value. +#' @param start_year year in which the convergence from origin to aim starts. +#' If set to NULL the the first year of aim is used as start_year +#' @param end_year year in which the convergence from origin to aim shall be +#' (nearly) reached. If set to NULL the the last year of aim is used as +#' end_year. +#' @param direction NULL, "up" or "down". NULL means normal convergence in both +#' directions, "up" is only a convergence if originaim +#' @param type "smooth", "s", "linear" or "decay". Describes the type of +#' convergence: linear means a linear conversion , s is an s-curve which starts +#' from origin in start_year and reaches aim precisely in end_year. After 50 +#' percent of the convergence time, it reaches about the middle of the two +#' values. Its based on the function min(1, pos^4/(0.07+pos^4)*1.07) smooth is +#' a conversion based on the function x^3/(0.1+x^3). In the latter case only +#' 90\% of convergence will be reached in the end year, because full +#' convergence is reached in infinity. decay is a conversion based on the +#' function x/(1.5 + x)*2.5. +#' @param par parameter value for convergence function; currently only used for +#' type="decay" +#' @return returns a time-series with the same timesteps as origin, which +#' lineary fades into the values of the aim object +#' @author Benjamin Bodirsky, Jan Philipp Dietrich +#' @seealso \code{\link{lin.convergence}} +#' @examples +#' +#' data(population_magpie) +#' population <- add_columns(population_magpie,"MIX") +#' population[,,"MIX"]<-convergence(population[,,"A2"],population[,,"B1"]) +#' +#' +#' @export convergence +convergence <- function(origin, aim, start_year=NULL, end_year=NULL, + direction=NULL, type="smooth", par=1.5) { + + ### Basic checks ### + if(!is.magpie(origin)) stop("origin is no magpie object") + + if(is.null(dim(aim))) aim<-as.magpie(array(aim,dim(origin),dimnames(origin))) + if(!is.magpie(aim)) stop("aim is no magpie object") + + if (all(dimnames(aim)[[1]]!=dimnames(origin)[[1]])) + stop("regions have to be the same") + + if (ndata(origin)!=1 & !identical(getNames(origin), getNames(aim))) + stop("If there ist more than one name-column, dimnames have to be the same") + + if(nyears(aim)==1) { + tmp <- setYears(aim,NULL) + aim <- origin + aim[,,] <- tmp + rm(tmp) + } + + if(nyears(origin)==1) { + tmp <- setYears(origin,NULL) + origin <- aim + origin[,,] <- tmp + rm(tmp) + } + + if (any(getYears(aim) != getYears(origin))) + stop("Objects need the same timesteps, or aim has to have only one timestep") + + if (is.null(start_year)) start_year <- getYears(aim)[1] + if (is.null(end_year)) end_year <- getYears(aim)[nyears(aim)] + + if(isYear(start_year,with_y=TRUE)) start_year <- substr(start_year,2,5) + if(isYear(end_year,with_y=TRUE)) end_year <- substr(end_year,2,5) + start_year <- as.numeric(start_year) + end_year <- as.numeric(end_year) + if(!isYear(start_year,with_y=FALSE)) stop("wrong year format for convergence aim") + if(!isYear(end_year,with_y=FALSE)) stop("wrong year format for convergence aim") + + + # In the case of direction up or down data should only be manipulated in one + # direction. Therefor, the aim object is manipulated accordingly + if(!is.null(direction)) { + aim <- as.array(aim) + if(direction=="up") aim[which(aimorigin)] <- as.array(origin)[which(aim>origin)] + else stop("Illegal direction setting, only up and down are allowed arguments!") + aim <- as.magpie(aim) + } + + years<-new.magpie("GLO",getYears(origin),NULL,getYears(origin,as.integer=TRUE)) + pos <- (years - start_year)/(end_year - start_year) + pos[pos<0] <- 0 + pos[pos>1] <- 1 + if (type == "linear") { mix <- pos + } else if (type == "s") { mix <- pos^4/(0.07+pos^4)*1.07 + } else if (type == "smooth") {mix <- pos^3/(0.1 + pos^3) +# } else if (type == "decay") {mix <- pos/(0.5 + pos)*1.5 + } else if (type == "decay") {mix <- pos/(par + pos)*(par+1) + } else {stop("type does not exist")} + converged <- aim * mix + origin * (1 - mix) + + return(converged) +} diff --git a/R/convert.report.R b/R/convert.report.R new file mode 100644 index 00000000..0308ae02 --- /dev/null +++ b/R/convert.report.R @@ -0,0 +1,75 @@ +#' Converts a report from one model to another +#' +#' This function converts the content of a reporting file from one model to +#' another +#' +#' The function converts data based on a region mapping and transformation +#' rules which are stored in the variable magclassdata which comes with this +#' library. +#' +#' @param rep Report. Either the file name of a mif file or a report already +#' read in in R. +#' @param inmodel Model the input comes from. If NULL the script tries to +#' detect the inmodel automatically. +#' @param outmodel Model format the data should be converted to. Currently, +#' only "MAgPIE" is available +#' @param full Boolean deciding whether only the converted output should be +#' returned (FALSE) or the new output together with the input (TRUE) +#' @param as.list if TRUE a list is returned (default), if FALSE it is tried to +#' merge all information in one MAgPIE object (still under development and +#' works currently only if the entries for the different models and scenarios +#' have exactly the same regions and years). +#' @author Jan Philipp Dietrich +#' @seealso +#' \code{\link{read.report}},\code{\link{write.report}},\code{\link{magclassdata}} +#' @examples +#' +#' \dontrun{convert.report("report.mif")} +#' +#' @export convert.report +convert.report <- function(rep,inmodel=NULL,outmodel="MAgPIE",full=FALSE,as.list=TRUE) { + # Commets would improve the code + .convert <- function(input,inmodel=NULL,outmodel="MAgPIE",full=FALSE) { + map <- magclassdata$map + if(!(outmodel %in% names(map))) stop("No existing transformation rules for output model \"",outmodel,"\"!",call.=FALSE) + if(!(inmodel %in% names(map[[outmodel]]))) stop("No existing transformation rules for input model \"",inmodel,"\" in combination with output model \"",outmodel,"\"!",call.=FALSE) + if(outmodel %in% names(input)) stop("Input already contains data for model \"",outmodel,"\"",call.=FALSE) + map <- map[[outmodel]][[inmodel]] + if(!inmodel %in% names(input)) stop(paste0("The inmodel ",inmodel," is not available in the names of input: ",names(input))) + mag <- input[[inmodel]] + if("GLO" %in% getRegions(mag)) map$GLO <- "GLO" + outmag <- mag[rep(1,length(map)),,unlist(magclassdata$trans)[unlist(magclassdata$trans) %in% getNames(mag)]] + outmag[,,] <- NA + dimnames(outmag)[[1]] <- names(map) + for(reg in names(map)) { + #sum + elem <- getNames(mag)[getNames(mag) %in% magclassdata$trans$sum] + if(length(elem)>0) if(!is.na(map[[reg]])) suppressWarnings(outmag[reg,,elem] <- colSums(mag[map[[reg]],,elem])) + #mean + elem <- getNames(mag)[getNames(mag) %in% magclassdata$trans$mean] + if(length(elem)>0) if(!is.na(map[[reg]])) suppressWarnings(outmag[reg,,elem] <- colMeans(mag[map[[reg]],,elem])) + } + out <- list(); + if(full) out[[inmodel]]=mag; + out[[outmodel]]=outmag; + return(out) + } + if(is.character(rep)) rep <- read.report(rep) + if(is.null(inmodel)) { + if(length(names(rep[[1]]))==1) inmodel <- names(rep[[1]]) + else stop("Not clear which model should be used as input!") + } + if(inmodel!=outmodel) { + rep <- lapply(rep,.convert,inmodel,outmodel,full) + } + if(!as.list) { + for(scenario in names(rep)) { + for(model in names(rep[[scenario]])) { + getNames(rep[[scenario]][[model]]) <- paste(scenario,model,getNames(rep[[scenario]][[model]]),sep=".") + } + } + rep <- mbind(unlist(rep,recursive=FALSE)) + names(dimnames(rep))[3] <- "scenario.model.value" + } + return(rep) +} diff --git a/R/copy.attributes.R b/R/copy.attributes.R new file mode 100644 index 00000000..ca37c652 --- /dev/null +++ b/R/copy.attributes.R @@ -0,0 +1,45 @@ +#' Copy Attributes +#' +#' This function copies attributes from one object and assigns them to another. +#' +#' +#' @aliases copy.attributes copy.attributes<- +#' @param from object from which the attributes should be taken +#' @param value Same as "from" (object from which the attributes should be +#' taken) +#' @param to object to which the attributes should be written +#' @param delete attributes which should not be copied. By default this are +#' class specific attributes which might cause problems if copied to another +#' object. But you can add or remove attributes from the vector. +#' @param delete2 Identical to delete and just added for convenience for the +#' case that you want to delete additional attributes but do not want to repeat +#' the vector given in delete. In the function both vectors, delete and +#' delete2, are just merged to one deletion vector. +#' @author Jan Philipp Dietrich +#' @examples +#' +#' from <- array(12) +#' attr(from,"blablub") <- "I am an attribute!" +#' attr(from,"blablub2") <- "I am another attribute!" +#' +#' print(attributes(from)) +#' +#' to <- as.magpie(0) +#' print(attributes(to)) +#' +#' copy.attributes(to) <- from +#' print(attributes(to)) +#' +#' @export +copy.attributes <- function(from,to,delete=c('names','row.names','class','dim','dimnames'),delete2=NULL) { + a <- attributes(from) + a[c(delete,delete2)] <- NULL + attributes(to) <- c(attributes(to),a) + return(to) +} + +#' @describeIn copy.attributes assign attributes from object "value" +#' @export +"copy.attributes<-" <- function(to,delete=c('names','row.names','class','dim','dimnames'),delete2=NULL,value) { + return(copy.attributes(from=value,to=to,delete=delete,delete2=delete2)) +} diff --git a/R/copy.magpie.R b/R/copy.magpie.R new file mode 100644 index 00000000..e204978d --- /dev/null +++ b/R/copy.magpie.R @@ -0,0 +1,26 @@ +#' Copy MAgPIE-files +#' +#' This function copies MAgPIE-files from one location to another. During the +#' copying it is also possible to change the file type (e.g. from 'mz' to +#' 'csv') +#' +#' +#' @aliases copy.magpie copy.magpie +#' @param input_file file, that should be copied +#' @param output_file copy destination +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{read.magpie}},\code{\link{write.magpie}} +#' @examples +#' +#' # copy.magpie("bla.csv","blub.mz") +#' +#' @export copy.magpie +copy.magpie <- function(input_file,output_file) { + in_type <- tail(strsplit(input_file,'\\.')[[1]],1) + out_type <- tail(strsplit(output_file,'\\.')[[1]],1) + if(in_type==out_type) { + tmp <- file.copy(input_file, output_file, overwrite=TRUE) + } else { + write.magpie(read.magpie(input_file), output_file) + } +} diff --git a/R/dimCode.R b/R/dimCode.R new file mode 100644 index 00000000..05bb2ae0 --- /dev/null +++ b/R/dimCode.R @@ -0,0 +1,41 @@ +#' dimCode +#' +#' Function converts a dimension name or number to a dimension Code used for +#' MAgPIE objects +#' +#' +#' @param dim A vector of dimension numbers or dimension names which should be +#' translated +#' @param x MAgPIE object in which the dimensions should be searched for. +#' @param missing Either a value to which a dimension should be set in case +#' that it is not found (default is 0), or "stop" indicating that the function +#' should throw an error in these cases. +#' @return A dimension code identifying the dimension. Either a integer which +#' represents the main dimensions (1=spatial, 2=temporal, 3=data) or a numeric, +#' representing the subdimensions of a dimension (e.g. 3.2 for the second data +#' dimension). +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{mselect}}, \code{\link{getDim}} +#' @examples +#' +#' data(population_magpie) +#' dimCode(c("t","scenario","blablub"),population_magpie) +#' +#' @export dimCode +dimCode <- function(dim,x,missing=0){ + #function to translate dim to dim code + if(is.character(dim)) { + dnames <- dim + dim <- match(dim,getSets(x),nomatch=0) + if(length(dim)>length(dnames)) stop('One or more elements were found more than once in x!') + names(dim) <- dnames + + #translate sub-datadimensions to 3.1, 3.2,... + dim[dim>=3] <- 3 + (dim[dim>=3]-2)/10 + } + if(any(dim>=4) | any(dim<1)) { + if(missing=="stop") stop("illegal dimension. Use either dimension 1, 2, or 3, or if you want to address subdimensions use 3.1, 3.2, ...") + dim[dim>=4 | dim<1] <- missing + } + return(dim) +} diff --git a/R/dimOrder.R b/R/dimOrder.R new file mode 100644 index 00000000..7d526aec --- /dev/null +++ b/R/dimOrder.R @@ -0,0 +1,31 @@ +#' @title dimOrder +#' @description Changes the order of the 3rd dimension in a magpie object similar to unwrapping and applying the aperm command, but more efficient. +#' +#' @param x magpie object +#' @param perm vector with the new order of the 3rd dimension +#' +#' @return magpie object +#' @author Benjamin Leon Bodirsky + +#' @examples +#' +#' \dontrun{ +#' data("population_magpie") +#' x<-setNames(population_magpie,c("kj","kej"))*population_magpie +#' dimOrder(x=x,perm=c(2,1)) +#' } +#' @export + + + +dimOrder <- function(x,perm){ + dimensions=length(fulldim(x)[[1]])-2 + if (dimensions!=length(perm)) {stop("perm has to have the length of the 3rd dimensions")} + if (!identical(levels(as.factor(1:dimensions)),levels(as.factor(perm)))) {stop("perm has to include all 3rd dimensions")} + if (dimensions>1){ + pattern=paste0("^([^\\.]*)\\.",rep("([^\\.]*)\\.",dimensions-2),"([^\\.]*)$") + order=paste0(paste0("\\",perm),collapse=".") + getNames(x) <- gsub(pattern = pattern,replacement=order,getNames(x)) + } + return(x) +} diff --git a/R/dimSums.R b/R/dimSums.R new file mode 100644 index 00000000..c813898b --- /dev/null +++ b/R/dimSums.R @@ -0,0 +1,131 @@ +.dimSums_fallback<-function (x, na.rm = FALSE, dims = NULL, sep = ".", ...) +{ + dims <- as.integer(round((dims-3)*10 + 2)) + #fallback option if data dimension is sparse + if (!is.magpie(x)) stop("Input is not a MAgPIE object!") + f <- fulldim(x) + ndim <- length(f[[1]]) + if (any(dims > ndim)) stop("Invalid dimension(s) specified") + + if(any(dims<3)) stop("not implemented yet") + + #remove names from dimensions that should be summed up + s <- paste0("^",paste(rep("([^\\.]*)",ndim-2),collapse="\\."),"$") + d <- setdiff(1:ndim,dims)-2 + d <- d[d>0] + r <- paste0("\\",d,collapse="\\.") + + getNames(x) <- sub(s,r,getNames(x)) + getSets(x,fulldim=FALSE)[3] <- sub(s,r,getSets(x,fulldim=FALSE)[3]) + if(getSets(x,fulldim=FALSE)[3]=="") getSets(x,fulldim=FALSE)[3] <- "data1" + un <- unique(getNames(x)) + + out <- new.magpie(cells_and_regions=getCells(x),years=getYears(x),names=un,sets=getSets(x)) + names(dimnames(out)) <- names(dimnames(x)) + x <- as.array(x) + for(i in un) { + j <- which(dimnames(x)[[3]]==i) + out[,,i] <- dimSums(x[,,j,drop=FALSE],na.rm=na.rm,dim=3,sep=sep,...) + } + if(ndata(out)==1) if(getNames(out)=="") getNames(out) <- NULL + + return(out) +} + + + + + +#' Summation over dimensions +#' +#' This function sums over any dimension of a magpie object or an array +#' +#' +#' @param x A MAgPIE-object or an array +#' @param na.rm logical. Should missing values (including NaN) be omitted from +#' the calculations? +#' @param dims Depreceated version of argument dim. Please use dim instead (it +#' is just it there for back compatibility and will be removed soon.) +#' @param dim The dimensions(s) to sum over. A vector of integers or characters +#' (dimension names). If the MAgPIE object has more than 1 actual dimension +#' collected in the third real dimension, each actual dimension can be summed +#' over using the corresponding dim code (see \code{\link{dimCode}} for more +#' information) +#' @param sep A character separating joined dimension names +#' @param ... Further arguments passed to rowSums internally +#' @return \item{value}{A MAgPIE object or an array (depending on the format of +#' x) with values summed over the specified dimensions} +#' @author Markus Bonsch, Ina Neher, Benjamin Bodirsky, Jan Philipp Dietrich +#' @seealso \code{\link{rowSums}}, \code{\link{dimSums}}, \code{\link{dimCode}} +#' @examples +#' +#' test<-as.magpie(array(1:4,dim=c(2,2))) +#' dimSums(test,dim=c(1,3)) +#' dimSums(test[,,1],na.rm=TRUE,dim=c(1,2)) +#' +#' +#' @export dimSums +dimSums<-function (x, na.rm = FALSE, dims = NULL, dim = 3, sep = ".", ...) +{ + if(!is.null(dims)) { + warning('Argument "dims" is depreceated, please use "dim" instead. See ?dimSums for more information!') + if(is.character(dims)) { + dim <- dims + } else { + dim <- dims + dim[dim>=3] <- 3 + (dim[dim>=3]-2)/10 + } + } + if (is.magpie(x)){ + dim <- dimCode(dim,x) + if(prod(fulldim(x)[[1]])!=prod(dim(x))) { + if(any(dim>3)) { + tmp <- .dimSums_fallback(x, na.rm = na.rm, dims = dim[dim>3], sep = sep, ...) + } else { + tmp <- x + } + dim <- dim[dim<=3] + if(length(dim)==0) { + return(tmp) + } else { + tmp <- as.array(tmp) + } + } else { + if(all(dim!=3)) { + tmp <- unwrap(x) + dim[dim>3] <- as.integer(round((dim[dim>3]-3)*10+2)) + } else { + tmp <- as.array(x) + dim <- dim[dim<=3] + } + } + } else if (is.array(x)) { + tmp<-x + } else { + stop("Input is neiter an array nor a MAgPIE object!") + } + + if (any(dim > length(dim(tmp)))) + stop("Invalid dimension(s) specified") + unchanged_dims <- which(!1:length(dim(tmp)) %in% dim) + out <- aperm(tmp, perm = c(unchanged_dims, dim)) + out <- rowSums(out, na.rm = na.rm, dims = length(unchanged_dims), + ...) + remaining_dims <- match(1:length(dim(tmp)), unchanged_dims, + nomatch = 0) + remaining_dims <- remaining_dims[remaining_dims > 0] + + if (is.magpie(x)){ + spatial <- ifelse(1 %in% dim, 0, 1) + temporal <- ifelse(2 %in% dim, 0, ifelse(1 %in% dim, 1, 2)) + out <- as.magpie(aperm(as.array(out), perm = remaining_dims),spatial=spatial,temporal=temporal) + if (1 %in% dim && nregions(x) == 1) + dimnames(out)[[1]] <- getRegions(x) + if (2 %in% dim && nyears(x) == 1) + dimnames(out)[[2]] <- getYears(x) + out <- clean_magpie(out) + } else { + out <- aperm(as.array(out), perm = remaining_dims) + } + return(out) +} diff --git a/R/duplicates_check.R b/R/duplicates_check.R new file mode 100644 index 00000000..ed6dad88 --- /dev/null +++ b/R/duplicates_check.R @@ -0,0 +1,7 @@ +.duplicates_check <- function(coord) { + coord <- as.data.frame(coord) + duplicates <- duplicated(coord) + if(any(duplicates)) { + warning("Duplicate entries found, only the last entry will be used (duplicate entries: ",paste(apply(rbind(NULL,unique(coord[duplicates,])),1,paste,collapse="|"),collapse=", "),")!") + } +} \ No newline at end of file diff --git a/R/escapeRegex.R b/R/escapeRegex.R new file mode 100644 index 00000000..08b8dae2 --- /dev/null +++ b/R/escapeRegex.R @@ -0,0 +1,14 @@ +#' escapeRegex +#' +#' Escapes all symbols in a string which have a special meaning in regular +#' expressions. +#' +#' +#' @param x String or vector of strings that should be escaped. +#' @return The escaped strings. +#' @author Jan Philipp Dietrich +#' @seealso \code{\link[base]{grep}} +escapeRegex <- function(x) +{ + return(gsub("([.|()\\^{}+$*?]|\\[|\\])", "\\\\\\1", x)) +} diff --git a/R/fulldim.R b/R/fulldim.R new file mode 100644 index 00000000..2d2309b3 --- /dev/null +++ b/R/fulldim.R @@ -0,0 +1,53 @@ +#' Reconstructs full dimensionality of MAgPIE objects +#' +#' If a MAgPIE object is created from a source with more than one data +#' dimension, these data dimensions are combined to a single dimension. fulldim +#' reconstructs the original dimensionality and reports it. +#' +#' +#' @param x A MAgPIE-object +#' @param sep A character separating joined dimension names +#' @return A list containing in the first element the dim output and in the +#' second element the dimnames output of the reconstructed array. +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{as.magpie}},\code{\link{unwrap}},\code{\link{wrap}} +#' @examples +#' +#' a <- as.magpie(array(1:6,c(3,2),list(c("bla","blub","ble"),c("up","down")))) +#' fulldim(a) +#' +#' +#' @export fulldim +fulldim <- function(x,sep=".") { + if(!is.null(dimnames(x)[[3]])){ + elemsplit <- strsplit(dimnames(x)[[3]],sep,fixed=TRUE) + tmp <- sapply(elemsplit,length) + } else{ + tmp<-1 + } + if(length(tmp)==1) if(tmp==0) tmp <- 1 + if(any(tmp != rep(tmp[1],length(tmp))) | tmp[1]==1) { + #data dimension cannot be splitted return dim(x) + return(list(dim(x),dimnames(x))) + } else { + nElemDims <- tmp[1] + tmp <- t(matrix(unlist(elemsplit),nElemDims)) + dimnames <- list() + dimnames[[1]] <- dimnames(x)[[1]] + dimnames[[2]] <- dimnames(x)[[2]] + dim <- dim(x)[1:2] + for(i in 1:nElemDims) { + dimnames[[i+2]] <- unique(tmp[,i]) + dim <- c(dim,length(dimnames[[i+2]])) + } + tmp <- getSets(x,sep=sep) + if(length(tmp)==length(dimnames) | is.null(tmp)) { + names(dimnames) <- tmp + } else { + if(length(tmp)==length(dimnames)+1 & length(grep(sep,names(dimnames(x))[1],fixed=TRUE))) { + names(dimnames) <- c(names(dimnames(x))[1],tmp[3:length(tmp)]) + } + } + return(list(dim,dimnames)) + } +} diff --git a/R/getCPR.R b/R/getCPR.R new file mode 100644 index 00000000..f53f62ce --- /dev/null +++ b/R/getCPR.R @@ -0,0 +1,40 @@ +#' Get cells per region +#' +#' Counts how many cells each region has and returns it as vector +#' +#' +#' @param x MAgPIE object or a resolution written as numeric (currently only +#' data for 0.5 degree resolution is available). +#' @return cells per region +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{getRegions}}, \code{\link{read.magpie}}, +#' \code{\link{write.magpie}} +#' @examples +#' +#' # a <- read.magpie("example.mz") +#' # getCPR(a) +#' getCPR(0.5) +#' +#' @export getCPR +getCPR <- function(x) { + if(!is.magpie(x)) { + if(x==0.5) { + region.code <- magclassdata$half_deg$region + cpr <- rep(0,length(levels(region.code))) + names(cpr) <- levels(region.code) + for(region in names(cpr)) { + cpr[region] <- length(grep(region,region.code)) + } + } else { + stop(paste("No cells-per-region information available for resolution",x)) + } + } else { + region_names <- getRegions(x) + cpr <- rep(0,length(region_names)) + names(cpr) <- region_names + for(region in region_names) { + cpr[region] <- length(grep(region,dimnames(x)[[1]])) + } + } + return(cpr) +} diff --git a/R/getCells.R b/R/getCells.R new file mode 100644 index 00000000..20454807 --- /dev/null +++ b/R/getCells.R @@ -0,0 +1,38 @@ +#' Get Cells +#' +#' Extracts cell names of a MAgPIE-object +#' +#' setCells is a shortcut to use a MAgPIE object with manipulated cell names. +#' setCells uses the variable names "object" and "nm" in order to be consistent +#' to the already existing function setNames. +#' +#' @aliases getCells getCells<- setCells +#' @param x,object MAgPIE object +#' @param value,nm cell names the data should be set to. +#' @return getCells returns cell names of the MAgPIE-object, whereas setCells +#' returns the MAgPIE object with the manipulated cell names. +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{getRegions}}, \code{\link{getNames}}, +#' \code{\link{setNames}}, \code{\link{getCPR}}, \code{\link{read.magpie}}, +#' \code{\link{write.magpie}}, \code{"\linkS4class{magpie}"} +#' @examples +#' +#' a <- as.magpie(1) +#' getCells(a) +#' setCells(a,"AFR.1") +#' +#' @export +getCells <- function(x) { + return(dimnames(x)[[1]]) +} + +#' @describeIn getCells set cell names +#' @export +"getCells<-" <- function(x,value) { + if(length(value)!=ncells(x)) stop("Wrong number of cell names supplied!") + if(ncells(x)==0) return(x) + if(is.null(value)) stop("Setting cell names to NULL is not allowed!") + if(length(value)==1) value <- list(value) + dimnames(x)[[1]] <- value + return(x) +} diff --git a/R/getComment.R b/R/getComment.R new file mode 100644 index 00000000..63c2c26f --- /dev/null +++ b/R/getComment.R @@ -0,0 +1,35 @@ +#' getComment +#' +#' Extracts the comment from a MAgPIE-object +#' +#' +#' @aliases getComment getComment<- setComment +#' @param x,object MAgPIE object +#' @param value,nm A vector containing the comment. +#' @return getComment returns the comment attached to a MAgPIE-object, NULL if +#' no comment is present. setComment returns the magpie object with the +#' modified comment. +#' @author Markus Bonsch +#' @seealso \code{\link{getRegions}}, \code{\link{getNames}}, +#' \code{\link{getYears}}, \code{\link{getCPR}}, \code{\link{read.magpie}}, +#' \code{\link{write.magpie}}, \code{"\linkS4class{magpie}"} +#' @examples +#' +#' a <- as.magpie(1) +#' #returns NULL +#' getComment(a) +#' #set the comment +#' getComment(a)<-c("bla","blubb") +#' getComment(a) +#' +#' @export +getComment <- function(x) { + return(attr(x,"comment")) +} + +#' @describeIn getComment set comment +#' @export +"getComment<-" <- function(x,value) { + attr(x,"comment")<-value + return(x) +} diff --git a/R/getDim.R b/R/getDim.R new file mode 100644 index 00000000..054215c0 --- /dev/null +++ b/R/getDim.R @@ -0,0 +1,24 @@ +#' getDim +#' +#' Function which tries to detect the dimension to which the given elems belong +#' +#' +#' @param elems A vector of characters containing the elements that should be +#' found in the MAgPIE object +#' @param x MAgPIE object in which elems should be searched for. +#' @return The name of the dimension in which elems were found. +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{mcalc}},\code{\link{dimCode}} +#' @examples +#' +#' data(population_magpie) +#' magclass:::getDim(c("AFR","CPA"),population_magpie) +#' +getDim <- function(elems, x){ + r <- sapply(elems,grepl,fulldim(x)[[2]],fixed=TRUE) + if(any(colSums(r)==0)) stop("An element was not found in the given data set (",paste(colnames(r)[colSums(r)==0],collapse=", "),")!") + if(any(colSums(r)>1)) stop("An element was found in more than one dimension in the given data set (",paste(colnames(r)[colSums(r)>1],collapse=", "),"). Please specify the dim to use!") + if(!any(rowSums(r)==length(elems))) stop("Used elements belong to different dimensions!") + dim <- which(rowSums(r)==length(elems)) + return(names(fulldim(x)[[2]])[dim]) +} diff --git a/R/getNames.R b/R/getNames.R new file mode 100644 index 00000000..7c6081fe --- /dev/null +++ b/R/getNames.R @@ -0,0 +1,132 @@ +.dim_fulldim <- function(x,dim) { + tmp <- fulldim(x)[[2]] + tmp[[2]] <- NULL #remove temporal dimension + tmp[[1]] <- NULL #remove spatial dimension + + if(!is.null(dim)) { + #check whether dim contains only 1 element + if(length(dim)>1) stop("Only a single dimension can be chosen with argument \"dim\"!") + #check whether chosen dimension exists + if(is.numeric(dim)) { + if(dim < 1 | dim > length(tmp)) stop("Chosen data dimension does not exist (dim = ",dim,")") + which_dim <- dim + } else { + if(sum(names(tmp) %in% dim)==0) stop("Chosen data dimension does not exist (dim = ",dim,")") + which_dim <- which(names(tmp) %in% dim) + } + maxdim <- length(tmp) + tmp <- tmp[[dim]] + if(!is.null(tmp)) { + attr(tmp,"which_dim") <- which_dim + attr(tmp,"maxdim") <- maxdim + } + } + return(tmp) +} + + + + + + + +#' Get dataset names +#' +#' Extracts dataset names of a MAgPIE-object +#' +#' setNames is a shortcut to use a MAgPIE object with manipulated data names. +#' The setNames method uses the variable names "object" and "nm" in order to be +#' consistent to the already existing function setNames. +#' +#' @aliases getNames getNames<- +#' @param x MAgPIE object +#' @param fulldim specifies, how the object is treated. In case of FALSE, it is +#' assumed that x is 3 dimensional and dimnames(x)[[3]] is returned. In case of +#' TRUE, the dimnames of the real third dimension namesare returned +#' @param dim Argument to choose a specific data dimension either by name of +#' the dimension or by number of the data dimension. +#' @param value a vector of names current names should be replaced with. If +#' only one data element exists you can also set the name to NULL. +#' @return getNames returns data names of the MAgPIE-object, whereas setNames +#' returns the MAgPIE object with the manipulated data names. +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{setNames-methods}}, \code{\link{getRegions}}, \code{\link{getYears}}, +#' \code{\link{getCPR}}, \code{\link{read.magpie}}, +#' \code{\link{write.magpie}},\code{\link{ndata}}, +#' \code{"\linkS4class{magpie}"} +#' @examples +#' +#' a <- as.magpie(1) +#' getNames(a) +#' setNames(a,"bla") +#' +#' x <- new.magpie("GLO",2000,c("a.o1","b.o1","a.o2")) +#' getNames(x,dim=2) +#' +#' getSets(x,fulldim=FALSE)[3] <- "bla.blub" +#' getNames(x,dim="bla") +#' +#' getSets(x)[4] <- "ble" +#' getNames(x,dim="ble") <- c("Hi","Bye") +#' x +#' +#' @export +getNames <- function(x,fulldim=FALSE,dim=NULL) { + if(!is.null(dim)) fulldim <- TRUE + if(fulldim==FALSE){ + return(dimnames(x)[[3]]) + } else { + tmp <- .dim_fulldim(x,dim) + if(!is.null(tmp)) { + attr(tmp,"which_dim") <- NULL + attr(tmp,"maxdim") <- NULL + } + return(tmp) + } +} + +#' @describeIn getNames set names +#' @export +"getNames<-" <- function(x,dim=NULL,value) { + if(is.null(dim)) { + if(is.null(value)) { + if(ndata(x)>1) stop("Setting data names to NULL is not possible as ndata is bigger than 1!") + s <- getSets(x,fulldim=FALSE)[3] + dimnames(x)[[3]] <- value + getSets(x,fulldim=FALSE)[3] <- s + } else { + if(ndata(x)!=length(value)) stop("Wrong number of data names supplied!") + if(ndata(x)==0) return(x) + tmp <- nchar(gsub("[^\\.]*","",value)) + if(any(tmp!=tmp[1])) stop("Inconsistent names! Number of dots per name has always to be the same as it is separating different data dimensions") + dimnames(x)[[3]] <- value + } + return(x) + } else { + old_names <- .dim_fulldim(x,dim) + if(is.null(old_names)) { + getNames(x,dim=NULL) <- value + return(x) + } + which_dim <- attr(old_names,"which_dim") + maxdim <- attr(old_names,"maxdim") + if(is.null(which_dim)) which_dim <- 1 + if(is.null(maxdim)) maxdim <- 1 + + if(is.null(value)) { + if(length(old_names) > 1) stop("Setting data names to NULL is not possible as data dimension has more than 1 element!") + return(collapseNames(x,collapsedim=which_dim)) + } else { + if(length(old_names)!=length(value)) stop("Wrong number of data names supplied!") + d <- dimnames(x)[[3]] + searchstring <- + start_pattern <- paste0("^(",paste(rep("[^\\.]*\\.",which_dim-1),collapse=""),")") + end_pattern <- paste0("(",paste(rep("\\.[^\\.]*",maxdim-which_dim),collapse=""),")$") + for(i in 1:length(value)) { + d <- sub(paste0(start_pattern,escapeRegex(old_names[i]),end_pattern),paste0("\\1",value[i],"\\2"),d) + } + dimnames(x)[[3]] <- d + return(x) + } + } +} diff --git a/R/getRegionList.R b/R/getRegionList.R new file mode 100644 index 00000000..e525f7ff --- /dev/null +++ b/R/getRegionList.R @@ -0,0 +1,33 @@ +#' Get a list of celluare region-belongings +#' +#' Extracts a vector containing the region of each cell of a MAgPIE-object +#' +#' +#' @aliases getRegionList getRegionList<- +#' @param x MAgPIE object +#' @param value A vector with ncell elements containing the regions of each +#' cell. +#' @return A vector with ncell elements containing the region of each cell. +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{getRegions}},\code{\link{getYears}}, +#' \code{\link{getNames}}, \code{\link{getCPR}}, \code{\link{read.magpie}}, +#' \code{\link{write.magpie}}, \code{"\linkS4class{magpie}"} +#' @examples +#' +#' # a <- read.magpie("example.mz") +#' # getRegionList(a) +#' +#' @export +getRegionList <- function(x) { + return(factor(sub("\\..*$","",dimnames(x)[[1]]))) +} + +#' @describeIn getRegionList set region names +#' @export +"getRegionList<-" <- function(x,value) { + reg <- getRegionList(x) + if(length(reg)!=length(value)) stop("Lengths of RegionLists do not agree!") + tmp <- sub("^.*\\.","",dimnames(x)[[1]]) + dimnames(x)[[1]] <- paste(as.vector(value),tmp,sep=".") + return(x) +} diff --git a/R/getRegions.R b/R/getRegions.R new file mode 100644 index 00000000..53258dbe --- /dev/null +++ b/R/getRegions.R @@ -0,0 +1,46 @@ +#' Get regions +#' +#' Extracts regions of a MAgPIE-object +#' +#' +#' @aliases getRegions getRegions<- +#' @param x MAgPIE object +#' @param value Vector containing the new region names of the MAgPIE objects. +#' If you also want to change the mapping of regions to cell please use +#' \code{\link{getRegionList}} instead. +#' @return Regions of the MAgPIE-object +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{getYears}}, \code{\link{getNames}}, +#' \code{\link{getCPR}}, \code{\link{read.magpie}}, \code{\link{write.magpie}}, +#' \code{"\linkS4class{magpie}"} +#' @examples +#' +#' # a <- read.magpie("example.mz") +#' # getRegions(a) +#' +#' @export +getRegions <- function(x) { + if(sum(substr(dimnames(x)[[1]],4,4)!=".")>0) { #not all regions have 3-character names (need to use slow method) + output <- unique(as.vector(as.matrix(cbind.data.frame(strsplit(dimnames(x)[[1]],'\\.'))[1,]))) + } else { #region names all have 3 characters -> fast method + output <- unique(substr(dimnames(x)[[1]],1,3)) + } + return(output) +} + +#' @describeIn getRegions overwrite region names +#' @export +"getRegions<-" <- function(x,value) { + reg <- getRegions(x) + if(!grepl(".",reg[1],fixed=TRUE)) { + getCells(x) <- value + return(x) + } + if(length(reg)!=length(value)) stop("Number of regions must agree with current number of regions!") + tmp <- paste("SAVEREPLACE",dimnames(x)[[1]]) + for(i in 1:nregions(x)) { + tmp <- sub(paste("SAVEREPLACE ",reg[i],"\\.",sep=""),paste(value[i],"\\.",sep=""),tmp) + } + dimnames(x)[[1]] <- tmp + return(x) +} diff --git a/R/getSets.R b/R/getSets.R new file mode 100644 index 00000000..f5ef5e65 --- /dev/null +++ b/R/getSets.R @@ -0,0 +1,75 @@ +#' Get sets +#' +#' Extracts sets of a MAgPIE-object if available +#' +#' +#' @aliases getSets getSets<- +#' @param x MAgPIE object +#' @param sep A character separating joined dimension names +#' @param fulldim bool: Consider dimension 3 as a possible aggregate of more +#' dimensions (TRUE) or stick to it as one dimension (FALSE) +#' @param value A vector with set names you want to replace the current set +#' names of the object with. +#' @return Sets of the MAgPIE-object. If no information about contained sets is +#' available NULL +#' @author Markus Bonsch +#' @seealso \code{\link{getRegions}}, +#' \code{\link{getNames}},\code{\link{getYears}}, \code{\link{getCPR}}, +#' \code{\link{read.magpie}}, \code{\link{write.magpie}}, +#' \code{"\linkS4class{magpie}"} +#' @examples +#' +#' a <- new.magpie("GLO.1",2000,c("a.o1","b.o1","a.o2")) +#' getSets(a) <- c("reg","cell","t","bla","blub") +#' getSets(a) +#' +#' getSets(a)[4] <- "BLA" +#' getSets(a,fulldim=FALSE) +#' getSets(a) +#' +#' @export +getSets <- function(x,fulldim=TRUE,sep=".") { + out <- names(dimnames(x))[drop=FALSE] + if(is.null(out)) return(NULL) + + if(fulldim==TRUE){ + tmp<- strsplit(out,split=sep,fixed=TRUE) + tmp<- lapply(tmp,FUN=function(x){ + if(length(x)==0) x<-NA + return(x) + } + ) + out <- as.vector(unlist(tmp)) + } + return(out) +} + + + +#' @describeIn getSets replace set names +#' @export +"getSets<-" <- function(x,fulldim=TRUE,sep=".",value) { + x <- clean_magpie(x,what="sets") + if(is.null(value)) return(x) + if(length(names(dimnames(x)))==0) fulldim <- FALSE + if(length(value)==3) fulldim <- FALSE + if(length(value)==0) fulldim <- FALSE + if(!fulldim) { + names(dimnames(x)) <- value + return(x) + } else { + s1 <- getSets(x,fulldim=FALSE) + s2 <- getSets(x,fulldim=TRUE) + search_s2 <- paste0("(^|\\.)",s2,"(\\.|$)") + where <- sapply(search_s2,grep,s1) + names(where) <- s2 + + if(length(value)!=length(s2)) stop("Input length does not agree with the number of sets in x!") + + for(i in 1:3) { + s1[i] <- paste(value[where==i],collapse=sep) + } + getSets(x,fulldim=FALSE,sep=sep) <- s1 + return(x) + } +} diff --git a/R/getYears.R b/R/getYears.R new file mode 100644 index 00000000..04dcf5e0 --- /dev/null +++ b/R/getYears.R @@ -0,0 +1,57 @@ +#' Get years +#' +#' Extracts years of a MAgPIE-object +#' +#' setYears is a shortcut to use a MAgPIE object with manipulated year names. +#' setYears uses the variable names "object" and "nm" in order to be consistent +#' to the already existing function setNames. +#' +#' @aliases getYears getYears<- setYears +#' @param x,object MAgPIE object +#' @param as.integer Switch to decide, if output should be the used year-name +#' (e.g. "y1995") or the year as integer value (e.g. 1995) +#' @param value,nm Years the data should be set to. Either supplied as a vector +#' of integers or a vector of characters in the predefined year format +#' ("y0000"). If only 1 year exist you can also set the name of the year to +#' NULL. +#' @return getYears returns years of the MAgPIE-object, whereas setYears +#' returns the MAgPIE object with the manipulated years. +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{getRegions}}, \code{\link{getNames}}, +#' \code{\link{setNames}}, \code{\link{getCPR}}, \code{\link{read.magpie}}, +#' \code{\link{write.magpie}}, \code{"\linkS4class{magpie}"} +#' @examples +#' +#' a <- as.magpie(1) +#' getYears(a) +#' setYears(a,1995) +#' +#' @export +getYears <- function(x,as.integer=FALSE) { + if(as.integer) { + return(as.integer(substring(dimnames(x)[[2]],2))) + } else { + return(dimnames(x)[[2]]) + } +} + +#' @describeIn getYears rename years +#' @export +"getYears<-" <- function(x,value) { + if(!is.null(value)) if(length(value)!=nyears(x)) stop("Wrong number of years supplied!") + if(nyears(x)==0) return(x) + if(is.null(value) & nyears(x)!=1) stop("Setting years to NULL is not possible as the number of years is not 1!") + if(is.null(value)) { + tmp <- list(NULL,NULL,NULL) + if(!is.null(dimnames(x)[[1]])) tmp[[1]] <- dimnames(x)[[1]] + if(!is.null(dimnames(x)[[3]])) tmp[[3]] <- dimnames(x)[[3]] + names(tmp) <- names(dimnames(x)) + dimnames(x) <- tmp + } else { + if(all(is.numeric(value))) value <- gsub(" ","0",format(value,width=4)) + if(all(nchar(value)==4)) value <- paste("y",value,sep="") + if(any(nchar(value)!=5) | any(substr(value,1,1)!="y")) stop("Wrong year format. Please supply either integer values or years in the format y0000!") + dimnames(x)[[2]] <- value + } + return(x) +} diff --git a/R/head.magpie.R b/R/head.magpie.R new file mode 100644 index 00000000..bcdf4b03 --- /dev/null +++ b/R/head.magpie.R @@ -0,0 +1,30 @@ +#' head/tail +#' +#' head and tail methods for MAgPIE objects to extract the head or tail of an +#' object +#' +#' +#' @aliases head.magpie tail.magpie +#' @param x MAgPIE object +#' @param n1,n2,n3 number of lines in first, second and third dimension that +#' should be returned. If the given number is higher than the length of the +#' dimension all entries in this dimension will be returned. +#' @param ... arguments to be passed to or from other methods. +#' @return head returns the first n1 x n2 x n3 entries, tail returns the last +#' n1 x n2 x n3 entries. +#' @author Jan Philipp Dietrich +#' @seealso \code{\link[utils]{head}}, \code{\link[utils]{tail}} +#' @examples +#' +#' data(population_magpie) +#' head(population_magpie) +#' tail(population_magpie,2,4,1) +#' +#' @importFrom utils head +#' @export +head.magpie <- function(x, n1=3L, n2=6L, n3=2L, ...) { + if(dim(x)[1]1)) { + mix_up<-1 + mix_down<-0 + } + if (before=="stable"){ + if(mix_up<0) { + mix_up<-0 + mix_down<-1 + } + } else if (isYear(before)) { + if(mix_up<0) { + mix_up <- (start_year_num - year_x_num )/(convergence_distance_back) + mix_down <- 1-mix_up + } + } + converged[,year_x,name_x]<-aim[,year_x,name_x]*mix_up + origin[,year_x,name_x]*mix_down + } + } + + return(converged) +} diff --git a/R/lowpass.R b/R/lowpass.R new file mode 100644 index 00000000..32ff4c93 --- /dev/null +++ b/R/lowpass.R @@ -0,0 +1,48 @@ +#' Lowpass Filter +#' +#' Filters high frequencies out of a time series. The filter has the structure +#' x'(n) = (x(n-1)+2*x(n)+x(n+1))/4 +#' +#' +#' @param x Vector of data points, that should be filtered or MAgPIE object +#' @param i number of iterations the filter should be applied to the data +#' @param fix Fixes the starting and/or ending data point. Default value is +#' \code{NULL} which doesn't fix any point. Available options are: +#' \code{"start"} for fixing the starting point, \code{"end"} for fixing the +#' ending point and \code{"both"} for fixing both ends of the data. +#' @return The filtered data vector or MAgPIE object +#' @author Jan Philipp Dietrich, Misko Stevanovic +#' @examples +#' +#' lowpass(c(1,2,11,3,4)) +#' # to fix the starting point +#' lowpass(c(0,9,1,5,14,20,6,11,0), i=2, fix="start") +#' +#' @export lowpass +lowpass <- function(x,i=1, fix=NULL) { + + if(!is.null(fix)) warning("Fixing start or end does might modify the total sum of values! Use fix=NULL to let the total sum unchanged!") + + if(i==0) return(x) + + if(is.magpie(x)) { + for(k in 1:dim(x)[1]) { + for(j in if(is.null(getNames(x))) 1 else getNames(x)) { + x[k,,j] <- lowpass(as.vector(x[k,,j]),i=i,fix=fix) + } + } + } else { + l <- length(x) + for(j in 1:i) { + y <- x + x[2:(l-1)] <- (y[1:(l-2)] + 2*y[2:(l-1)] + y[3:l])/4 + if(is.null(fix)){ + x[1] <- (3*y[1]+y[2])/4 + x[l] <- (3*y[l]+y[l-1])/4 + } + else if (fix=="start") x[l] <- (3*y[l]+y[l-1])/4 + else if (fix=="end") x[1] <- (3*y[1]+y[2])/4 + else if (fix!="both") stop(paste("Option \"",fix,"\" is not available for the \"fix\" argunemt!",sep="")) } + } + return(x) +} diff --git a/R/magclass-package.R b/R/magclass-package.R new file mode 100644 index 00000000..ee95c16d --- /dev/null +++ b/R/magclass-package.R @@ -0,0 +1,28 @@ + + +#' MAgPIE Class Functions +#' +#' Package containing the MAgPIE-Object-Class together with relevant functions +#' and methods. +#' +#' \tabular{ll}{ Package: \tab magclass\cr Type: \tab Package\cr Version: \tab +#' 3.93\cr Date: \tab 2016-09-08\cr License: \tab LGPL-3\cr LazyLoad: \tab +#' yes\cr } +#' +#' @name magclass-package +#' @aliases magclass-package magclass +#' @docType package +#' @author Jan Philipp Dietrich, Benjamin Bodirsky, Misko Stevanovic, Lavinia +#' Baumstark, Christoph Bertram, Markus Bonsch, Anastasis Giannousakis, Florian +#' Humpenoeder, David Klein, Ina Neher, Michaja Pehl, Anselm Schultes +#' +#' Maintainer: Jan Philipp Dietrich +NULL + + + + + + + + diff --git a/R/magpie-class.R b/R/magpie-class.R new file mode 100644 index 00000000..277b6604 --- /dev/null +++ b/R/magpie-class.R @@ -0,0 +1,274 @@ + +#' Class "magpie" ~~~ +#' +#' The MAgPIE class is a data format for cellular MAgPIE data with a close +#' relationship to the array data format. \code{is.magpie} tests if \code{x} is +#' an MAgPIE-object, \code{as.magpie} transforms \code{x} to an MAgPIE-object +#' (if possible). +#' +#' +#' @name magpie-class +#' @aliases magpie-class as.magpie as.magpie-methods as.magpie,magpie-method +#' as.magpie,array-method as.magpie,lpj-method as.magpie,data.frame-method +#' as.magpie,numeric-method as.magpie,NULL-method as.magpie,quitte-method +#' as.magpie,tbl_df-method +#' is.magpie [,magpie-method [,magpie,ANY,ANY-method [<-,magpie,ANY,ANY-method +#' [<-,magpie-method Ops,magpie,magpie-method +#' @docType class +#' @param x An object that should be either tested or transformed as/to an +#' MAgPIE-object. +#' @param ... additional arguments supplied for the conversion to a MAgPIE +#' object. Allowed arguments for arrays and dataframes are \code{spatial} and +#' \code{temporal} both expecting a vector of dimension or column numbers which +#' contain the spatial or temporal information. By default both arguments are +#' set to NULL which means that the \code{as.magpie} will try to detect +#' automatically the temporal and spatial dimensions. The arguments will just +#' overwrite the automatic detection. If you want to specify that the data does +#' not contain a spatial or temporal dimension you can set the corresponding +#' argument to 0. In addition \code{as.magpie} for data.frames is also +#' expecting an argument called \code{datacol} which expects a number stating +#' which is the first column containing data. This argument should be used if +#' the dimensions are not detected corretly, e.g. if the last dimension column +#' contains years which are then detected as values and therefore interpreted +#' as first data column. In addition an argument \code{tidy=TRUE} can be used +#' to indicate that the data.frame structure is following the rules of tidy +#' data (last column is the data column all other columns contain dimension +#' information). This information will help the conversion. +#' @section Objects from the Class: Objects can be created by calls of the form +#' \code{new("magpie", data, dim, dimnames, ...)}. MAgPIE objects have three +#' dimensions (cells,years,datatype) and the dimensionnames of the first +#' dimension have the structure "REGION.cellnumber". MAgPIE-objects behave the +#' same like array-objects with 2 exceptions: \cr 1.Dimensions of the object +#' will not collapse (e.g. \code{x[1,1,1]} will remain 3D instead of becoming +#' 1D)\cr 2.It is possible to extract full regions just by typing +#' \code{x["REGIONNAME",,]}. \cr\cr +#' +#' Please mind following standards: \cr Header must not contain any purely +#' numeric entries, but combinations of characters and numbers are allowed +#' (e.g. "bla","12" is forbidden, wheras "bla","b12" is allowed)\cr Years +#' always have the structure "y" + 4-digit number, e.g. "y1995"\cr Regions +#' always have the structure 3 capital letters, e.g. "AFR" or "GLO"\cr\cr This +#' standards are necessary to allow the scripts to detect headers, years and +#' regions properly and to have a distinction to other data. +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{read.magpie}}, \code{\link{write.magpie}}, +#' \code{\link{getRegions}}, \code{\link{getYears}}, \code{\link{getNames}}, +#' \code{\link{getCPR}}, \code{\link{ncells}}, \code{\link{nyears}}, +#' \code{\link{ndata}} +#' @keywords classes +#' @examples +#' +#' showClass("magpie") +#' +#' data(population_magpie) +#' +#' # returning PAO and PAS for 2025 +#' population_magpie["PA",2025,,pmatch="left"] +#' +#' # returning CPA for 2025 +#' population_magpie["PA",2025,,pmatch="right"] +#' +#' # returning CPA PAO and PAS for 2025 +#' population_magpie["PA",2025,,pmatch=TRUE] +#' +#' # returning PAS and 2025 +#' population_magpie["PAS",2025,] +#' +#' # returning everything but values for PAS or values for 2025 +#' population_magpie["PAS",2025,,invert=TRUE] +#' +#' +#' +#' @exportClass magpie +#' @importFrom methods setClass + + +setClass("magpie",contains="array",prototype=array(0,c(0,0,0))) + +.dimextract <- function(x,i,dim,pmatch=FALSE,invert=FALSE) { + if(length(i)==0) return(NULL) + .countdots <- function(i) { + return(nchar(gsub("[^\\.]","",i))) + } + if(.countdots(i[1])==.countdots(dimnames(x)[[dim]][1]) & pmatch==FALSE){ + #i vector seems to specify the full dimname + if(!anyDuplicated(dimnames(x)[[dim]])) { + if(invert) { + return(which(!(dimnames(x)[[dim]] %in% i))) + } else { + match <- match(i,dimnames(x)[[dim]]) + if(any(is.na(match))) { + stop("subscript out of bounds (\"",paste0(i[is.na(match)],collapse="\", \""),"\")") + } + return(match) + } + } else { + warning("Your dimnames in dim=",dim," contain duplicates! This might lead to erronous results and bad code performance. Please try to avoid duplicates in dimnames under all circumstances!") + } + } + + pmatch1 <- ifelse(pmatch==TRUE | pmatch=="right",".*","") + pmatch2 <- ifelse(pmatch==TRUE | pmatch=="left",".*","") + tmp <- lapply(paste("(^|\\.)",pmatch1,escapeRegex(i),pmatch2,"(\\.|$)",sep=""),grep,dimnames(x)[[dim]]) + if(any(vapply(tmp,length,length(tmp))==0)) stop("Data element(s) \"",paste(i[vapply(tmp,length,length(tmp))==0],collapse="\", \""),"\" not existent in MAgPIE object!") + tmp <- unlist(tmp) + if(invert) { + tmp <- setdiff(1:dim(x)[dim],tmp) + } + return(tmp) +} + +.mselect_df <- function(x,df) { + if(is.null(names(dimnames(x)))) stop("Dimnames must have names in order to use mselect!") + dims <- dimCode(names(df),x) + if(all(dims==0)) stop('None of the dimensions in the mapping could be found in the magpie object!') + if(any(dims==0)) { + dfmissing <- df[dims==0] + df <- df[dims!=0] + fdims <- dims + dims <- dims[dims>0] + } else { + dfmissing <- NULL + } + if(anyDuplicated(dims)) stop('Dimension(s) "',paste(names(dims)[duplicated(dims)],collapse='", "'),'" appear(s) more than once in the given mapping!') + + if(any(dims<3)) { + stop("Currently only mappings within the data dimensions are supported!") + } else { + sdims <- as.integer(round((dims-3)*10)) + maxdim <- nchar(gsub("[^\\.]","",names(dimnames(x))[3]))+1 + if(any(sdims>maxdim)) stop("Inconsistent dimension information. Data dimension specified which does not seem to exist!") + if(nrow(df)>0) df <- matrix(sapply(df,escapeRegex),dim(df),dimnames=dimnames(df)) + dmissing <- which(!(1:maxdim%in%sdims)) + sdims <- c(sdims,dmissing) + for(d in dmissing) df <- cbind(df,"[^\\.]*") + elems <- NULL + search <- paste0("^",apply(df[,sdims, drop=FALSE],1,paste,collapse="\\."),"$") + found <- lapply(search,grep,getNames(x)) + x <- x[,,unlist(found)] + length <- unlist(lapply(found,length)) + if(!is.null(dfmissing)) { + if(length(dfmissing)>1) { + name_extensions <- do.call("paste",c(dfmissing,sep=".")) + } else { + name_extensions <- dfmissing[[1]] + } + getNames(x) <- paste(getNames(x),name_extensions[rep(1:length(name_extensions),length)],sep=".") + getSets(x,fulldim=FALSE)[3] <- paste(getSets(x,fulldim=FALSE)[3],paste(names(dfmissing),collapse="."),sep=".") + } + if(any(length==0) & nrow(df)>0) { + row_extensions <- gsub('\\.',".",sub('[^\\.]*','NA',sub("^\\^","",sub("\\$$","",search[length==0])),fixed=TRUE),fixed=TRUE) + if(!is.null(dfmissing)) { + row_extensions <- paste(row_extensions,name_extensions[length==0],sep=".") + } + tmp <- new.magpie(getCells(x),getYears(x),row_extensions,0,sets=getSets(x)) + if(ndata(x)==0) { + x <- tmp + } else { + x <- mbind(x,tmp) + } + if(getOption("magclass.verbosity")>1) cat("NOTE (.mselect_df): The following elements were added to x as they appeared in the mapping but not in x: ",paste0(row_extensions,collapse=", ")," (values set to 0)\n") + } + return(return(x)) + } +} + +#' @exportMethod [ +setMethod("[", + signature(x = "magpie"), + function (x, i, j, k, drop=FALSE,pmatch=FALSE,invert=FALSE) + { + if(is.null(dim(x))) return(x@.Data[i]) + if(!missing(i)) { + if(is.data.frame(i)) { + return(.mselect_df(x,i)) + } + if(is.factor(i)) i <- as.character(i) + if(is.character(i)) i <- .dimextract(x,i,1,pmatch=pmatch,invert=invert) + } + if(!missing(j)) { + if(is.factor(j)) j <- as.character(j) + if(is.numeric(j) & any(j>dim(x)[2])) { + j <- paste("y",j,sep="") + if(invert) j <- getYears(x)[!(getYears(x) %in% j)] + } else if(is.null(j)) { + j <- 1:dim(x)[2] + } else if(invert) { + j <- getYears(x)[!(getYears(x) %in% j)] + } + } + if(!missing(k)) { + if(is.factor(k)) k <- as.character(k) + if(is.character(k)) k <- .dimextract(x,k,3,pmatch=pmatch,invert=invert) + } + if(ifelse(missing(i),FALSE,is.array(i) | any(abs(i)>dim(x)[1]))) { + #indices are supplied as array, return data as numeric + return(x@.Data[i]) + } else if(missing(j) & ifelse(missing(k),TRUE,is.logical(k)) & ifelse(missing(i),FALSE,all(abs(i)<=dim(x)[1]))) { + if(length(x@.Data[i,,,drop=FALSE])==0) { + return(x@.Data[i]) + } else { + x@.Data <- x@.Data[i,,,drop=FALSE] + if(drop) x <- collapseNames(x) + return(x) + } + } else { + if(!missing(k)) { + if(is.logical(k)) { + # weird case in which k should be actually missing but gets the value of the next argument in the argument list (drop) + x@.Data <- x@.Data[i,j,,drop=FALSE] + } else { + x@.Data <- x@.Data[i,j,k,drop=FALSE] + } + } else { + x@.Data <- x@.Data[i,j,,drop=FALSE] + } + if(drop) x <- collapseNames(x) + return(x) + } + } +) + +#' @exportMethod [<- +setMethod("[<-", + signature(x = "magpie"), + function (x, i, j, k, value, pmatch=FALSE) + { + if(is.null(dim(x))) { + tmp <- x@.Data + tmp[i] <- k + return(tmp) + } + if(!missing(i)) { + if(is.factor(i)) i <- as.character(i) + if(is.character(i)) i <- .dimextract(x,i,1,pmatch=pmatch) + } + if(!missing(j)) { + if(is.factor(j)) j <- as.character(j) + if(is.numeric(j) & any(j>dim(x)[2])) j <- paste("y",j,sep="") + else if(is.null(j)) j <- 1:dim(x)[2] + } + if(!missing(k)) { + if(is.factor(k)) k <- as.character(k) + if(is.character(k)) k <- .dimextract(x,k,3,pmatch=pmatch) + } + if(missing(value)) { + x@.Data[i] <- k + return(x) + } else { + if(is.magpie(value)){ + if(missing(i)) ii <- 1:dim(x)[1] else ii <- i + if(missing(j)) jj <- 1:dim(x)[2] else jj <- j + if(missing(k)) kk <- 1:dim(x)[3] else kk <- k + value <- magpie_expand(value,x[ii,jj,kk]) + } else if(length(value)!=length(x@.Data[i,j,k]) & length(value)!=1) { + #dangerous writing of value as order might be wrong! + stop("Replacement does not work! Different replacement length!") + } else if(length(value)!=1) { + if(getOption("magclass.verbosity")>1) cat("NOTE ([<-): Dangerous replacement! As replacement value is not an MAgPIE object name checking is deactivated!\n") + } + x@.Data[i,j,k] <- value + return(x) + } + } +) \ No newline at end of file diff --git a/R/magpieComp.R b/R/magpieComp.R new file mode 100644 index 00000000..a806f947 --- /dev/null +++ b/R/magpieComp.R @@ -0,0 +1,44 @@ +#' magpieComp +#' +#' Function that compares two magpie objects. +#' +#' Function that compares two magpie objects. +#' +#' @param bench A \code{MAgPIE} object. +#' @param comp A \code{MAgPIE} object. +#' @param reg The region(s) you want to focus on +#' @return a list containing a1) the names found only in bench, a2) the names +#' found only in comp, b) a sorted data frame with the largest relative +#' difference between bench and comp in percentage values, and c) a magclass +#' object with the same values +#' @author Anastasis Giannousakis +#' @export magpieComp +magpieComp<-function(bench,comp,reg=NA) { + + if(!is.na(reg)){ + bench<-bench[reg,,] + comp<-comp[reg,,] + } + # keep only common variable names + comp1<-collapseNames(comp[,,intersect(getNames(comp),getNames(bench))]) + bench1<-collapseNames(bench[,,intersect(getNames(comp),getNames(bench))]) + + nas<-which(is.na(comp1)&is.na(bench1)) + bench1[nas]<-0 + comp1[nas]<-0 + rem0<-which(bench1==0 & comp1==0) + bench1[rem0]<-1 + comp1[rem0]<-1 + data<-200*abs(bench1-comp1)/(abs(bench1)+abs(comp1)) + + out<-list() + out$varnames<-list() + out$varnames$bench_only<-setdiff(getNames(bench),getNames(comp)) + out$varnames$comp_only<-setdiff(getNames(comp),getNames(bench)) + d<-as.data.frame(data,rev=2) + names(d)<-sub(".value","value",names(d)) + out$diff_sorted<-d[order(d$value,decreasing = TRUE,na.last = T),] + out$data<-data + +return(out) +} diff --git a/R/magpieResolution.R b/R/magpieResolution.R new file mode 100644 index 00000000..68cc5d19 --- /dev/null +++ b/R/magpieResolution.R @@ -0,0 +1,30 @@ +#' magpieResolution +#' +#' Returns the Resolution of a MAgPIE object +#' +#' +#' @param object An MAgPIE object +#' @return "glo", "reg" or "cell" +#' @author Benjamin Bodirsky +#' @seealso \code{\link{population_magpie}} +#' @examples +#' +#' data(population_magpie) +#' magpieResolution(population_magpie) +#' +#' @export magpieResolution +magpieResolution<- function(object) { + if(!is.magpie(object)){stop("Object is no magpie object") + } else { + n_magpie_regions <-length(getRegions(object)) + n_magpie_cells <-dim(object)[[1]] + if (n_magpie_cells==1) { + resolution<-"glo" + } else if(n_magpie_cells==n_magpie_regions) { + resolution<-"reg" + } else { + resolution<-"cell" + } + } + return(resolution) +} diff --git a/R/magpie_expand.R b/R/magpie_expand.R new file mode 100644 index 00000000..4e110ad4 --- /dev/null +++ b/R/magpie_expand.R @@ -0,0 +1,195 @@ +#' magpie_expand +#' +#' Expands a MAgPIE object based on a reference +#' +#' Expansion means here that the dimensions of x are expanded acordingly to +#' ref. Please note that this is really only about expansion. In the case that +#' one dimension of ref is smaller than of x nothing happens with this +#' dimension. At the moment magpie_expand is only internally available in the +#' magclass library +#' +#' You can influence the verbosity of this function by setting the option +#' "magclass.verbosity". By default verbosity is set to 2 which means that +#' warnings as well as notes are returned. Setting verbosity to 1 means that +#' only warnings are returned but no notes. This is done by +#' options(verbosity.level=1) +#' +#' @param x MAgPIE object that should be expanded +#' @param ref MAgPIE object that serves as a reference +#' @return An expanded version of x. +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{as.magpie}}, \code{\link[base]{options}} +#' @examples +#' +#' a <- new.magpie(c("AFR","CPA"),"y1995",c("m","n")) +#' b <- new.magpie("GLO","y1995",c("bla","blub")) +#' magpie_expand(b,a) +#' options(magclass.verbosity=1) +#' magpie_expand(b,a) +#' +#' @export magpie_expand +magpie_expand <- function(x,ref) { + #x: MAgPIE object which should be expanded + #ref: Reference object defining the structure to which x should be expanded + #1.spatial dimension + if(ncells(ref)>ncells(x)) { + #regional or global data? + if(nregions(x)==ncells(x)) { + if(nregions(x)==1 & getRegions(x)[1]=="GLO") { + #global data + x <- x[rep(1,ncells(ref)),,] + getCells(x) <- getCells(ref) + } else { + #regional data + if(nregions(x)!=nregions(ref)) stop("Cannot expand MAgPIE object! Incompatible cells (different number of regions).") + if(any(sort(getRegions(x))!=sort(getRegions(ref)))) stop("Cannot expand MAgPIE object! Incompatible cells (different regions).") + #If this place is reached it means that x is regional data with the same regions as ref + cells<-gsub("\\.[0-9]+$","",getCells(ref)) + x<-x[cells,,] + getCells(x)<-getCells(ref) + } + } else { + stop("Cannot expand MAgPIE object! Incompatible cells (different length and neither purely regional or global data).") + } + } else if(ncells(ref)==ncells(x)) { + if(any(getCells(ref)!=getCells(x))) { + if(ncells(x)!=1 & any(sort(getCells(ref))!=sort(getCells(x)))){ + if(all(sort(getRegions(ref))==sort(getRegions(x))) & ncells(x)==nregions(x)) { + #same regions, but different pseudo cells + x <- x[getRegions(ref),,] + getCells(x) <- getCells(ref) + } else { + stop("Cannot expand MAgPIE object! Incompatible cells (same length, different cell names).") + } + } else if(ncells(x)==1){ + if(getRegions(x)=="GLO") { + getCells(x) <- getCells(ref) + } else { + if(getRegions(ref)!="GLO" & getRegions(ref)!=getRegions(x)) stop("Region names do not agree! x:",getRegions(x)," ref:",getRegions(ref)) + } + } else { + #Different order...reorder cells + x <- x[getCells(ref),,] + } + } + } + + #2.temporal dimension + if(nyears(ref)>nyears(x)) { + if(nyears(x)==1) { + if(!is.null(getYears(x))) stop("Years do not agree! x:",getYears(x)," ref:",getYears(ref)) + x <- x[,rep(1,nyears(ref)),] + getYears(x) <- getYears(ref) + getSets(x,fulldim=FALSE)[2] <- ifelse(is.null(getSets(ref,fulldim=FALSE)[2]),"year",getSets(ref,fulldim=FALSE)[2]) + } else { + stop("Cannot expand MAgPIE object! No clear mapping in temporal dimension") + } + } else if(nyears(ref)==nyears(x)) { + if(is.null(getYears(x))) { + getYears(x) <- getYears(ref) + } else if(any(getYears(ref)!=getYears(x))) { + if(any(sort(getYears(ref))!=sort(getYears(x)))){ + if(nyears(x)==1) { + stop("Years do not agree! x:",paste(getYears(x),collapse=" ")," ref:",paste(getYears(ref),collapse=" ")) + } else { + stop("Years do not agree! No mapping possible! x:",paste(getYears(x),collapse=" ")," ref:",paste(getYears(ref),collapse=" ")) + } + } else { + #Different order...reorder years + x <- x[,getYears(ref),] + } + } + } + + #3.data dimension + if(length(getNames(x))==0) { + if(ndata(x)>1) stop("Inconsistent MAgPIE file: more than 1 element in data dimension but no names given!") + x <- x[,,rep(1,ndata(ref))] + getNames(x) <- getNames(ref) + } else if(length(getNames(ref))==0) { + if(ndata(ref)>1) stop("Inconsistent MAgPIE reference file: more than 1 element in data dimension but no names given!") + } else if(any(suppressWarnings(getNames(x)!=getNames(ref)))){ + if(all(suppressWarnings(sort(getNames(x))==sort(getNames(ref))))) { + x <- x[,,getNames(ref)] + } else { + #both, x and ref, have data names + #data names do not agree + .fulldatadim <- function(x,sort=TRUE) { + x <- fulldim(x)[[2]] + x[[2]] <- NULL #remove temporal dim + x[[1]] <- NULL #remove spatial dim + if(sort) x <- lapply(x,sort) + return(x) + } + rfdim <- .fulldatadim(ref,TRUE) + xfdim <- .fulldatadim(x,TRUE) + + toadd <- which(!(rfdim %in% xfdim)) #which dimensions have to be added? + if(length(toadd)>0) { + tmp <- NULL + for(i in toadd) { + tmp <- paste(rep(tmp,each=length(rfdim[[i]])),rfdim[[i]],sep=".") + } + newnames <- paste(rep(getNames(x),each=length(tmp)),tmp,sep="") + x <- x[,,rep(1:ndata(x),each=length(tmp))] + getNames(x) <- newnames + getSets(x,fulldim=FALSE)[3] <- paste(getSets(x,fulldim=FALSE)[3],paste(names(rfdim)[toadd],collapse="."),sep=".") + if(getOption("magclass.verbosity")>1) cat("NOTE (magpie_expand): data dimensionality of MAgPIE object expanded (added dimensions:",paste(rfdim[toadd]),")\n") + } + + #is the order of the dimensions in the data dimension identical? reorder if necessary (only performed if the number of dimensions is the same) + xfdim <- .fulldatadim(x,TRUE) + .tmp <- function(rfdim,xfdim) return(which(xfdim%in% list(rfdim))) + order <- lapply(rfdim,.tmp,xfdim) + lengths_order <- sapply(order,length) + if(any(lengths_order==0)) stop("Some ref dimensions cannot be found in x after expansion. magpie_expand-function seems to be bugged!") + if(any(lengths_order>1)) { + warning("Some ref dimensions are found more than once in x after expansion. Mapping might go wrong!") + probs <- which(lengths_order>1) + taken <- NULL + for(i in probs) { + order[[i]] <- setdiff(order[[i]],taken) + taken <- c(taken,order[[i]][-1]) + order[[i]] <- order[[i]][1] + if(length(order[[i]])==0) stop("Something went wrong in mapping correction in magpie_expand. Function seems to be bugged!") + } + } + order <- unlist(order) + #add missing dimensions at the end + order <- c(order,setdiff(1:length(xfdim),order)) + + if(any(order!=1:length(order))) { + #different order + search <- paste("^",paste(rep("([^\\.]*)",length(order)),collapse="\\."),"$",sep="") + replace <- paste(paste("\\",order,sep=""),collapse="\\.") + getNames(x) <- sub(search,replace,getNames(x)) + getSets(x,fulldim=FALSE)[3] <- sub(search,replace,getSets(x,fulldim=FALSE)[3]) + } + + + #try to order x based on ref (only possible if objects have the same size) + if(ndata(x)==ndata(ref)) { + if(length(xfdim)==length(rfdim)) { + #simple case: same number of dimensions + #in the case that now all data names of x and ref agree reorder the data best on order of ref + if(all(sort(getNames(x))==sort(getNames(ref)))) { + x@.Data <- x@.Data[,,getNames(ref),drop=FALSE] + } else { + stop("Data names do not agree between ref and expanded x, magpie_expand seems to be bugged! (same #dimensions)") + } + } else { + #more complicated case in which x has more dimensions than ref + search <- paste0(paste0(rep("\\.[^\\.]*",length(xfdim)-length(rfdim)),collapse=""),"$") + reduced_xnames <- sub(search,"",getNames(x)) + #in the case that now all data names of x and ref agree reorder the data best on order of ref + if(all(sort(reduced_xnames)==sort(getNames(ref)))) { + x <- x[,,getNames(ref)] + } else { + stop("Data names do not agree between ref and expanded x, magpie_expand seems to be bugged! (different #dimensions)") + } + } + } + } + } + return(x) +} diff --git a/R/magpiesort.R b/R/magpiesort.R new file mode 100644 index 00000000..379968a1 --- /dev/null +++ b/R/magpiesort.R @@ -0,0 +1,32 @@ +#' MAgPIE-Sort +#' +#' Brings the spatial and temporal structure of MAgPIE objects in the right +#' order. This function is especially useful when you create new MAgPIE objects +#' as the order typically should be correct for MAgPIE objects. +#' +#' +#' @param x MAgPIE object which might not be in the right order. +#' @return The eventually corrected MAgPIE object (right order in spatial in +#' temporal dimension) +#' @author Jan Philipp Dietrich +#' @seealso \code{"\linkS4class{magpie}"} +#' @examples +#' +#' data(population_magpie) +#' a <- magpiesort(population_magpie) +#' +#' @export magpiesort +magpiesort <- function(x) { + if(!is.magpie(x)) stop("Input is not a MAgPIE object!") + if(any(dim(x)==0)) return(x) + if(dim(x)[1]==1) { + spatial_order <- 1 + } else if(length(grep("\\.[0-9]*$",dimnames(x)[[1]]))==dim(x)[1]) { + spatial_order <- order(as.numeric(gsub("^[A-Z]+\\.","",dimnames(x)[[1]]))) + } else { + spatial_order <- order(dimnames(x)[[1]]) + } + if(!is.null(dimnames(x)[[2]])) temporal_order <- order(dimnames(x)[[2]]) + else temporal_order <- 1:dim(x)[2] + return(x[spatial_order,temporal_order,]) +} diff --git a/R/magpply.R b/R/magpply.R new file mode 100644 index 00000000..a868709e --- /dev/null +++ b/R/magpply.R @@ -0,0 +1,38 @@ +#' @title magpply +#' @description apply command for magpieobjects. Very efficient for replacing loops. +#' +#' @param X magpie object +#' @param FUN function that shall be applied X +#' @param MARGIN dimension over which FUN shall be applied (like a loop over that dimension). This dimension will be preserved in the output object +#' @param ... further parameters passed on to FUN +#' @param integrate if TRUE, the output will be filled into an magpie object of the same dimensionality as X +#' +#' @return magpie object +#' @author Benjamin Leon Bodirsky +#' @examples +#' +#' \dontrun{ +#' data("population_magpie") +#' magpply(population_magpie,FUN=sum,MARGIN=2) +#' fourdim<-population_magpie*setNames(population_magpie,c("jkk","lk")) +#' magpply(fourdim,FUN=sum,MARGIN=c(1,3.1)) +#' magpply(fourdim,FUN=function(x){return(x+1)},MARGIN=c(1,3.1),integrate=TRUE) +#' } +#' + +magpply<-function(X,FUN,MARGIN,...,integrate=FALSE){ + if(any(MARGIN>3)){ + for(counter in which(MARGIN>3)){ + MARGIN[counter]=old_dim_convention(MARGIN[counter]) + } + X<-unwrap(X) + } + out<-apply(X = X,FUN = FUN,MARGIN=MARGIN) + if(integrate==TRUE){ + X[,,]<-out + out<-X + } else { + out<-as.magpie(out) + } + return(out) +} \ No newline at end of file diff --git a/R/make.ISOyear.R b/R/make.ISOyear.R new file mode 100644 index 00000000..1b1b19a0 --- /dev/null +++ b/R/make.ISOyear.R @@ -0,0 +1,37 @@ +# Create lookup-table for efficient conversion of years to POSIX +# +# Create lookup-table for efficient conversion of years to POSIX +# +# +# @param start start year +# @param end end year +# @param by by +# @return POSIX format as used in quitte +# @author Michaja Pehl, Anselm Schultes +# @examples +# +# # ISOyear <- make.ISOyear() +# # ISOyear(2016) +# +# Made an internal function since it is implemented in the quitte package and +# used only in context with quitte objects. +make.ISOyear <- function(start = 1900, end = 2200, by = 5) { + ISOyear <- data.frame(key = seq(start, end, by), + value = seq.POSIXt(ISOdate(start, 7, 2), + ISOdate(end, 7, 2), + paste(by, "years"))) + f <- function(keys) { + + rows <- match(keys, ISOyear$key) + if (any(is.na(rows))) { + new.keys <- keys[is.na(rows)] + ISOyear <<- rbind(ISOyear, data.frame(key = new.keys, + value = ISOdate(new.keys, 7, 2))) + rows <- match(keys, ISOyear$key) + } + + return(ISOyear[rows,"value"]) + } + + return(f) +} diff --git a/R/mbind.R b/R/mbind.R new file mode 100644 index 00000000..5cda0bfd --- /dev/null +++ b/R/mbind.R @@ -0,0 +1,88 @@ +#' mbind +#' +#' Merges MAgPIE-objects with identical structure in two dimensions. If data +#' differs in the temporal or spatial dimension each year or region/cell must +#' appear only once! +#' +#' mbind2 is a reimplementation from mbind which had the aim to increase its +#' overall memory efficiency. However, it is not clear which function is better +#' and there are also some changes in behaviour of both functions. Therefore, +#' the new version was just added as mbind2 instead of using it as a full +#' replacement for mbind. +#' +#' @aliases mbind mbind2 +#' @param ... MAgPIE objects or a list of MAgPIE objects that should be merged. +#' @return The merged MAgPIE object +#' @author Jan Philipp Dietrich, Misko Stevanovic +#' @seealso \code{"\linkS4class{magpie}"} +#' @examples +#' +#' m <- new.magpie(c("AFR","CPA","EUR"), c(1995,2005),"Data1",fill=c(1,2,3,4,5,6)) +#' ms <- dimSums(m, dims=1) +#' mbind(m, ms) +#' my <- new.magpie(getRegions(m), 2010, getNames(m), fill=c(6,6,4)) +#' mbind(m, my) +#' md <- new.magpie(getRegions(m), getYears(m), "Data2", fill=c(7,6,5,7,8,9)) +#' mbind(m, md) +#' +#' data(population_magpie) +#' a <- mbind(population_magpie,population_magpie) +#' dim(population_magpie) +#' dim(a) +#' +#' +#' @export mbind +#' @importFrom methods new +mbind <- function(...) { + inputs <- list(...) + if(length(inputs)==1 & is.list(inputs[[1]])) inputs <- inputs[[1]] + #Remove NULL elements from list + for(i in length(inputs):1) if(is.null(inputs[[i]])) inputs[[i]] <- NULL + + + regio <- NULL + cells <- NULL + elems <- NULL + years <- NULL + diffspat <- FALSE + difftemp <- FALSE + diffdata <- FALSE + for(i in 1:length(inputs)) { + if(!is.magpie(inputs[[i]])) stop("Inputs must all be MAgPIE-objects") + if(is.null(dimnames(inputs[[i]])[[3]])) dimnames(inputs[[i]])[[3]] <- paste("dummydimname",1:ndata(inputs[[i]]),sep="") + #Check which dimensions differ + if(suppressWarnings(any(sort(dimnames(inputs[[1]])[[1]])!=sort(dimnames(inputs[[i]])[[1]])))) diffspat <- TRUE + if(suppressWarnings(any(sort(dimnames(inputs[[1]])[[2]])!=sort(dimnames(inputs[[i]])[[2]])))) difftemp <- TRUE + if(suppressWarnings(any(sort(dimnames(inputs[[1]])[[3]])!=sort(dimnames(inputs[[i]])[[3]])))) diffdata <- TRUE + years <- c(years, getYears(inputs[[i]])) + elems <- c(elems, getNames(inputs[[i]])) + cells <- c(cells, getCells(inputs[[i]])) + if(!diffspat & ncells(inputs[[1]])>1) inputs[[i]] <- inputs[[i]][getCells(inputs[[1]]),,] + if(!difftemp & nyears(inputs[[1]])>1) inputs[[i]] <- inputs[[i]][,getYears(inputs[[1]]),] + if(!diffdata & ndata(inputs[[1]])>1) inputs[[i]] <- inputs[[i]][,,getNames(inputs[[1]])] + } + + if(!(length(grep(".",cells,fixed=TRUE)) %in% c(0,length(cells)))) stop("Mixture of regional (no cell numbers) and cellular (with cell numbers) data objects! Cannot handle this case!") + + if(diffspat & difftemp) stop("Cannot handle objects! Spatial as well as temporal dimensions differ!") + if(difftemp & diffdata) stop("Cannot handle objects! Data as well as temporal dimensions differ!") + if(diffdata & diffspat) stop("Cannot handle objects! Data as well as spatial dimensions differ!") + if(!diffspat) { + + } + if(difftemp) { + if(length(years)!=length(unique(years))) stop("Some years occur more than once! Cannot handle this case!") + output <- new("magpie",abind::abind(inputs,along=2)) + } else if(diffspat){ + if(length(cells) != length(unique(cells))) stop("Some regions/cells occur more than once! Cannot handle this case!") + output <- new("magpie",abind::abind(inputs,along=1)) + } else { + tmp <- function(x) return(length(getNames(x,fulldim = TRUE))) + tmp <- sapply(inputs,tmp) + if(length(unique(tmp))>1) warning("mbind most likely returned an erronous magpie object due to differnt numbers of data subdimensions in inputs!") + output <- new("magpie",abind::abind(inputs,along=3)) + } + if(length(grep("dummydimname",getNames(output),fixed=TRUE))==ndata(output)) dimnames(output)[[3]] <- NULL + names(dimnames(output)) <- names(dimnames(inputs[[1]])) + return(output) +} diff --git a/R/mbind2.R b/R/mbind2.R new file mode 100644 index 00000000..15f52d50 --- /dev/null +++ b/R/mbind2.R @@ -0,0 +1,46 @@ +#' @export +mbind2 <- function(...) { + isnull <- sapply(list(...),is.null) + ismagpie <- sapply(list(...),is.magpie) + if(any(!ismagpie & !isnull)) stop("Input(s) ",paste(which(!ismagpie & !isnull),collapse=", ")," is/are no MAgPIE objects(s)!") + if(length(list(...))==1 & is.list(list(...)[[1]])) stop("Input is a list!") #will be stopped earlier because of magpie-check ... inputs <- inputs[[1]] + + if(sum(ismagpie)==1) return(list(...)[[which(ismagpie)]]) #exactly one MAgPIE object + if(sum(ismagpie)==0) return(NULL) #only NULL values + #compare size of MAgPIE objects + diffdata <- !(length(unique(lapply(list(...)[ismagpie],getNames)))==1) + difftemp <- !(length(unique(lapply(list(...)[ismagpie],getYears)))==1) + .tmp <- function(x) return(getCells(clean_magpie(x))) + diffcells <- !(length(unique(lapply(list(...)[ismagpie],.tmp)))==1) + if(diffcells) stop("Cannot handle different spatial dimensions!") + if(diffdata & difftemp) stop("Cannot handle objects! Data as well as temporal dimensions differ!") + if(difftemp) { + years <- unlist(lapply(list(...)[ismagpie],getYears)) + nyears <- sapply(list(...)[ismagpie],nyears) + if(sum(nyears)!=length(years)) stop("Combining MAgPIE objects with and without years is not possible!") + if(length(years)!=length(unique(years))) stop("Some years occur more than once! Cannot handle this case!") + output <- new.magpie(getCells(list(...)[ismagpie][[1]]),years,getNames(list(...)[ismagpie][[1]])) + for(i in 1:length(list(...)[ismagpie])) output[,getYears(list(...)[ismagpie][[i]]),] <- list(...)[ismagpie][[i]] + return(output) + } else { + elems <- unlist(lapply(list(...)[ismagpie],getNames)) + nelem <- sapply(list(...)[ismagpie],ndata) + if(sum(nelem)!=length(elems)) stop("Combining MAgPIE objects with and without data names is not possible!") + if(length(elems)!=length(unique(elems))) { + #duplicates exist -> make dimnames unique + lelems <- lapply(list(...)[ismagpie],getNames) + for(i in 1:length(lelems)) lelems[[i]] <- paste(lelems[[i]],i,sep=".x") + elems <- unlist(lelems) + output <- new.magpie(getCells(list(...)[ismagpie][[1]]),getYears(list(...)[ismagpie][[1]]),elems) + for(i in 1:length(list(...)[ismagpie])) { + getNames <- paste(getNames(list(...)[ismagpie][[i]]),i,sep=".x") + output[,,getNames] <- setNames(list(...)[ismagpie][[i]],getNames) + } + } else { + output <- new.magpie(getCells(list(...)[ismagpie][[1]]),getYears(list(...)[ismagpie][[1]]),elems) + names(dimnames(output)) <- names(dimnames(list(...)[ismagpie][[1]])) + for(i in 1:length(list(...)[ismagpie])) output[,,getNames(list(...)[ismagpie][[i]])] <- list(...)[ismagpie][[i]] + } + return(output) + } +} diff --git a/R/mcalc.R b/R/mcalc.R new file mode 100644 index 00000000..55436df4 --- /dev/null +++ b/R/mcalc.R @@ -0,0 +1,50 @@ +#' mcalc +#' +#' Select values from a MAgPIE-object +#' +#' This functions only work for MAgPIE objects with named dimensions as the +#' dimension name (set_name) has to be used to indicate in which dimension the +#' entries should be searched for! +#' +#' @aliases mcalc mcalc<- +#' @param x MAgPIE object +#' @param f A formula describing the calculation that should be performed +#' @param dim The dimension in which the manipulation should take place. If set +#' to NULL function tries to detect the dimension automatically. +#' @param append If set to TRUE the result will be appended to x, otherwise the +#' result will be returned. +#' @return The calculated MAgPIE object in the case that append is set to +#' FALSE. Otherwise nothing is returned (as x is appended in place) +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{mselect}} +#' @examples +#' +#' data(population_magpie) +#' population_magpie +#' mcalc(population_magpie,X12 ~ A2*B1,append=TRUE) +#' population_magpie +#' mcalc(population_magpie,`Nearly B1` ~ 0.5*A2 + 99.5*B1) +#' +#' +#' @export mcalc +#' @importFrom stats as.formula +mcalc <- function(x,f,dim=NULL,append=FALSE) { + x <- clean_magpie(x) + f <- as.formula(f) + vars <- all.vars(f[[3]]) + + if(is.null(dim)) dim <- getDim(vars,x) + + for(v in vars) { + l <- list() + l[dim] <- v + tmp <- mselect(x,l,collapseNames=FALSE) + getNames(tmp,dim=dim) <- all.vars(f[[2]]) + assign(v,tmp) + } + if(append) { + assign(as.character(as.list(match.call())$x),mbind(x,eval(f[[3]])),envir = parent.frame()) + } else { + return(eval(f[[3]])) + } +} diff --git a/R/mselect.R b/R/mselect.R new file mode 100644 index 00000000..2571b8b4 --- /dev/null +++ b/R/mselect.R @@ -0,0 +1,85 @@ +.mselect_support <- function(search,where,ndim,names) { + search <- escapeRegex(search) + search <- paste0("(",paste(search,collapse="|"),")") + search <- paste0("^",paste(rep("[^\\.]*\\.",where-1),collapse=""),search,paste(rep("\\.[^\\.]*",ndim-where),collapse=""),"$") + return(names[grep(search,names)]) +} + +.mselect_coords <- function(x,...) { + if(is.null(names(dimnames(x)))) stop("Dimnames must have names in order to use mselect!") + args <- list(...) + if(length(args)==1) if(is.list(args[[1]])) args <- args[[1]] + sep="\\." + sets <- strsplit(names(dimnames(x)),sep) + + i <- getCells(x) + j <- getYears(x) + k <- getNames(x) + + for(n in names(args)) { + where <-grep(paste0("^",n,"$"),unlist(sets)) + if(length(where)>1) stop(paste0("set name \"",n,"\" found more than once!")) + if(length(where)==0) stop(paste0("set name \"",n,"\" not found!")) + + if(where<=length(sets[[1]])) { + # spatial + ndim <- nchar(gsub("[^\\.]","",getCells(x)[1])) + 1 + i <- .mselect_support(args[[n]],where,ndim,i) + } else if(where<=length(unlist(sets[1:2]))){ + #temporal + j <- .mselect_support(args[[n]],where-length(sets[[1]]),length(sets[[2]]),j) + } else { + #data + k <- .mselect_support(args[[n]],where-length(unlist(sets[1:2])),length(sets[[3]]),k) + } + } + m <- list(i=i,j=j,k=k) + m[lapply(m,length)==0] <- NULL + return(m) +} + + + + + +#' MSelect +#' +#' Select values from a MAgPIE-object +#' +#' This functions only work for MAgPIE objects with named dimensions as the +#' dimension name (set_name) has to be used to indicate in which dimension the +#' entries should be searched for! +#' +#' @aliases mselect mselect<- +#' @param x MAgPIE object +#' @param ... entry selections of the form +#' \code{set_name=c(set_elem1,set_elem2)}. Alternatively a single list element +#' containing these selections can be provided. +#' @param collapseNames Boolean which decides whether names should be collapsed +#' or not. +#' @param value values on which the selected magpie entries should be set. +#' @return The reduced MAgPIE object containing only the selected entries or +#' the full MAgPIE object in which a selection of entries was manipulated. +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{collapseNames}}, \code{"\linkS4class{magpie}"} +#' @examples +#' +#' data(population_magpie) +#' population_magpie +#' mselect(population_magpie,i=c("AFR","EUR"),scenario="A2",t="y2035") +#' +#' @export +mselect <- function(x,...,collapseNames=FALSE) { + m <- .mselect_coords(x,...) + if(collapseNames) return(collapseNames(x[m$i,m$j,m$k])) + return(x[m$i,m$j,m$k]) +} + +#' @describeIn mselect replace values in magpie object +#' @export +"mselect<-" <- function(x,...,value) { + m <- .mselect_coords(x,...) + x[m$i,m$j,m$k] <- value + return(x) +} + diff --git a/R/ncells.R b/R/ncells.R new file mode 100644 index 00000000..b970465b --- /dev/null +++ b/R/ncells.R @@ -0,0 +1,25 @@ +#' Count elements +#' +#' Functions to count the number of cells/years/datasets/regions of an +#' MAgPIE-object +#' +#' +#' @aliases ncells nyears ndata nregions +#' @param x A MAgPIE-object +#' @param fulldim specifies, how the object is treated. In case of FALSE, it is +#' assumed that x is 3 dimensional and dimnames(x)[[3]] is returned. In case of +#' TRUE, the dimnames of the real third dimension namesare returned +#' @return \item{value}{The number of cells/years/datasets/regions of \code{x}} +#' @author Jan Philipp Dietrich +#' @examples +#' +#' a <- is.magpie(NULL) +#' ncells(a) +#' nyears(a) +#' ndata(a) +#' nregions(a) +#' +#' @export +ncells <- function(x) { + return(dim(x)[1]) +} diff --git a/R/ndata.R b/R/ndata.R new file mode 100644 index 00000000..104c25b3 --- /dev/null +++ b/R/ndata.R @@ -0,0 +1,9 @@ +#' @describeIn ncells count datasets +#' @export +ndata <- function(x,fulldim=FALSE) { + if(fulldim==FALSE){ + return(dim(x)[3]) + } else { + return(fulldim(x)[[1]][3]) + } +} \ No newline at end of file diff --git a/R/new.magpie.R b/R/new.magpie.R new file mode 100644 index 00000000..8ce68073 --- /dev/null +++ b/R/new.magpie.R @@ -0,0 +1,47 @@ +#' new.magpie +#' +#' Creates a new MAgPIE object +#' +#' +#' @param cells_and_regions Either the region names (e.g. "AFR"), or the cells +#' (e.g. 1:10), or both in combination (e.g. "AFR.1"). NULL means no spatial +#' element. +#' @param years dimnames for years in the format "yXXXX" or as integers. NULL +#' means one year which is not further specified +#' @param names dimnames for names. NULL means one data element which is not +#' further specified +#' @param fill Default value for the MAgPIE object +#' @param sort Bolean. Decides, wheher output should be sorted or not. +#' @param sets A vector of dimension names. See \code{\link{getSets}} for more +#' information. +#' @return an empty magpie object filled with fill, with the given dimnames +#' @author Benjamin Bodirsky, Jan Philipp Dietrich +#' @seealso \code{\link{as.magpie}} +#' @examples +#' +#' a <- new.magpie(1:10,1995:2000) +#' b <- new.magpie(c("AFR","CPA"),"y1995",c("bla","blub"),sets=c("i","t","value")) +#' c <- new.magpie() +#' +#' @export new.magpie +#' @importFrom methods new +new.magpie <- function(cells_and_regions="GLO",years=NULL,names=NULL,fill=NA,sort=FALSE,sets=NULL) { + ncells <- length(cells_and_regions) + nyears <- ifelse(is.null(years),1,length(years)) + ndata <- ifelse(is.null(names),1,length(names)) + if(all(!grepl("\\.",cells_and_regions)) & !is.null(cells_and_regions)) { + if(all(is.numeric(cells_and_regions))) { + cells_and_regions <- paste("GLO",cells_and_regions,sep=".") + } else { + #cells_and_regions <- paste(cells_and_regions,1:ncells,sep=".") + } + } + object<-new("magpie",array(fill,dim=c(ncells,nyears,ndata))) + getCells(object) <- cells_and_regions + getYears(object) <- years + getNames(object) <- names + if(sort) object <- magpiesort(object) + object <- clean_magpie(object,"sets") + if(!is.null(sets)) getSets(object) <- sets + return(object) +} diff --git a/R/nregions.R b/R/nregions.R new file mode 100644 index 00000000..7ed3dd36 --- /dev/null +++ b/R/nregions.R @@ -0,0 +1,5 @@ +#' @describeIn ncells count regions +#' @export +nregions <- function(x) { + return(length(getRegions(x))) +} \ No newline at end of file diff --git a/R/nyears.R b/R/nyears.R new file mode 100644 index 00000000..17502067 --- /dev/null +++ b/R/nyears.R @@ -0,0 +1,5 @@ +#' @describeIn ncells count years +#' @export +nyears <- function(x) { + return(dim(x)[2]) +} diff --git a/R/old_dim_convention.R b/R/old_dim_convention.R new file mode 100644 index 00000000..3bf67851 --- /dev/null +++ b/R/old_dim_convention.R @@ -0,0 +1,29 @@ +#' old_dim_convention +#' +#' Transforms new dim convention (e.g. 3.2) into old dim convention(e.g. 4) +#' +#' +#' @param dim The dim number in the new convention +#' @return The dim number according to the old convention +#' @author Benjamin Bodirsky +#' @seealso \code{\link{add_columns}},\code{\link{add_dimension}} +#' @examples +#' +#' dim=old_dim_convention(3.2) +#' dim=old_dim_convention(1.1) +#' +#' @export old_dim_convention +old_dim_convention<-function(dim){ + dim<-as.character(dim) + elemsplit <- as.numeric(as.vector(strsplit(dim,".",fixed=TRUE)[[1]])) + if (length(elemsplit)==1) {stop("Format has to be x.y")} + if (elemsplit[1]==1) { + if (elemsplit[2]==1){newdim=1} else {stop("old dim convention has only 1.1, 2.1 and 3.x")} + } else if (elemsplit[1]==2) { + if (elemsplit[2]==1){newdim=2} else {stop("old dim convention has only 1.1, 2.1 and 3.x")} + } else if (elemsplit[1]==3) { + if (elemsplit[2]==0) {stop("3.0 not supported")} + newdim=2+elemsplit[2] + } else {stop("dim cannot be higher than 3.x")} + return(newdim) +} diff --git a/R/onLoad.R b/R/onLoad.R new file mode 100644 index 00000000..7ed0b24e --- /dev/null +++ b/R/onLoad.R @@ -0,0 +1,9 @@ +.onLoad <- function(libname, pkgname){ + #Set MAgClass verbosity level to 1 (warnings, but no notes) + options(magclass.verbosity=1) + #Due to a function name conflict with the grid library + #(both packages contain the function getNames), + #it has to be assured that the grid library is loaded before the magclass library + #if the grid library is installed + suppressWarnings(try(do.call(what="library",args=list("grid")))) +} \ No newline at end of file diff --git a/R/ops-method.R b/R/ops-method.R new file mode 100644 index 00000000..8e02a4dd --- /dev/null +++ b/R/ops-method.R @@ -0,0 +1,14 @@ +#' @importFrom methods Ops callGeneric new +#' @exportMethod Ops +setMethod(Ops, signature(e1='magpie', e2='magpie'), + function(e1, e2){ + if(is.null(dim(e1)) & is.null(dim(e2))) { + return(callGeneric(e1@.Data,e2@.Data)) + } + e2 <- magpie_expand(e2,e1) + e1 <- magpie_expand(e1,e2) + if(any(unlist(dimnames(e1))!=unlist(dimnames(e2)))) stop("MAgPIE objects after MAgPIE object expansion do not agree in dimnames! magpie_expand seems to be bugged!\n e1:", + paste(unlist(dimnames(e1))[unlist(dimnames(e1))!=unlist(dimnames(e2))],collapse=" "),"\n e2:",paste(unlist(dimnames(e2))[unlist(dimnames(e1))!=unlist(dimnames(e2))],collapse=" ")) + return(new("magpie",callGeneric(e1@.Data,e2@.Data))) + } +) diff --git a/R/place_x_in_y.R b/R/place_x_in_y.R new file mode 100644 index 00000000..26b68d54 --- /dev/null +++ b/R/place_x_in_y.R @@ -0,0 +1,48 @@ +#' place_x_in_y +#' +#' Function positions magpie object x into magpie object y. +#' +#' +#' @param x Object to be placed. +#' @param y Object in which x shall be placed +#' @param expand T: if x is larger than y, new columns are added. +#' @return The combination of x and y. x overwrites y values which are in the +#' same place. +#' @author Benjamin Bodirsky +#' @seealso +#' \code{\link{add_dimension}},\code{\link{add_columns}},\code{\link{mbind}} +#' @examples +#' +#' data(population_magpie) +#' x <- population_magpie[,"y1995",]*0.2 +#' a <- place_x_in_y(x, population_magpie) +#' +#' @export place_x_in_y +place_x_in_y<-function(x,y,expand=T){ + if(!all(getYears(x)%in%getYears(y))) { + if (expand){ + print("x has years that dont exist in y. Expand y.") + y<-add_columns(x = y,dim = 2.1,addnm = setdiff(getYears(x),getYears(y))) + y<-magpiesort(y) + }else{ + x<-x[,getYears(x)[getYears(x)%in%getYears(y)],] + } + } + if(!all(getRegions(x)%in%getRegions(y))) { + if (expand){ + print("x has regions that dont exist in y. Expand y.") + y<-add_columns(x = y,dim = 2.1,addnm = setdiff(getYears(x),getYears(y))) + y<-magpiesort(y) + } else { + x<-x[getRegions(x)[getRegions(x)%in%getRegions(y)],,] + } + } + if(!all(getNames(x)%in%getNames(y))) { + if (expand){ + stop("x has names that dont exist in y. Cannot handle this yet. Please improve me!")} + } else { + x<-x[,,getNames(x)[getNames(x)%in%getNames(y)]] + } + y[getRegions(x),getYears(x),getNames(x)]<-x + return(y) +} diff --git a/R/pmin-method.R b/R/pmin-method.R new file mode 100644 index 00000000..c5833e14 --- /dev/null +++ b/R/pmin-method.R @@ -0,0 +1,8 @@ +setMethod("round", + signature(x = "magpie"), + function (x, digits=0) + { + x@.Data <- round(x@.Data,digits=digits) + return(x) + } +) \ No newline at end of file diff --git a/R/population_magpie.R b/R/population_magpie.R new file mode 100644 index 00000000..17c6c2d1 --- /dev/null +++ b/R/population_magpie.R @@ -0,0 +1,9 @@ +#' population_magpie +#' +#' Example dataset for a regional MAgPIE object +#' +#' +#' @name population_magpie +#' @return A2 and B1 population scenario from SRES +#' @author Benjamin Bodirsky +NULL diff --git a/R/print.magpie.R b/R/print.magpie.R new file mode 100644 index 00000000..d8ebb8d1 --- /dev/null +++ b/R/print.magpie.R @@ -0,0 +1,23 @@ +#' print +#' +#' print method for MAgPIE objects for conventient display of magpie data. +#' +#' +#' @param x MAgPIE object +#' @param drop argument which controls whether empty dimensions should be +#' skipped or not. +#' @param ... arguments to be passed to or from other methods. +#' @return print displays the given MAgPIE object on screen. +#' @author Jan Philipp Dietrich +#' @seealso \code{\link[base]{print}} +#' @examples +#' +#' data(population_magpie) +#' print(population_magpie) +#' print(population_magpie[,1,], drop=FALSE) +#' print(population_magpie[,1,]) +#' +#' @export +print.magpie <- function(x, drop=TRUE, ...) { + print(as.array(x)[,,,drop=drop], ...) +} diff --git a/R/read.magpie.R b/R/read.magpie.R new file mode 100644 index 00000000..46027806 --- /dev/null +++ b/R/read.magpie.R @@ -0,0 +1,536 @@ +#' Read MAgPIE-object from file +#' +#' Reads a MAgPIE-file and converts it to a 3D array of the structure +#' (cells,years,datacolumn) +#' +#' This function reads from 10 different MAgPIE file\_types. "cs2" is the new +#' standard format for cellular data with or without header and the first +#' columns (year,regiospatial) or only (regiospatial), "csv" is the standard +#' format for regional data with or without header and the first columns +#' (year,region,cellnumber) or only (region,cellnumber). "cs3" is a format +#' similar to csv and cs2, but with the difference that it supports +#' multidimensional data in a format which can be read by GAMS, "put" is a +#' newly supported format which is mosty used for the REMIND-MAgPIE coupling. +#' This format is only partly supported at the moment. "asc" is the AsciiGrid +#' format (for example used for Arc Gis data). "nc" is the netCDF format (only +#' "nc" files written by write.magpie can be read). All these variants are +#' read without further specification. "magpie" (.m) and "magpie zipped" (.mz) +#' are new formats developed to allow a less storage intensive management of +#' MAgPIE-data. The only difference between both formats is that .mz is gzipped +#' whereas .m is not compressed. So .mz needs less memory, whereas .m might +#' have a higher compatibility to other languages. \cr\cr Since library version +#' 1.4 read.magpie can also read regional or global MAgPIE csv-files. +#' +#' @param file_name file name including file ending (wildcards are supported). +#' Optionally also the full path can be specified here (instead of splitting it +#' to file\_name and file\_folder) +#' @param file_folder folder the file is located in (alternatively you can also +#' specify the full path in file\_name - wildcards are supported) +#' @param file_type format the data is stored in. Currently 12 formats are +#' available: "cs2" (cellular standard MAgPIE format), "csv" (regional standard +#' MAgPIE format), "cs3" (multidimensional format compatible to GAMS), "cs4" +#' (alternative multidimensional format compatible to GAMS, in contrast to cs3 +#' it can also handle sparse data), "csvr", "cs2r", "cs3r" and "cs4r" which are +#' the same formats as the previous mentioned ones with the only difference +#' that they have a REMIND compatible format, "m" (binary MAgPIE format +#' "magpie"), "mz" (compressed binary MAgPIE format "magpie zipped") "put" +#' (format used primarily for the REMIND-MAgPIE coupling) and "asc", +#' (ASCII-Grid format as used by ArcGis) . If file\_type=NULL the file ending +#' of the file\_name is used as format. If format is different to the formats +#' mentioned standard MAgPIE format is assumed. +#' @param as.array Should the input be transformed to an array? This can be +#' useful for regional or global inputs, but all advantages of the magpie-class +#' are lost. +#' @param old_format used to read files in old MAgPIE-format (unused space was +#' not located at the beginning of the file), will be removed soon. +#' @param comment.char character: a character vector of length one containing a +#' single character or an empty string. Use "" to turn off the interpretation +#' of comments altogether. If a comment is found it will be stored in +#' attr(,"comment"). In text files the comment has to be at the beginning of +#' the file in order to be recognized by read.magpie. +#' @param check.names logical. If TRUE then the names of the variables in the +#' data frame are checked to ensure that they are syntactically valid variable +#' names. Same functionality as in read.table. +#' @return \item{x}{MAgPIE-object} +#' @note +#' +#' The binary MAgPIE formats .m and .mz have the following content/structure +#' (you only have to care for that if you want to implement +#' read.magpie/write.magpie functions in other languages): \cr \cr +#' [ FileFormatVersion | Current file format version number (currently 2) | integer | 2 Byte ] \cr +#' [ nchar_comment | Number of characters of the file comment | integer | 4 Byte ] \cr +#' [ nchar_sets | Number of characters of all regionnames + 2 delimiter | integer | 2 Byte] \cr +#' [ not used | Bytes reserved for later file format improvements | integer | 92 Byte ] \cr +#' [ nyears | Number of years | integer | 2 Byte ]\cr +#' [ year_list | All years of the dataset (0, if year is not present) | integer | 2*nyears Byte ] \cr +#' [ nregions | Number of regions | integer | 2 Byte ] \cr +#' [ nchar_reg | Number of characters of all regionnames + (nreg-1) for delimiters | integer | 2 Byte ] \cr +#' [ regions | Regionnames saved as reg1\\nreg2 (\\n is the delimiter) | character | 1*nchar_reg Byte ] \cr +#' [ cpr | Cells per region | integer | 4*nreg Byte ] \cr +#' [ nelem | Total number of data elements | integer | 4 Byte ] \cr +#' [ nchar_data | Number of char. of all datanames + (ndata - 1) for delimiters | integer | 4 Byte ] \cr +#' [ datanames | Names saved in the format data1\\ndata2 (\\n as del.) | character | 1*nchar_data Byte ] \cr +#' [ data | Data of the MAgPIE array in vectorized form | numeric | 4*nelem Byte ] \cr +#' [ comment | Comment with additional information about the data | character | 1*nchar_comment Byte ] \cr +#' [ sets | Set names with \\n as delimiter | character | 1*nchar_sets Byte] \cr +#' +#' Please note that if your data in the spatial dimension is not ordered by +#' region name each new appearance of a region which already appeared before +#' will be treated and counted as a new region (e.g. +#' AFR.1,AFR.2,CPA.3,CPA.4,AFR.5 will count AFR twice and nregions will be set +#' to 3!). +#' @author Jan Philipp Dietrich +#' @seealso \code{"\linkS4class{magpie}"}, \code{\link{write.magpie}} +#' @examples +#' +#' \dontrun{ +#' a <- read.magpie("lpj_yield_ir.csv") +#' write.magpie(a,"lpj_yield_ir.mz") +#' } +#' +#' @export read.magpie +#' @importFrom methods is new +#' @importFrom utils read.csv +#' +read.magpie <- function(file_name,file_folder="",file_type=NULL,as.array=FALSE,old_format=FALSE,comment.char="*",check.names=FALSE) { + + file_name <- paste(file_folder,file_name,sep="") + + if(length(Sys.glob(file_name))==0) { + stop(paste("file",file_name,"does not exist")) + } + + #expand wildcards + file_name_unexpanded <- file_name + file_name <- Sys.glob(file_name) + if(length(file_name)>1) { + file_name <- file_name[1] + warning(paste("file name",file_name_unexpanded,"is ambiguous, only first alternative is used!")) + } else if(length(file)==0) { + stop("File ",file_name_unexpanded," could not be found!") + } + + #if file-type is not mentioned file-ending is used as file-type + if(is.null(file_type)) { + file_type <- tail(strsplit(file_name,'\\.')[[1]],1) + } + if(!(file_type %in% c('m','mz','csv','cs2','cs3','cs4','csvr','cs2r','cs3r','cs4r','put',"asc","nc","nc2"))) stop(paste("Unkown file type:",file_type)) + + .readComment <- function(file_name,comment.char="*") { + comment <- NULL + if(!is.null(comment.char)) { + if(comment.char!="") { + zz <- file(file_name) + open(zz) + read_repeat <- TRUE + while(read_repeat){ + tmp <- readLines(zz,1) + if(length(grep(paste("^",escapeRegex(comment.char),sep=""),tmp))) { + comment <- c(comment,tmp) + } else { + read_repeat <- FALSE + } + } + close(zz) + } + } + return(substring(comment,2)) + } + + if(file.exists(file_name)) { + if(file_type=="m" | file_type=="mz") { + + if(file_type=="mz") { + zz <- gzfile(file_name,"rb") + } else { + zz <- file(file_name,"rb") + } + + if(!old_format) { + fformat_version <- readBin(zz,integer(),1,size=2) + nchar_comment <- readBin(zz,integer(),1,size=4) + empty <- 94 + if(fformat_version > 1) { + nchar_sets <- readBin(zz,integer(),1,size=2) + empty <- empty - 2 + } + readBin(zz,integer(),empty,size=1) #Bytes reserved for later file format improvements + } else { + fformat_version <- 0 + } + nyears <- readBin(zz,integer(),1,size=2) + year_list <- readBin(zz,integer(),nyears,size=2) + nregions <- readBin(zz,integer(),1,size=2) + nchar_regions <- readBin(zz,integer(),1,size=2) + + regions <- strsplit(readChar(zz,nchar_regions),"\n")[[1]] + + cpr <- readBin(zz,integer(),nregions,size=4) + nelem <- readBin(zz,integer(),1,size=4) + nchar_data <- readBin(zz,integer(),1,size=4) + + datanames <- strsplit(readChar(zz,nchar_data),"\n")[[1]] + + if(old_format) readBin(zz,integer(),100,size=1) #100 Byte reserved for later file format improvements + + output <- array(readBin(zz,numeric(),nelem,size=4),c(sum(cpr),nyears,nelem/sum(cpr)/nyears)) + output[is.nan(output)] <- NA + if(any(cpr!=1)) { + cellnames <- paste(rep(regions,cpr),1:sum(cpr),sep=".") + } else { + cellnames <- regions + } + if(length(cellnames)==1) cellnames <- list(cellnames) + dimnames(output)[[1]] <- cellnames + if(year_list[1]>0) dimnames(output)[[2]] <- paste("y",year_list,sep="") + if(length(datanames)>0) dimnames(output)[[3]] <- datanames + + if(fformat_version > 0) { + if(nchar_comment>0) attr(output,"comment") <- strsplit(readChar(zz,nchar_comment),"\n")[[1]] + } + if(fformat_version > 1) { + if(nchar_sets > 0) names(dimnames(output)) <- strsplit(readChar(zz,nchar_sets),"\n")[[1]] + } + close(zz) + attr(output,"FileFormatVersion") <- fformat_version + read.magpie <- new("magpie",output) + + } else if(file_type=="cs3" | file_type=="cs3r") { + x <- read.csv(file_name,comment.char=comment.char, check.names=check.names) + datacols <- grep("^dummy\\.?[0-9]*$",colnames(x)) + xdimnames <- apply(x[datacols],2,unique) + if(!is.list(xdimnames)) xdimnames <- list(xdimnames) + xdimnames[[length(xdimnames)+1]] <- colnames(x)[-datacols] + names(xdimnames) <- NULL + tmparr <- array(NA,dim=sapply(xdimnames,length),dimnames=xdimnames) + for(i in xdimnames[[length(xdimnames)]]) { + j <- as.matrix(cbind(x[datacols],i)) + .duplicates_check(j) + tmparr[j] <- x[,i] + } + read.magpie <- as.magpie(tmparr) + attr(read.magpie,"comment") <- .readComment(file_name,comment.char=comment.char) + } else if(file_type=="cs4" | file_type=="cs4r") { + x <- read.csv(file_name,comment.char=comment.char,header=FALSE, check.names=check.names) + read.magpie <- as.magpie(x,tidy=TRUE) + attr(read.magpie,"comment") <- .readComment(file_name,comment.char=comment.char) + } else if(file_type=="asc"){ + grid<-suppressWarnings(try(maptools::readAsciiGrid(file_name,dec="."),silent=T)) + if(is(grid,"try-error")){ + grid<-try(maptools::readAsciiGrid(file_name,dec=",")) + if(is(grid,"try-error")) stop("File cannot be read. Make sure the file is in AsciiGrid format with either '.' or ',' as decimal point character.") + } + if(!all(grid@grid@cellsize==0.5)) stop("Only 0.5 degree data supported. Input data is in (",paste(grid@grid@cellsize,collapse=","),") degree (x,y).") + #Convert to SpatialPixelsDataFrame + sp::fullgrid(grid)<-FALSE + magpie_coords<-as.matrix(magclassdata$half_deg[,c("lon","lat")]) + rowmatch<- function(A,B) { + # Rows in A that match the rows in B + f <- function(...) paste(..., sep=":") + if(!is.matrix(B)) B <- matrix(B, 1, length(B)) + a <- do.call("f", as.data.frame(A)) + b <- do.call("f", as.data.frame(B)) + match(b, a) + } + mp_rows<-rowmatch(grid@coords,magpie_coords) + names(mp_rows)<-1:59199 + if(any(is.na(mp_rows)))warning(sum(is.na(mp_rows))," magpie cells are missing in the grid file. They will be set to NA.") + omitted_cells<-which(!(1:length(grid@data[[1]]))%in%mp_rows) + if(length(omitted_cells)>0){ + omitted_fraction<-sum(grid@data[[1]][omitted_cells]/sum(grid@data[[1]])) + warning(length(omitted_cells)," of ",length(grid@data[[1]])," cells in the file that contain data are discarded because they do not correspond to magpie cells.\n Those cells contain ",omitted_fraction*100," percent of the global sum of the input file.") + } + read.magpie<-rep(-1001,59199) + names(read.magpie)<-1:59199 + goodcells<-names(mp_rows)[which(!is.na(mp_rows))] + read.magpie[goodcells]<-grid@data[[1]][mp_rows[goodcells]] + read.magpie[is.na(mp_rows)]<-NA + names(read.magpie)<-paste(magclassdata$half_deg$region,1:59199,sep=".") + read.magpie<-as.magpie(read.magpie) + } else if(file_type=="nc") { #netcdf + nc_file <- ncdf4::nc_open(file_name) + options("magclass.verbosity" = 1) + + if (nc_file$dim$lat$len != 360) stop(paste0("Only netcdf files with 0.5 degree resolution (720x360) are supported. Your file has a dimension of ",nc_file$dim$lon$len, "x", nc_file$dim$lat$len,".")) + if(is.null(nc_file$dim$time$len)) nc_file$dim$time$len <- 1 + if(is.null(nc_file$dim$time$vals)) nc_file$dim$time$vals <- 1995 + + #create a single array of all ncdf variables + nc_data <- array(NA,dim=c(nc_file$dim$lon$len,nc_file$dim$lat$len,nc_file$dim$time$len,nc_file$nvars)) + for (i in 1:nc_file$nvars) { + nc_data[,,,i] <- ncdf4::ncvar_get(nc_file,varid=names(nc_file$var)[i]) + } + + #taking out lat and lon from nc file + lat<-nc_file$dim$lat$vals + lon<-nc_file$dim$lon$vals + #coord from magclass data + coord <- magclassdata$half_deg[, c("lon", "lat")] + + #reorder ncdf array into magpie cellular format (still as array) + #create emtpy array in magpie cellular format + mag <- array(NA,dim=c(59199,nc_file$dim$time$len,nc_file$nvars),dimnames=list(paste(magclassdata$half_deg$region,1:59199,sep="."),paste("y",nc_file$dim$time$vals,sep=""),names(nc_file$var))) + #Loop over cells to give mag values taken from nc_data. For each cell in mag, we know the exact coordinates (coord). Hence, we can use coord to map coordinates in nc_data to cells in mag. + for (i in 1:ncells(mag)) { + mag[i,,] <- nc_data[which(coord[i, 1]==lon), which(coord[i,2]==lat),,] + } + + #convert array to magpie object + read.magpie <- as.magpie(mag) + } else { + #check for header + if(file_type=="put") { + temp <- read.csv(file_name,nrow=1,header=FALSE,sep="\t",comment.char=comment.char, check.names=check.names) + } else { + temp <- read.csv(file_name,nrow=1,header=FALSE,comment.char=comment.char, check.names=check.names) + } + + #check for numeric elements in first row, which means a missing header + header <- TRUE + for(temp_elem in temp) { + if(is.numeric(temp_elem)) header <- FALSE + } + + if(file_type=="put") { + temp <- read.csv(file_name,header=header,sep="\t",comment.char=comment.char, check.names=check.names) + } else { + temp <- read.csv(file_name,header=header,comment.char=comment.char, check.names=check.names) + } + + #analyse column content + coltypes <- rep(0,dim(temp)[2]) + for(column in 1:dim(temp)[2]) { + if(sum(coltypes=="year")==0 & length(grep("^(y[0-9]{4}|[0-2][0-9]{3})$",temp[,column]))==dim(temp)[1]) { + coltypes[column] <- "year" + } else if(sum(coltypes=="region")==0 & sum(coltypes=="regiospatial")==0 & length(grep("^[A-Z]{3}$",temp[,column]))==dim(temp)[1]) { + coltypes[column] <- "region" + } else if(sum(coltypes=="regiospatial")==0 & sum(coltypes=="region")==0 & length(grep("^[A-Z]{3}_[0-9]+$",temp[,column]))==dim(temp)[1]) { + coltypes[column] <- "regiospatial" + } else if(!is.numeric(temp[1,column])) { + coltypes[column] <- "other" + } else if(sum(coltypes=="cell")==0 & all(!is.na(temp[,column])) & all(temp[,column]!=0)) { + if(length(temp[,column])%%max(temp[,column])==0) { + if(suppressWarnings(try(all(unique(temp[,column])==1:max(temp[,column])),silent=TRUE)==TRUE)) { + coltypes[column] <- "cell" + } else { + coltypes[column] <- "data" + } + } else { + coltypes[column] <- "data" + } + } else { + coltypes[column] <- "data" + } + } + + if(any(coltypes=="year")) { + temp <- temp[order(temp[,which(coltypes=="year")]),] + if(length(grep("y",temp[,which(coltypes=="year")]))==0) { + temp[,which(coltypes=="year")] <- as.factor(paste("y",temp[,which(coltypes=="year")],sep="")) + } + } + + #backup check if cell column is really a cell column + if(any(coltypes=="cell")){ + if(dimnames(temp)[[2]][which(coltypes=="cell")]=="iteration") { + temp[,which(coltypes=="cell")] <- paste("iter",format(temp[,which(coltypes=="cell")]),sep="") + coltypes[which(coltypes=="cell")] <- "other" + } else if(header & !(dimnames(temp)[[2]][which(coltypes=="cell")]%in%c("dummy","dummy.1","dummy.2","dummy.3",""," ","cell","cells","Cell","Cells"))){ + coltypes[which(coltypes=="cell")] <- "data" + } + } + + if(any(coltypes=="cell")) { + ncells <- dim(temp)[1] + if(any(coltypes=="year")) ncells <- ncells/length(unique(temp[,which(coltypes=="year")])) + if(any(coltypes=="other")) ncells <- ncells/length(unique(temp[,which(coltypes=="other")])) + if(!all(temp[1:ncells,which(coltypes=="cell")]==1:ncells)) coltypes[which(coltypes=="cell")] <- "data" + } + + #set all coltypes after the first occurrence of "data" to "data" + if(any(coltypes=="data")) coltypes[min(which(coltypes=="data")):length(coltypes)] <- "data" + + #set first columntype from "cell" to "data" if it seems that the data set is just a vector of numbers + if(all(coltypes == c("cell",rep("data",length(coltypes)-1))) & dim(temp)[1]==1) coltypes[1] <- "data" + + #check coltypes for consistency + if(length(which(coltypes=="data"))==0) { + print(coltypes) + stop(paste("Inconsistency in data columns! No data column found in",file_name)) + } + + if(sum(coltypes=="data")!=(length(coltypes)-min(which(coltypes=="data"))+1)){ + print(coltypes) + stop("Inconsistency in data columns!") + } + if(!all(which(coltypes=="data")==min(which(coltypes=="data")):length(coltypes))){ + print(coltypes) + stop("Inconsistency in data columns!") + } + if(sum(coltypes=="data")==0){ + print(coltypes) + stop("No data column found!") + } + if(sum(coltypes=="other")>1){ + print(coltypes) + stop("Invalid format. More than one \"other\" column is not allowed!") + } + + if(header) { + if(length(grep("^y+[0-9]{4}$",dimnames(temp)[[2]][which(coltypes=="data")[1]]))==1) { + headertype <- "year" + } else if(length(grep("^[A-Z]{3}$",dimnames(temp)[[2]][which(coltypes=="data")[1]]))==1) { + headertype <- "region" + } else { + headertype <- "other" + } + } else { + headertype <- "none" + } + + if(any(coltypes=="other")){ + othernames <- levels(as.factor(temp[,which(coltypes=="other")])) + nother <- length(othernames) + if(header) { + if(headertype=="other") { + elemnames <- dimnames(temp)[[2]][which(coltypes=="data")] + elemnames <- paste(rep(othernames,each=length(elemnames)),elemnames,sep=".") + } else { + elemnames <- othernames + } + } else { + if(sum(coltypes=="data")==1) { + elemnames <- othernames + } else { + elemnames <- 1:sum(coltypes=="data") + elemnames <- paste(rep(othernames,each=length(elemnames)),elemnames,sep=".") + } + } + ncols <- length(elemnames) + } else { + nother <- 1 + if(header) { + if(headertype=="other") { + elemnames <- dimnames(temp)[[2]][which(coltypes=="data")] + ncols <- length(elemnames) + } else { + elemnames <- NULL + ncols <- 1 + } + } else { + elemnames <- NULL + ncols <- sum(coltypes=="data") + } + } + + + if(any(coltypes=="year")){ + yearnames <- levels(temp[,which(coltypes=="year")]) + nyears <- length(yearnames) + } else if(headertype=="year") { + yearnames <- dimnames(temp)[[2]][which(coltypes=="data")] + nyears <- length(yearnames) + } else { + yearnames <- NULL + nyears <- 1 + } + + if(any(coltypes=="cell")){ + ncells <- max(temp[,which(coltypes=="cell")]) + } else { + if(headertype!="year"){ + ncells <- dim(temp)[1]/(nyears*nother) + } else { + ncells <- dim(temp)[1]/nother + } + } + + if(any(coltypes=="regiospatial")) { + cellnames <- gsub("_",".",temp[1:ncells,which(coltypes=="regiospatial")],fixed=TRUE) + } else { + if(any(coltypes=="region")){ + tmp_regionnames <- levels(temp[,which(coltypes=="region")]) + regionnames <- tmp_regionnames[temp[,which(coltypes=="region")]] + if(ncells==length(tmp_regionnames)) regionnames <- unique(regionnames) + } else if(headertype=="region") { + regionnames <- dimnames(temp)[[2]][which(coltypes=="data")] + ncells <- ncells*length(regionnames) + } else { + regionnames <- "GLO" + } + if(length(unique(regionnames)) < length(regionnames)) { + cellnames <- paste(regionnames,1:ncells,sep=".") + } else { + cellnames <- regionnames + } + } + if(length(cellnames)==1) cellnames <- list(cellnames) + + if(any(coltypes=="other") & (headertype=="other" | headertype=="none")) { + output <- array(NA,c(ncells,nyears,ncols)) + dimnames(output)[[1]] <- cellnames + dimnames(output)[[2]] <- yearnames + dimnames(output)[[3]] <- elemnames + counter <- 0 + for(other.elem in othernames){ + output[,,(1:sum(coltypes=="data"))+counter] <- array(as.vector( + as.matrix(temp[which(temp[,which(coltypes=="other")]==other.elem), + which(coltypes=="data")])),c(ncells,nyears,sum(coltypes=="data"))) + counter <- counter + sum(coltypes=="data") + } + } else if(!any(coltypes=="other") & headertype=="region") { + output <- array(NA,c(ncells,nyears,ncols)) + dimnames(output)[[1]] <- cellnames + dimnames(output)[[2]] <- yearnames + dimnames(output)[[3]] <- elemnames + for(i in 1:length(cellnames)) { + output[i,,1] <- temp[,which(coltypes=="data")[i]] + } + } else if(!any(coltypes=="other") & headertype=="year"){ + output <- array(NA,c(ncells,nyears,ncols)) + dimnames(output)[[1]] <- cellnames + dimnames(output)[[2]] <- yearnames + dimnames(output)[[3]] <- elemnames + for(year in yearnames) { + output[,year,1] <- temp[,year] + } + } else if(any(coltypes=="other") & headertype=="region") { + output <- array(NA,c(ncells,nyears,ncols)) + dimnames(output)[[1]] <- cellnames + dimnames(output)[[2]] <- yearnames + dimnames(output)[[3]] <- elemnames + for(i in 1:length(cellnames)) { + for(elem in elemnames) { + output[i,,elem] <- temp[which(temp[,which(coltypes=="other")]==elem),which(coltypes=="data")[i]] + } + } + } else if(any(coltypes=="other") & headertype=="year"){ + output <- array(NA,c(ncells,nyears,ncols)) + dimnames(output)[[1]] <- cellnames + dimnames(output)[[2]] <- yearnames + dimnames(output)[[3]] <- elemnames + for(year in yearnames) { + for(elem in elemnames) { + output[,year,elem] <- temp[which(temp[,which(coltypes=="other")]==elem),year] + } + } + } else { + output <- array(as.vector(as.matrix(temp[,which(coltypes=="data")])),c(ncells,nyears,ncols)) + dimnames(output)[[1]] <- cellnames + dimnames(output)[[2]] <- yearnames + dimnames(output)[[3]] <- elemnames + } + read.magpie <- output + attr(read.magpie,"comment") <- .readComment(file_name,comment.char=comment.char) + } + } else { + warning(paste("File",file_name,"does not exist")) + read.magpie <- NULL + } + if(as.array){ + read.magpie <- as.array(as.magpie(read.magpie))[,,] + } else { + read.magpie <- as.magpie(read.magpie) + } + return(read.magpie) +} diff --git a/R/read.report.R b/R/read.report.R new file mode 100644 index 00000000..0487431c --- /dev/null +++ b/R/read.report.R @@ -0,0 +1,141 @@ +#' Read file in report format +#' +#' This function reads the content of a reporting file (a file in the model +#' intercomparison file format *.mif) into a list of MAgPIE objects or a single +#' MAgPIE object +#' +#' +#' @param file file name the object should be read from. +#' @param as.list if TRUE a list is returned (default), if FALSE it is tried to +#' merge all information in one MAgPIE object (still under development and +#' works currently only if the entries for the different models and scenarios +#' have exactly the same regions and years). +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{write.report}} +#' @examples +#' +#' \dontrun{ +#' read.report("report.csv") +#' } +#' +#' @export read.report +#' @importFrom utils read.table +#' +read.report <- function(file,as.list=TRUE) { + + .trim <- function(a) return(gsub("(^ +)|( +$)", "",as.character(a))) + + .return_magpie <- function(tmp,scenario,model) { + regions <- unique(as.character(tmp$Region)) + names(regions) <- regions + years <- sub("X","y",grep("^X[0-9]{4}$",dimnames(tmp)[[2]],value=TRUE)) + names <- unique(paste(tmp$Variable, "#SPLITHERE# (",tmp$Unit,")",sep ="")) + units <- sub("^.*#SPLITHERE# \\((.*)\\)$","\\1",names) + names(names) <- sub("#SPLITHERE#", "", names) + names <- sub("#SPLITHERE#","",names) + #delete dots if they are aparrently not used as dimension separator + ndots <- nchar(gsub("[^\\.]*","",names)) + if(any(ndots!=ndots[1])) names <- gsub("\\.","",names) + mag <- new.magpie(sub("ZZZZZZGLO","GLO",(sort(sub("GLO","ZZZZZZGLO",regions)))),years,names) + yearelems <- grep("^X[0-9]{4}$",dimnames(tmp)[[2]]) + regions[order(sub("GLO","ZZZZZZGLO",regions))] <- dimnames(mag)[[1]] + mag <- as.array(mag) + coord <- cbind(regions[tmp$Region],rep(years,each=dim(tmp)[1]),names[paste(tmp$Variable, " (",tmp$Unit,")",sep ="")]) + if(dim(coord)[1]>length(mag)) { + duplicates <- duplicated(coord) + warning("Duplicate entries found for model \"",model,"\" and scenario \"",scenario,"\" and only the last entry found in the data will be used (duplicate entries: ",paste(apply(rbind(NULL,unique(coord[duplicates,c(1,3)])),1,paste,collapse="|"),collapse=", "),")!") + } + + mag[coord] <- suppressWarnings(as.numeric(as.vector(as.matrix(tmp[,yearelems])))) + names(dimnames(mag)) <- c("region","year","variable") +return(as.magpie(mag,spatial=1,temporal=2)) + } + + .readmif <- function(file) { + default_header <- c("Model","Scenario","Region","Variable","Unit","X2005", + "X2010","X2020","X2030","X2040","X2050","X2060","X2070", + "X2080","X2090","X2100") + #determine seperator + s <- read.table(file,sep=";",header=FALSE,nrows=1) + if (all(names(s) == "V1")) sep <- "," else sep <- ";" + #recognize header + s <- read.table(file,sep=sep,header=FALSE,nrows=1) + header <- (.trim(s[,1]) == "Model" | .trim(s[,1]) == "MODEL") + #read in raw data + raw <- read.table(file,sep=sep,header=header,stringsAsFactors=FALSE,na.strings = "N/A")#,fileEncoding = "UTF8") + ugly_format <- all(is.na(raw[,dim(raw)[2]])) + if(ugly_format) raw <- raw[,-dim(raw)[2]] + + if("number of items read is not a multiple of the number of columns" %in% names(warnings())) { + stop("Inconsistent input data! At least one line is incomplete!") + } + + #rename from uppercase to lowercase + if (header & .trim(s[,1]) == "MODEL") { + names(raw)[1:5] <- default_header[1:5] + } + + if(!header) { + if(dim(raw)[2]==length(default_header)) dimnames(raw)[[2]] <- default_header + else stop("Cannot read report. No header given and report has not the standard size!") + } + + output <- list() + raw$Scenario <- .trim(raw$Scenario) + raw$Model <- .trim(raw$Model) + raw$Region <- .trim(raw$Region) + raw$Unit <- .trim(raw$Unit) + raw$Variable <- .trim(raw$Variable) + + raw$Model[is.na(raw$Model)] <- "NA" + raw$Scenario[is.na(raw$Scenario)] <- "NA" + + raw$Region <- sub("R5\\.2","",raw$Region) + raw$Region <- sub("World|glob","GLO",raw$Region) + models <- unique(raw$Model) + scenarios <- unique(raw$Scenario) + for(scenario in scenarios) { + output[[scenario]] <- list() + for(model in models) { + if (nrow(raw[raw$Model==model & raw$Scenario==scenario,]) > 0) { + output[[scenario]][[model]] <- .return_magpie(raw[raw$Model==model & raw$Scenario==scenario,],scenario,model) + if(!as.list) getNames(output[[scenario]][[model]]) <- paste(scenario,model,getNames(output[[scenario]][[model]]),sep=".") + } + } + } + return(output) + } + + #expand wildcards + file_name_unexpanded <- file + file <- Sys.glob(file) + if(length(file)>1) { + output <- NULL + for(f in file) { + output <- c(output,.readmif(f)) + } + } else if(length(file)==0) { + stop("File ",file_name_unexpanded," could not be found!") + } else { + output <- .readmif(file) + } + + if(!as.list) { + output <- mbind(unlist(output,recursive=FALSE)) + names(dimnames(output))[3] <- "scenario.model.variable" + } + return(output) +} + + + + + + + + + + + + + diff --git a/R/remind2magpie.R b/R/remind2magpie.R new file mode 100644 index 00000000..1518af92 --- /dev/null +++ b/R/remind2magpie.R @@ -0,0 +1,32 @@ +#' Remind2MAgPIE +#' +#' Converts a MAgPIE object with Remind regions to a MAgPIE object with MAgPIE +#' regions +#' +#' +#' @param x MAgPIE object with Remind regions +#' @return MAgPIE object with MAgPIE regions +#' @author Florian Humpenoeder +#' @seealso \code{"\linkS4class{magpie}"} +#' @examples +#' +#' \dontrun{a <- remind2magpie(remind_c_prices)} +#' +#' @export remind2magpie +remind2magpie <- function(x) { + #MAgPIE regions + reg <- c("AFR.1", "CPA.2", "EUR.3", "FSU.4", "LAM.5", "MEA.6", "NAM.7", "PAO.8", "PAS.9", "SAS.10") + if(!is.magpie(x)) stop("input is not a MAgPIE object!") + x2 <- new.magpie(cells_and_regions=reg,years=getYears(x),names=getNames(x)) + x2["AFR",,] <- x["AFR",,] + x2["CPA",,] <- x["CHN",,] + x2["EUR",,] <- x["EUR",,] + x2["FSU",,] <- x["RUS",,] + x2["LAM",,] <- x["LAM",,] + x2["MEA",,] <- x["MEA",,] + x2["NAM",,] <- x["USA",,] + x2["PAO",,] <- x["ROW",,] + x2["PAS",,] <- x["OAS",,] + x2["SAS",,] <- x["IND",,] + return(x2) +} diff --git a/R/round-method.R b/R/round-method.R new file mode 100644 index 00000000..629253fb --- /dev/null +++ b/R/round-method.R @@ -0,0 +1,27 @@ +#' Round-method for MAgPIE objects +#' +#' Round-method for MAgPIE-objects respectively. Works exactly as for arrays. +#' +#' +#' @name round-methods +#' @aliases round-methods round,magpie-method +#' @param x a magpie object +#' @param digits integer indicating the number of decimal places (round) or significant +#' digits (signif) to be used. Negative values are allowed. +#' @docType methods +#' @section Methods: \describe{ +#' +#' \item{x = "magpie"}{ works as round(x) for arrays. } +#' +#' } +#' @exportMethod round + + +setMethod("round", + signature(x = "magpie"), + function (x, digits=0) + { + x@.Data <- round(x@.Data,digits=digits) + return(x) + } +) \ No newline at end of file diff --git a/R/rowMeans-method.R b/R/rowMeans-method.R new file mode 100644 index 00000000..770f79ec --- /dev/null +++ b/R/rowMeans-method.R @@ -0,0 +1,10 @@ +#' @exportMethod rowMeans +#' +setMethod("rowMeans", + signature(x = "magpie"), + function (x, na.rm = FALSE, dims = 1, ...) + { + x <- rowMeans(as.array(x), na.rm=na.rm, dims=dims, ...) + return(as.magpie(as.array(x))) + } + ) \ No newline at end of file diff --git a/R/rowSums-method.R b/R/rowSums-method.R new file mode 100644 index 00000000..4ad3777f --- /dev/null +++ b/R/rowSums-method.R @@ -0,0 +1,31 @@ +#' ~~ Methods for Function rowSums and rowMeans ~~ +#' +#' ~~ Methods for function \code{rowSums} and \code{rowMeans}~~ +#' +#' +#' @name rowSums-methods +#' @aliases rowSums-methods rowSums,ANY-method rowSums,magpie-method +#' rowMeans-methods rowMeans,ANY-method rowMeans,magpie-method +#' @param x object on which calculation should be performed +#' @param na.rm logical. Should missing values (including NaN) be omitted from the calculations? +#' @param dims integer: Which dimensions are regarded as "rows" or "columns" to sum over. For row*, +#' the sum or mean is over dimensions dims+1, ...; for col* it is over dimensions 1:dims. +#' @param ... further arguments passed to other colSums/colMeans methods +#' @docType methods +#' @section Methods: \describe{ +#' +#' \item{list("signature(x = \"ANY\")")}{ normal rowSums and rowMeans method } +#' +#' \item{list("signature(x = \"magpie\")")}{ classical method prepared to +#' handle MAgPIE objects } } +#' @keywords methods ~~ other possible keyword(s) ~~ +#' @exportMethod rowSums + +setMethod("rowSums", + signature(x = "magpie"), + function (x, na.rm = FALSE, dims = 1, ...) + { + x <- rowSums(as.array(x), na.rm=na.rm, dims=dims, ...) + return(as.magpie(as.array(x),spatial=1)) + } + ) \ No newline at end of file diff --git a/R/setCells.R b/R/setCells.R new file mode 100644 index 00000000..89c7b889 --- /dev/null +++ b/R/setCells.R @@ -0,0 +1,6 @@ +#' @describeIn getCells set cell names +#' @export +setCells <- function(object,nm="GLO.1") { + getCells(object) <- nm + return(object) +} \ No newline at end of file diff --git a/R/setComment.R b/R/setComment.R new file mode 100644 index 00000000..3d00455b --- /dev/null +++ b/R/setComment.R @@ -0,0 +1,6 @@ +#' @describeIn getComment set comment +#' @export +setComment <- function(object,nm=NULL) { + getComment(object) <- nm + return(object) +} \ No newline at end of file diff --git a/R/setNames_method.R b/R/setNames_method.R new file mode 100644 index 00000000..b7e74e60 --- /dev/null +++ b/R/setNames_method.R @@ -0,0 +1,32 @@ +#' Get dataset names +#' +#' Extracts dataset names of a MAgPIE-object +#' +#' setNames is a shortcut to use a MAgPIE object with manipulated data names. +#' The setNames method uses the variable names "object" and "nm" in order to be +#' consistent to the already existing function setNames. +#' +#' @name setNames-methods +#' @aliases setNames setNames,magpie-method +#' setNames,NULL-method +#' @param object MAgPIE object +#' @param nm a vector of names current names should be replaced with. If +#' only one data element exists you can also set the name to NULL. +#' @docType methods +#' @section Methods: \describe{ +#' +#' \item{list("signature(object = \"ANY\")")}{ normal setNames method } +#' +#' \item{list("signature(object = \"magpie\")")}{ setNames for MAgPIE objects} } +#' @seealso \code{\link{getNames}}, +#' @keywords methods +#' @exportMethod setNames + +setMethod("setNames", + signature(object = "magpie"), + function (object, nm) + { + getNames(object) <- nm + return(object) + } +) diff --git a/R/setYears.R b/R/setYears.R new file mode 100644 index 00000000..e2d10121 --- /dev/null +++ b/R/setYears.R @@ -0,0 +1,6 @@ +#' @describeIn getYears set years +#' @export +setYears <- function(object,nm=NULL) { + getYears(object) <- nm + return(object) +} \ No newline at end of file diff --git a/R/sysdata.R b/R/sysdata.R new file mode 100644 index 00000000..15cec785 --- /dev/null +++ b/R/sysdata.R @@ -0,0 +1,9 @@ +#' magclassdata +#' +#' General magclass-dataset +#' +#' Please do not directly access that data. It should be only used by library +#' functions. +#' @name magclassdata +#' @author Jan Philipp Dietrich +NULL \ No newline at end of file diff --git a/R/sysdata.rda b/R/sysdata.rda new file mode 100644 index 00000000..89ac06c9 Binary files /dev/null and b/R/sysdata.rda differ diff --git a/R/tail.magpie.R b/R/tail.magpie.R new file mode 100644 index 00000000..ed6f2270 --- /dev/null +++ b/R/tail.magpie.R @@ -0,0 +1,8 @@ +#' @importFrom utils tail +#' @export +tail.magpie <- function(x, n1=3L, n2=6L, n3=2L, ...) { + if(dim(x)[1]1) { + t <- .collapsecol(x,which(colnames(x) %in% temporal),sep) + } else if(sum(colnames(x) %in% temporal)==1) { + t <- x[,which(colnames(x) %in% temporal),drop=FALSE] + } else { + t <- data.frame(year=rep("NOTIME",dim(x)[1])) + } + t[[1]] <- as.character(t[[1]]) + + if(sum(colnames(x) %in% spatial)>1) { + s <- .collapsecol(x,which(colnames(x) %in% spatial),sep) + } else if(sum(colnames(x) %in% spatial)==1) { + s <- x[,which(colnames(x) %in% spatial),drop=FALSE] + } else { + s <- data.frame(region=rep("GLO",dim(x)[1])) + } + s[[1]] <- as.character(s[[1]]) + + if(sum(!(colnames(x)[-dim(x)[2]] %in% c(temporal,spatial)))>1) { + d <- .collapsecol(x,which(!(colnames(x)[-dim(x)[2]] %in% c(temporal,spatial))),sep) + } else if(sum(!(colnames(x)[-dim(x)[2]] %in% c(temporal,spatial)))==1) { + d <- x[,which(!(colnames(x)[-dim(x)[2]] %in% c(temporal,spatial))),drop=FALSE] + } else { + d <- data.frame(data=rep("NODATA",dim(x)[1])) + } + d[[1]] <- as.character(d[[1]]) + + u_spat <- as.character(unique(s[,1])) + u_temp <- as.character(unique(t[,1])) + u_data <- as.character(unique(d[,1])) + dimnames <- list(u_spat,u_temp,u_data) + m <- array(dim=c(length(u_spat),length(u_temp),length(u_data)),dimnames=dimnames) + coord <- as.matrix(cbind(s,t,d)) + .duplicates_check(coord) + m[coord] <- x[,dim(x)[2]] + if(dim(m)[2]==1) if(dimnames(m)[[2]]=="NOTIME") dimnames(m) <- list(dimnames(m)[[1]],NULL,dimnames(m)[[3]]) + if(dim(m)[3]==1) if(dimnames(m)[[3]]=="NODATA") dimnames(m) <- list(dimnames(m)[[1]],dimnames(m)[[2]],NULL) + + names(dimnames(m)) <- c(names(s),names(t),names(d)) + m <- as.magpie(m,spatial=1,temporal=2) + return(copy.attributes(x,m)) +} \ No newline at end of file diff --git a/R/time_interpolate.R b/R/time_interpolate.R new file mode 100644 index 00000000..c9e7871a --- /dev/null +++ b/R/time_interpolate.R @@ -0,0 +1,96 @@ +#' time_interpolate +#' +#' Function to extrapolate missing years in MAgPIE objects. +#' +#' +#' @param dataset An MAgPIE object +#' @param interpolated_year Vector of years, of which values are required. Can +#' be in the formats 1999 or y1999. +#' @param integrate_interpolated_years FALSE returns only the dataset of the +#' interpolated year, TRUE returns the whole dataset, including all years of +#' data and the itnerpolated year +#' @param extrapolation_type Determines what happens if extrapolation is +#' required, i.e. if a requested year lies outside the range of years in +#' \code{dataset}. Specify "linear" for a linear extrapolation. "constant" uses +#' the value from dataset closest in time to the requested year. +#' @return Uses linear extrapolation to estimate the values of the interpolated +#' year, using the values of the two surrounding years. If the value is before +#' or after the years in data, the two closest neighbours are used for +#' extrapolation. +#' @author Benjamin Bodirsky, Jan Philipp Dietrich +#' @seealso \code{\link{lin.convergence}} +#' @examples +#' +#' data(population_magpie) +#' time_interpolate(population_magpie,"y2000",integrate=TRUE) +#' time_interpolate(population_magpie,c("y1980","y2000"),integrate=TRUE,extrapolation_type="constant") +#' +#' @export time_interpolate +time_interpolate <- function(dataset, interpolated_year, integrate_interpolated_years=FALSE,extrapolation_type="linear") { + if(!is.magpie(dataset)){stop("Invalid Data format of measured data. Has to be a MAgPIE-object.")} + if (all(isYear(interpolated_year,with_y=FALSE))) { interpolated_year<-paste("y",interpolated_year,sep="")} else + { if (any(isYear(interpolated_year, with_y=TRUE))==FALSE) {stop("year not in the right format")} } + + if(nyears(dataset)==1) { + tmp <- dataset + dimnames(tmp)[[2]] <- "y0000" + dataset <- mbind(tmp,dataset) + } + + interpolated_year_filtered <- interpolated_year[!interpolated_year%in%getYears(dataset)] + dataset_interpolated <- array(NA, + dim=c(dim(dataset)[1],length(interpolated_year_filtered),dim(dataset)[3]), + dimnames=list(getCells(dataset),interpolated_year_filtered,getNames(dataset)) + ) + dataset<-as.array(dataset) + + + for(single_interpolated_year in interpolated_year_filtered) { + sorted_years <- sort(c(dimnames(dataset)[[2]],single_interpolated_year)) + if (sorted_years[1]==single_interpolated_year) + { + year_before <-sorted_years[2] + year_after <-sorted_years[3] + year_extrapolate<-ifelse(extrapolation_type=="constant",sorted_years[2],-1) + } else if (sorted_years[length(sorted_years)]==single_interpolated_year){ + year_before <-sorted_years[length(sorted_years)-2] + year_after <-sorted_years[length(sorted_years)-1] + year_extrapolate<-ifelse(extrapolation_type=="constant",sorted_years[length(sorted_years)-1],-1) + } else{ + year_before<-sorted_years[which(sorted_years==single_interpolated_year)-1] + year_after<-sorted_years[which(sorted_years==single_interpolated_year)+1] + year_extrapolate<- -1 + } + + interpolated_year_int <- as.integer(substring(single_interpolated_year,2)) + year_before_int <- as.integer(substring(year_before,2)) + year_after_int <- as.integer(substring(year_after,2)) + + dataset_difference <- dataset[,year_after,,drop=FALSE] - dataset[,year_before,,drop=FALSE] + year_before_to_after <- year_after_int - year_before_int + year_before_to_interpolated <- interpolated_year_int - year_before_int + + + if(year_extrapolate== -1){ + dataset_interpolated[,single_interpolated_year,] <- dataset[,year_before,,drop=FALSE]+ year_before_to_interpolated * dataset_difference / year_before_to_after + } else { + dataset_interpolated[,single_interpolated_year,] <- dataset[,year_extrapolate,,drop=FALSE] + } + } + if(integrate_interpolated_years==FALSE) { + add_years <- setdiff(interpolated_year,interpolated_year_filtered) + if(length(add_years)>0){ + dataset <- abind::abind(dataset_interpolated,dataset[,add_years,,drop=FALSE],along=2) + } else { + dataset <- dataset_interpolated + } + } else { + if (any(getYears(dataset)=="y0000")){ + dataset <- dataset[,-which(getYears(dataset)=="y0000"),,drop=FALSE] + } + dataset<-abind::abind(dataset,dataset_interpolated,along=2) + } + dataset <- as.magpie(dataset) + dataset <- dataset[,sort(getYears(dataset)),] + return(dataset) +} diff --git a/R/unwrap.R b/R/unwrap.R new file mode 100644 index 00000000..ae930547 --- /dev/null +++ b/R/unwrap.R @@ -0,0 +1,30 @@ +#' Unwrap +#' +#' Reconstruct the full dimensionality of a MAgPIE object +#' +#' +#' @param x A MAgPIE object +#' @param sep A character separating joined dimension names +#' @return An array with the full dimensionality of the original data +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{wrap}},\code{\link{fulldim}} +#' @examples +#' +#' a <- as.magpie(array(1:6,c(3,2),list(c("bla","blub","ble"),c("up","down")))) +#' fulldim(a) +#' unwrap(a) +#' +#' @export unwrap +unwrap <- function(x,sep=".") { + if(!is.magpie(x)) stop("Input is not a MAgPIE object. unwrap works only for MAgPIE objects") + dim <- fulldim(x,sep) + if(any(duplicated(getNames(x)))) stop("Malformed MAgPIE object. Duplictaed names detected!") + if(prod(dim[[1]])!=prod(dim(x))) stop("Malformed MAgPIE object. Different number of entries in original and unwrapped object! (prod(dim(in))!=prod(dim(out)))") + reorder <- dimnames(wrap(array(NA,dim[[1]],dim[[2]]),list(1,2,NA),sep=sep))[[3]] + if(!is.null(reorder)) x <- x[,,reorder] + return(array(as.vector(x),dim[[1]],dim[[2]])) +} + + + + diff --git a/R/where.R b/R/where.R new file mode 100644 index 00000000..2bf7a820 --- /dev/null +++ b/R/where.R @@ -0,0 +1,73 @@ +#' where +#' +#' Analysis function for magpie objects +#' +#' +#' @param x A logical statement with a magpie object +#' @param plot depreciated. Use the function whereplot in package luplot. +#' @return A list of analysis parameters +#' @author Benjamin Leon Bodirsky +#' @seealso whereplot in package luplot +#' @examples +#' +#' data(population_magpie) +#' test<-population_magpie +#' dimnames(test)[[1]]<-c("AFG","DEU","FRA","EGY","IND","IDN","RUS","CHN","USA","YEM") +#' where(test>500) +#' +#' @export where +where<-function(x, plot=NULL){ + if(!is.null(plot)){warning("Argument plot is depreciated. Use whereplot() for plot=T and where() for plot=F.")} + + if(is.null(getNames(x)[[1]])) {getNames(x)<-"dummy"} + + analysis<-list() + + tmp<-which(x==TRUE,arr.ind = TRUE) + tmp[,1]<-getRegions(x)[as.numeric(tmp[,1])] + tmp[,2]<-getYears(x)[as.numeric(tmp[,2])] + tmp[,3]<-getNames(x)[as.numeric(tmp[,3])] + analysis$true$individual<-tmp + + tmp<-which(x==FALSE,arr.ind = TRUE) + tmp[,1]<-getRegions(x)[as.numeric(tmp[,1])] + tmp[,2]<-getYears(x)[as.numeric(tmp[,2])] + tmp[,3]<-getNames(x)[as.numeric(tmp[,3])] + analysis$false$individual<-tmp + + tmp<-which(is.na(x),arr.ind = TRUE) + tmp[,1]<-getRegions(x)[as.numeric(tmp[,1])] + tmp[,2]<-getYears(x)[as.numeric(tmp[,2])] + tmp[,3]<-getNames(x)[as.numeric(tmp[,3])] + analysis$na$individual<-tmp + + tmp<-as.magpie(apply(x,MARGIN=1,FUN=function(x){any(x==FALSE,na.rm=TRUE)})*1) + analysis$false$regions<-dimnames(tmp)[[1]][tmp==1] + + tmp<-as.magpie(apply(x,MARGIN=2,FUN=function(x){any(x==FALSE,na.rm=TRUE)})*1) + analysis$false$years<-getYears(tmp)[tmp==1] + + tmp<-as.magpie(apply(x,MARGIN=1,FUN=function(x){any(is.na(x),na.rm=TRUE)})*1) + analysis$na$regions<-dimnames(tmp)[[1]][tmp==1] + + tmp<-as.magpie(apply(x,MARGIN=2,FUN=function(x){any(is.na(x),na.rm=TRUE)})*1) + analysis$na$years<-getYears(tmp)[tmp==1] + + tmp<-as.magpie(apply(x,MARGIN=1,FUN=function(x){any(x==TRUE,na.rm=TRUE)})*1) + analysis$true$regions<-dimnames(tmp)[[1]][tmp==1] + + tmp<-as.magpie(apply(x,MARGIN=2,FUN=function(x){any(x==TRUE,na.rm=TRUE)})*1) + analysis$true$years<-getYears(tmp)[tmp==1] + + # check how many T, F, NAs and NANs- + + tmp=c(sum((x==TRUE)*1,na.rm = TRUE),sum((x==FALSE)*1,na.rm = TRUE),sum(is.na(x)*1,na.rm = TRUE)) + other=length(x)-sum(tmp) + if(other!=0){warning("function is made to analyse logical statements. Your values contain values that are not 1/0/NA")} + tmp=c(tmp,other) + names(tmp)=c("TRUE","FALSE","NA","other") + analysis$summary<-tmp + + + return(analysis) +} diff --git a/R/wrap.R b/R/wrap.R new file mode 100644 index 00000000..6a9df1e6 --- /dev/null +++ b/R/wrap.R @@ -0,0 +1,90 @@ +#' Wrap +#' +#' Reshape an array or a matrix by permuting and/or joining dimensions. +#' +#' +#' @param x An array +#' @param map A list of length equal to the number of dimensions in the +#' reshaped array. Each element should be an integer vectors specifying the +#' dimensions to be joined in corresponding new dimension. One element may +#' equal NA to indicate that that dimension should be a join of all +#' non-specified (remaining) dimensions. Default is to wrap everything into a +#' vector. +#' @param sep A character separating joined dimension names +#' @note This function is extracted from the R.utils library which is licensed +#' under LGPL>=2.1 and written by Henrik Bengtsson. +#' @author Henrik Bengtsson, Jan Philipp Dietrich +#' @seealso \code{\link{unwrap}},\code{\link{fulldim}} +#' @export wrap +wrap <- function (x, map = list(NA), sep = ".") { + if (!is.array(x) && !is.matrix(x)) + stop("Argument 'x' is not an array or a matrix: ", class(x)[1]) + if (!is.list(map)) + stop("Argument 'map' is not a list: ", class(map)[1]) + umap <- unlist(map) + if (any(duplicated(umap))) { + stop("Argument 'map' contains duplicated dimension indices: ", + paste(umap[duplicated(umap)], collapse = ", ")) + } + dim <- dim(x) + ndims <- length(dim) + missingDims <- setdiff(1:ndims, umap) + if (length(missingDims) > 0) { + wildcard <- is.na(map) + if (any(wildcard)) { + map[[which(wildcard)]] <- missingDims + umap <- unlist(map) + } + else { + stop("Argument 'map' miss some dimensions: ", paste(missingDims, + collapse = ", ")) + } + } + falseDims <- setdiff(umap, 1:ndims) + if (length(falseDims) > 0) { + stop("Argument 'map' contains non-existing dimensions: ", + paste(falseDims, collapse = ", ")) + } + if (any(diff(umap) < 0)) { + perm <- umap + x <- aperm(x, perm = perm) + map <- lapply(map, FUN = function(ii) match(ii, perm)) + } + dim <- dim(x) + dim2 <- lapply(map, FUN = function(ii) prod(dim[ii])) + dimnames <- dimnames(x) + + tmp_dn<-function(map,dimnames) { + dimnames2 <- list() + nn <- NULL + for(dim in 1:length(map)){ + names<-NULL + for (ii in map[[dim]]) { + if (is.null(names)) { + names <- dimnames[[ii]] + name_names<-names(dimnames)[ii] + } + else { + names <- paste(names, rep(dimnames[[ii]], each = length(names)), + sep = sep) + name_names<-paste(name_names,names(dimnames)[ii],sep=sep) + } + } + dimnames2[[dim]]<-names + nn <- c(nn, name_names) + } + #Trick to set names even for NULL entries + dimnames2[[dim+1]] <- "fake" + names(dimnames2) <- c(nn,"fake") + dimnames2[[dim+1]] <- NULL + return(dimnames2) + } + + dim(x) <- dim2 + dimnames <- tmp_dn(map,dimnames) + if(any(dim(x)==0)) { + dimnames[dim(x)==0] <- NULL + } + dimnames(x) <- dimnames + return(x) +} diff --git a/R/write.magpie.R b/R/write.magpie.R new file mode 100644 index 00000000..7a97ae50 --- /dev/null +++ b/R/write.magpie.R @@ -0,0 +1,358 @@ +#' Write MAgPIE-object to file +#' +#' Writes a MAgPIE-3D-array (cells,years,datacolumn) to a file in one of three +#' MAgPIE formats (standard, "magpie", "magpie zipped") +#' +#' This function can write 9 different MAgPIE file\_types. "cs2" is the new +#' standard format for cellular data with or without header and the first +#' columns (year,regiospatial) or only (regiospatial), "csv" is the standard +#' format for regional data with or without header and the first columns +#' (year,region,cellnumber) or only (region,cellnumber), "cs3" is another csv +#' format which is specifically designed for multidimensional data for usage in +#' GAMS. All these variants are written without further specification. +#' "magpie" (.m) and "magpie zipped" (.mz) are new formats developed to allow a +#' less storage intensive management of MAgPIE-data. The only difference +#' between both formats is that .mz is gzipped whereas .m is not compressed. So +#' .mz needs less memory, whereas .m might have a higher compatibility to other +#' languages. "asc" is the ASCII grid format. "nc" is the netCDF format. It +#' can only be applied for half degree data and writes one file per year per +#' data column. In the case that more than one year and data column is supplied +#' several files are written with the structure filename_year_datacolumn.asc +#' +#' @param x MAgPIE-object +#' @param file_name file name including file ending (wildcards are supported). +#' Optionally also the full path can be specified here (instead of splitting it +#' to file\_name and file\_folder) +#' @param file_folder folder the file should be written to (alternatively you +#' can also specify the full path in file\_name - wildcards are supported) +#' @param file_type Format the data should be stored as. Currently 11 formats +#' are available: "cs2" (cellular standard MAgPIE format), "csv" (regional +#' standard MAgPIE format), "cs3" (Format for multidimensional MAgPIE data, +#' compatible to GAMS), "cs4" (alternative multidimensional format compatible +#' to GAMS, in contrast to cs3 it can also handle sparse data), "csvr", "cs2r", +#' "cs3r" and "cs4r" which are the same formats as the previous mentioned ones +#' with the only difference that they have a REMIND compatible format, "m" +#' (binary MAgPIE format "magpie"), "mz" (compressed binary MAgPIE format +#' "magpie zipped"), "asc" (ASCII grid format / only available for 0.5deg data) +#' and "nc" (netCDF format / only available for 0.5deg data). If +#' file\_type=NULL the file ending of the file\_name is used as format. If +#' format is different to the formats mentioned standard MAgPIE format is +#' assumed. Please be aware that the file\_name is independent of the +#' file\_type you choose here, so no additional file ending will be added! +#' @param append Decides whether an existing file should be overwritten (FALSE) +#' or the data should be added to it (TRUE). Append = TRUE only works if the +#' existing data can be combined with the new data using the mbind function +#' @param comment Vector of strings: Optional comment giving additional +#' information about the data. If different to NULL this will overwrite the +#' content of attr(x,"comment") +#' @param comment.char character: a character vector of length one containing a +#' single character or an empty string. Use "" to turn off the interpretation +#' of comments altogether. +#' @param mode File permissions the file should be written with as 3-digit +#' number (e.g. "777" means full access for user, group and all, "750" means +#' full access for user, read access for group and no acess for anybody else). +#' Set to NULL system defaults will be used. Access codes are identical to the +#' codes used in unix function chmod. +#' @param nc_compression Only used if file\_type="nc". Sets the compression +#' level for netCDF files (default is 9). If set to an integer between 1 (least +#' compression) and 9 (most compression), the netCDF file is written in netCDF +#' version 4 format. If set to NA, the netCDF file is written in netCDF version +#' 3 format. +#' @note +#' +#' The binary MAgPIE formats .m and .mz have the following content/structure +#' (you only have to care for that if you want to implement +#' read.magpie/write.magpie functions in other languages): \cr \cr +#' [ FileFormatVersion | Current file format version number (currently 2) | integer | 2 Byte ] \cr +#' [ nchar_comment | Number of characters of the file comment | integer | 4 Byte ] \cr +#' [ nchar_sets | Number of characters of all regionnames + 2 delimiter | integer | 2 Byte] \cr +#' [ not used | Bytes reserved for later file format improvements | integer | 92 Byte ] \cr +#' [ nyears | Number of years | integer | 2 Byte ]\cr +#' [ year_list | All years of the dataset (0, if year is not present) | integer | 2*nyears Byte ] \cr +#' [ nregions | Number of regions | integer | 2 Byte ] \cr +#' [ nchar_reg | Number of characters of all regionnames + (nreg-1) for delimiters | integer | 2 Byte ] \cr +#' [ regions | Regionnames saved as reg1\\nreg2 (\\n is the delimiter) | character | 1*nchar_reg Byte ] \cr +#' [ cpr | Cells per region | integer | 4*nreg Byte ] \cr +#' [ nelem | Total number of data elements | integer | 4 Byte ] \cr +#' [ nchar_data | Number of char. of all datanames + (ndata - 1) for delimiters | integer | 4 Byte ] \cr +#' [ datanames | Names saved in the format data1\\ndata2 (\\n as del.) | character | 1*nchar_data Byte ] \cr +#' [ data | Data of the MAgPIE array in vectorized form | numeric | 4*nelem Byte ] \cr +#' [ comment | Comment with additional information about the data | character | 1*nchar_comment Byte ] \cr +#' [ sets | Set names with \\n as delimiter | character | 1*nchar_sets Byte] \cr +#' +#' Please note that if your data in the spatial dimension is not ordered by +#' region name each new appearance of a region which already appeared before +#' will be treated and counted as a new region (e.g. +#' AFR.1,AFR.2,CPA.3,CPA.4,AFR.5 will count AFR twice and nregions will be set +#' to 3!). +#' @author Jan Philipp Dietrich +#' @seealso \code{"\linkS4class{magpie}"}, +#' \code{\link{read.magpie}},\code{\link{mbind}} +#' @examples +#' +#' # a <- read.magpie("lpj_yield_ir.csv") +#' # write.magpie(a,"lpj_yield_ir.mz") +#' +#' @export write.magpie +#' @importFrom utils setTxtProgressBar txtProgressBar write.csv write.table +write.magpie <- function(x,file_name,file_folder="",file_type=NULL,append=FALSE,comment=NULL,comment.char="*",mode=NULL,nc_compression=9) { + if(!is.null(mode)) { + umask <- Sys.umask() + umask_mode <- as.character(777-as.integer(mode)) + Sys.umask(umask_mode) + } + if(is.null(x)) x <- as.magpie(numeric(0)) + if(is.magpie(x)) { + years <- !(is.null(dimnames(x)[[2]])) + + #if file-type is not mentioned file-ending is used as file-type + if(is.null(file_type)) { + file_type <- tail(strsplit(file_name,'\\.')[[1]],1) + } + if(!file_folder==""){ + file_path <- paste(file_folder,file_name,sep="/") + } + else{ + file_path <- file_name + } + + #look for comment/addtitional information + if(is.null(comment) & !is.null(attr(x,"comment"))) comment <- attr(x,"comment") + if(is.null(comment)) comment <- "" + + #expand wildcards + file_path <- paste(Sys.glob(dirname(file_path)),basename(file_path),sep="/") + if(length(file_path)>1) { + file_path <- file_path[1] + warning("file name is ambiguous, only first alternative is used!") + } + + if(append & file.exists(file_path)) { + x2 <- read.magpie(file_path) + x <- mbind(x2,x) + } + + if(file_type=="m" | file_type=="mz") { + fformat_version <- "2" #File format version 1 (older data has version 0) + comment <- paste(comment,collapse="\n") + ncells <- dim(x)[1] + nyears <- dim(x)[2] + ndata <- dim(x)[3] + rle <- rle(gsub("\\..*$","",dimnames(x)[[1]])) + regions <- rle$values + cpr <- rle$lengths + nregions <- length(regions) + regions_collapsed <- paste(regions,collapse='\n') + datanames <- dimnames(x)[[3]] + datanames_collapsed <- paste(datanames,collapse='\n') + sets_collapsed <- paste(getSets(x,fulldim = FALSE), collapse = '\n') + + if(years) { + year_list <- as.integer(substr(dimnames(x)[[2]],2,5)) + } else { + year_list <- 0 + } + + if(file_type=="mz") { + zz <- gzfile(file_path,"wb") + } else { + zz <- file(file_path,"wb") + } + + writeBin(as.integer(fformat_version),zz,size=2) + writeBin(as.integer(nchar(comment)),zz,size=4) + writeBin(as.integer(nchar(sets_collapsed)),zz,size=2) + writeBin(as.integer(rep(0,92)),zz,size=1) #92 Byte reserved for later file format improvements + writeBin(as.integer(c(nyears,year_list,nregions,nchar(regions_collapsed))),zz,size=2) + writeChar(regions_collapsed,zz,eos=NULL) + writeBin(as.integer(c(cpr,ndata*ncells*nyears,nchar(datanames_collapsed))),zz,size=4) + if(datanames_collapsed!="") writeChar(datanames_collapsed,zz,eos=NULL) + writeBin(as.numeric(as.vector(x)),zz,size=4) + if(comment!="") writeChar(comment,zz,eos=NULL) + if(nchar(sets_collapsed)>0) writeChar(sets_collapsed,zz,eos=NULL) + close(zz) + } else if(file_type=="asc") { + coord <- magclassdata$half_deg[,c("lon","lat")] + if(dim(coord)[1]!=dim(x)[1]) stop("Wrong format! Only 0.5deg data can be written as ascii grid!") + if(any(comment!="")) warning("asc format does not support comments!") + for(y in 1:nyears(x)) { + tmp_file <- ifelse(nyears(x)>1,sub("(\\.[^\\.]*)$",paste("_",getYears(x)[y],"\\1",sep=""),file_path),file_path) + for(d in 1:ndata(x)) { + tmp2_file <- ifelse(ndata(x)>1,sub("(\\.[^\\.]*)$",paste("_",getNames(x)[d],"\\1",sep=""),tmp_file),tmp_file) + data <- as.data.frame(as.vector((x[,y,d]))) + grid <- suppressWarnings(sp::SpatialPixelsDataFrame(points = coord[c("lon", "lat")], data = data)) + sp::write.asciigrid(grid,tmp2_file) + } + } + } else if(file_type=="nc") { + if (is.null(getNames(x)) | is.null(getYears(x))) stop("Year and Data name are necessary for saving to NetCDF format") + mag <- as.array(x) + + #coord from magclass data + coord <- magclassdata$half_deg[,c("lon","lat")] + + # netcdf generation #### + NODATA <- NA + + # 4D array: lon, lat, time, data + lon <- seq(-179.75,179.75,by=0.5) + lat <- seq(-89.75,89.75,by=0.5) + time <- as.numeric(unlist(lapply(strsplit(dimnames(mag)[[2]],"y"),function(mag) mag[2]))) + data <- dimnames(mag)[[3]] + + #Convert magpie data to array; coord is used for mapping cells in mag to coordinates in netcdf + cat("Converting MAgPIE Data to 720 x 360 array") + netcdf <- array(NODATA,dim=c(720,360,dim(mag)[2],dim(mag)[3]),dimnames=list(lon,lat,time,data)) + pb <- txtProgressBar(min = 0, max = dim(mag)[1], style = 3) + for (i in 1:ncells(mag)) { + netcdf[which(coord[i, 1]==lon), which(coord[i,2]==lat),,] <- mag[i,,,drop=FALSE] + setTxtProgressBar(pb, i) + } + close(pb) + + # NC file dimensions + dim_lon <- ncdf4::ncdim_def("lon","degrees_east",lon) + dim_lat <- ncdf4::ncdim_def("lat","degrees_north",lat) + dim_time <- ncdf4::ncdim_def("time","years",time,calendar = "standard") + + #Define variables + ncv <- list() + for (i in dimnames(netcdf)[[4]]) ncv[[i]] <- ncdf4::ncvar_def(i, comment, list(dim_lon,dim_lat,dim_time), NODATA, prec="double",compression=nc_compression) + + #Create file + if (file.exists(file_path)) file.remove(file_path) + ncf <- ncdf4::nc_create(file_path, ncv) + + #Put data into file + cat("Saving to NetCDF format") + pb <- txtProgressBar(min = 0, max = dim(netcdf)[4], style = 3) + for (i in dimnames(netcdf)[[4]]) { + ncdf4::ncvar_put(ncf, ncv[[i]], netcdf[,,,i]) + setTxtProgressBar(pb, which(dimnames(netcdf)[[4]] == i)) + } + close(pb) + ncdf4::nc_close(ncf) + } else if(file_type=="cs3" | file_type=="cs3r") { + if(file_type=="cs3r") dimnames(x)[[2]] <- sub("y","",dimnames(x)[[2]]) + if(dim(x)[3]!=prod(fulldim(x)[[1]][-1:-2])) stop("Input data seems to be sparse but ",file_type," does not support sparse data. Please use ",sub("3","4",file_type)," instead!") + x <- unwrap(x) + if(dim(x)[1]==1 & length(grep("GLO",dimnames(x)[[1]]))==1) { + dimnames(x)[[1]] <- "TODELETE" + } else { + if(nregions(x) == dim(x)[1]) { + dimnames(x)[[1]] <- sub("\\..*$","",dimnames(x)[[1]]) + } else { + dimnames(x)[[1]] <- sub("\\.","_",dimnames(x)[[1]]) + } + } + x <- wrap(x,map=list(NA,length(dim(x)))) + dimnames(x)[[1]] <- sub("^([^\\.]*)\\.([^\\.]*)","\\2\\.\\1",dimnames(x)[[1]]) + + dimnames(x)[[1]] <- gsub("TODELETE","",dimnames(x)[[1]]) + dimnames(x)[[1]] <- gsub("\\.\\.","\\.",dimnames(x)[[1]]) + dimnames(x)[[1]] <- gsub("^\\.","",dimnames(x)[[1]]) + dimnames(x)[[1]] <- gsub("\\.$","",dimnames(x)[[1]]) + dimnames(x)[[1]] <- gsub("\\.",",",dimnames(x)[[1]]) + + + header <- dimnames(x)[[2]] + x <- cbind(dimnames(x)[[1]],x) + dimnames(x)[[2]] <- c(gsub("[^,]*(,|$)","dummy\\1",x[1,1]),header) + zz <- file(file_path,open="w") + if(any(comment!="")) writeLines(paste(comment.char,comment,sep=""),zz) + write.csv(x,file=zz,quote=FALSE,row.names=FALSE) + close(zz) + } else if(file_type=="cs4" | file_type=="cs4r") { + print_cells <- nregions(x)1) | !is.null(getNames(x))) + + output <- as.data.frame(x) + output <- output[c("Year","Region","Cell",names(output)[-c(1:3)])] + + if(!print_cells) output["Cell"] <- NULL + if(!print_regions) output["Region"] <- NULL + if(!print_data) output["Data1"] <- NULL + if(!years) { + output["Year"] <- NULL + } else { + if(file_type=="cs4") levels(output[["Year"]]) <- paste0("y",levels(output[["Year"]])) + } + zz <- file(file_path,open="w") + if(any(comment!="")) writeLines(paste(comment.char,comment,sep=""),zz) + write.table(output,file=zz,quote=FALSE,row.names=FALSE,col.names=FALSE,sep=",") + close(zz) + + } else { + print_cells <- nregions(x)1) | !is.null(getNames(x))) + + #non-cellular data + if(!print_cells & (!print_data | !years | !print_regions )) { + if(file_type=="csvr" | file_type=="cs2r") dimnames(x)[[2]] <- sub("y","",dimnames(x)[[2]]) + if(!print_data) { + output <- array(x,dim=dim(x)[1:2],dimnames=list(dimnames(x)[[1]],dimnames(x)[[2]])) + output <- aperm(output) + if(print_regions) { + output <- rbind(substring(dimnames(x)[[1]],1,3),output) + if(years) output <- cbind(c("dummy",dimnames(x)[[2]]),output) + } else { + if(years) output <- cbind(dimnames(x)[[2]],output) + } + header <- FALSE + } else if(!years) { + output <- array(x,dim=dim(x)[c(1,3)],dimnames=list(dimnames(x)[[1]],dimnames(x)[[3]])) + header <- !is.null(dimnames(output)[[2]]) + if(print_regions) output <- cbind(substring(dimnames(x)[[1]],1,3),output) + if(header & !print_regions) { + output <- t(output) + header <- FALSE + output <- cbind(dimnames(x)[[3]],output) + } + } else { + output <- array(x,dim=dim(x)[2:3],dimnames=list(dimnames(x)[[2]],dimnames(x)[[3]])) + header <- !is.null(dimnames(output)[[2]]) + output <- cbind(dimnames(x)[[2]],output) + dimnames(output)[[2]][1] <- "dummy" + } + if(header & print_regions) dimnames(output)[[2]][1] <- "dummy" + zz <- file(file_path,open="w") + if(any(comment!="")) writeLines(paste(comment.char,comment,sep=""),zz) + write.table(output,zz,sep=",",col.names=header,row.names=FALSE,quote=FALSE) + close(zz) + } else { + if(file_type=="csvr" | file_type=="cs2r") dimnames(x)[[2]] <- sub("y","",dimnames(x)[[2]]) + if(file_type=="cs2" | file_type=="cs2r") print_regions <- FALSE + output <- array(NA,c(dim(x)[1]*dim(x)[2],dim(x)[3]+print_regions+print_cells+years)) + output[,(1+print_regions+print_cells+years):dim(output)[2]] <- as.vector(as.matrix(x)) + if(years) { + yearvec <- c() + for(year in dimnames(x)[[2]]) yearvec <- c(yearvec,rep(year,dim(x)[1])) + output[,1] <- yearvec + } + if(print_regions) output[,1+years] <- substring(rep(dimnames(x)[[1]],dim(x)[2]),1,3) + if(print_cells) { + if(file_type=="cs2" | file_type=="cs2r") { + output[,1+print_regions+years] <- rep(gsub(".","_",dimnames(x)[[1]],fixed=TRUE),dim(x)[2]) + } else { + output[,1+print_regions+years] <- rep(1:dim(x)[1],dim(x)[2]) + } + } + if(!is.null(dimnames(x)[[3]])) { + dimnames(output)[[2]] <- c(rep("dummy",print_regions+print_cells+years),dimnames(x)[[3]]) + header <- TRUE + } else { + header <- FALSE + } + zz <- file(file_path,open="w") + if(any(comment!="")) writeLines(paste(comment.char,comment,sep=""),zz) + write.table(output,zz,sep=",",col.names=header,row.names=FALSE,quote=FALSE) + close(zz) + } + } + } else { + stop("Input is not in MAgPIE-format!") + } + if(!is.null(mode)) Sys.umask(umask) +} diff --git a/R/write.report.R b/R/write.report.R new file mode 100644 index 00000000..d66bfcb1 --- /dev/null +++ b/R/write.report.R @@ -0,0 +1,166 @@ +#' Write file in report format +#' +#' This function writes the content of a MAgPIE object into a file or returns +#' it directly using the reporting format as it is used for many model +#' intercomparisons. +#' +#' +#' @param x MAgPIE object or a list of lists with MAgPIE objects as created by +#' read.report. In the latter case settings for model and scenario are +#' overwritten by the information given in the list. +#' @param file file name the object should be written to. If NULL the formatted +#' content is returned +#' @param model Name of the model which calculated the results +#' @param scenario The scenario which was used to get that results. +#' @param unit Unit of the data. Only relevant if unit is not already supplied +#' in Dimnames (format "name (unit)"). Can be either a single string or a +#' vector of strings with a length equal to the number of different data +#' elements in the MAgPIE object +#' @param ndigit Number of digits the output should have +#' @param append Logical which decides whether data should be added to an +#' existing file or an existing file should be overwritten +#' @param skipempty Determines whether empty entries (all data NA) should be +#' written to file or not. +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{read.report}} +#' @examples +#' +#' \dontrun{ +#' data(population_magpie) +#' write.report(population_magpie) +#' } +#' +#' @export write.report +#' @importFrom utils write.table +#' +write.report <- function(x,file=NULL,model="MAgPIE",scenario="default",unit=NA,ndigit=4,append=FALSE,skipempty=TRUE) { + if(is.list(x)) { + if(is.list(x[[1]])) { + for(scenario in names(x)){ + for(model in names(x[[scenario]])) { + write.report(x[[scenario]][[model]],file=file,model=model,scenario=scenario,unit=unit,ndigit=ndigit,append=append) + append <- TRUE + } + } + } else { + stop("Wrong format. x must be either a list of lists or a MAgPIE object! Only single list found!") + } + } else { + + if(!is.magpie(x)) stop("Input is not a MAgPIE object!") + dimnames(x)[[1]] <- sub("^GLO(\\.{0,1}[0-9]*)$","World\\1",dimnames(x)[[1]]) + + # If data was read in by read.report there is an attribute $dimnames$scenario.model.variable. + # This will be used below to structure the output of write.report exactly like the input. + # That means: write.report automatically recognizes models and scenarios and + # does not put it into the data-dimension + if (scenario[1] == "default" & length(scenario) == 1 & length(names(attr(x,"dimnames"))) >2) { + if (names(attr(x,"dimnames"))[[3]] == "scenario.model.variable") { + scenario <- fulldim(x)[[2]]$scenario + model <- fulldim(x)[[2]]$model + } + } + + unitdef<-unit + ii<-1 + for (mod in model) { + for (scen in scenario) { + if (length(fulldim(x)[[2]]) == 5 ) { + if (length(strsplit(getNames(x)[1],split="\\.")[[1]]) > 1 + & scen %in% unlist(lapply(strsplit(getNames(x),split="\\."),'[[',1)) + & mod %in% unlist(lapply(strsplit(getNames(x),split="\\."),'[[',2))) { + scenmod <- paste(scen,mod,sep=".") + if(!any(grepl(scenmod,getNames(x)))) { + next() + } + xtemp<-x[,,scenmod] + } else { + xtemp <- x + } + } else { + xtemp<-x + } + ndata <- ndata(xtemp) + nregions <- nregions(xtemp) + nyears <- nyears(xtemp) + regions <- getRegions(xtemp) + years <- gsub(" ",0,prettyNum(getYears(xtemp,as.integer=TRUE),width=4)) + if(length(unit)==1) { + nelem_with_brackets <- length(grep("\\(*\\)$",getNames(xtemp))) + if(nelem_with_brackets==dim(xtemp)[3]) { + tmp <- getNames(xtemp) + dimnames(xtemp)[[3]] <- sub(" ?\\([^\\(]*\\)$","",tmp) + unit <- sub("^.*\\((.*)\\)$","\\1",tmp) + } else { + if(nelem_with_brackets > 0) warning("Some but not all variable entries provide information in brackets which might be a unit information. To have it detected as unit all entries must provide this information!") + unit <- rep(unit,ndata) + } + } + + output <- matrix(NA,nregions*ndata,5+nyears) + colnames(output) <- c("Model","Scenario","Region","Variable","Unit",years) + output[,"Model"] <- mod + output[,"Scenario"] <- scen + output[,"Region"] <- rep(regions,ndata) + + for(i in 1:ndata){ + if (length(fulldim(x)[[2]]) == 5){ + if (length(strsplit(getNames(xtemp)[i],split="\\.")[[1]]) > 1 + & strsplit(getNames(xtemp)[i],split="\\.")[[1]][[1]]==scen + & strsplit(getNames(xtemp)[i],split="\\.")[[1]][[2]]==mod) { + output[(i-1)*nregions + 1:nregions,"Variable"] <- strsplit(getNames(xtemp)[i],split="\\.")[[1]][[3]] + } else { + output[(i-1)*nregions + 1:nregions,"Variable"] <- gsub(".","|",getNames(xtemp)[i],fixed=TRUE) + } + } else { + output[(i-1)*nregions + 1:nregions,"Variable"] <- gsub(".","|",getNames(xtemp)[i],fixed=TRUE) + } + output[(i-1)*nregions + 1:nregions,"Unit"] <- unit[i] + output[(i-1)*nregions + 1:nregions,5+1:nyears] <- round(xtemp[,,i],ndigit) + } + + if(skipempty) { + toskip <- which(rowSums(!is.na(output[,5+(1:nyears),drop=FALSE]))==0) + if(length(toskip)>0) output <- output[-toskip,,drop=FALSE] + } + output[is.na(output)] <- "N/A" + output[which(output=="NaN")]<-"N/A" + if(is.null(file)) { + print(output) + } else { + if(!file.exists(file)) append <- FALSE + if(ii > 1) append <-TRUE + if(append) { + #check header for consistency + header <- read.table(file, nrows = 1, sep = ";", stringsAsFactors = FALSE) + years1 <- as.numeric(header[sapply(header,is.numeric)]) + years2 <- as.numeric(colnames(output)[!is.na(suppressWarnings(as.numeric(colnames(output))))]) + union <- sort(union(years1,years2)) + addycols <- function(data,years) { + ycols <- !is.na(suppressWarnings(as.numeric(colnames(data)))) + tmp <- data[ycols] + data <- data[!ycols] + data[as.character(sort(years))] <- "N/A" + data[names(tmp)] <- tmp + return(data) + } + if(length(union)>length(years1)) { + data <- read.table(file, sep = ";", stringsAsFactors = FALSE, header = TRUE, check.names=FALSE) + data <- data[-length(data)] + write.table(addycols(data,union),file,quote=FALSE,sep=";",row.names=FALSE,col.names=TRUE,append=FALSE,eol=";\n") + } + if(length(union)>length(years2)) { + output <- addycols(as.data.frame(output),union) + } + } + write.table(output,file,quote=FALSE,sep=";",row.names=FALSE,col.names=!append,append=append,eol=";\n") + ii<-ii+1 + } + unit<-unitdef + } + } + + + + } +} diff --git a/R/write.report2.R b/R/write.report2.R new file mode 100644 index 00000000..dd330777 --- /dev/null +++ b/R/write.report2.R @@ -0,0 +1,154 @@ +#' Write file in report format +#' +#' This function writes the content of a MAgPIE object into a file or returns +#' it directly using the reporting format as it is used for many model +#' intercomparisons. It is a rewritten version of write.report and will +#' probably replace write.report somewhen in the future +#' +#' +#' @param x MAgPIE object or a list of lists with MAgPIE objects as created by +#' read.report. In the latter case settings for model and scenario are +#' overwritten by the information given in the list. +#' @param file file name the object should be written to. If NULL the formatted +#' content is returned +#' @param model Name of the model which calculated the results +#' @param scenario The scenario which was used to get that results. +#' @param unit Unit of the data. Only relevant if unit is not already supplied +#' in Dimnames (format "name (unit)"). Can be either a single string or a +#' vector of strings with a length equal to the number of different data +#' elements in the MAgPIE object +#' @param ndigit Number of digits the output should have +#' @param append Logical which decides whether data should be added to an +#' existing file or an existing file should be overwritten +#' @param skipempty Determines whether empty entries (all data NA) should be +#' written to file or not. +#' @author Jan Philipp Dietrich +#' @seealso \code{\link{read.report}} +#' @examples +#' +#' data(population_magpie) +#' write.report2(population_magpie) +#' +#' @importFrom utils write.table +#' @importFrom reshape2 dcast melt +#' @export +write.report2 <- function(x,file=NULL,model=NULL,scenario=NULL,unit=NULL,ndigit=4,append=FALSE,skipempty=TRUE) { + if(is.list(x)) { + if(is.list(x[[1]])) { + for(scenario in names(x)){ + for(model in names(x[[scenario]])) { + write.report2(x[[scenario]][[model]],file=file,model=model,scenario=scenario,unit=unit,ndigit=ndigit,append=append) + append <- TRUE + } + } + } else { + stop("Wrong format. x must be either a list of lists or a MAgPIE object! Only single list found!") + } + } else { + if(!is.magpie(x)) stop("Input is not a MAgPIE object!") + prepare_data <- function(x, model=NULL, scenario=NULL, unit=NULL, skipempty=FALSE, ndigit=4) { + sep <- "." + # clean data + x <- round(clean_magpie(x,what="sets"), digits = ndigit) + names(dimnames(x))[1] <- "Region" + dimnames(x)[[1]] <- sub("^GLO(\\.{0,1}[0-9]*)$","World\\1",dimnames(x)[[1]]) + dimnames(x)[[2]] <- substring(dimnames(x)[[2]],2) + + # convert to data frame + x <- dcast(melt(x,as.is=TRUE,na.rm = skipempty),eval(parse(text=paste0("...~",names(dimnames(x))[2])))) + + # split data and dimension information + data <- x[3:length(x)] + x <- x[1:2] + + # split subdimensions + colsplit <- function(x,col,sep=".") { + if(all(grepl(sep,x[[col]],fixed=TRUE))) { + tmp <- data.frame(t(matrix(unlist(strsplit(as.character(x[[col]]),split=sep,fixed=TRUE)),ncol=length(x[[col]]))),stringsAsFactors=FALSE) + names(tmp) <- strsplit(names(x)[col],split=sep,fixed=TRUE)[[1]] + x <- cbind(tmp,x[setdiff(1:ncol(x),col)]) + } + return(x) + } + for(i in grep(sep,names(x),fixed=TRUE)) x <- colsplit(x,i,sep=sep) + + unitsplit <- function(x,col) { + w <- grepl("\\(.*\\)",x[[col]]) + x[[col]][!w] <- paste0(x[[col]][!w]," (N/A)") + tmp <- data.frame(sub("^([^\\(]*) \\((.*)\\)$","\\1",x[[col]]), + sub("^([^\\(]*) \\((.*)\\)$","\\2",x[[col]])) + names(tmp) <- c(names(x)[col],"unit") + x <- cbind(tmp,x[setdiff(1:ncol(x),col)]) + return(x) + } + for(i in 1:length(x)) { + if(!(tolower(names(x)[i]) %in% c("scenario","model","region"))) { + if(any(grepl(" \\(.*\\)$",x[i]))) x <- unitsplit(x,i) + } + } + + correct_names <- function(x,name="Scenario", replacement=NULL) { + if(is.null(replacement)) replacement <- "N/A" + w <- which(tolower(names(x))==tolower(name)) + if(length(w)==0) { + x <- cbind(replacement,x) + } else if(length(w)==1) { + x <- cbind(x[w],x[-w]) + } else { + warning("Found ",name," more than once! First occurrence will be used") + w <- w[1] + x <- cbind(x[w],x[-w]) + } + names(x)[1] <- name + return(x) + } + + x <- correct_names(x,name="Unit", replacement=unit) + x <- correct_names(x,name="Region", replacement=NULL) + x <- correct_names(x,name="Scenario", replacement=scenario) + x <- correct_names(x,name="Model", replacement=model) + + if(length(x)==4) { + tmp <- "N/A" + } else { + tmp <- eval(parse(text=paste0("paste(",paste0("x[[",5:length(x),"]]",collapse=", "),", sep=sep)"))) + } + x <- cbind(x[1:3],Variable=tmp,x[4]) + + data[is.na(data)] <- "N/A" + + return(cbind(x,data)) + } + x <- prepare_data(x, model=model, scenario=scenario, unit=unit, skipempty = skipempty, ndigit=ndigit) + if(is.null(file)) { + print(x) + } else { + if(!file.exists(file)) append <- FALSE + if(append) { + #check header for consistency + header <- read.table(file, nrows = 1, sep = ";", stringsAsFactors = FALSE) + years1 <- as.numeric(header[sapply(header,is.numeric)]) + years2 <- as.numeric(colnames(x)[!is.na(suppressWarnings(as.numeric(colnames(x))))]) + union <- sort(union(years1,years2)) + addycols <- function(data,years) { + ycols <- !is.na(suppressWarnings(as.numeric(colnames(data)))) + tmp <- data[ycols] + data <- data[!ycols] + data[as.character(sort(years))] <- "N/A" + data[names(tmp)] <- tmp + return(data) + } + if(length(union)>length(years1)) { + data <- read.table(file, sep = ";", stringsAsFactors = FALSE, header = TRUE, check.names=FALSE) + data <- data[-length(data)] + write.table(addycols(data,union),file,quote=FALSE,sep=";",row.names=FALSE,col.names=TRUE,append=FALSE,eol=";\n") + } + if(length(union)>length(years2)) { + x <- addycols(as.data.frame(x),union) + } + } + write.table(x,file,quote=FALSE,sep=";",row.names=FALSE,col.names=!append,append=append,eol=";\n") + } + } +} + diff --git a/R/write.reportProject.R b/R/write.reportProject.R new file mode 100644 index 00000000..f92bfcb8 --- /dev/null +++ b/R/write.reportProject.R @@ -0,0 +1,77 @@ +#' Write file in specific project format +#' +#' Reads in a reporting.mif or uses a magpie object based on a read in +#' reporting.mif, substitutes names of variables according to the mappping, +#' mutliplies by an optional factor in the 3rd column of the mapping, and saves +#' the output in a new *.mif +#' +#' +#' @param mif Lists with magpie-objects or a magpie-object as created by read.report or a path to +#' a report.mif +#' @param mapping mapping of the varialbe names of the read in mif. the header +#' is used for naming. +#' @param file name of the project specipic report, default=NULL means that the names of the header of the reporting is used +#' @author Christoph Bertram, Lavinia Baumstark, Anastasis Giannousakis +#' @seealso \code{\link{write.report}} +#' @examples +#' +#' \dontrun{ +#' write.reportProject("REMIND_generic_test.mif","Mapping_generic_ADVANCE.csv") +#' } +#' +#' @export write.reportProject +#' @importFrom utils read.csv2 +#' +write.reportProject <- function(mif,mapping,file=NULL){ + if(is.character(mif)){ + data <- read.report(mif,as.list=TRUE) + } else if (is.list(mif)){ + data <- mif + } else if (is.magpie(mif)){ + scenario <- getNames(mif,dim=1) + model <- getNames(mif,dim=2) + data <- list() + for (s in scenario){ + for (m in model) { + data[[s]][[m]] <- collapseNames(mif[,,s][,,m]) + } + } + } else { + stop("please provide either a path to a mif-file, a read in mif-file (in list-structure or as a magpie object)") + } + # read in mapping of the names of variables for the project, handle NAs + map <- read.csv2(mapping,colClasses="character") + map <- sapply(X = map,FUN = function(x) gsub("N/A","NA",x,fixed = T)) + map <- as.data.frame(map,stringsAsFactors = FALSE) + + + missingc <- c() + # select variables and change names of reported variables + new_data <- list() + for (n in names(data)){ + for (m in names(data[[n]])){ + ind <- which(map[,names(map)[1]] %in% intersect(map[,names(map)[1]],getNames(data[[n]][[m]]))) + if ("factor" %in% names(map)) { + if (unique(map$factor)=="") map$factor <- 1 + new_data[[n]][[m]] <- setNames(mbind(lapply(map[ind,names(map)[1]],function(x) as.numeric(map[which(map[,names(map)[1]]==x),"factor"])*(data[[n]][[m]][,,x]))),map[ind,names(map)[2]]) + } else { + new_data[[n]][[m]] <- setNames(mbind(lapply(map[ind,names(map)[1]],function(x) (data[[n]][[m]][,,x]))),map[ind,names(map)[2]]) + } + + if (length(setdiff(map[,names(map)[1]],getNames(data[[n]][[m]]))) !=0) { + missingc <- c(missingc,setdiff(map[,names(map)[1]],getNames(data[[n]][[m]]))) + } + } + } + if (length(missingc) !=0) warning(paste0("Following variables were not found in the generic data and were excluded: \"",paste(unique(missingc),collapse = "\", \""),"\"")) + if(!is.null(file)){ + file <- file + } else { + # calculate name of new reporting + file <- gsub(names(map)[1],names(map)[2],mif) + } + # save project reporting + write.report(new_data,file=file) +} + + diff --git a/data/population_magpie.rda b/data/population_magpie.rda new file mode 100644 index 00000000..745b3002 Binary files /dev/null and b/data/population_magpie.rda differ diff --git a/magclass.Rproj b/magclass.Rproj new file mode 100644 index 00000000..bf73ff48 --- /dev/null +++ b/magclass.Rproj @@ -0,0 +1,19 @@ +Version: 1.0 + +RestoreWorkspace: Default +SaveWorkspace: Default +AlwaysSaveHistory: Default + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: Sweave +LaTeX: pdfLaTeX + +BuildType: Package +PackageUseDevtools: Yes +PackageInstallArgs: --no-multiarch --with-keep.source +PackageCheckArgs: --as-cran +PackageRoxygenize: rd,collate,namespace,vignette diff --git a/man/add_columns.Rd b/man/add_columns.Rd new file mode 100644 index 00000000..0b79a625 --- /dev/null +++ b/man/add_columns.Rd @@ -0,0 +1,36 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/add_columns.R +\name{add_columns} +\alias{add_columns} +\title{add_columns} +\usage{ +add_columns(x, addnm = c("new"), dim = 3.1) +} +\arguments{ +\item{x}{MAgPIE object which should be extended.} + +\item{addnm}{The new columns within dimension "dim"} + +\item{dim}{The number of the dimension that should be extended} +} +\value{ +The extended MAgPIE object +} +\description{ +Function adds new columns to the existing magpie object. The new columns are +filled with NAs. +} +\examples{ + + data(population_magpie) + a <- add_columns(population_magpie) + str(a) + fulldim(a) + +} +\seealso{ +\code{\link{add_dimension}},\code{\link{mbind}} +} +\author{ +Benjamin Bodirsky +} diff --git a/man/add_dimension.Rd b/man/add_dimension.Rd new file mode 100644 index 00000000..79c28cb0 --- /dev/null +++ b/man/add_dimension.Rd @@ -0,0 +1,39 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/add_dimension.R +\name{add_dimension} +\alias{add_dimension} +\title{add_dimension} +\usage{ +add_dimension(x, dim = 3.1, add = "new", nm = "dummy") +} +\arguments{ +\item{x}{MAgPIE object which should be extended.} + +\item{dim}{The dimension number of the new dimension. 4 stands for the +second name dimension.} + +\item{add}{The name of the new dimension} + +\item{nm}{The name of the first entry in dimension "add".} +} +\value{ +The extended MAgPIE object +} +\description{ +Function adds a name dimension as dimension number "dim" with the name "add" +with an empty data column with the name "nm". +} +\examples{ + + data(population_magpie) + a <- add_dimension(population_magpie) + str(a) + fulldim(a) + +} +\seealso{ +\code{\link{add_columns}},\code{\link{mbind}} +} +\author{ +Benjamin Bodirsky +} diff --git a/man/as.array-methods.Rd b/man/as.array-methods.Rd new file mode 100644 index 00000000..7b69fbf3 --- /dev/null +++ b/man/as.array-methods.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/as.array.R +\docType{methods} +\name{as.array-methods} +\alias{as.array-methods} +\alias{as.array,ANY-method} +\alias{as.array,magpie-method} +\title{~~ Methods for Function as.array ~~} +\usage{ +\S4method{as.array}{magpie}(x) +} +\arguments{ +\item{x}{object which should be converted to an array} +} +\description{ +~~ Methods for function \code{as.array} ~~ +} +\section{Methods}{ + \describe{ + +\item{list("signature(x = \"ANY\")")}{ standard as.array-method } + +\item{list("signature(x = \"magpie\")")}{ Conversion takes place just by +removing MAgPIE-object specific elements } } +} + +\keyword{methods} diff --git a/man/as.data.frame-methods.Rd b/man/as.data.frame-methods.Rd new file mode 100644 index 00000000..869e4a3f --- /dev/null +++ b/man/as.data.frame-methods.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/as.data.frame.R +\docType{methods} +\name{as.data.frame-methods} +\alias{as.data.frame-methods} +\alias{as.data.frame} +\alias{as.data.frame,ANY-method} +\alias{as.data.frame,magpie-method} +\title{~~ Methods for Function as.data.frame ~~} +\usage{ +\S4method{as.data.frame}{magpie}(x, rev = 1) +} +\arguments{ +\item{x}{A MAgPIE-object} + +\item{rev}{The revision of the algorithm that should be used for conversion. +rev=1 creates columns with the predefined names Cell, Region, Year, Data1, +Data2,... and Value, rev=2 uses the set names of the MAgPIE object for +naming and adds an attribute "dimtype" to the data.frame which contains +information about the types of the different columns (spatial, temporal, +data or value).} +} +\description{ +~~ Methods for function \code{as.data.frame} ~~ +} +\section{Methods}{ + \describe{ + +\item{list("signature(x = \"magpie\")")}{ Conversion creates columns for +Cell, Region, Year, Data1, Data2,... and Value } } +} + +\examples{ + +data(population_magpie) +head(as.data.frame(population_magpie)) +head(as.data.frame(population_magpie,rev=2)) + +} +\keyword{methods} diff --git a/man/calibrate_it.Rd b/man/calibrate_it.Rd new file mode 100644 index 00000000..ae1d4419 --- /dev/null +++ b/man/calibrate_it.Rd @@ -0,0 +1,49 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/calibrate_it.R +\name{calibrate_it} +\alias{calibrate_it} +\title{calibrate_it} +\usage{ +calibrate_it(origin, cal_to, cal_type = "convergence", cal_year = NULL, + end_year = NULL, report_calibration_factors = FALSE) +} +\arguments{ +\item{origin}{Original Values (MAgPIE object)} + +\item{cal_to}{Values to calibrate to (MAgPIE object).} + +\item{cal_type}{"none" leaves the values as they are, "convergence" starts +from the aim values and then linearily converges towards the values of +origin, "growth_rate" uses the growth-rates of origin and applies them on +aim.} + +\item{cal_year}{year on which the dataset should be calibrated.} + +\item{end_year}{only for cal_type="convergence". Year in which the +calibration shall be faded out.} + +\item{report_calibration_factors}{prints out the multipliers which are used +for calibration.} +} +\value{ +Calibrated dataset. +} +\description{ +Standardized functions to calibrate values to a certain baseyear. +} +\examples{ + + data(population_magpie) + test<-as.magpie(array(1000,dim(population_magpie[,,"A2"]),dimnames(population_magpie[,,"A2"]))) + calibrate_it(origin=population_magpie,cal_to=test[,"y1995",],cal_type="growth_rate") + calibrate_it(origin=population_magpie,cal_to=test[,"y1995",],cal_type="convergence", + cal_year="y1995", end_year="y2055") + calibrate_it(origin=population_magpie,cal_to=test[,"y1995",],cal_type="none") + +} +\seealso{ +\code{\link{convergence}},\code{\link{lin.convergence}} +} +\author{ +Benjamin Bodirsky +} diff --git a/man/clean_magpie.Rd b/man/clean_magpie.Rd new file mode 100644 index 00000000..cb512926 --- /dev/null +++ b/man/clean_magpie.Rd @@ -0,0 +1,37 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/clean_magpie.R +\name{clean_magpie} +\alias{clean_magpie} +\title{MAgPIE-Clean} +\usage{ +clean_magpie(x, what = "all") +} +\arguments{ +\item{x}{MAgPIE object which should be cleaned.} + +\item{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)} +} +\value{ +The eventually corrected MAgPIE object +} +\description{ +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) +} +\examples{ + + data(population_magpie) + a <- clean_magpie(population_magpie) + +} +\seealso{ +\code{"\linkS4class{magpie}"} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/colSums-methods.Rd b/man/colSums-methods.Rd new file mode 100644 index 00000000..937b360b --- /dev/null +++ b/man/colSums-methods.Rd @@ -0,0 +1,41 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/colSums-method.R +\docType{methods} +\name{colSums-methods} +\alias{colSums-methods} +\alias{colSums,ANY-method} +\alias{colSums,magpie-method} +\alias{colMeans-methods} +\alias{colMeans,ANY-method} +\alias{colMeans,magpie-method} +\title{~~ Methods for Function colSums and colMeans ~~} +\usage{ +\S4method{colSums}{magpie}(x, na.rm = FALSE, dims = 1, ...) +} +\arguments{ +\item{x}{object on which calculation should be performed} + +\item{na.rm}{logical. Should missing values (including NaN) be omitted from the calculations?} + +\item{dims}{integer: Which dimensions are regarded as "rows" or "columns" to sum over. For row*, +the sum or mean is over dimensions dims+1, ...; for col* it is over dimensions 1:dims.} + +\item{...}{further arguments passed to other colSums/colMeans methods} +} +\description{ +~~ Methods for function \code{colSums} and \code{colMeans} ~~ +} +\section{Methods}{ + \describe{ + +\item{list("signature(x = \"ANY\")")}{ normal colSums and colMeans method } + +\item{list("signature(x = \"magpie\")")}{ classical method prepared to +handle MAgPIE objects } } +} + +\keyword{keyword(s)} +\keyword{methods} +\keyword{other} +\keyword{possible} +\keyword{~~} diff --git a/man/collapseNames.Rd b/man/collapseNames.Rd new file mode 100644 index 00000000..efb2063b --- /dev/null +++ b/man/collapseNames.Rd @@ -0,0 +1,62 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/collapseNames.R +\name{collapseNames} +\alias{collapseNames} +\title{Collapse dataset names} +\usage{ +collapseNames(x, collapsedim = NULL) +} +\arguments{ +\item{x}{MAgPIE object} + +\item{collapsedim}{If you want to remove the names of particular dimensions +provide the dimensions here. Since the function only works in the third dimension, +you have to count from there on (e.g. dim = 3.2 refers to collapsedim = 2). Default: NULL. +CAUTION with parameter collapsedim! You could also force him to remove dimnames, +which are NOT the same for each element and so create duplicates in dimnames.} +} +\value{ +The provided MAgPIE object with collapsed names +} +\description{ +This function will remove names in the data dimension which are the same for +each element (meaning that this data dimension contains exactly one element) +} +\examples{ + + x <- new.magpie("GLO",2000,c("bla.a","bla.b")) + print(x) + # An object of class "magpie" + # , , bla.a + # y2000 + # GLO.1 NA + # , , bla.b + # y2000 + # GLO.1 NA + + print(collapseNames(x)) + # An object of class "magpie" + # , , a + # y2000 + # GLO.1 NA + # , , b + # y2000 + # GLO.1 NA + + print(collapseNames(x), collapseNames = 2) + # An object of class "magpie" + # , , bla + # y2000 + # GLO.1 NA + # , , bla + # y2000 + # GLO.1 NA + +} +\seealso{ +\code{\link{getNames}}, \code{\link{setNames}}, +\code{"\linkS4class{magpie}"} +} +\author{ +Jan Philipp Dietrich, David Klein, Xiaoxi Wang +} diff --git a/man/complete_magpie.Rd b/man/complete_magpie.Rd new file mode 100644 index 00000000..1888d92b --- /dev/null +++ b/man/complete_magpie.Rd @@ -0,0 +1,36 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/complete_magpie.R +\name{complete_magpie} +\alias{complete_magpie} +\title{complete_magpie} +\usage{ +complete_magpie(x, fill = NA) +} +\arguments{ +\item{x}{MAgPIE object which should be completed.} + +\item{fill}{Value that shall be written into the missing entries} +} +\value{ +The completed MAgPIE object +} +\description{ +MAgPIE objects can be incomplete to reduce memory. This function blows up a +magpie object to its real dimensions, so you can apply unwrap. +} +\examples{ + + data(population_magpie) + a <- complete_magpie(population_magpie) + b <- add_dimension(a) + c <- add_dimension(a,nm="dummy2") + incomplete<-mbind(b[,,1],c) + d<-complete_magpie(incomplete) + +} +\seealso{ +\code{\link{add_dimension}},\code{\link{clean_magpie}} +} +\author{ +Benjamin Bodirsky +} diff --git a/man/convergence.Rd b/man/convergence.Rd new file mode 100644 index 00000000..3fa72a9d --- /dev/null +++ b/man/convergence.Rd @@ -0,0 +1,60 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/convergence.R +\name{convergence} +\alias{convergence} +\title{convergence} +\usage{ +convergence(origin, aim, start_year = NULL, end_year = NULL, + direction = NULL, type = "smooth", par = 1.5) +} +\arguments{ +\item{origin}{an object with one name-column} + +\item{aim}{Can be twofold: An magpie object or a numeric value.} + +\item{start_year}{year in which the convergence from origin to aim starts. +If set to NULL the the first year of aim is used as start_year} + +\item{end_year}{year in which the convergence from origin to aim shall be +(nearly) reached. If set to NULL the the last year of aim is used as +end_year.} + +\item{direction}{NULL, "up" or "down". NULL means normal convergence in both +directions, "up" is only a convergence if originaim} + +\item{type}{"smooth", "s", "linear" or "decay". Describes the type of +convergence: linear means a linear conversion , s is an s-curve which starts +from origin in start_year and reaches aim precisely in end_year. After 50 +percent of the convergence time, it reaches about the middle of the two +values. Its based on the function min(1, pos^4/(0.07+pos^4)*1.07) smooth is +a conversion based on the function x^3/(0.1+x^3). In the latter case only +90\% of convergence will be reached in the end year, because full +convergence is reached in infinity. decay is a conversion based on the +function x/(1.5 + x)*2.5.} + +\item{par}{parameter value for convergence function; currently only used for +type="decay"} +} +\value{ +returns a time-series with the same timesteps as origin, which +lineary fades into the values of the aim object +} +\description{ +Cross-Fades the values of one MAGPIE object into the values of another over +a certain time +} +\examples{ + +data(population_magpie) +population <- add_columns(population_magpie,"MIX") +population[,,"MIX"]<-convergence(population[,,"A2"],population[,,"B1"]) + + +} +\seealso{ +\code{\link{lin.convergence}} +} +\author{ +Benjamin Bodirsky, Jan Philipp Dietrich +} diff --git a/man/convert.report.Rd b/man/convert.report.Rd new file mode 100644 index 00000000..38e7d809 --- /dev/null +++ b/man/convert.report.Rd @@ -0,0 +1,47 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/convert.report.R +\name{convert.report} +\alias{convert.report} +\title{Converts a report from one model to another} +\usage{ +convert.report(rep, inmodel = NULL, outmodel = "MAgPIE", full = FALSE, + as.list = TRUE) +} +\arguments{ +\item{rep}{Report. Either the file name of a mif file or a report already +read in in R.} + +\item{inmodel}{Model the input comes from. If NULL the script tries to +detect the inmodel automatically.} + +\item{outmodel}{Model format the data should be converted to. Currently, +only "MAgPIE" is available} + +\item{full}{Boolean deciding whether only the converted output should be +returned (FALSE) or the new output together with the input (TRUE)} + +\item{as.list}{if TRUE a list is returned (default), if FALSE it is tried to +merge all information in one MAgPIE object (still under development and +works currently only if the entries for the different models and scenarios +have exactly the same regions and years).} +} +\description{ +This function converts the content of a reporting file from one model to +another +} +\details{ +The function converts data based on a region mapping and transformation +rules which are stored in the variable magclassdata which comes with this +library. +} +\examples{ + +\dontrun{convert.report("report.mif")} + +} +\seealso{ +\code{\link{read.report}},\code{\link{write.report}},\code{\link{magclassdata}} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/copy.attributes.Rd b/man/copy.attributes.Rd new file mode 100644 index 00000000..87f98fbe --- /dev/null +++ b/man/copy.attributes.Rd @@ -0,0 +1,57 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/copy.attributes.R +\name{copy.attributes} +\alias{copy.attributes} +\alias{copy.attributes<-} +\alias{copy.attributes<-} +\title{Copy Attributes} +\usage{ +copy.attributes(from, to, delete = c("names", "row.names", "class", "dim", + "dimnames"), delete2 = NULL) + +copy.attributes(to, delete = c("names", "row.names", "class", "dim", + "dimnames"), delete2 = NULL) <- value +} +\arguments{ +\item{from}{object from which the attributes should be taken} + +\item{to}{object to which the attributes should be written} + +\item{delete}{attributes which should not be copied. By default this are +class specific attributes which might cause problems if copied to another +object. But you can add or remove attributes from the vector.} + +\item{delete2}{Identical to delete and just added for convenience for the +case that you want to delete additional attributes but do not want to repeat +the vector given in delete. In the function both vectors, delete and +delete2, are just merged to one deletion vector.} + +\item{value}{Same as "from" (object from which the attributes should be +taken)} +} +\description{ +This function copies attributes from one object and assigns them to another. +} +\section{Functions}{ +\itemize{ +\item \code{copy.attributes<-}: assign attributes from object "value" +}} + +\examples{ + +from <- array(12) +attr(from,"blablub") <- "I am an attribute!" +attr(from,"blablub2") <- "I am another attribute!" + +print(attributes(from)) + +to <- as.magpie(0) +print(attributes(to)) + +copy.attributes(to) <- from +print(attributes(to)) + +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/copy.magpie.Rd b/man/copy.magpie.Rd new file mode 100644 index 00000000..c76f0730 --- /dev/null +++ b/man/copy.magpie.Rd @@ -0,0 +1,29 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/copy.magpie.R +\name{copy.magpie} +\alias{copy.magpie} +\title{Copy MAgPIE-files} +\usage{ +copy.magpie(input_file, output_file) +} +\arguments{ +\item{input_file}{file, that should be copied} + +\item{output_file}{copy destination} +} +\description{ +This function copies MAgPIE-files from one location to another. During the +copying it is also possible to change the file type (e.g. from 'mz' to +'csv') +} +\examples{ + +# copy.magpie("bla.csv","blub.mz") + +} +\seealso{ +\code{\link{read.magpie}},\code{\link{write.magpie}} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/dimCode.Rd b/man/dimCode.Rd new file mode 100644 index 00000000..0637cfdb --- /dev/null +++ b/man/dimCode.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/dimCode.R +\name{dimCode} +\alias{dimCode} +\title{dimCode} +\usage{ +dimCode(dim, x, missing = 0) +} +\arguments{ +\item{dim}{A vector of dimension numbers or dimension names which should be +translated} + +\item{x}{MAgPIE object in which the dimensions should be searched for.} + +\item{missing}{Either a value to which a dimension should be set in case +that it is not found (default is 0), or "stop" indicating that the function +should throw an error in these cases.} +} +\value{ +A dimension code identifying the dimension. Either a integer which +represents the main dimensions (1=spatial, 2=temporal, 3=data) or a numeric, +representing the subdimensions of a dimension (e.g. 3.2 for the second data +dimension). +} +\description{ +Function converts a dimension name or number to a dimension Code used for +MAgPIE objects +} +\examples{ + +data(population_magpie) +dimCode(c("t","scenario","blablub"),population_magpie) + +} +\seealso{ +\code{\link{mselect}}, \code{\link{getDim}} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/dimOrder.Rd b/man/dimOrder.Rd new file mode 100644 index 00000000..51ebd8d1 --- /dev/null +++ b/man/dimOrder.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/dimOrder.R +\name{dimOrder} +\alias{dimOrder} +\title{dimOrder} +\usage{ +dimOrder(x, perm) +} +\arguments{ +\item{x}{magpie object} + +\item{perm}{vector with the new order of the 3rd dimension} +} +\value{ +magpie object +} +\description{ +Changes the order of the 3rd dimension in a magpie object similar to unwrapping and applying the aperm command, but more efficient. +} +\examples{ + +\dontrun{ +data("population_magpie") +x<-setNames(population_magpie,c("kj","kej"))*population_magpie +dimOrder(x=x,perm=c(2,1)) +} +} +\author{ +Benjamin Leon Bodirsky +} diff --git a/man/dimSums.Rd b/man/dimSums.Rd new file mode 100644 index 00000000..2b3d9822 --- /dev/null +++ b/man/dimSums.Rd @@ -0,0 +1,48 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/dimSums.R +\name{dimSums} +\alias{dimSums} +\title{Summation over dimensions} +\usage{ +dimSums(x, na.rm = FALSE, dims = NULL, dim = 3, sep = ".", ...) +} +\arguments{ +\item{x}{A MAgPIE-object or an array} + +\item{na.rm}{logical. Should missing values (including NaN) be omitted from +the calculations?} + +\item{dims}{Depreceated version of argument dim. Please use dim instead (it +is just it there for back compatibility and will be removed soon.)} + +\item{dim}{The dimensions(s) to sum over. A vector of integers or characters +(dimension names). If the MAgPIE object has more than 1 actual dimension +collected in the third real dimension, each actual dimension can be summed +over using the corresponding dim code (see \code{\link{dimCode}} for more +information)} + +\item{sep}{A character separating joined dimension names} + +\item{...}{Further arguments passed to rowSums internally} +} +\value{ +\item{value}{A MAgPIE object or an array (depending on the format of +x) with values summed over the specified dimensions} +} +\description{ +This function sums over any dimension of a magpie object or an array +} +\examples{ + + test<-as.magpie(array(1:4,dim=c(2,2))) + dimSums(test,dim=c(1,3)) + dimSums(test[,,1],na.rm=TRUE,dim=c(1,2)) + + +} +\seealso{ +\code{\link{rowSums}}, \code{\link{dimSums}}, \code{\link{dimCode}} +} +\author{ +Markus Bonsch, Ina Neher, Benjamin Bodirsky, Jan Philipp Dietrich +} diff --git a/man/escapeRegex.Rd b/man/escapeRegex.Rd new file mode 100644 index 00000000..1a3f856a --- /dev/null +++ b/man/escapeRegex.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/escapeRegex.R +\name{escapeRegex} +\alias{escapeRegex} +\title{escapeRegex} +\usage{ +escapeRegex(x) +} +\arguments{ +\item{x}{String or vector of strings that should be escaped.} +} +\value{ +The escaped strings. +} +\description{ +Escapes all symbols in a string which have a special meaning in regular +expressions. +} +\seealso{ +\code{\link[base]{grep}} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/fulldim.Rd b/man/fulldim.Rd new file mode 100644 index 00000000..bc12cd2a --- /dev/null +++ b/man/fulldim.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/fulldim.R +\name{fulldim} +\alias{fulldim} +\title{Reconstructs full dimensionality of MAgPIE objects} +\usage{ +fulldim(x, sep = ".") +} +\arguments{ +\item{x}{A MAgPIE-object} + +\item{sep}{A character separating joined dimension names} +} +\value{ +A list containing in the first element the dim output and in the +second element the dimnames output of the reconstructed array. +} +\description{ +If a MAgPIE object is created from a source with more than one data +dimension, these data dimensions are combined to a single dimension. fulldim +reconstructs the original dimensionality and reports it. +} +\examples{ + + a <- as.magpie(array(1:6,c(3,2),list(c("bla","blub","ble"),c("up","down")))) + fulldim(a) + + +} +\seealso{ +\code{\link{as.magpie}},\code{\link{unwrap}},\code{\link{wrap}} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/getCPR.Rd b/man/getCPR.Rd new file mode 100644 index 00000000..956b9b8f --- /dev/null +++ b/man/getCPR.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/getCPR.R +\name{getCPR} +\alias{getCPR} +\title{Get cells per region} +\usage{ +getCPR(x) +} +\arguments{ +\item{x}{MAgPIE object or a resolution written as numeric (currently only +data for 0.5 degree resolution is available).} +} +\value{ +cells per region +} +\description{ +Counts how many cells each region has and returns it as vector +} +\examples{ + +# a <- read.magpie("example.mz") +# getCPR(a) +getCPR(0.5) + +} +\seealso{ +\code{\link{getRegions}}, \code{\link{read.magpie}}, +\code{\link{write.magpie}} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/getCells.Rd b/man/getCells.Rd new file mode 100644 index 00000000..cde0565b --- /dev/null +++ b/man/getCells.Rd @@ -0,0 +1,55 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/getCells.R, R/setCells.R +\name{getCells} +\alias{getCells} +\alias{getCells<-} +\alias{setCells} +\alias{getCells<-} +\alias{setCells} +\title{Get Cells} +\usage{ +getCells(x) + +getCells(x) <- value + +setCells(object, nm = "GLO.1") +} +\arguments{ +\item{x, object}{MAgPIE object} + +\item{value, nm}{cell names the data should be set to.} +} +\value{ +getCells returns cell names of the MAgPIE-object, whereas setCells +returns the MAgPIE object with the manipulated cell names. +} +\description{ +Extracts cell names of a MAgPIE-object +} +\details{ +setCells is a shortcut to use a MAgPIE object with manipulated cell names. +setCells uses the variable names "object" and "nm" in order to be consistent +to the already existing function setNames. +} +\section{Functions}{ +\itemize{ +\item \code{getCells<-}: set cell names + +\item \code{setCells}: set cell names +}} + +\examples{ + + a <- as.magpie(1) + getCells(a) + setCells(a,"AFR.1") + +} +\seealso{ +\code{\link{getRegions}}, \code{\link{getNames}}, +\code{\link{setNames}}, \code{\link{getCPR}}, \code{\link{read.magpie}}, +\code{\link{write.magpie}}, \code{"\linkS4class{magpie}"} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/getComment.Rd b/man/getComment.Rd new file mode 100644 index 00000000..3a97cbf6 --- /dev/null +++ b/man/getComment.Rd @@ -0,0 +1,54 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/getComment.R, R/setComment.R +\name{getComment} +\alias{getComment} +\alias{getComment<-} +\alias{setComment} +\alias{getComment<-} +\alias{setComment} +\title{getComment} +\usage{ +getComment(x) + +getComment(x) <- value + +setComment(object, nm = NULL) +} +\arguments{ +\item{x, object}{MAgPIE object} + +\item{value, nm}{A vector containing the comment.} +} +\value{ +getComment returns the comment attached to a MAgPIE-object, NULL if +no comment is present. setComment returns the magpie object with the +modified comment. +} +\description{ +Extracts the comment from a MAgPIE-object +} +\section{Functions}{ +\itemize{ +\item \code{getComment<-}: set comment + +\item \code{setComment}: set comment +}} + +\examples{ + + a <- as.magpie(1) + #returns NULL + getComment(a) + #set the comment + getComment(a)<-c("bla","blubb") + getComment(a) + +} +\seealso{ +\code{\link{getRegions}}, \code{\link{getNames}}, +\code{\link{getYears}}, \code{\link{getCPR}}, \code{\link{read.magpie}}, +\code{\link{write.magpie}}, \code{"\linkS4class{magpie}"} +} +\author{ +Markus Bonsch +} diff --git a/man/getDim.Rd b/man/getDim.Rd new file mode 100644 index 00000000..a1f7e2b3 --- /dev/null +++ b/man/getDim.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/getDim.R +\name{getDim} +\alias{getDim} +\title{getDim} +\usage{ +getDim(elems, x) +} +\arguments{ +\item{elems}{A vector of characters containing the elements that should be +found in the MAgPIE object} + +\item{x}{MAgPIE object in which elems should be searched for.} +} +\value{ +The name of the dimension in which elems were found. +} +\description{ +Function which tries to detect the dimension to which the given elems belong +} +\examples{ + + data(population_magpie) + magclass:::getDim(c("AFR","CPA"),population_magpie) + +} +\seealso{ +\code{\link{mcalc}},\code{\link{dimCode}} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/getNames.Rd b/man/getNames.Rd new file mode 100644 index 00000000..803aaf3b --- /dev/null +++ b/man/getNames.Rd @@ -0,0 +1,68 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/getNames.R +\name{getNames} +\alias{getNames} +\alias{getNames<-} +\alias{getNames<-} +\title{Get dataset names} +\usage{ +getNames(x, fulldim = FALSE, dim = NULL) + +getNames(x, dim = NULL) <- value +} +\arguments{ +\item{x}{MAgPIE object} + +\item{fulldim}{specifies, how the object is treated. In case of FALSE, it is +assumed that x is 3 dimensional and dimnames(x)[[3]] is returned. In case of +TRUE, the dimnames of the real third dimension namesare returned} + +\item{dim}{Argument to choose a specific data dimension either by name of +the dimension or by number of the data dimension.} + +\item{value}{a vector of names current names should be replaced with. If +only one data element exists you can also set the name to NULL.} +} +\value{ +getNames returns data names of the MAgPIE-object, whereas setNames +returns the MAgPIE object with the manipulated data names. +} +\description{ +Extracts dataset names of a MAgPIE-object +} +\details{ +setNames is a shortcut to use a MAgPIE object with manipulated data names. +The setNames method uses the variable names "object" and "nm" in order to be +consistent to the already existing function setNames. +} +\section{Functions}{ +\itemize{ +\item \code{getNames<-}: set names +}} + +\examples{ + + a <- as.magpie(1) + getNames(a) + setNames(a,"bla") + + x <- new.magpie("GLO",2000,c("a.o1","b.o1","a.o2")) + getNames(x,dim=2) + + getSets(x,fulldim=FALSE)[3] <- "bla.blub" + getNames(x,dim="bla") + + getSets(x)[4] <- "ble" + getNames(x,dim="ble") <- c("Hi","Bye") + x + +} +\seealso{ +\code{\link{setNames-methods}}, \code{\link{getRegions}}, \code{\link{getYears}}, +\code{\link{getCPR}}, \code{\link{read.magpie}}, +\code{\link{write.magpie}},\code{\link{ndata}}, +\code{"\linkS4class{magpie}"} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/getRegionList.Rd b/man/getRegionList.Rd new file mode 100644 index 00000000..d3a7b616 --- /dev/null +++ b/man/getRegionList.Rd @@ -0,0 +1,43 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/getRegionList.R +\name{getRegionList} +\alias{getRegionList} +\alias{getRegionList<-} +\alias{getRegionList<-} +\title{Get a list of celluare region-belongings} +\usage{ +getRegionList(x) + +getRegionList(x) <- value +} +\arguments{ +\item{x}{MAgPIE object} + +\item{value}{A vector with ncell elements containing the regions of each +cell.} +} +\value{ +A vector with ncell elements containing the region of each cell. +} +\description{ +Extracts a vector containing the region of each cell of a MAgPIE-object +} +\section{Functions}{ +\itemize{ +\item \code{getRegionList<-}: set region names +}} + +\examples{ + +# a <- read.magpie("example.mz") +# getRegionList(a) + +} +\seealso{ +\code{\link{getRegions}},\code{\link{getYears}}, +\code{\link{getNames}}, \code{\link{getCPR}}, \code{\link{read.magpie}}, +\code{\link{write.magpie}}, \code{"\linkS4class{magpie}"} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/getRegions.Rd b/man/getRegions.Rd new file mode 100644 index 00000000..6894e67c --- /dev/null +++ b/man/getRegions.Rd @@ -0,0 +1,44 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/getRegions.R +\name{getRegions} +\alias{getRegions} +\alias{getRegions<-} +\alias{getRegions<-} +\title{Get regions} +\usage{ +getRegions(x) + +getRegions(x) <- value +} +\arguments{ +\item{x}{MAgPIE object} + +\item{value}{Vector containing the new region names of the MAgPIE objects. +If you also want to change the mapping of regions to cell please use +\code{\link{getRegionList}} instead.} +} +\value{ +Regions of the MAgPIE-object +} +\description{ +Extracts regions of a MAgPIE-object +} +\section{Functions}{ +\itemize{ +\item \code{getRegions<-}: overwrite region names +}} + +\examples{ + +# a <- read.magpie("example.mz") +# getRegions(a) + +} +\seealso{ +\code{\link{getYears}}, \code{\link{getNames}}, +\code{\link{getCPR}}, \code{\link{read.magpie}}, \code{\link{write.magpie}}, +\code{"\linkS4class{magpie}"} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/getSets.Rd b/man/getSets.Rd new file mode 100644 index 00000000..7d40eabf --- /dev/null +++ b/man/getSets.Rd @@ -0,0 +1,55 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/getSets.R +\name{getSets} +\alias{getSets} +\alias{getSets<-} +\alias{getSets<-} +\title{Get sets} +\usage{ +getSets(x, fulldim = TRUE, sep = ".") + +getSets(x, fulldim = TRUE, sep = ".") <- value +} +\arguments{ +\item{x}{MAgPIE object} + +\item{fulldim}{bool: Consider dimension 3 as a possible aggregate of more +dimensions (TRUE) or stick to it as one dimension (FALSE)} + +\item{sep}{A character separating joined dimension names} + +\item{value}{A vector with set names you want to replace the current set +names of the object with.} +} +\value{ +Sets of the MAgPIE-object. If no information about contained sets is +available NULL +} +\description{ +Extracts sets of a MAgPIE-object if available +} +\section{Functions}{ +\itemize{ +\item \code{getSets<-}: replace set names +}} + +\examples{ + + a <- new.magpie("GLO.1",2000,c("a.o1","b.o1","a.o2")) + getSets(a) <- c("reg","cell","t","bla","blub") + getSets(a) + + getSets(a)[4] <- "BLA" + getSets(a,fulldim=FALSE) + getSets(a) + +} +\seealso{ +\code{\link{getRegions}}, +\code{\link{getNames}},\code{\link{getYears}}, \code{\link{getCPR}}, +\code{\link{read.magpie}}, \code{\link{write.magpie}}, +\code{"\linkS4class{magpie}"} +} +\author{ +Markus Bonsch +} diff --git a/man/getYears.Rd b/man/getYears.Rd new file mode 100644 index 00000000..12f58755 --- /dev/null +++ b/man/getYears.Rd @@ -0,0 +1,61 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/getYears.R, R/setYears.R +\name{getYears} +\alias{getYears} +\alias{getYears<-} +\alias{setYears} +\alias{getYears<-} +\alias{setYears} +\title{Get years} +\usage{ +getYears(x, as.integer = FALSE) + +getYears(x) <- value + +setYears(object, nm = NULL) +} +\arguments{ +\item{x, object}{MAgPIE object} + +\item{as.integer}{Switch to decide, if output should be the used year-name +(e.g. "y1995") or the year as integer value (e.g. 1995)} + +\item{value, nm}{Years the data should be set to. Either supplied as a vector +of integers or a vector of characters in the predefined year format +("y0000"). If only 1 year exist you can also set the name of the year to +NULL.} +} +\value{ +getYears returns years of the MAgPIE-object, whereas setYears +returns the MAgPIE object with the manipulated years. +} +\description{ +Extracts years of a MAgPIE-object +} +\details{ +setYears is a shortcut to use a MAgPIE object with manipulated year names. +setYears uses the variable names "object" and "nm" in order to be consistent +to the already existing function setNames. +} +\section{Functions}{ +\itemize{ +\item \code{getYears<-}: rename years + +\item \code{setYears}: set years +}} + +\examples{ + + a <- as.magpie(1) + getYears(a) + setYears(a,1995) + +} +\seealso{ +\code{\link{getRegions}}, \code{\link{getNames}}, +\code{\link{setNames}}, \code{\link{getCPR}}, \code{\link{read.magpie}}, +\code{\link{write.magpie}}, \code{"\linkS4class{magpie}"} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/head.magpie.Rd b/man/head.magpie.Rd new file mode 100644 index 00000000..6b0c1196 --- /dev/null +++ b/man/head.magpie.Rd @@ -0,0 +1,39 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/head.magpie.R +\name{head.magpie} +\alias{head.magpie} +\alias{tail.magpie} +\title{head/tail} +\usage{ +\method{head}{magpie}(x, n1 = 3L, n2 = 6L, n3 = 2L, ...) +} +\arguments{ +\item{x}{MAgPIE object} + +\item{n1, n2, n3}{number of lines in first, second and third dimension that +should be returned. If the given number is higher than the length of the +dimension all entries in this dimension will be returned.} + +\item{...}{arguments to be passed to or from other methods.} +} +\value{ +head returns the first n1 x n2 x n3 entries, tail returns the last +n1 x n2 x n3 entries. +} +\description{ +head and tail methods for MAgPIE objects to extract the head or tail of an +object +} +\examples{ + + data(population_magpie) + head(population_magpie) + tail(population_magpie,2,4,1) + +} +\seealso{ +\code{\link[utils]{head}}, \code{\link[utils]{tail}} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/is.temporal.Rd b/man/is.temporal.Rd new file mode 100644 index 00000000..701076a9 --- /dev/null +++ b/man/is.temporal.Rd @@ -0,0 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/is.temporal.R +\name{is.temporal} +\alias{is.temporal} +\alias{is.spatial} +\title{is.temporal, is.spatial} +\usage{ +is.temporal(x) +} +\arguments{ +\item{x}{A vector} +} +\value{ +Returns TRUE or FALSE +} +\description{ +Functions to find out whether a vector consists of strings consistent with +the definition for auto-detection of temporal or spatial data. +} +\examples{ + +is.temporal(1991:1993) +is.spatial(c("GLO","AFR")) + +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/isYear.Rd b/man/isYear.Rd new file mode 100644 index 00000000..1068f2d2 --- /dev/null +++ b/man/isYear.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/isYear.R +\name{isYear} +\alias{isYear} +\title{isYear} +\usage{ +isYear(x, with_y = TRUE) +} +\arguments{ +\item{x}{A vector} + +\item{with_y}{indicates which dataformat years have to have (4-digit without +y (e.g.1984) or 5digit including y (y1984))} +} +\value{ +Returns a vector of the length of x with TRUE and FALSE +} +\description{ +Function to find out whether a vector consists of strings in the format +"yXXXX" or "XXXX" with X being a number +} +\examples{ + +x<-c("1955","y1853","12a4") +isYear(x, with_y=TRUE) +isYear(x, with_y=FALSE) + +} +\author{ +Benjamin Bodirsky +} diff --git a/man/lin.convergence.Rd b/man/lin.convergence.Rd new file mode 100644 index 00000000..8dda2c73 --- /dev/null +++ b/man/lin.convergence.Rd @@ -0,0 +1,63 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lin.convergence.R +\name{lin.convergence} +\alias{lin.convergence} +\title{lin.convergence} +\usage{ +lin.convergence(origin, aim, convergence_time_steps = NULL, + start_year = NULL, end_year = NULL, before = "stable", + after = "stable") +} +\arguments{ +\item{origin}{an object with one name-column} + +\item{aim}{Can be twofold: An object with one name-column and the same +timesteps as origin. Then the model fades over from timestep 1, in which the +value of origin is valid, to the last timestep, n which the value of aim is +valid. In the second case, the aim object has to have only one timestep, +which is also in origin. Then, the data will be faded from the value of +origin in the first timestep to the value of aim in the timestep passed on +by aim.} + +\item{convergence_time_steps}{In the case of +timesteps(origin)==timesteps(aim), convergence_time_steps delivers the +number of time_steps in which the convergence process shall be completed +(e.g. 6 for y2055).} + +\item{start_year}{year in which the convergence from origin to aim starts. +Value can also be a year not contained in the dataset.} + +\item{end_year}{year in which the convergence from origin to aim shall be +reached. Value can also be a year not contained in the dataset. Can be used +only alternatively to convergence_time_steps.} + +\item{before}{"stable" leaves the value at origin. If a year is entered, +convergence begins at aim, reaches origin at start_year, and goes back to +aim until end_year.} + +\item{after}{"stable" leaves the value at aim. All other values let the +convergence continue in the same speed even beyond the end_year, such that +the values of aim are left.} +} +\value{ +returns a time-series with the same timesteps as origin, which +lineary fades into the values of the aim object +} +\description{ +Cross-Fades the values of one MAGPIE object into the values of another over +a certain time +} +\examples{ + +data(population_magpie) +population <- add_columns(population_magpie,"MIX") +population[,,"MIX"] <- lin.convergence(population[,,"A2"],population[,,"B1"], + convergence_time_steps=10) + +} +\seealso{ +\code{\link{lin.convergence}} +} +\author{ +Benjamin Bodirsky +} diff --git a/man/lowpass.Rd b/man/lowpass.Rd new file mode 100644 index 00000000..3995be66 --- /dev/null +++ b/man/lowpass.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lowpass.R +\name{lowpass} +\alias{lowpass} +\title{Lowpass Filter} +\usage{ +lowpass(x, i = 1, fix = NULL) +} +\arguments{ +\item{x}{Vector of data points, that should be filtered or MAgPIE object} + +\item{i}{number of iterations the filter should be applied to the data} + +\item{fix}{Fixes the starting and/or ending data point. Default value is +\code{NULL} which doesn't fix any point. Available options are: +\code{"start"} for fixing the starting point, \code{"end"} for fixing the +ending point and \code{"both"} for fixing both ends of the data.} +} +\value{ +The filtered data vector or MAgPIE object +} +\description{ +Filters high frequencies out of a time series. The filter has the structure +x'(n) = (x(n-1)+2*x(n)+x(n+1))/4 +} +\examples{ + +lowpass(c(1,2,11,3,4)) +# to fix the starting point +lowpass(c(0,9,1,5,14,20,6,11,0), i=2, fix="start") + +} +\author{ +Jan Philipp Dietrich, Misko Stevanovic +} diff --git a/man/magclass-package.Rd b/man/magclass-package.Rd new file mode 100644 index 00000000..507dc0a5 --- /dev/null +++ b/man/magclass-package.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/magclass-package.R +\docType{package} +\name{magclass-package} +\alias{magclass-package} +\alias{magclass} +\title{MAgPIE Class Functions} +\description{ +Package containing the MAgPIE-Object-Class together with relevant functions +and methods. +} +\details{ +\tabular{ll}{ Package: \tab magclass\cr Type: \tab Package\cr Version: \tab +3.93\cr Date: \tab 2016-09-08\cr License: \tab LGPL-3\cr LazyLoad: \tab +yes\cr } +} +\author{ +Jan Philipp Dietrich, Benjamin Bodirsky, Misko Stevanovic, Lavinia +Baumstark, Christoph Bertram, Markus Bonsch, Anastasis Giannousakis, Florian +Humpenoeder, David Klein, Ina Neher, Michaja Pehl, Anselm Schultes + +Maintainer: Jan Philipp Dietrich +} diff --git a/man/magclassdata.Rd b/man/magclassdata.Rd new file mode 100644 index 00000000..b4aa78a7 --- /dev/null +++ b/man/magclassdata.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/sysdata.R +\name{magclassdata} +\alias{magclassdata} +\title{magclassdata} +\description{ +General magclass-dataset +} +\details{ +Please do not directly access that data. It should be only used by library +functions. +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/magpie-class.Rd b/man/magpie-class.Rd new file mode 100644 index 00000000..a95e6f6a --- /dev/null +++ b/man/magpie-class.Rd @@ -0,0 +1,103 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/magpie-class.R +\docType{class} +\name{magpie-class} +\alias{magpie-class} +\alias{as.magpie} +\alias{as.magpie-methods} +\alias{as.magpie,magpie-method} +\alias{as.magpie,array-method} +\alias{as.magpie,lpj-method} +\alias{as.magpie,data.frame-method} +\alias{as.magpie,numeric-method} +\alias{as.magpie,NULL-method} +\alias{as.magpie,quitte-method} +\alias{as.magpie,tbl_df-method} +\alias{is.magpie} +\alias{[,magpie-method} +\alias{[,magpie,ANY,ANY-method} +\alias{[<-,magpie,ANY,ANY-method} +\alias{[<-,magpie-method} +\alias{Ops,magpie,magpie-method} +\title{Class "magpie" ~~~} +\arguments{ +\item{x}{An object that should be either tested or transformed as/to an +MAgPIE-object.} + +\item{...}{additional arguments supplied for the conversion to a MAgPIE +object. Allowed arguments for arrays and dataframes are \code{spatial} and +\code{temporal} both expecting a vector of dimension or column numbers which +contain the spatial or temporal information. By default both arguments are +set to NULL which means that the \code{as.magpie} will try to detect +automatically the temporal and spatial dimensions. The arguments will just +overwrite the automatic detection. If you want to specify that the data does +not contain a spatial or temporal dimension you can set the corresponding +argument to 0. In addition \code{as.magpie} for data.frames is also +expecting an argument called \code{datacol} which expects a number stating +which is the first column containing data. This argument should be used if +the dimensions are not detected corretly, e.g. if the last dimension column +contains years which are then detected as values and therefore interpreted +as first data column. In addition an argument \code{tidy=TRUE} can be used +to indicate that the data.frame structure is following the rules of tidy +data (last column is the data column all other columns contain dimension +information). This information will help the conversion.} +} +\description{ +The MAgPIE class is a data format for cellular MAgPIE data with a close +relationship to the array data format. \code{is.magpie} tests if \code{x} is +an MAgPIE-object, \code{as.magpie} transforms \code{x} to an MAgPIE-object +(if possible). +} +\section{Objects from the Class}{ + Objects can be created by calls of the form +\code{new("magpie", data, dim, dimnames, ...)}. MAgPIE objects have three +dimensions (cells,years,datatype) and the dimensionnames of the first +dimension have the structure "REGION.cellnumber". MAgPIE-objects behave the +same like array-objects with 2 exceptions: \cr 1.Dimensions of the object +will not collapse (e.g. \code{x[1,1,1]} will remain 3D instead of becoming +1D)\cr 2.It is possible to extract full regions just by typing +\code{x["REGIONNAME",,]}. \cr\cr + +Please mind following standards: \cr Header must not contain any purely +numeric entries, but combinations of characters and numbers are allowed +(e.g. "bla","12" is forbidden, wheras "bla","b12" is allowed)\cr Years +always have the structure "y" + 4-digit number, e.g. "y1995"\cr Regions +always have the structure 3 capital letters, e.g. "AFR" or "GLO"\cr\cr This +standards are necessary to allow the scripts to detect headers, years and +regions properly and to have a distinction to other data. +} + +\examples{ + +showClass("magpie") + +data(population_magpie) + +# returning PAO and PAS for 2025 +population_magpie["PA",2025,,pmatch="left"] + +# returning CPA for 2025 +population_magpie["PA",2025,,pmatch="right"] + +# returning CPA PAO and PAS for 2025 +population_magpie["PA",2025,,pmatch=TRUE] + +# returning PAS and 2025 +population_magpie["PAS",2025,] + +# returning everything but values for PAS or values for 2025 +population_magpie["PAS",2025,,invert=TRUE] + + + +} +\seealso{ +\code{\link{read.magpie}}, \code{\link{write.magpie}}, +\code{\link{getRegions}}, \code{\link{getYears}}, \code{\link{getNames}}, +\code{\link{getCPR}}, \code{\link{ncells}}, \code{\link{nyears}}, +\code{\link{ndata}} +} +\author{ +Jan Philipp Dietrich +} +\keyword{classes} diff --git a/man/magpieComp.Rd b/man/magpieComp.Rd new file mode 100644 index 00000000..ac3ea135 --- /dev/null +++ b/man/magpieComp.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/magpieComp.R +\name{magpieComp} +\alias{magpieComp} +\title{magpieComp} +\usage{ +magpieComp(bench, comp, reg = NA) +} +\arguments{ +\item{bench}{A \code{MAgPIE} object.} + +\item{comp}{A \code{MAgPIE} object.} + +\item{reg}{The region(s) you want to focus on} +} +\value{ +a list containing a1) the names found only in bench, a2) the names +found only in comp, b) a sorted data frame with the largest relative +difference between bench and comp in percentage values, and c) a magclass +object with the same values +} +\description{ +Function that compares two magpie objects. +} +\details{ +Function that compares two magpie objects. +} +\author{ +Anastasis Giannousakis +} diff --git a/man/magpieResolution.Rd b/man/magpieResolution.Rd new file mode 100644 index 00000000..205bbdc2 --- /dev/null +++ b/man/magpieResolution.Rd @@ -0,0 +1,29 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/magpieResolution.R +\name{magpieResolution} +\alias{magpieResolution} +\title{magpieResolution} +\usage{ +magpieResolution(object) +} +\arguments{ +\item{object}{An MAgPIE object} +} +\value{ +"glo", "reg" or "cell" +} +\description{ +Returns the Resolution of a MAgPIE object +} +\examples{ + +data(population_magpie) +magpieResolution(population_magpie) + +} +\seealso{ +\code{\link{population_magpie}} +} +\author{ +Benjamin Bodirsky +} diff --git a/man/magpie_expand.Rd b/man/magpie_expand.Rd new file mode 100644 index 00000000..4fc39a16 --- /dev/null +++ b/man/magpie_expand.Rd @@ -0,0 +1,47 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/magpie_expand.R +\name{magpie_expand} +\alias{magpie_expand} +\title{magpie_expand} +\usage{ +magpie_expand(x, ref) +} +\arguments{ +\item{x}{MAgPIE object that should be expanded} + +\item{ref}{MAgPIE object that serves as a reference} +} +\value{ +An expanded version of x. +} +\description{ +Expands a MAgPIE object based on a reference +} +\details{ +Expansion means here that the dimensions of x are expanded acordingly to +ref. Please note that this is really only about expansion. In the case that +one dimension of ref is smaller than of x nothing happens with this +dimension. At the moment magpie_expand is only internally available in the +magclass library + +You can influence the verbosity of this function by setting the option +"magclass.verbosity". By default verbosity is set to 2 which means that +warnings as well as notes are returned. Setting verbosity to 1 means that +only warnings are returned but no notes. This is done by +options(verbosity.level=1) +} +\examples{ + + a <- new.magpie(c("AFR","CPA"),"y1995",c("m","n")) + b <- new.magpie("GLO","y1995",c("bla","blub")) + magpie_expand(b,a) + options(magclass.verbosity=1) + magpie_expand(b,a) + +} +\seealso{ +\code{\link{as.magpie}}, \code{\link[base]{options}} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/magpiesort.Rd b/man/magpiesort.Rd new file mode 100644 index 00000000..29e9f0db --- /dev/null +++ b/man/magpiesort.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/magpiesort.R +\name{magpiesort} +\alias{magpiesort} +\title{MAgPIE-Sort} +\usage{ +magpiesort(x) +} +\arguments{ +\item{x}{MAgPIE object which might not be in the right order.} +} +\value{ +The eventually corrected MAgPIE object (right order in spatial in +temporal dimension) +} +\description{ +Brings the spatial and temporal structure of MAgPIE objects in the right +order. This function is especially useful when you create new MAgPIE objects +as the order typically should be correct for MAgPIE objects. +} +\examples{ + + data(population_magpie) + a <- magpiesort(population_magpie) + +} +\seealso{ +\code{"\linkS4class{magpie}"} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/magpply.Rd b/man/magpply.Rd new file mode 100644 index 00000000..4b8ab860 --- /dev/null +++ b/man/magpply.Rd @@ -0,0 +1,39 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/magpply.R +\name{magpply} +\alias{magpply} +\title{magpply} +\usage{ +magpply(X, FUN, MARGIN, ..., integrate = FALSE) +} +\arguments{ +\item{X}{magpie object} + +\item{FUN}{function that shall be applied X} + +\item{MARGIN}{dimension over which FUN shall be applied (like a loop over that dimension). This dimension will be preserved in the output object} + +\item{...}{further parameters passed on to FUN} + +\item{integrate}{if TRUE, the output will be filled into an magpie object of the same dimensionality as X} +} +\value{ +magpie object +} +\description{ +apply command for magpieobjects. Very efficient for replacing loops. +} +\examples{ + +\dontrun{ +data("population_magpie") +magpply(population_magpie,FUN=sum,MARGIN=2) +fourdim<-population_magpie*setNames(population_magpie,c("jkk","lk")) +magpply(fourdim,FUN=sum,MARGIN=c(1,3.1)) +magpply(fourdim,FUN=function(x){return(x+1)},MARGIN=c(1,3.1),integrate=TRUE) +} + +} +\author{ +Benjamin Leon Bodirsky +} diff --git a/man/mbind.Rd b/man/mbind.Rd new file mode 100644 index 00000000..02c23721 --- /dev/null +++ b/man/mbind.Rd @@ -0,0 +1,50 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mbind.R +\name{mbind} +\alias{mbind} +\alias{mbind2} +\title{mbind} +\usage{ +mbind(...) +} +\arguments{ +\item{...}{MAgPIE objects or a list of MAgPIE objects that should be merged.} +} +\value{ +The merged MAgPIE object +} +\description{ +Merges MAgPIE-objects with identical structure in two dimensions. If data +differs in the temporal or spatial dimension each year or region/cell must +appear only once! +} +\details{ +mbind2 is a reimplementation from mbind which had the aim to increase its +overall memory efficiency. However, it is not clear which function is better +and there are also some changes in behaviour of both functions. Therefore, +the new version was just added as mbind2 instead of using it as a full +replacement for mbind. +} +\examples{ + +m <- new.magpie(c("AFR","CPA","EUR"), c(1995,2005),"Data1",fill=c(1,2,3,4,5,6)) +ms <- dimSums(m, dims=1) +mbind(m, ms) +my <- new.magpie(getRegions(m), 2010, getNames(m), fill=c(6,6,4)) +mbind(m, my) +md <- new.magpie(getRegions(m), getYears(m), "Data2", fill=c(7,6,5,7,8,9)) +mbind(m, md) + +data(population_magpie) +a <- mbind(population_magpie,population_magpie) +dim(population_magpie) +dim(a) + + +} +\seealso{ +\code{"\linkS4class{magpie}"} +} +\author{ +Jan Philipp Dietrich, Misko Stevanovic +} diff --git a/man/mcalc.Rd b/man/mcalc.Rd new file mode 100644 index 00000000..03d20d45 --- /dev/null +++ b/man/mcalc.Rd @@ -0,0 +1,48 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mcalc.R +\name{mcalc} +\alias{mcalc} +\alias{mcalc<-} +\title{mcalc} +\usage{ +mcalc(x, f, dim = NULL, append = FALSE) +} +\arguments{ +\item{x}{MAgPIE object} + +\item{f}{A formula describing the calculation that should be performed} + +\item{dim}{The dimension in which the manipulation should take place. If set +to NULL function tries to detect the dimension automatically.} + +\item{append}{If set to TRUE the result will be appended to x, otherwise the +result will be returned.} +} +\value{ +The calculated MAgPIE object in the case that append is set to +FALSE. Otherwise nothing is returned (as x is appended in place) +} +\description{ +Select values from a MAgPIE-object +} +\details{ +This functions only work for MAgPIE objects with named dimensions as the +dimension name (set_name) has to be used to indicate in which dimension the +entries should be searched for! +} +\examples{ + + data(population_magpie) + population_magpie + mcalc(population_magpie,X12 ~ A2*B1,append=TRUE) + population_magpie + mcalc(population_magpie,`Nearly B1` ~ 0.5*A2 + 99.5*B1) + + +} +\seealso{ +\code{\link{mselect}} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/mselect.Rd b/man/mselect.Rd new file mode 100644 index 00000000..488a22c9 --- /dev/null +++ b/man/mselect.Rd @@ -0,0 +1,54 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/mselect.R +\name{mselect} +\alias{mselect} +\alias{mselect<-} +\alias{mselect<-} +\title{MSelect} +\usage{ +mselect(x, ..., collapseNames = FALSE) + +mselect(x, ...) <- value +} +\arguments{ +\item{x}{MAgPIE object} + +\item{...}{entry selections of the form +\code{set_name=c(set_elem1,set_elem2)}. Alternatively a single list element +containing these selections can be provided.} + +\item{collapseNames}{Boolean which decides whether names should be collapsed +or not.} + +\item{value}{values on which the selected magpie entries should be set.} +} +\value{ +The reduced MAgPIE object containing only the selected entries or +the full MAgPIE object in which a selection of entries was manipulated. +} +\description{ +Select values from a MAgPIE-object +} +\details{ +This functions only work for MAgPIE objects with named dimensions as the +dimension name (set_name) has to be used to indicate in which dimension the +entries should be searched for! +} +\section{Functions}{ +\itemize{ +\item \code{mselect<-}: replace values in magpie object +}} + +\examples{ + + data(population_magpie) + population_magpie + mselect(population_magpie,i=c("AFR","EUR"),scenario="A2",t="y2035") + +} +\seealso{ +\code{\link{collapseNames}}, \code{"\linkS4class{magpie}"} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/ncells.Rd b/man/ncells.Rd new file mode 100644 index 00000000..1e8615de --- /dev/null +++ b/man/ncells.Rd @@ -0,0 +1,55 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ncells.R, R/ndata.R, R/nregions.R, R/nyears.R +\name{ncells} +\alias{ncells} +\alias{nyears} +\alias{ndata} +\alias{nregions} +\alias{ndata} +\alias{nregions} +\alias{nyears} +\title{Count elements} +\usage{ +ncells(x) + +ndata(x, fulldim = FALSE) + +nregions(x) + +nyears(x) +} +\arguments{ +\item{x}{A MAgPIE-object} + +\item{fulldim}{specifies, how the object is treated. In case of FALSE, it is +assumed that x is 3 dimensional and dimnames(x)[[3]] is returned. In case of +TRUE, the dimnames of the real third dimension namesare returned} +} +\value{ +\item{value}{The number of cells/years/datasets/regions of \code{x}} +} +\description{ +Functions to count the number of cells/years/datasets/regions of an +MAgPIE-object +} +\section{Functions}{ +\itemize{ +\item \code{ndata}: count datasets + +\item \code{nregions}: count regions + +\item \code{nyears}: count years +}} + +\examples{ + + a <- is.magpie(NULL) + ncells(a) + nyears(a) + ndata(a) + nregions(a) + +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/new.magpie.Rd b/man/new.magpie.Rd new file mode 100644 index 00000000..7d7a5831 --- /dev/null +++ b/man/new.magpie.Rd @@ -0,0 +1,46 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/new.magpie.R +\name{new.magpie} +\alias{new.magpie} +\title{new.magpie} +\usage{ +new.magpie(cells_and_regions = "GLO", years = NULL, names = NULL, + fill = NA, sort = FALSE, sets = NULL) +} +\arguments{ +\item{cells_and_regions}{Either the region names (e.g. "AFR"), or the cells +(e.g. 1:10), or both in combination (e.g. "AFR.1"). NULL means no spatial +element.} + +\item{years}{dimnames for years in the format "yXXXX" or as integers. NULL +means one year which is not further specified} + +\item{names}{dimnames for names. NULL means one data element which is not +further specified} + +\item{fill}{Default value for the MAgPIE object} + +\item{sort}{Bolean. Decides, wheher output should be sorted or not.} + +\item{sets}{A vector of dimension names. See \code{\link{getSets}} for more +information.} +} +\value{ +an empty magpie object filled with fill, with the given dimnames +} +\description{ +Creates a new MAgPIE object +} +\examples{ + + a <- new.magpie(1:10,1995:2000) + b <- new.magpie(c("AFR","CPA"),"y1995",c("bla","blub"),sets=c("i","t","value")) + c <- new.magpie() + +} +\seealso{ +\code{\link{as.magpie}} +} +\author{ +Benjamin Bodirsky, Jan Philipp Dietrich +} diff --git a/man/old_dim_convention.Rd b/man/old_dim_convention.Rd new file mode 100644 index 00000000..7a515a2a --- /dev/null +++ b/man/old_dim_convention.Rd @@ -0,0 +1,29 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/old_dim_convention.R +\name{old_dim_convention} +\alias{old_dim_convention} +\title{old_dim_convention} +\usage{ +old_dim_convention(dim) +} +\arguments{ +\item{dim}{The dim number in the new convention} +} +\value{ +The dim number according to the old convention +} +\description{ +Transforms new dim convention (e.g. 3.2) into old dim convention(e.g. 4) +} +\examples{ + + dim=old_dim_convention(3.2) + dim=old_dim_convention(1.1) + +} +\seealso{ +\code{\link{add_columns}},\code{\link{add_dimension}} +} +\author{ +Benjamin Bodirsky +} diff --git a/man/place_x_in_y.Rd b/man/place_x_in_y.Rd new file mode 100644 index 00000000..d786c291 --- /dev/null +++ b/man/place_x_in_y.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/place_x_in_y.R +\name{place_x_in_y} +\alias{place_x_in_y} +\title{place_x_in_y} +\usage{ +place_x_in_y(x, y, expand = T) +} +\arguments{ +\item{x}{Object to be placed.} + +\item{y}{Object in which x shall be placed} + +\item{expand}{T: if x is larger than y, new columns are added.} +} +\value{ +The combination of x and y. x overwrites y values which are in the +same place. +} +\description{ +Function positions magpie object x into magpie object y. +} +\examples{ + + data(population_magpie) + x <- population_magpie[,"y1995",]*0.2 + a <- place_x_in_y(x, population_magpie) + +} +\seealso{ +\code{\link{add_dimension}},\code{\link{add_columns}},\code{\link{mbind}} +} +\author{ +Benjamin Bodirsky +} diff --git a/man/population_magpie.Rd b/man/population_magpie.Rd new file mode 100644 index 00000000..d5d9de61 --- /dev/null +++ b/man/population_magpie.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/population_magpie.R +\name{population_magpie} +\alias{population_magpie} +\title{population_magpie} +\value{ +A2 and B1 population scenario from SRES +} +\description{ +Example dataset for a regional MAgPIE object +} +\author{ +Benjamin Bodirsky +} diff --git a/man/print.magpie.Rd b/man/print.magpie.Rd new file mode 100644 index 00000000..1b6f208a --- /dev/null +++ b/man/print.magpie.Rd @@ -0,0 +1,36 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/print.magpie.R +\name{print.magpie} +\alias{print.magpie} +\title{print} +\usage{ +\method{print}{magpie}(x, drop = TRUE, ...) +} +\arguments{ +\item{x}{MAgPIE object} + +\item{drop}{argument which controls whether empty dimensions should be +skipped or not.} + +\item{...}{arguments to be passed to or from other methods.} +} +\value{ +print displays the given MAgPIE object on screen. +} +\description{ +print method for MAgPIE objects for conventient display of magpie data. +} +\examples{ + + data(population_magpie) + print(population_magpie) + print(population_magpie[,1,], drop=FALSE) + print(population_magpie[,1,]) + +} +\seealso{ +\code{\link[base]{print}} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/read.magpie.Rd b/man/read.magpie.Rd new file mode 100644 index 00000000..f48804a5 --- /dev/null +++ b/man/read.magpie.Rd @@ -0,0 +1,115 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/read.magpie.R +\name{read.magpie} +\alias{read.magpie} +\title{Read MAgPIE-object from file} +\usage{ +read.magpie(file_name, file_folder = "", file_type = NULL, + as.array = FALSE, old_format = FALSE, comment.char = "*", + check.names = FALSE) +} +\arguments{ +\item{file_name}{file name including file ending (wildcards are supported). +Optionally also the full path can be specified here (instead of splitting it +to file\_name and file\_folder)} + +\item{file_folder}{folder the file is located in (alternatively you can also +specify the full path in file\_name - wildcards are supported)} + +\item{file_type}{format the data is stored in. Currently 12 formats are +available: "cs2" (cellular standard MAgPIE format), "csv" (regional standard +MAgPIE format), "cs3" (multidimensional format compatible to GAMS), "cs4" +(alternative multidimensional format compatible to GAMS, in contrast to cs3 +it can also handle sparse data), "csvr", "cs2r", "cs3r" and "cs4r" which are +the same formats as the previous mentioned ones with the only difference +that they have a REMIND compatible format, "m" (binary MAgPIE format +"magpie"), "mz" (compressed binary MAgPIE format "magpie zipped") "put" +(format used primarily for the REMIND-MAgPIE coupling) and "asc", +(ASCII-Grid format as used by ArcGis) . If file\_type=NULL the file ending +of the file\_name is used as format. If format is different to the formats +mentioned standard MAgPIE format is assumed.} + +\item{as.array}{Should the input be transformed to an array? This can be +useful for regional or global inputs, but all advantages of the magpie-class +are lost.} + +\item{old_format}{used to read files in old MAgPIE-format (unused space was +not located at the beginning of the file), will be removed soon.} + +\item{comment.char}{character: a character vector of length one containing a +single character or an empty string. Use "" to turn off the interpretation +of comments altogether. If a comment is found it will be stored in +attr(,"comment"). In text files the comment has to be at the beginning of +the file in order to be recognized by read.magpie.} + +\item{check.names}{logical. If TRUE then the names of the variables in the +data frame are checked to ensure that they are syntactically valid variable +names. Same functionality as in read.table.} +} +\value{ +\item{x}{MAgPIE-object} +} +\description{ +Reads a MAgPIE-file and converts it to a 3D array of the structure +(cells,years,datacolumn) +} +\details{ +This function reads from 10 different MAgPIE file\_types. "cs2" is the new +standard format for cellular data with or without header and the first +columns (year,regiospatial) or only (regiospatial), "csv" is the standard +format for regional data with or without header and the first columns +(year,region,cellnumber) or only (region,cellnumber). "cs3" is a format +similar to csv and cs2, but with the difference that it supports +multidimensional data in a format which can be read by GAMS, "put" is a +newly supported format which is mosty used for the REMIND-MAgPIE coupling. +This format is only partly supported at the moment. "asc" is the AsciiGrid +format (for example used for Arc Gis data). "nc" is the netCDF format (only +"nc" files written by write.magpie can be read). All these variants are +read without further specification. "magpie" (.m) and "magpie zipped" (.mz) +are new formats developed to allow a less storage intensive management of +MAgPIE-data. The only difference between both formats is that .mz is gzipped +whereas .m is not compressed. So .mz needs less memory, whereas .m might +have a higher compatibility to other languages. \cr\cr Since library version +1.4 read.magpie can also read regional or global MAgPIE csv-files. +} +\note{ +The binary MAgPIE formats .m and .mz have the following content/structure +(you only have to care for that if you want to implement +read.magpie/write.magpie functions in other languages): \cr \cr +[ FileFormatVersion | Current file format version number (currently 2) | integer | 2 Byte ] \cr +[ nchar_comment | Number of characters of the file comment | integer | 4 Byte ] \cr +[ nchar_sets | Number of characters of all regionnames + 2 delimiter | integer | 2 Byte] \cr +[ not used | Bytes reserved for later file format improvements | integer | 92 Byte ] \cr +[ nyears | Number of years | integer | 2 Byte ]\cr +[ year_list | All years of the dataset (0, if year is not present) | integer | 2*nyears Byte ] \cr +[ nregions | Number of regions | integer | 2 Byte ] \cr +[ nchar_reg | Number of characters of all regionnames + (nreg-1) for delimiters | integer | 2 Byte ] \cr +[ regions | Regionnames saved as reg1\\nreg2 (\\n is the delimiter) | character | 1*nchar_reg Byte ] \cr +[ cpr | Cells per region | integer | 4*nreg Byte ] \cr +[ nelem | Total number of data elements | integer | 4 Byte ] \cr +[ nchar_data | Number of char. of all datanames + (ndata - 1) for delimiters | integer | 4 Byte ] \cr +[ datanames | Names saved in the format data1\\ndata2 (\\n as del.) | character | 1*nchar_data Byte ] \cr +[ data | Data of the MAgPIE array in vectorized form | numeric | 4*nelem Byte ] \cr +[ comment | Comment with additional information about the data | character | 1*nchar_comment Byte ] \cr +[ sets | Set names with \\n as delimiter | character | 1*nchar_sets Byte] \cr + +Please note that if your data in the spatial dimension is not ordered by +region name each new appearance of a region which already appeared before +will be treated and counted as a new region (e.g. +AFR.1,AFR.2,CPA.3,CPA.4,AFR.5 will count AFR twice and nregions will be set +to 3!). +} +\examples{ + +\dontrun{ +a <- read.magpie("lpj_yield_ir.csv") +write.magpie(a,"lpj_yield_ir.mz") +} + +} +\seealso{ +\code{"\linkS4class{magpie}"}, \code{\link{write.magpie}} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/read.report.Rd b/man/read.report.Rd new file mode 100644 index 00000000..1e4ab3be --- /dev/null +++ b/man/read.report.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/read.report.R +\name{read.report} +\alias{read.report} +\title{Read file in report format} +\usage{ +read.report(file, as.list = TRUE) +} +\arguments{ +\item{file}{file name the object should be read from.} + +\item{as.list}{if TRUE a list is returned (default), if FALSE it is tried to +merge all information in one MAgPIE object (still under development and +works currently only if the entries for the different models and scenarios +have exactly the same regions and years).} +} +\description{ +This function reads the content of a reporting file (a file in the model +intercomparison file format *.mif) into a list of MAgPIE objects or a single +MAgPIE object +} +\examples{ + +\dontrun{ + read.report("report.csv") +} + +} +\seealso{ +\code{\link{write.report}} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/remind2magpie.Rd b/man/remind2magpie.Rd new file mode 100644 index 00000000..d3f361d0 --- /dev/null +++ b/man/remind2magpie.Rd @@ -0,0 +1,29 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/remind2magpie.R +\name{remind2magpie} +\alias{remind2magpie} +\title{Remind2MAgPIE} +\usage{ +remind2magpie(x) +} +\arguments{ +\item{x}{MAgPIE object with Remind regions} +} +\value{ +MAgPIE object with MAgPIE regions +} +\description{ +Converts a MAgPIE object with Remind regions to a MAgPIE object with MAgPIE +regions +} +\examples{ + + \dontrun{a <- remind2magpie(remind_c_prices)} + +} +\seealso{ +\code{"\linkS4class{magpie}"} +} +\author{ +Florian Humpenoeder +} diff --git a/man/round-methods.Rd b/man/round-methods.Rd new file mode 100644 index 00000000..b947a296 --- /dev/null +++ b/man/round-methods.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/round-method.R +\docType{methods} +\name{round-methods} +\alias{round-methods} +\alias{round,magpie-method} +\title{Round-method for MAgPIE objects} +\usage{ +\S4method{round}{magpie}(x, digits = 0) +} +\arguments{ +\item{x}{a magpie object} + +\item{digits}{integer indicating the number of decimal places (round) or significant +digits (signif) to be used. Negative values are allowed.} +} +\description{ +Round-method for MAgPIE-objects respectively. Works exactly as for arrays. +} +\section{Methods}{ + \describe{ + +\item{x = "magpie"}{ works as round(x) for arrays. } + +} +} + diff --git a/man/rowSums-methods.Rd b/man/rowSums-methods.Rd new file mode 100644 index 00000000..8885c713 --- /dev/null +++ b/man/rowSums-methods.Rd @@ -0,0 +1,41 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/rowSums-method.R +\docType{methods} +\name{rowSums-methods} +\alias{rowSums-methods} +\alias{rowSums,ANY-method} +\alias{rowSums,magpie-method} +\alias{rowMeans-methods} +\alias{rowMeans,ANY-method} +\alias{rowMeans,magpie-method} +\title{~~ Methods for Function rowSums and rowMeans ~~} +\usage{ +\S4method{rowSums}{magpie}(x, na.rm = FALSE, dims = 1, ...) +} +\arguments{ +\item{x}{object on which calculation should be performed} + +\item{na.rm}{logical. Should missing values (including NaN) be omitted from the calculations?} + +\item{dims}{integer: Which dimensions are regarded as "rows" or "columns" to sum over. For row*, +the sum or mean is over dimensions dims+1, ...; for col* it is over dimensions 1:dims.} + +\item{...}{further arguments passed to other colSums/colMeans methods} +} +\description{ +~~ Methods for function \code{rowSums} and \code{rowMeans}~~ +} +\section{Methods}{ + \describe{ + +\item{list("signature(x = \"ANY\")")}{ normal rowSums and rowMeans method } + +\item{list("signature(x = \"magpie\")")}{ classical method prepared to +handle MAgPIE objects } } +} + +\keyword{keyword(s)} +\keyword{methods} +\keyword{other} +\keyword{possible} +\keyword{~~} diff --git a/man/setNames-methods.Rd b/man/setNames-methods.Rd new file mode 100644 index 00000000..26822067 --- /dev/null +++ b/man/setNames-methods.Rd @@ -0,0 +1,38 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/setNames_method.R +\docType{methods} +\name{setNames-methods} +\alias{setNames-methods} +\alias{setNames} +\alias{setNames,magpie-method} +\alias{setNames,NULL-method} +\title{Get dataset names} +\usage{ +\S4method{setNames}{magpie}(object = nm, nm) +} +\arguments{ +\item{object}{MAgPIE object} + +\item{nm}{a vector of names current names should be replaced with. If +only one data element exists you can also set the name to NULL.} +} +\description{ +Extracts dataset names of a MAgPIE-object +} +\details{ +setNames is a shortcut to use a MAgPIE object with manipulated data names. +The setNames method uses the variable names "object" and "nm" in order to be +consistent to the already existing function setNames. +} +\section{Methods}{ + \describe{ + +\item{list("signature(object = \"ANY\")")}{ normal setNames method } + +\item{list("signature(object = \"magpie\")")}{ setNames for MAgPIE objects} } +} + +\seealso{ +\code{\link{getNames}}, +} +\keyword{methods} diff --git a/man/time_interpolate.Rd b/man/time_interpolate.Rd new file mode 100644 index 00000000..788bbca6 --- /dev/null +++ b/man/time_interpolate.Rd @@ -0,0 +1,46 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/time_interpolate.R +\name{time_interpolate} +\alias{time_interpolate} +\title{time_interpolate} +\usage{ +time_interpolate(dataset, interpolated_year, + integrate_interpolated_years = FALSE, extrapolation_type = "linear") +} +\arguments{ +\item{dataset}{An MAgPIE object} + +\item{interpolated_year}{Vector of years, of which values are required. Can +be in the formats 1999 or y1999.} + +\item{integrate_interpolated_years}{FALSE returns only the dataset of the +interpolated year, TRUE returns the whole dataset, including all years of +data and the itnerpolated year} + +\item{extrapolation_type}{Determines what happens if extrapolation is +required, i.e. if a requested year lies outside the range of years in +\code{dataset}. Specify "linear" for a linear extrapolation. "constant" uses +the value from dataset closest in time to the requested year.} +} +\value{ +Uses linear extrapolation to estimate the values of the interpolated +year, using the values of the two surrounding years. If the value is before +or after the years in data, the two closest neighbours are used for +extrapolation. +} +\description{ +Function to extrapolate missing years in MAgPIE objects. +} +\examples{ + +data(population_magpie) +time_interpolate(population_magpie,"y2000",integrate=TRUE) +time_interpolate(population_magpie,c("y1980","y2000"),integrate=TRUE,extrapolation_type="constant") + +} +\seealso{ +\code{\link{lin.convergence}} +} +\author{ +Benjamin Bodirsky, Jan Philipp Dietrich +} diff --git a/man/unwrap.Rd b/man/unwrap.Rd new file mode 100644 index 00000000..b7790242 --- /dev/null +++ b/man/unwrap.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/unwrap.R +\name{unwrap} +\alias{unwrap} +\title{Unwrap} +\usage{ +unwrap(x, sep = ".") +} +\arguments{ +\item{x}{A MAgPIE object} + +\item{sep}{A character separating joined dimension names} +} +\value{ +An array with the full dimensionality of the original data +} +\description{ +Reconstruct the full dimensionality of a MAgPIE object +} +\examples{ + + a <- as.magpie(array(1:6,c(3,2),list(c("bla","blub","ble"),c("up","down")))) + fulldim(a) + unwrap(a) + +} +\seealso{ +\code{\link{wrap}},\code{\link{fulldim}} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/where.Rd b/man/where.Rd new file mode 100644 index 00000000..4021be95 --- /dev/null +++ b/man/where.Rd @@ -0,0 +1,33 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/where.R +\name{where} +\alias{where} +\title{where} +\usage{ +where(x, plot = NULL) +} +\arguments{ +\item{x}{A logical statement with a magpie object} + +\item{plot}{depreciated. Use the function whereplot in package luplot.} +} +\value{ +A list of analysis parameters +} +\description{ +Analysis function for magpie objects +} +\examples{ + +data(population_magpie) + test<-population_magpie + dimnames(test)[[1]]<-c("AFG","DEU","FRA","EGY","IND","IDN","RUS","CHN","USA","YEM") + where(test>500) + +} +\seealso{ +whereplot in package luplot +} +\author{ +Benjamin Leon Bodirsky +} diff --git a/man/wrap.Rd b/man/wrap.Rd new file mode 100644 index 00000000..bbd692a5 --- /dev/null +++ b/man/wrap.Rd @@ -0,0 +1,33 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/wrap.R +\name{wrap} +\alias{wrap} +\title{Wrap} +\usage{ +wrap(x, map = list(NA), sep = ".") +} +\arguments{ +\item{x}{An array} + +\item{map}{A list of length equal to the number of dimensions in the +reshaped array. Each element should be an integer vectors specifying the +dimensions to be joined in corresponding new dimension. One element may +equal NA to indicate that that dimension should be a join of all +non-specified (remaining) dimensions. Default is to wrap everything into a +vector.} + +\item{sep}{A character separating joined dimension names} +} +\description{ +Reshape an array or a matrix by permuting and/or joining dimensions. +} +\note{ +This function is extracted from the R.utils library which is licensed +under LGPL>=2.1 and written by Henrik Bengtsson. +} +\seealso{ +\code{\link{unwrap}},\code{\link{fulldim}} +} +\author{ +Henrik Bengtsson, Jan Philipp Dietrich +} diff --git a/man/write.magpie.Rd b/man/write.magpie.Rd new file mode 100644 index 00000000..49072f29 --- /dev/null +++ b/man/write.magpie.Rd @@ -0,0 +1,120 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/write.magpie.R +\name{write.magpie} +\alias{write.magpie} +\title{Write MAgPIE-object to file} +\usage{ +write.magpie(x, file_name, file_folder = "", file_type = NULL, + append = FALSE, comment = NULL, comment.char = "*", mode = NULL, + nc_compression = 9) +} +\arguments{ +\item{x}{MAgPIE-object} + +\item{file_name}{file name including file ending (wildcards are supported). +Optionally also the full path can be specified here (instead of splitting it +to file\_name and file\_folder)} + +\item{file_folder}{folder the file should be written to (alternatively you +can also specify the full path in file\_name - wildcards are supported)} + +\item{file_type}{Format the data should be stored as. Currently 11 formats +are available: "cs2" (cellular standard MAgPIE format), "csv" (regional +standard MAgPIE format), "cs3" (Format for multidimensional MAgPIE data, +compatible to GAMS), "cs4" (alternative multidimensional format compatible +to GAMS, in contrast to cs3 it can also handle sparse data), "csvr", "cs2r", +"cs3r" and "cs4r" which are the same formats as the previous mentioned ones +with the only difference that they have a REMIND compatible format, "m" +(binary MAgPIE format "magpie"), "mz" (compressed binary MAgPIE format +"magpie zipped"), "asc" (ASCII grid format / only available for 0.5deg data) +and "nc" (netCDF format / only available for 0.5deg data). If +file\_type=NULL the file ending of the file\_name is used as format. If +format is different to the formats mentioned standard MAgPIE format is +assumed. Please be aware that the file\_name is independent of the +file\_type you choose here, so no additional file ending will be added!} + +\item{append}{Decides whether an existing file should be overwritten (FALSE) +or the data should be added to it (TRUE). Append = TRUE only works if the +existing data can be combined with the new data using the mbind function} + +\item{comment}{Vector of strings: Optional comment giving additional +information about the data. If different to NULL this will overwrite the +content of attr(x,"comment")} + +\item{comment.char}{character: a character vector of length one containing a +single character or an empty string. Use "" to turn off the interpretation +of comments altogether.} + +\item{mode}{File permissions the file should be written with as 3-digit +number (e.g. "777" means full access for user, group and all, "750" means +full access for user, read access for group and no acess for anybody else). +Set to NULL system defaults will be used. Access codes are identical to the +codes used in unix function chmod.} + +\item{nc_compression}{Only used if file\_type="nc". Sets the compression +level for netCDF files (default is 9). If set to an integer between 1 (least +compression) and 9 (most compression), the netCDF file is written in netCDF +version 4 format. If set to NA, the netCDF file is written in netCDF version +3 format.} +} +\description{ +Writes a MAgPIE-3D-array (cells,years,datacolumn) to a file in one of three +MAgPIE formats (standard, "magpie", "magpie zipped") +} +\details{ +This function can write 9 different MAgPIE file\_types. "cs2" is the new +standard format for cellular data with or without header and the first +columns (year,regiospatial) or only (regiospatial), "csv" is the standard +format for regional data with or without header and the first columns +(year,region,cellnumber) or only (region,cellnumber), "cs3" is another csv +format which is specifically designed for multidimensional data for usage in +GAMS. All these variants are written without further specification. +"magpie" (.m) and "magpie zipped" (.mz) are new formats developed to allow a +less storage intensive management of MAgPIE-data. The only difference +between both formats is that .mz is gzipped whereas .m is not compressed. So +.mz needs less memory, whereas .m might have a higher compatibility to other +languages. "asc" is the ASCII grid format. "nc" is the netCDF format. It +can only be applied for half degree data and writes one file per year per +data column. In the case that more than one year and data column is supplied +several files are written with the structure filename_year_datacolumn.asc +} +\note{ +The binary MAgPIE formats .m and .mz have the following content/structure +(you only have to care for that if you want to implement +read.magpie/write.magpie functions in other languages): \cr \cr +[ FileFormatVersion | Current file format version number (currently 2) | integer | 2 Byte ] \cr +[ nchar_comment | Number of characters of the file comment | integer | 4 Byte ] \cr +[ nchar_sets | Number of characters of all regionnames + 2 delimiter | integer | 2 Byte] \cr +[ not used | Bytes reserved for later file format improvements | integer | 92 Byte ] \cr +[ nyears | Number of years | integer | 2 Byte ]\cr +[ year_list | All years of the dataset (0, if year is not present) | integer | 2*nyears Byte ] \cr +[ nregions | Number of regions | integer | 2 Byte ] \cr +[ nchar_reg | Number of characters of all regionnames + (nreg-1) for delimiters | integer | 2 Byte ] \cr +[ regions | Regionnames saved as reg1\\nreg2 (\\n is the delimiter) | character | 1*nchar_reg Byte ] \cr +[ cpr | Cells per region | integer | 4*nreg Byte ] \cr +[ nelem | Total number of data elements | integer | 4 Byte ] \cr +[ nchar_data | Number of char. of all datanames + (ndata - 1) for delimiters | integer | 4 Byte ] \cr +[ datanames | Names saved in the format data1\\ndata2 (\\n as del.) | character | 1*nchar_data Byte ] \cr +[ data | Data of the MAgPIE array in vectorized form | numeric | 4*nelem Byte ] \cr +[ comment | Comment with additional information about the data | character | 1*nchar_comment Byte ] \cr +[ sets | Set names with \\n as delimiter | character | 1*nchar_sets Byte] \cr + +Please note that if your data in the spatial dimension is not ordered by +region name each new appearance of a region which already appeared before +will be treated and counted as a new region (e.g. +AFR.1,AFR.2,CPA.3,CPA.4,AFR.5 will count AFR twice and nregions will be set +to 3!). +} +\examples{ + +# a <- read.magpie("lpj_yield_ir.csv") +# write.magpie(a,"lpj_yield_ir.mz") + +} +\seealso{ +\code{"\linkS4class{magpie}"}, +\code{\link{read.magpie}},\code{\link{mbind}} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/write.report.Rd b/man/write.report.Rd new file mode 100644 index 00000000..25a1d136 --- /dev/null +++ b/man/write.report.Rd @@ -0,0 +1,53 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/write.report.R +\name{write.report} +\alias{write.report} +\title{Write file in report format} +\usage{ +write.report(x, file = NULL, model = "MAgPIE", scenario = "default", + unit = NA, ndigit = 4, append = FALSE, skipempty = TRUE) +} +\arguments{ +\item{x}{MAgPIE object or a list of lists with MAgPIE objects as created by +read.report. In the latter case settings for model and scenario are +overwritten by the information given in the list.} + +\item{file}{file name the object should be written to. If NULL the formatted +content is returned} + +\item{model}{Name of the model which calculated the results} + +\item{scenario}{The scenario which was used to get that results.} + +\item{unit}{Unit of the data. Only relevant if unit is not already supplied +in Dimnames (format "name (unit)"). Can be either a single string or a +vector of strings with a length equal to the number of different data +elements in the MAgPIE object} + +\item{ndigit}{Number of digits the output should have} + +\item{append}{Logical which decides whether data should be added to an +existing file or an existing file should be overwritten} + +\item{skipempty}{Determines whether empty entries (all data NA) should be +written to file or not.} +} +\description{ +This function writes the content of a MAgPIE object into a file or returns +it directly using the reporting format as it is used for many model +intercomparisons. +} +\examples{ + +\dontrun{ +data(population_magpie) +write.report(population_magpie) +} + +} +\seealso{ +\code{\link{read.report}} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/write.report2.Rd b/man/write.report2.Rd new file mode 100644 index 00000000..6922ece9 --- /dev/null +++ b/man/write.report2.Rd @@ -0,0 +1,52 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/write.report2.R +\name{write.report2} +\alias{write.report2} +\title{Write file in report format} +\usage{ +write.report2(x, file = NULL, model = NULL, scenario = NULL, + unit = NULL, ndigit = 4, append = FALSE, skipempty = TRUE) +} +\arguments{ +\item{x}{MAgPIE object or a list of lists with MAgPIE objects as created by +read.report. In the latter case settings for model and scenario are +overwritten by the information given in the list.} + +\item{file}{file name the object should be written to. If NULL the formatted +content is returned} + +\item{model}{Name of the model which calculated the results} + +\item{scenario}{The scenario which was used to get that results.} + +\item{unit}{Unit of the data. Only relevant if unit is not already supplied +in Dimnames (format "name (unit)"). Can be either a single string or a +vector of strings with a length equal to the number of different data +elements in the MAgPIE object} + +\item{ndigit}{Number of digits the output should have} + +\item{append}{Logical which decides whether data should be added to an +existing file or an existing file should be overwritten} + +\item{skipempty}{Determines whether empty entries (all data NA) should be +written to file or not.} +} +\description{ +This function writes the content of a MAgPIE object into a file or returns +it directly using the reporting format as it is used for many model +intercomparisons. It is a rewritten version of write.report and will +probably replace write.report somewhen in the future +} +\examples{ + +data(population_magpie) +write.report2(population_magpie) + +} +\seealso{ +\code{\link{read.report}} +} +\author{ +Jan Philipp Dietrich +} diff --git a/man/write.reportProject.Rd b/man/write.reportProject.Rd new file mode 100644 index 00000000..ee9f479c --- /dev/null +++ b/man/write.reportProject.Rd @@ -0,0 +1,36 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/write.reportProject.R +\name{write.reportProject} +\alias{write.reportProject} +\title{Write file in specific project format} +\usage{ +write.reportProject(mif, mapping, file = NULL) +} +\arguments{ +\item{mif}{Lists with magpie-objects or a magpie-object as created by read.report or a path to +a report.mif} + +\item{mapping}{mapping of the varialbe names of the read in mif. the header +is used for naming.} + +\item{file}{name of the project specipic report, default=NULL means that the names of the header of the reporting is used} +} +\description{ +Reads in a reporting.mif or uses a magpie object based on a read in +reporting.mif, substitutes names of variables according to the mappping, +mutliplies by an optional factor in the 3rd column of the mapping, and saves +the output in a new *.mif +} +\examples{ + +\dontrun{ +write.reportProject("REMIND_generic_test.mif","Mapping_generic_ADVANCE.csv") +} + +} +\seealso{ +\code{\link{write.report}} +} +\author{ +Christoph Bertram, Lavinia Baumstark, Anastasis Giannousakis +} diff --git a/tests/testthat.R b/tests/testthat.R new file mode 100644 index 00000000..906addfe --- /dev/null +++ b/tests/testthat.R @@ -0,0 +1,4 @@ +library(testthat) +library(magclass) + +test_check("magclass") diff --git a/tests/testthat/test-as.magpie.R b/tests/testthat/test-as.magpie.R new file mode 100644 index 00000000..0aaf5c7c --- /dev/null +++ b/tests/testthat/test-as.magpie.R @@ -0,0 +1,9 @@ +context("Conversion Test") + +test_that("conversions do not affect content", { + data("population_magpie") + mag <- population_magpie + expect_identical(as.magpie(mag),mag) + expect_identical(as.magpie(as.array(mag)),mag) +# expect_identical(as.magpie(as.data.frame(mag)),mag) +}) \ No newline at end of file diff --git a/tests/testthat/test-readwritemagpie.R b/tests/testthat/test-readwritemagpie.R new file mode 100644 index 00000000..54720d37 --- /dev/null +++ b/tests/testthat/test-readwritemagpie.R @@ -0,0 +1,16 @@ +context("Read/Write Test") + +test_that("read/write do not affect content", { + data("population_magpie") + mag <- population_magpie + names(dimnames(mag)) <- NULL + getNames(mag) <- c("A2-A","B1-A") + for(ext in c(".csv",".cs3",".cs4")) { + tmpfile <- tempfile(fileext = ext) + write.magpie(mag,tmpfile) + mag2 <- read.magpie(tmpfile) + names(dimnames(mag2)) <- NULL + expect_equal(mag,mag2) + } +}) +