Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read ST clusters with readAntares() #252

Merged
merged 15 commits into from
Jun 14, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@ Authors@R: c(
person("Clement", "Berthet", role = "ctb"),
person("Kamel", "Kemiha", role = "ctb"),
person("Abdallah", "Mahoudi", role = "ctb"),
person("Nicolas", "Boitard", role = "ctb"),
person("RTE", role = "cph")
)
Description: Import, manipulate and explore results generated by 'Antares', a
@@ -40,7 +41,8 @@ Imports:
utils,
memuse,
purrr,
lifecycle
lifecycle,
assertthat
Suggests:
rhdf5 (>= 2.24.0),
testthat,
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -79,6 +79,7 @@ import(doParallel)
import(jsonlite)
import(parallel)
import(plyr)
importFrom(assertthat,assert_that)
importFrom(doParallel,registerDoParallel)
importFrom(grDevices,col2rgb)
importFrom(grDevices,rgb)
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ NEW FEATURES:
* `readInputRES()` new parameter **areas** to get desired clusters from selected areas.
* `setSimulationPath()` return a new parameter `binding` (for studies >= v8.7.0).
It contains a table with group dimensions of time series for binding constraints.
* `readAntares()` new parameter **clustersST** to read (output simulation) short-term clusters

BREAKING CHANGES :

@@ -18,6 +19,7 @@ BREAKING CHANGES :
BUGFIXES :

* `readInputThermal()` return data from file data.txt with `thermalData` parameter
* `setSimulationPath()` has also the parameter **areasWithSTClusters** in 'output' mode


# antaresRead 2.7.0
167 changes: 92 additions & 75 deletions R/importOutput.R
Original file line number Diff line number Diff line change
@@ -47,6 +47,7 @@
#' - "areas", "values" => areas
#' - "areas", "details" => clusters
#' - "areas", "details-res" => renewables clusters
#' - "areas", "details-STstorage" => short-term clusters
#' - "links", "values" => links
#'
#' @return
@@ -281,30 +282,37 @@

#' .get_value_columns_details_file
#'
#' Private function used to get the column names for the details-timeStep.txt or details-res-timeStep.txt.
#' Used in .importOutputForClusters() and .importOutputForResClusters()
#' Private function used to get the column names for the details-timeStep.txt, details-res-timeStep.txt, or details-STstorage-timeStep.txt.
#' Used in .importOutputForClusters(), .importOutputForResClusters(), and .importOutputForSTClusters()
#' From the opts, we detect which outputs the user decides to take
#'
#' @return
#' a vector
#'
#' @importFrom assertthat assert_that
#'
#' @noRd
#'
.get_value_columns_details_file <- function(opts, type) {

if(type == "details") {
# Order is important. There is a correspondance between elements.
all_thematic_variables <- c("DTG by plant", "NP Cost by plant", "NODU by plant")
colNames <- c("production", "NP Cost", "NODU")
if (opts$antaresVersion >= 830){
all_thematic_variables <- c(all_thematic_variables, "Profit by plant")
colNames <- c(colNames, "profit")
}
} else if(type == "details-res") {
# Order is important. There is a correspondance between elements.
all_thematic_variables <- c("RES generation by plant")
colNames <- c("production")
}
assert_that(type %in% c("details","details-res","details-STstorage"))

simulation_variables_names_by_support <- read.table(system.file(
"format_output","simulation_variables_names_by_support.csv",package="antaresRead"
),sep=";",fileEncoding="UTF-8",header = TRUE)

filtered_variables_names <- subset(simulation_variables_names_by_support,DETAILS_FILES_TYPE==type)
if (type=="details" && opts$antaresVersion < 830)
filtered_variables_names <- subset(filtered_variables_names,ANTARES_DISPLAYED_NAME!="Profit by plant")

# Order is important. There is a correspondance between elements
ordered_filtered_variables_names <- filtered_variables_names[
order(filtered_variables_names$ORDINAL_POSITION_BY_TOPIC),
]

all_thematic_variables <- ordered_filtered_variables_names$ANTARES_DISPLAYED_NAME
colNames <- ordered_filtered_variables_names$RPACKAGE_DISPLAYED_NAME

# With thematic-trimming enabled
if (opts$parameters$general$`thematic-trimming`) {
if ("variables selection" %in% names(opts$parameters)) {
@@ -346,36 +354,8 @@
.importOutputForClusters <- function(areas, timeStep, select = NULL, mcYears = NULL,
showProgress, opts, mustRun = FALSE, parallel) {

# In output files, there is one file per area with the follwing form:
# cluster1-var1 | cluster2-var1 | cluster1-var2 | cluster2-var2
# the following function reshapes the result to have variable cluster in column.
# To improve greatly the performance we use our knowledge of the position of
# the columns instead of using more general functions like dcast.
reshapeFun <- function(x) {

# Get cluster names
n <- names(x)
idx <- ! n %in% pkgEnv$idVars
clusterNames <- tolower(unique(n[idx]))

# Id vars names
idVarsId <- which(!idx)
idVarsNames <- n[idVarsId]

# Column names of the output table
colNames <- .get_value_columns_details_file(opts, "details")

# Loop over clusters
nclusters <- length(clusterNames)

res <- llply(1:nclusters, function(i) {
dt <- x[, c(nclusters * 0:(length(colNames) - 1) + i, idVarsId), with = FALSE]
setnames(dt, c(colNames, idVarsNames))
dt[, cluster := as.factor(clusterNames[i])]
dt
})

rbindlist(res)
reshapeFun <- function(x){
.reshape_details_file(x,file_type="details",opts=opts)
}

if (!mustRun) {
@@ -488,6 +468,47 @@
}


#' .reshape_details_file
#'
#' In output files, there is one file per area with the follwing form:
#' cluster1-var1 | cluster2-var1 | cluster1-var2 | cluster2-var2
#' the following function reshapes the result to have variable cluster in column.
#' To improve greatly the performance we use our knowledge of the position of
#' the columns instead of using more general functions like dcast.
#'
#' @return
#' a data.table
#'
#' @noRd
#'
.reshape_details_file <- function(x,file_type,opts) {

# Get cluster names
n <- names(x)
idx <- ! n %in% pkgEnv$idVars
clusterNames <- tolower(unique(n[idx]))

# Id vars names
idVarsId <- which(!idx)
idVarsNames <- n[idVarsId]

# Column names of the output table
colNames <- .get_value_columns_details_file(opts=opts,type=file_type)

# Loop over clusters
nclusters <- length(clusterNames)

res <- llply(1:nclusters, function(i) {
dt <- x[, c(nclusters * 0:(length(colNames) - 1) + i, idVarsId), with = FALSE]
setnames(dt, c(colNames, idVarsNames))
dt[, cluster := as.factor(clusterNames[i])]
dt
})

rbindlist(res)
}


#' .importOutputForResClusters
#'
#' Private function used to import the output for the renewable clusters of one area
@@ -500,38 +521,11 @@
.importOutputForResClusters <- function(areas, timeStep, select = NULL, mcYears = NULL,
showProgress, opts, parallel) {

# In output files, there is one file per area with the follwing form:
# cluster1-var1 | cluster2-var1 | cluster1-var2 | cluster2-var2
# the following function reshapes the result to have variable cluster in column.
# To improve greatly the performance we use our knowledge of the position of
# the columns instead of using more general functions like dcast.

reshapeFun <- function(x) {

# Get cluster names
n <- names(x)
idx <- ! n %in% pkgEnv$idVars
clusterNames <- tolower(unique(n[idx]))

# Id vars names
idVarsId <- which(!idx)
idVarsNames <- n[idVarsId]

# Column names of the output table
colNames <- .get_value_columns_details_file(opts, "details-res")

# Loop over clusters
nclusters <- length(clusterNames)

res <- llply(1:nclusters, function(i) {
dt <- x[, c(nclusters * 0:(length(colNames) - 1) + i, idVarsId), with = FALSE]
setnames(dt, c(colNames, idVarsNames))
dt[, cluster := as.factor(clusterNames[i])]
dt
})

rbindlist(res)
.reshape_details_file(x,file_type="details-res",opts=opts)
}

suppressWarnings(
.importOutput("areas", "details-res", "area", areas, timeStep, NULL,
mcYears, showProgress, opts, reshapeFun, sameNames = FALSE,
@@ -540,6 +534,29 @@
}


#' .importOutputForSTClusters
#'
#' Private function used to import the output for the short-term clusters of one area
#'
#' @return
#' a data.table
#'
#' @noRd
#'
.importOutputForSTClusters <- function(areas, timeStep, select = NULL, mcYears = NULL,
showProgress, opts, parallel) {

reshapeFun <- function(x) {
.reshape_details_file(x,file_type="details-STstorage",opts=opts)
}

suppressWarnings(
.importOutput("areas", "details-STstorage", "area", areas, timeStep, NULL,
mcYears, showProgress, opts, reshapeFun, sameNames = FALSE,
objectDisplayName = "clustersST", parallel = parallel)
)
}

#' .importOutputForBindingConstraints
#'
#' Private function used to import the output for binding constraints.
32 changes: 27 additions & 5 deletions R/readAntares.R
Original file line number Diff line number Diff line change
@@ -14,6 +14,8 @@
#' Read the data of an Antares simulation
#'
#' @description
#' `r antaresRead:::badge_api_ok()`
#'
#' \code{readAntares} is a swiss-army-knife function used to read almost every
#' possible time series of an antares Project at any desired time resolution
#' (hourly, daily, weekly, monthly or annual).
@@ -85,6 +87,11 @@
#' import results at renewable cluster level. If \code{NULL} no cluster is imported. The
#' special value \code{"all"} tells the function to import renewable clusters from all
#' areas.
#' @param clustersST
#' Vector containing the name of the areas for which you want to
#' import results at short-term cluster level. If \code{NULL} no cluster is imported. The
#' special value \code{"all"} tells the function to import short-term clusters from all
#' areas.
#' @param bindingConstraints
#' Should binding constraints be imported (v8.4+)?
#' @param districts
@@ -210,8 +217,8 @@
#' @export
#'
readAntares <- function(areas = NULL, links = NULL, clusters = NULL,
districts = NULL, clustersRes = NULL, bindingConstraints = FALSE,
misc = FALSE, thermalAvailabilities = FALSE,
districts = NULL, clustersRes = NULL, clustersST = NULL,
bindingConstraints = FALSE, misc = FALSE, thermalAvailabilities = FALSE,
hydroStorage = FALSE, hydroStorageMaxPower = FALSE,
reserve = FALSE, linkCapacity = FALSE, mustRun = FALSE,
thermalModulation = FALSE,
@@ -221,7 +228,7 @@ readAntares <- function(areas = NULL, links = NULL, clusters = NULL,
mcWeights = NULL,
opts = simOptions(),
parallel = FALSE, simplify = TRUE, showProgress = TRUE) {

if((!is.null(opts$parameters$`other preferences`$`renewable-generation-modelling`) &&
!opts$parameters$`other preferences`$`renewable-generation-modelling` %in% "clusters") ||
is.null(opts$parameters$`other preferences`$`renewable-generation-modelling`)){
@@ -309,6 +316,7 @@ readAntares <- function(areas = NULL, links = NULL, clusters = NULL,
links = links,
clusters = clusters,
clustersRes = clustersRes,
clustersST = clustersST,
districts = districts,
mcYears = mcYears)

@@ -317,6 +325,7 @@ readAntares <- function(areas = NULL, links = NULL, clusters = NULL,
links <- reqInfos$links
clusters <- reqInfos$clusters
clustersRes <- reqInfos$clustersRes
clustersST <- reqInfos$clustersST
districts <- reqInfos$districts
mcYears <- reqInfos$mcYears
synthesis <- reqInfos$synthesis
@@ -328,7 +337,7 @@ readAntares <- function(areas = NULL, links = NULL, clusters = NULL,
return(aggregateResult(opts = opts,
verbose = showProgress,
filtering = TRUE,
selected = list(areas = areas, links = links, clusters = clusters, clustersRes = clustersRes),
selected = list(areas = areas, links = links, clusters = clusters, clustersRes = clustersRes, clustersST = clustersST),
timestep = timeStep,
writeOutput = FALSE,
mcWeights = mcWeights, mcYears = mcYears))
@@ -342,7 +351,7 @@ readAntares <- function(areas = NULL, links = NULL, clusters = NULL,
}

# If all arguments are NULL, import all areas
if (is.null(areas) & is.null(links) & is.null(clusters) & is.null(clustersRes) & is.null(districts)) {
if (is.null(areas) & is.null(links) & is.null(clusters) & is.null(clustersRes) & is.null(clustersST) & is.null(districts)) {
areas <- "all"
}

@@ -353,6 +362,7 @@ readAntares <- function(areas = NULL, links = NULL, clusters = NULL,
links <- .checkArg(links, opts$linkList, "Links %s do not exist in the simulation.")
clusters <- .checkArg(clusters, opts$areasWithClusters, "Areas %s do not exist in the simulation or do not have any thermal cluster.")
clustersRes <- .checkArg(clustersRes, opts$areasWithResClusters, "Areas %s do not exist in the simulation or do not have any renewable cluster.")
clustersST <- .checkArg(clustersST, opts$areasWithSTClusters, "Areas %s do not exist in the simulation or do not have any short-term cluster.")
districts <- .checkArg(districts, opts$districtList, "Districts %s do not exist in the simulation.")
mcYears <- .checkArg(mcYears, opts$mcYears, "Monte-Carlo years %s have not been exported.", allowDup = TRUE)

@@ -476,6 +486,12 @@ readAntares <- function(areas = NULL, links = NULL, clusters = NULL,
opts, parallel = parallel)
if(!is.null(res$clustersRes) && nrow(res$clustersRes) == 0) res$clustersRes <- NULL

# Import short-term clusters
res$clustersST <- .importOutputForSTClusters(clustersST, timeStep, NULL,
mcYears, showProgress,
opts, parallel = parallel)
if(!is.null(res$clustersST) && nrow(res$clustersST) == 0) res$clustersST <- NULL

# Import thermal clusters and eventually must run
if (!mustRun) {
res$clusters <- .importOutputForClusters(clusters, timeStep, NULL, mcYears,
@@ -820,6 +836,7 @@ readAntaresAreas <- function(areas, links = TRUE, clusters = TRUE, clustersRes =
links,
clusters,
clustersRes,
clustersST,
districts,
mcYears){

@@ -873,6 +890,10 @@ readAntaresAreas <- function(areas, links = TRUE, clusters = TRUE, clustersRes =
if (!is.null(areas)) clustersRes <- areas
else clustersRes <- "all"
}
if ("clustersST" %in% unlist(select) & is.null(clustersST)) {
if (!is.null(areas)) clustersST <- areas
else clustersST <- "all"
}
if ("mcYears" %in% unlist(select) & is.null(mcYears)) mcYears <- "all"

# If all arguments are NULL, import all areas
@@ -888,6 +909,7 @@ readAntaresAreas <- function(areas, links = TRUE, clusters = TRUE, clustersRes =
links = links,
clusters = clusters,
clustersRes = clustersRes,
clustersST = clustersST,
districts = districts,
mcYears = mcYears,
synthesis = synthesis,
15 changes: 15 additions & 0 deletions R/setSimulationPath.R
Original file line number Diff line number Diff line change
@@ -482,6 +482,20 @@ setSimulationPath <- function(path, simulation = NULL) {
areasWithResClusters <- sort(union(areaList_mc_all[hasResClusters_mc_all],
areaList_mc_ind[hasResClusters_mc_ind]))


# Areas containing short-term clusters
hasSTClusters_mc_all <- laply(file.path(dataPath_mc_all, "areas", areaList_mc_all), function(x) {
f <- list.files(x)
any(grepl("details-STstorage-", f))
})
hasSTClusters_mc_ind <- laply(file.path(dataPath_mc_ind, "areas", areaList_mc_ind), function(x) {
f <- list.files(x)
any(grepl("details-STstorage-", f))
})

areasWithSTClusters <- sort(union(areaList_mc_all[hasSTClusters_mc_all],
areaList_mc_ind[hasSTClusters_mc_ind]))

# Available variables
variables <- list()

@@ -523,6 +537,7 @@ setSimulationPath <- function(path, simulation = NULL) {
linksDef = linksDef,
areasWithClusters = areasWithClusters,
areasWithResClusters = areasWithResClusters,
areasWithSTClusters = areasWithSTClusters,
variables = variables,
parameters = params
)
10 changes: 10 additions & 0 deletions R/utils_api.R
Original file line number Diff line number Diff line change
@@ -162,6 +162,15 @@ read_secure_json <- function(url, token = NULL, timeout = 60, config = list()) {
)

areasWithResClusters <- names(hasResClusters)[hasResClusters]

hasSTClusters <- unlist(
lapply(
read_secure_json(file.path(dataPath, "areas&depth=2"), ...),
function(x) any(grepl("details-STstorage-", names(x)))
)
)

areasWithSTClusters <- names(hasSTClusters)[hasSTClusters]
# Available variables
variables <- list()

@@ -212,6 +221,7 @@ read_secure_json <- function(url, token = NULL, timeout = 60, config = list()) {
linksDef = linksDef,
areasWithClusters = intersect(areasWithClusters, areaList),
areasWithResClusters = intersect(areasWithResClusters, areaList),
areasWithSTClusters = intersect(areasWithSTClusters, areaList),
variables = variables,
parameters = params
)
3 changes: 2 additions & 1 deletion R/zzz.R
Original file line number Diff line number Diff line change
@@ -104,7 +104,8 @@ utils::globalVariables(
"NODU", "min.stable.power", "thermalPmin", "name", "value",
"Folder", "Mode", "Stats", "Name", "progNam", "mrgprice", "isLOLD_cum",
"...To", "upstream", "downstream", "LOLD", "LOLD_data", "LOLP", "warn_for_status",
"MRG. PRICE", "H. LEV", "V2", "V1", "size")
"MRG. PRICE", "H. LEV", "V2", "V1", "size", "ORDINAL_POSITION_BY_TOPIC",
"DETAILS_FILES_TYPE","ANTARES_DISPLAYED_NAME")
)

#----------------------------- HDF5 ------------------------------------#
9 changes: 9 additions & 0 deletions inst/format_output/simulation_variables_names_by_support.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"TOPIC";"DETAILS_FILES_TYPE";"ANTARES_DISPLAYED_NAME";"ORDINAL_POSITION_BY_TOPIC";"TITLE";"ALIAS";"MIN_VERSION";"OUTPUT_DISPLAYED_NAME";"RPACKAGE_DISPLAYED_NAME"
"Generation / Thermal";"details";"DTG by plant";1;"Dispatchable Thermal Generation by Thermal Cluster (MWh)";"dtgByPlant";;"MWh";"production"
"Generation / Thermal";"details";"NODU by plant";3;"Number of Dispatched Units by Thermal Cluster";"noduByPlant";;"NODU";"NODU"
"Generation / Thermal";"details";"NP Cost by plant";2;"Non-Proportional Costs by Thermal Cluster (€)";"npCostByPlant";;"NP Cost - Euro";"NP Cost"
"Generation / Thermal";"details";"Profit by plant";4;"Net Profit by Thermal Cluster (€)";"profitByPlant";830;"Profit - Euro";"profit"
"Generation / Renewables";"details-res";"RES generation by plant";1;"Renewable Energy Generation by Power Plant Cluster (MWh)";"resGenerationByPlant";810;"MWh";"production"
"Generation / Short-Term Storages";"details-STstorage";"STS inj by plant";1;"Short-Term Storage Injection by Power Plant (MWh)";"stsInjByPlant";860;"P-injection - MW";"P.injection"
"Generation / Short-Term Storages";"details-STstorage";"STS lvl by plant";2;"Short-Term Storage Level by Power Plant (MWh)";"stsLvlByPlant";860;"Levels - MWh";"levels"
"Generation / Short-Term Storages";"details-STstorage";"STS withdrawal by plant";3;"Short-Term Storage Withdrawal by Power Plant (MWh)";"stsWithdrawalByPlant";860;"P-withdrawal - MW";"P.withdrawal"
1 change: 1 addition & 0 deletions man/antaresRead-package.Rd
8 changes: 8 additions & 0 deletions man/readAntares.Rd
5 changes: 3 additions & 2 deletions revdep/README.md
Original file line number Diff line number Diff line change
@@ -10,18 +10,19 @@
|collate |French_France.utf8 |
|ctype |French_France.utf8 |
|tz |Europe/Paris |
|date |2024-05-27 |
|date |2024-06-13 |
|rstudio |2023.12.0+369 Ocean Storm (desktop) |
|pandoc |NA |

# Dependencies

|package |old |new |Δ |
|:-----------|:-----|:-----|:--|
|antaresRead |2.6.1 |2.7.0 |* |
|antaresRead |2.7.0 |2.7.1 |* |
|cachem |NA |1.0.8 |* |
|fastmap |NA |1.1.1 |* |
|openssl |NA |2.1.2 |* |
|rlang |NA |1.1.3 |* |
|stringi |NA |1.8.3 |* |

# Revdeps
62 changes: 62 additions & 0 deletions tests/testthat/test-importOutputForClusters.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#Copyright © 2016 RTE Réseau de transport d’électricité

context("Functions .importOutput")

path_study_test <- grep(pattern = "87", x = studyPathSV8, value = TRUE)

opts <- setSimulationPath(path_study_test,simulation="20240105-0934eco")

test_that(".importOutputForClusters is ok", {

OutputForClusters <- .importOutputForClusters(
areas="fr",
timeStep="annual",
showProgress=FALSE,
parallel=FALSE,
opts=opts
)

required_order_simulation_variables <- c("production","NP Cost","NODU","profit")

order_simulation_variables <- colnames(OutputForClusters)[colnames(OutputForClusters) %in% required_order_simulation_variables]

expect_equal(order_simulation_variables,required_order_simulation_variables)
expect_equal(nrow(OutputForClusters),1)
})


test_that(".importOutputForResClusters is ok", {

OutputForResClusters <- .importOutputForResClusters(
areas="fr",
timeStep="annual",
showProgress=FALSE,
parallel=FALSE,
opts=opts
)

required_order_simulation_variables <- c("production")

order_simulation_variables <- colnames(OutputForResClusters)[colnames(OutputForResClusters) %in% required_order_simulation_variables]

expect_equal(order_simulation_variables,required_order_simulation_variables)
expect_equal(nrow(OutputForResClusters),1)
})

test_that(".importOutputForSTClusters is ok", {

OutputForSTClusters <- .importOutputForSTClusters(
areas="fr",
timeStep="annual",
showProgress=FALSE,
parallel=FALSE,
opts=opts
)

required_order_simulation_variables <- c("P.injection","levels","P.withdrawal")

order_simulation_variables <- colnames(OutputForSTClusters)[colnames(OutputForSTClusters) %in% required_order_simulation_variables]

expect_equal(order_simulation_variables,required_order_simulation_variables)
expect_equal(nrow(OutputForSTClusters),1)
})
16 changes: 16 additions & 0 deletions tests/testthat/test-readAntares_STclusters.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#Copyright © 2016 RTE Réseau de transport d’électricité

context("Function readAntares (ST clusters)")

path_study_test <- grep(pattern = "87", x = studyPathSV8, value = TRUE)

opts <- setSimulationPath(path_study_test,simulation="20240105-0934eco")

test_that("ST clusters importation is ok", {

clustersST <- readAntares(clustersST="all",timeStep="annual",opts = opts)$clustersST
expect_true(all(opts$areasWithSTClusters %in% clustersST$area))

clustersST_fr <- readAntares(clustersST="fr",timeStep="annual",opts = opts)$clustersST
expect_true("fr"==unique(clustersST_fr$area))
})
15 changes: 15 additions & 0 deletions tests/testthat/test-setSimulationPath.R
Original file line number Diff line number Diff line change
@@ -178,13 +178,28 @@ test_that("Folder 'maps' is not interpreted as a study (#49)", {

}

test_that("No meta info areas with a ST cluster < 860", {
opts <- setSimulationPath(studyPath, "input")
expect_true(length(opts$areasWithSTClusters)==0)
})

test_that("No meta info binding study < 870", {
opts <- setSimulationPath(studyPath, "input")
expect_null(opts$binding)
})

})

# v860----
test_that("New meta data for areas with a ST cluster", {
# read latest version study
path_study_test <- grep(pattern = "87", x = studyPathSV8, value = TRUE)
opts_study_test <- setSimulationPath(path_study_test, simulation = "20240105-0934eco")

expect_false(is.null(opts_study_test$areasWithSTClusters))
})


# v870----
test_that("New meta data for group dimension of binding constraints", {
# read latest version study