diff --git a/NAMESPACE b/NAMESPACE index a2617a6c..4a6ea34e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -37,6 +37,7 @@ export(extractDataList) export(getAlias) export(getAreas) export(getDistricts) +export(getGeographicTrimming) export(getIdCols) export(getLinks) export(hvdcModification) @@ -52,6 +53,7 @@ export(readClusterResDesc) export(readIni) export(readIniAPI) export(readIniFile) +export(readInputRES) export(readInputTS) export(readInputThermal) export(readLayout) diff --git a/NEWS.md b/NEWS.md index 76ec5abb..54b52918 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,10 +4,12 @@ NEW FEATURES: -Function `getLinks()` now has a new argument **withTransmission**. if TRUE, return additional -column with type of transmission capacities +* New function `getGeographicTrimming()` returns filtering options for selected areas (links optional). +* New function added : `readInputRes()` for reading renewable clusters input data +* Existing function `getLinks()` now has a new argument **withTransmission**. if TRUE, return additional column with type of transmission capacities. +* Existing function `readInputThermal()` : added new argument for thermalData # antaresRead 2.4.1 @@ -38,11 +40,11 @@ Major upgrade to `aggregateResult()` and `parAggregateMCall()` : NEW FEATURES: -added "profit by cluster" when reading cluster data +added "profit by cluster" when reading cluster data. BUGFIXES: -Fix for 404 error when some output is missing in API mode(#188) +Fix for 404 error when some output is missing in API mode(#188). diff --git a/R/getGeographicTrimming.R b/R/getGeographicTrimming.R new file mode 100644 index 00000000..135d5767 --- /dev/null +++ b/R/getGeographicTrimming.R @@ -0,0 +1,49 @@ +#Copyright © 2016 RTE Réseau de transport d’électricité + +#' Read geographic trimming (filtering) options +#' +#' @param areas Character. vector of areas +#' @param links Logical. if TRUE, return filtering options for all links starting from selected areas +#' @param opts List. simulation options +#' +#' @return list of filtering options for areas and links +#' +#' @export +getGeographicTrimming <- function(areas = NULL, links = TRUE, opts = simOptions()){ + if (is.null(areas)) stop("You need to select at least one area.") + if (areas == "all") areas <- opts$areaList + + res <- list() + + if(!is.null(areas)){ + areaData <- lapply(as.list(areas), .readPropertiesFunction, opts2 = opts, type = "areas") + names(areaData) <- areas + res$areas <- areaData + } + + if (links){ + linkData <- lapply(as.list(areas), .readPropertiesFunction, opts2 = opts, type = "links") + names(linkData) <- areas + linkData <- unlist(linkData, recursive = F) + names(linkData) <- gsub("\\.", " - ", names(linkData)) + res$links <- linkData + } + + res +} + +.readPropertiesFunction <- function(x, opts2, type){ + if (type == "areas"){ + if (opts2$typeLoad != "api"){ + inputPath <- file.path(opts2$inputPath, "areas", x, "optimization.ini") + readIniFile(inputPath)$filtering + } else readIni(file.path("input", "areas", x, "optimization"))$filtering + + } else if (type == "links"){ + if (opts2$typeLoad != "api"){ + inputPath <- file.path(opts2$inputPath, "links", x, "properties.ini") + lapply(as.list(readIniFile(inputPath)), function(x){x[grep("filter", names(x))]}) + } else lapply(as.list(readIni(file.path("input", "links", x, "properties"))), function(x){x[grep("filter", names(x))]}) + } +} + diff --git a/R/importInput.R b/R/importInput.R index 29d499e8..9419e0de 100644 --- a/R/importInput.R +++ b/R/importInput.R @@ -324,6 +324,52 @@ } + + + +.importThermalData <- function(area, opts, timeStep, unselect = NULL, ...) { + if (!area %in% opts$areasWithClusters) return(NULL) + unselect <- unselect$areas + path <- file.path(opts$inputPath, "thermal/prepro", area) + + if(!"api" %in% opts$typeLoad){ + clusters <- list.files(path) + } else { + clusters <- names(read_secure_json(path, token = opts$token, timeout = opts$timeout, config = opts$httr_config)) + } + + beginName <- c("FODuration", "PODuration", "FORate", "PORate", "NPOMin", "NPOMax") + if(!is.null(unselect)){ + colSelect <- which(!beginName%in%unselect) + names <- beginName[colSelect] + }else{ + colSelect <- NULL + names <- beginName + } + + + res <- ldply(clusters, function(cl) { + if(is.null(colSelect)) + { + # data <- fread(file.path(path, cl, "data.txt"), colClasses = "numeric") + data <- fread_antares(opts = opts, file = file.path(path, cl, "data.txt"), colClasses = "numeric") + }else{ + # data <- fread(file.path(path, cl, "data.txt"), select = colSelect, colClasses = "numeric") + data <- fread_antares(opts = opts, file = file.path(path, cl, "data.txt"), select = colSelect, colClasses = "numeric") + } + + setnames(data, + names(data), names) + + data$area <- area + data$cluster <- cl + data <- data[opts$timeIdMin:opts$timeIdMax] + data$timeId <- opts$timeIdMin:opts$timeIdMax + + changeTimeStep(data, timeStep, "daily", fun = "mean") + }) +} + .importThermalModulation <- function(area, opts, timeStep, unselect = NULL, ...) { if (!area %in% opts$areasWithClusters) return(NULL) unselect <- unselect$areas @@ -359,11 +405,8 @@ setnames(modulation, names(modulation), names) - - if (all(modulation$minGenModulation == 0)) modulation[, minGenModulation := NA_real_] - modulation$area <- area modulation$cluster <- cl modulation <- modulation[opts$timeIdMin:opts$timeIdMax] diff --git a/R/readInputThermal.R b/R/readInputClusters.R similarity index 51% rename from R/readInputThermal.R rename to R/readInputClusters.R index 0b74d6c5..d902c274 100644 --- a/R/readInputThermal.R +++ b/R/readInputClusters.R @@ -9,11 +9,12 @@ #' #' @param clusters vector of clusters names for which thermal time series must be read. #' @param thermalModulation if TRUE, return thermalModulation data +#' @param thermalData if TRUE, return thermalData from prepro #' @inheritParams readAntares #' #' @return -#' If thermalModulation is TRUE, an object of class "antaresDataList" is returned. It is a list of -#' data.tables for thermalAvailabilities and thermalModulation +#' If thermalModulation or thermalData is TRUE, an object of class "antaresDataList" is returned. It is a list of +#' data.tables for selected input #' #' Else the result is a data.table with class "antaresDataTable". #' @@ -26,7 +27,7 @@ #' \code{\link{getAreas}}, \code{\link{getLinks}} #' #' @export -readInputThermal <- function(clusters = NULL, thermalModulation = FALSE, +readInputThermal <- function(clusters = NULL, thermalModulation = FALSE, thermalData = FALSE, opts = simOptions(), timeStep = c("hourly", "daily", "weekly", "monthly", "annual"), simplify = TRUE, parallel = FALSE, @@ -86,9 +87,97 @@ readInputThermal <- function(clusters = NULL, thermalModulation = FALSE, if (nrow(thermalMod) > 0) res$thermalModulation <- thermalMod } + + # thermalData processing + if (thermalData){ + areas <- unique(allAreasClusters[cluster %in% clusters]$area) + thermalDat <- as.data.table(ldply(areas, .importThermalData, opts = opts, timeStep = timeStep)) + thermalDat <- thermalDat[cluster %in% clusters] + setcolorder(thermalDat, c("area", "cluster", "timeId", setdiff(names(thermalDat), c("area", "cluster", "timeId")))) + + if (nrow(thermalDat) > 0) res$thermalData <- thermalDat + } if (length(res) == 0) stop("At least one argument of readInputTS has to be defined.") + # Class and attributes + res <- .addClassAndAttributes(res, NULL, timeStep, opts, simplify) + addDateTimeColumns(res) +} + + + + +#' Read Input RES time series +#' +#' @description +#' \code{readInputRes} is a function that reads renewable time series from an antares +#' project. But contrary to \code{\link{readAntares}}, it only reads time series +#' stored in the input folder, so it can work in "input" mode. +#' +#' @param clusters vector of RES clusters names for which renewable time series must be read. +#' @inheritParams readAntares +#' +#' @return +#' data.table with class "antaresDataTable". +#' +#' @seealso +#' \code{\link{setSimulationPath}}, \code{\link{readAntares}}, +#' \code{\link{getAreas}}, \code{\link{getLinks}} +#' +#' @export +readInputRES <- function(clusters = NULL, opts = simOptions(), + timeStep = c("hourly", "daily", "weekly", "monthly", "annual"), + simplify = TRUE, parallel = FALSE, + showProgress = TRUE) { + + timeStep <- match.arg(timeStep) + + # Can the importation be parallelized ? + if (parallel) { + if(!requireNamespace("foreach")) stop("Parallelized importation impossible. Please install the 'foreach' package and a parallel backend provider like 'doParallel'.") + if (!foreach::getDoParRegistered()) stop("Parallelized importation impossible. Please register a parallel backend, for instance with function 'registerDoParallel'") + } + + allAreasClusters <- readClusterResDesc()[area %in% opts$areasWithResClusters, c("area", "cluster")] + allClusters <- unique(allAreasClusters$cluster) + # Manage special value "all" + if(identical(clusters, "all")) clusters <- allClusters + + if (length(setdiff(tolower(clusters), tolower(allClusters))) > 0){ + cat(c("the following clusters are not available : ",setdiff(tolower(clusters), tolower(allClusters)))) + stop("Some clusters are not available in the areas specified") + } + + ind_cluster <- which(tolower(allClusters) %in% tolower(clusters)) + clusters <- unique(allClusters[ind_cluster]) + res <- list() # Object the function will return + + ResTS <- as.data.table(ldply(clusters, function(cl) { + + area <- unique(allAreasClusters[cluster == cl]$area) + if (length(area) > 1) warning(cl," is in more than one area") + resCl <- ldply(area, function(x){ + filePattern <- sprintf("%s/%s/%%s/series.txt", "renewables/series", x) + mid <- .importInputTS(cl, timeStep, opts, filePattern, "production", + inputTimeStep = "hourly", type = "matrix") + if (is.null(mid)) return (data.table()) + mid$area <- x + mid$cluster <- cl + mid + }) + + resCl <- dcast(as.data.table(resCl), area + cluster + timeId ~ tsId, value.var = "production") + })) + + tsCols <- setdiff(colnames(ResTS), c("area", "cluster", "timeId")) + setnames(ResTS, tsCols, paste0("ts",tsCols)) + setcolorder(ResTS, c("area", "cluster", "timeId", setdiff(names(ResTS), c("area", "cluster", "timeId")))) + + if (nrow(ResTS) > 0) res$ResProduction <- ResTS + + if (length(res) == 0) stop("At least one argument of readInputRes has to be defined.") + # Class and attributes res <- .addClassAndAttributes(res, NULL, timeStep, opts, simplify) addDateTimeColumns(res) diff --git a/docs/articles/antaresH5.html b/docs/articles/antaresH5.html index e1e80217..0426e9ec 100644 --- a/docs/articles/antaresH5.html +++ b/docs/articles/antaresH5.html @@ -84,7 +84,7 @@
vignettes/antaresH5.Rmd
antaresH5.Rmd
vignettes/antaresRead.Rmd
antaresRead.Rmd
NEW FEATURES:
-Function getLinks()
now has a new argument withTransmission. if TRUE, return additional column with type of transmission capacities
New function getGeographicTrimming()
returns filtering options for selected areas (links optional).
New function added : readInputRes()
for reading renewable clusters input data
Existing function getLinks()
now has a new argument withTransmission. if TRUE, return additional column with type of transmission capacities.
Existing function readInputThermal()
: added new argument for thermalData
NEW FEATURES:
@@ -78,9 +81,9 @@NEW FEATURES:
-added “profit by cluster” when reading cluster data
+added “profit by cluster” when reading cluster data.
BUGFIXES:
-Fix for 404 error when some output is missing in API mode(#188)
+Fix for 404 error when some output is missing in API mode(#188).
R/getGeographicTrimming.R
+ getGeographicTrimming.Rd
Read geographic trimming (filtering) options
+getGeographicTrimming(areas = NULL, links = TRUE, opts = simOptions())
Character. vector of areas
Logical. if TRUE, return filtering options for all links starting from selected areas
List. simulation options
list of filtering options for areas and links
+getAreas()
getDistricts()
Select and exclude areas
Read geographic trimming (filtering) options
readClusterDesc()
readClusterResDesc()
Import clusters description
Read Input RES time series
readInputRes
is a function that reads renewable time series from an antares
+project. But contrary to readAntares
, it only reads time series
+stored in the input folder, so it can work in "input" mode.
readInputRES(
+ clusters = NULL,
+ opts = simOptions(),
+ timeStep = c("hourly", "daily", "weekly", "monthly", "annual"),
+ simplify = TRUE,
+ parallel = FALSE,
+ showProgress = TRUE
+)
vector of RES clusters names for which renewable time series must be read.
list of simulation parameters returned by the function
+setSimulationPath
Resolution of the data to import: hourly (default), daily, +weekly, monthly or annual.
If TRUE and only one type of output is imported then a +data.table is returned. If FALSE, the result will always be a list of class +"antaresData".
Should the importation be parallelized ? (See details)
If TRUE the function displays information about the progress of the +importation.
data.table with class "antaresDataTable".
+R/readInputThermal.R
+ Source: R/readInputClusters.R
readInputThermal.Rd
readInputThermal(
clusters = NULL,
thermalModulation = FALSE,
+ thermalData = FALSE,
opts = simOptions(),
timeStep = c("hourly", "daily", "weekly", "monthly", "annual"),
simplify = TRUE,
@@ -91,6 +92,10 @@ Arguments
if TRUE, return thermalModulation data
+thermalData
+if TRUE, return thermalData from prepro
+
+
opts
list of simulation parameters returned by the function
setSimulationPath
@@ -120,8 +125,8 @@ Arguments
Value
-If thermalModulation is TRUE, an object of class "antaresDataList" is returned. It is a list of
-data.tables for thermalAvailabilities and thermalModulation
+If thermalModulation or thermalData is TRUE, an object of class "antaresDataList" is returned. It is a list of
+data.tables for selected input
Else the result is a data.table with class "antaresDataTable".
diff --git a/docs/sitemap.xml b/docs/sitemap.xml
index 245f3dd8..40af2f27 100644
--- a/docs/sitemap.xml
+++ b/docs/sitemap.xml
@@ -57,6 +57,9 @@
/reference/getAreas.html
+
+ /reference/getGeographicTrimming.html
+
/reference/getIdCols.html
@@ -93,6 +96,9 @@
/reference/readClusterDesc.html
+
+ /reference/readInputRES.html
+
/reference/readInputThermal.html
diff --git a/man/getGeographicTrimming.Rd b/man/getGeographicTrimming.Rd
new file mode 100644
index 00000000..20d526ce
--- /dev/null
+++ b/man/getGeographicTrimming.Rd
@@ -0,0 +1,21 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/getGeographicTrimming.R
+\name{getGeographicTrimming}
+\alias{getGeographicTrimming}
+\title{Read geographic trimming (filtering) options}
+\usage{
+getGeographicTrimming(areas = NULL, links = TRUE, opts = simOptions())
+}
+\arguments{
+\item{areas}{Character. vector of areas}
+
+\item{links}{Logical. if TRUE, return filtering options for all links starting from selected areas}
+
+\item{opts}{List. simulation options}
+}
+\value{
+list of filtering options for areas and links
+}
+\description{
+Read geographic trimming (filtering) options
+}
diff --git a/man/readInputRES.Rd b/man/readInputRES.Rd
new file mode 100644
index 00000000..567e7d9f
--- /dev/null
+++ b/man/readInputRES.Rd
@@ -0,0 +1,45 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/readInputClusters.R
+\name{readInputRES}
+\alias{readInputRES}
+\title{Read Input RES time series}
+\usage{
+readInputRES(
+ clusters = NULL,
+ opts = simOptions(),
+ timeStep = c("hourly", "daily", "weekly", "monthly", "annual"),
+ simplify = TRUE,
+ parallel = FALSE,
+ showProgress = TRUE
+)
+}
+\arguments{
+\item{clusters}{vector of RES clusters names for which renewable time series must be read.}
+
+\item{opts}{list of simulation parameters returned by the function
+\code{\link{setSimulationPath}}}
+
+\item{timeStep}{Resolution of the data to import: hourly (default), daily,
+weekly, monthly or annual.}
+
+\item{simplify}{If TRUE and only one type of output is imported then a
+data.table is returned. If FALSE, the result will always be a list of class
+"antaresData".}
+
+\item{parallel}{Should the importation be parallelized ? (See details)}
+
+\item{showProgress}{If TRUE the function displays information about the progress of the
+importation.}
+}
+\value{
+data.table with class "antaresDataTable".
+}
+\description{
+\code{readInputRes} is a function that reads renewable time series from an antares
+project. But contrary to \code{\link{readAntares}}, it only reads time series
+stored in the input folder, so it can work in "input" mode.
+}
+\seealso{
+\code{\link{setSimulationPath}}, \code{\link{readAntares}},
+\code{\link{getAreas}}, \code{\link{getLinks}}
+}
diff --git a/man/readInputThermal.Rd b/man/readInputThermal.Rd
index 6ef27374..68db2342 100644
--- a/man/readInputThermal.Rd
+++ b/man/readInputThermal.Rd
@@ -1,5 +1,5 @@
% Generated by roxygen2: do not edit by hand
-% Please edit documentation in R/readInputThermal.R
+% Please edit documentation in R/readInputClusters.R
\name{readInputThermal}
\alias{readInputThermal}
\title{Read Input thermal time series}
@@ -7,6 +7,7 @@
readInputThermal(
clusters = NULL,
thermalModulation = FALSE,
+ thermalData = FALSE,
opts = simOptions(),
timeStep = c("hourly", "daily", "weekly", "monthly", "annual"),
simplify = TRUE,
@@ -19,6 +20,8 @@ readInputThermal(
\item{thermalModulation}{if TRUE, return thermalModulation data}
+\item{thermalData}{if TRUE, return thermalData from prepro}
+
\item{opts}{list of simulation parameters returned by the function
\code{\link{setSimulationPath}}}
@@ -35,8 +38,8 @@ data.table is returned. If FALSE, the result will always be a list of class
importation.}
}
\value{
-If thermalModulation is TRUE, an object of class "antaresDataList" is returned. It is a list of
-data.tables for thermalAvailabilities and thermalModulation
+If thermalModulation or thermalData is TRUE, an object of class "antaresDataList" is returned. It is a list of
+data.tables for selected input
Else the result is a data.table with class "antaresDataTable".
}
diff --git a/tests/testthat/test-getGeographicTrimming.R b/tests/testthat/test-getGeographicTrimming.R
new file mode 100644
index 00000000..4bc7f63c
--- /dev/null
+++ b/tests/testthat/test-getGeographicTrimming.R
@@ -0,0 +1,15 @@
+#Copyright © 2016 RTE Réseau de transport d’électricité
+
+context("Function getGeographicTrimming")
+
+sapply(studyPathS, function(studyPath){
+
+ opts <- setSimulationPath(studyPath)
+
+ test_that("Areas filtering is ok", {
+ filtering <- getGeographicTrimming(areas = "all", links = T, opts = opts)
+ expect_identical(names(filtering), c("areas", "links"))
+ expect_true(length(filtering$areas) == length(opts$areaList))
+ })
+
+})
diff --git a/tests/testthat/test-readInputThermal.R b/tests/testthat/test-readInputClusters.R
similarity index 69%
rename from tests/testthat/test-readInputThermal.R
rename to tests/testthat/test-readInputClusters.R
index 043cf63c..7d45eafd 100644
--- a/tests/testthat/test-readInputThermal.R
+++ b/tests/testthat/test-readInputClusters.R
@@ -23,5 +23,13 @@ sapply(studyPathS, function(studyPath){
expect_equal(nrow(input$thermalModulation) %% (24 * 7 * nweeks), 0)
})
+ test_that("Thermal data importation works", {
+ input <- readInputThermal(clusters = "peak_must_run_partial", thermalModulation = TRUE, showProgress = FALSE)
+ expect_is(input, "antaresDataList")
+ expect_is(input$thermalModulation, "antaresDataTable")
+ expect_gt(nrow(input$thermalModulation), 0)
+ expect_equal(nrow(input$thermalModulation) %% (24 * 7 * nweeks), 0)
+ })
+
}
})