From a35b2c7c300a441ba87c85b4ad40afdb34e186f2 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Wed, 4 Sep 2024 10:33:25 -0400 Subject: [PATCH 01/16] derive an M matrix for IEF models #311 --- R/ExternalImportFactors.R | 35 ++++++++++++++++++++++++++++++++++- man/deriveMMatrix.Rd | 21 +++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 man/deriveMMatrix.Rd diff --git a/R/ExternalImportFactors.R b/R/ExternalImportFactors.R index 5eb01866..28f43453 100644 --- a/R/ExternalImportFactors.R +++ b/R/ExternalImportFactors.R @@ -100,7 +100,7 @@ castImportFactors <- function(IFTable, model) { buildModelwithImportFactors <- function(model, configpaths = NULL) { # (see Palm et al. 2019) - logging::loginfo("Building Import A (A_m) accounting for ITA in Domestic FD.\n") + logging::loginfo("Building A_m (import requirements) accounting for international trade adjustment in domestic final demand.\n") # Re-derive import values in Use and final demand # _m denotes import-related structures model$UseTransactions_m <- model$UseTransactions - model$DomesticUseTransactions @@ -126,5 +126,38 @@ buildModelwithImportFactors <- function(model, configpaths = NULL) { model$M_m <- M_m + model$M <- deriveMMatrix(model) + return(model) } + +#' Derives an aggregate M matrix from M_d and M_m based on the Consumption demand vector and +#' FINAL perspective. Results from this M matrix match those calculated using the Import Emission +#' Factors when using the Consumption demand vector and FINAL perspective. +#' @param model, An EEIO model object with model specs and crosswalk table loaded +#' @return An M matrix of flows x sector +deriveMMatrix <- function(model) { + y <- prepareDemandVectorForStandardResults(model, demand="Consumption", + location=model$specs$ModelRegionAcronyms[1], + use_domestic_requirements=FALSE) + y_d <- prepareDemandVectorForStandardResults(model, demand="Consumption", + location=model$specs$ModelRegionAcronyms[1], + use_domestic_requirements=TRUE) + y_m <- prepareDemandVectorForImportResults(model, demand="Consumption", + location=model$specs$ModelRegionAcronyms[1]) + if(!all.equal(y, y_d+y_m)) { + stop("Error in calculating demand for coupled model approach") + } + logging::loginfo("Deriving M matrix (total emissions and resource use per dollar) consistent with the FINAL perspective ...") + result <- calculateResultsWithExternalFactors(model, demand="Consumption", perspective="FINAL", + location=model$specs$ModelRegionAcronyms[1])[["LCI_f"]] + # Derive M by dividing the result by the final demand + M <- t(result) %*% solve(diag(as.vector(replace(y, y == 0 , 1)))) + colnames(M) <- colnames(model$M_d) + result2 <- calculateFinalPerspectiveLCI(M, y) + if(!all.equal(result, result2)) { + stop("Error deriving M matrix for coupled model approach") + } + + return(M) +} diff --git a/man/deriveMMatrix.Rd b/man/deriveMMatrix.Rd new file mode 100644 index 00000000..69cfa82b --- /dev/null +++ b/man/deriveMMatrix.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ExternalImportFactors.R +\name{deriveMMatrix} +\alias{deriveMMatrix} +\title{Derives an aggregate M matrix from M_d and M_m based on the Consumption demand vector and +FINAL perspective. Results from this M matrix match those calculated using the Import Emission +Factors when using the Consumption demand vector and FINAL perspective.} +\usage{ +deriveMMatrix(model) +} +\arguments{ +\item{model, }{An EEIO model object with model specs and crosswalk table loaded} +} +\value{ +An M matrix of flows x sector +} +\description{ +Derives an aggregate M matrix from M_d and M_m based on the Consumption demand vector and +FINAL perspective. Results from this M matrix match those calculated using the Import Emission +Factors when using the Consumption demand vector and FINAL perspective. +} From 119ea9cfaa4a5d2e70e9e9c656d1cfacd6aa6ca6 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Mon, 9 Sep 2024 21:20:28 -0400 Subject: [PATCH 02/16] use domestic production demand and import consumption demand to create ratios for M --- R/ExternalImportFactors.R | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/R/ExternalImportFactors.R b/R/ExternalImportFactors.R index 28f43453..1baf86a8 100644 --- a/R/ExternalImportFactors.R +++ b/R/ExternalImportFactors.R @@ -137,27 +137,38 @@ buildModelwithImportFactors <- function(model, configpaths = NULL) { #' @param model, An EEIO model object with model specs and crosswalk table loaded #' @return An M matrix of flows x sector deriveMMatrix <- function(model) { - y <- prepareDemandVectorForStandardResults(model, demand="Consumption", - location=model$specs$ModelRegionAcronyms[1], - use_domestic_requirements=FALSE) - y_d <- prepareDemandVectorForStandardResults(model, demand="Consumption", + + # Domestic production demand + y_d <- prepareDemandVectorForStandardResults(model, demand="Production", location=model$specs$ModelRegionAcronyms[1], use_domestic_requirements=TRUE) + # Import consumption y_m <- prepareDemandVectorForImportResults(model, demand="Consumption", location=model$specs$ModelRegionAcronyms[1]) - if(!all.equal(y, y_d+y_m)) { - stop("Error in calculating demand for coupled model approach") - } - logging::loginfo("Deriving M matrix (total emissions and resource use per dollar) consistent with the FINAL perspective ...") + + y <- y_m + y_d + y_mr <- pmax(pmin(y_m / y, 1), 0) + y_dr <- pmin(pmax(y_d / y, 0), 1) + + r1 <- model$M_d %*% diag(as.vector(y_dr)) + r2 <- model$M_m %*% model$A_m %*% model$L_d %*% diag(as.vector(y_dr)) + r3 <- model$M_m %*% diag(as.vector(y_mr)) + M <- r1 + r2 + r3 + colnames(M) <- colnames(model$M_d) + + # logging::loginfo("Deriving M matrix (total emissions and resource use per dollar) consistent with the FINAL perspective ...") result <- calculateResultsWithExternalFactors(model, demand="Consumption", perspective="FINAL", location=model$specs$ModelRegionAcronyms[1])[["LCI_f"]] # Derive M by dividing the result by the final demand - M <- t(result) %*% solve(diag(as.vector(replace(y, y == 0 , 1)))) - colnames(M) <- colnames(model$M_d) - result2 <- calculateFinalPerspectiveLCI(M, y) - if(!all.equal(result, result2)) { - stop("Error deriving M matrix for coupled model approach") - } + # M <- t(result) %*% solve(diag(as.vector(replace(y, y == 0 , 1)))) + # colnames(M) <- colnames(model$M_d) + y_cons <- prepareDemandVectorForStandardResults(model, demand="Consumption", + location=model$specs$ModelRegionAcronyms[1], + use_domestic_requirements=FALSE) + result2 <- calculateFinalPerspectiveLCI(M, y_cons) + # if(!all.equal(result, result2)) { + # stop("Error deriving M matrix for coupled model approach") + # } return(M) } From 04b7a8ecfd460ceac4a6958a6cfac59d1e146f17 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Tue, 10 Sep 2024 14:13:35 -0400 Subject: [PATCH 03/16] revise approach for deriving M to use q and y_m --- R/ExternalImportFactors.R | 51 ++++++++++++++------------------------- man/deriveMMatrix.Rd | 8 ++---- 2 files changed, 20 insertions(+), 39 deletions(-) diff --git a/R/ExternalImportFactors.R b/R/ExternalImportFactors.R index 1baf86a8..6c7d6468 100644 --- a/R/ExternalImportFactors.R +++ b/R/ExternalImportFactors.R @@ -131,44 +131,29 @@ buildModelwithImportFactors <- function(model, configpaths = NULL) { return(model) } -#' Derives an aggregate M matrix from M_d and M_m based on the Consumption demand vector and -#' FINAL perspective. Results from this M matrix match those calculated using the Import Emission -#' Factors when using the Consumption demand vector and FINAL perspective. +#' Derives an aggregate M matrix from M_d and M_m based on the ratio of commodity output to total imports. #' @param model, An EEIO model object with model specs and crosswalk table loaded #' @return An M matrix of flows x sector deriveMMatrix <- function(model) { - - # Domestic production demand - y_d <- prepareDemandVectorForStandardResults(model, demand="Production", - location=model$specs$ModelRegionAcronyms[1], - use_domestic_requirements=TRUE) - # Import consumption - y_m <- prepareDemandVectorForImportResults(model, demand="Consumption", - location=model$specs$ModelRegionAcronyms[1]) - - y <- y_m + y_d - y_mr <- pmax(pmin(y_m / y, 1), 0) - y_dr <- pmin(pmax(y_d / y, 0), 1) - - r1 <- model$M_d %*% diag(as.vector(y_dr)) - r2 <- model$M_m %*% model$A_m %*% model$L_d %*% diag(as.vector(y_dr)) - r3 <- model$M_m %*% diag(as.vector(y_mr)) - M <- r1 + r2 + r3 + # logging::loginfo("Deriving M matrix (total emissions and resource use per dollar) ...") + q <- model$q + loc <- grepl(model$specs$ModelRegionAcronyms[1], model$FinalDemandMeta$Code_Loc) + import_code <- model$FinalDemandMeta[model$FinalDemandMeta$Group=="Import" & loc, "Code_Loc"] + y_m <- sumDemandCols(model$FinalDemand, import_code) + + dr <- q / (q + abs(y_m)) + mr <- 1 - dr + # Derive M by taking the ratio of domestic vs imported goods + M <- model$M_d %*% diag(as.vector(dr)) + model$M_m %*% diag(as.vector(mr)) colnames(M) <- colnames(model$M_d) - # logging::loginfo("Deriving M matrix (total emissions and resource use per dollar) consistent with the FINAL perspective ...") - result <- calculateResultsWithExternalFactors(model, demand="Consumption", perspective="FINAL", - location=model$specs$ModelRegionAcronyms[1])[["LCI_f"]] - # Derive M by dividing the result by the final demand - # M <- t(result) %*% solve(diag(as.vector(replace(y, y == 0 , 1)))) - # colnames(M) <- colnames(model$M_d) - y_cons <- prepareDemandVectorForStandardResults(model, demand="Consumption", - location=model$specs$ModelRegionAcronyms[1], - use_domestic_requirements=FALSE) - result2 <- calculateFinalPerspectiveLCI(M, y_cons) - # if(!all.equal(result, result2)) { - # stop("Error deriving M matrix for coupled model approach") - # } + # result <- calculateResultsWithExternalFactors(model, demand="Consumption", perspective="FINAL", + # location=model$specs$ModelRegionAcronyms[1])[["LCI_f"]] + # model2 <- model + # model2$M <- M + # model2$N <- model$C %*% M + # result2 <- calculateStandardResults(model2, demand="Consumption", perspective="FINAL", + # location=model$specs$ModelRegionAcronyms[1])[["LCI_f"]] return(M) } diff --git a/man/deriveMMatrix.Rd b/man/deriveMMatrix.Rd index 69cfa82b..c56ac74e 100644 --- a/man/deriveMMatrix.Rd +++ b/man/deriveMMatrix.Rd @@ -2,9 +2,7 @@ % Please edit documentation in R/ExternalImportFactors.R \name{deriveMMatrix} \alias{deriveMMatrix} -\title{Derives an aggregate M matrix from M_d and M_m based on the Consumption demand vector and -FINAL perspective. Results from this M matrix match those calculated using the Import Emission -Factors when using the Consumption demand vector and FINAL perspective.} +\title{Derives an aggregate M matrix from M_d and M_m based on the ratio of commodity output to total imports.} \usage{ deriveMMatrix(model) } @@ -15,7 +13,5 @@ deriveMMatrix(model) An M matrix of flows x sector } \description{ -Derives an aggregate M matrix from M_d and M_m based on the Consumption demand vector and -FINAL perspective. Results from this M matrix match those calculated using the Import Emission -Factors when using the Consumption demand vector and FINAL perspective. +Derives an aggregate M matrix from M_d and M_m based on the ratio of commodity output to total imports. } From 7c7f8550e6a2cd4c37ab276a0ce4936a2c04c509 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Tue, 10 Sep 2024 15:18:31 -0400 Subject: [PATCH 04/16] derive m from use table --- R/ExternalImportFactors.R | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/R/ExternalImportFactors.R b/R/ExternalImportFactors.R index 6c7d6468..c026d602 100644 --- a/R/ExternalImportFactors.R +++ b/R/ExternalImportFactors.R @@ -139,21 +139,16 @@ deriveMMatrix <- function(model) { q <- model$q loc <- grepl(model$specs$ModelRegionAcronyms[1], model$FinalDemandMeta$Code_Loc) import_code <- model$FinalDemandMeta[model$FinalDemandMeta$Group=="Import" & loc, "Code_Loc"] - y_m <- sumDemandCols(model$FinalDemand, import_code) + # derive total imports (m) from the Use table + U_m <- model$U - model$U_d + # Exclude imports col when calculating total imports + m <- head(rowSums(U_m[, !(colnames(U_m) %in% import_code)]), -3) # drop VA - dr <- q / (q + abs(y_m)) + dr <- q / (q + m) mr <- 1 - dr # Derive M by taking the ratio of domestic vs imported goods M <- model$M_d %*% diag(as.vector(dr)) + model$M_m %*% diag(as.vector(mr)) colnames(M) <- colnames(model$M_d) - - # result <- calculateResultsWithExternalFactors(model, demand="Consumption", perspective="FINAL", - # location=model$specs$ModelRegionAcronyms[1])[["LCI_f"]] - # model2 <- model - # model2$M <- M - # model2$N <- model$C %*% M - # result2 <- calculateStandardResults(model2, demand="Consumption", perspective="FINAL", - # location=model$specs$ModelRegionAcronyms[1])[["LCI_f"]] return(M) } From adb2dafbf6b1af2f66223d939d2898556d78142b Mon Sep 17 00:00:00 2001 From: Ben Young Date: Tue, 10 Sep 2024 15:37:23 -0400 Subject: [PATCH 05/16] fix error in deriving M matrix for 2R models --- R/ExternalImportFactors.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/ExternalImportFactors.R b/R/ExternalImportFactors.R index c026d602..83fbdbbc 100644 --- a/R/ExternalImportFactors.R +++ b/R/ExternalImportFactors.R @@ -135,14 +135,14 @@ buildModelwithImportFactors <- function(model, configpaths = NULL) { #' @param model, An EEIO model object with model specs and crosswalk table loaded #' @return An M matrix of flows x sector deriveMMatrix <- function(model) { - # logging::loginfo("Deriving M matrix (total emissions and resource use per dollar) ...") + logging::loginfo("Deriving M matrix (total emissions and resource use per dollar) ...") q <- model$q loc <- grepl(model$specs$ModelRegionAcronyms[1], model$FinalDemandMeta$Code_Loc) import_code <- model$FinalDemandMeta[model$FinalDemandMeta$Group=="Import" & loc, "Code_Loc"] # derive total imports (m) from the Use table U_m <- model$U - model$U_d # Exclude imports col when calculating total imports - m <- head(rowSums(U_m[, !(colnames(U_m) %in% import_code)]), -3) # drop VA + m <- rowSums(U_m[model$Commodities$Code_Loc, !(colnames(U_m) %in% import_code)]) # drop VA dr <- q / (q + m) mr <- 1 - dr From b80c38b261c3810c1d7db08584053f9c7e22a87f Mon Sep 17 00:00:00 2001 From: Ben Young Date: Tue, 10 Sep 2024 16:03:31 -0400 Subject: [PATCH 06/16] ignore location when removing imports --- R/ExternalImportFactors.R | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/R/ExternalImportFactors.R b/R/ExternalImportFactors.R index 83fbdbbc..6aedcb77 100644 --- a/R/ExternalImportFactors.R +++ b/R/ExternalImportFactors.R @@ -137,8 +137,7 @@ buildModelwithImportFactors <- function(model, configpaths = NULL) { deriveMMatrix <- function(model) { logging::loginfo("Deriving M matrix (total emissions and resource use per dollar) ...") q <- model$q - loc <- grepl(model$specs$ModelRegionAcronyms[1], model$FinalDemandMeta$Code_Loc) - import_code <- model$FinalDemandMeta[model$FinalDemandMeta$Group=="Import" & loc, "Code_Loc"] + import_code <- model$FinalDemandMeta[model$FinalDemandMeta$Group=="Import", "Code_Loc"] # derive total imports (m) from the Use table U_m <- model$U - model$U_d # Exclude imports col when calculating total imports From c9762f422fcca422a3e6ee4a938e4d5ea22e9df0 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Wed, 11 Sep 2024 18:41:32 -0400 Subject: [PATCH 07/16] validate that M is between M_m and M_d --- R/ExternalImportFactors.R | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/R/ExternalImportFactors.R b/R/ExternalImportFactors.R index 6aedcb77..552b44b1 100644 --- a/R/ExternalImportFactors.R +++ b/R/ExternalImportFactors.R @@ -149,5 +149,14 @@ deriveMMatrix <- function(model) { M <- model$M_d %*% diag(as.vector(dr)) + model$M_m %*% diag(as.vector(mr)) colnames(M) <- colnames(model$M_d) + # Validate that M is between M_m and M_d + a <- signif(model$M_m, 6) + b <- signif(M, 6) + c <- signif(model$M_d, 6) + z <- ((b > a) & (b > c)) | ((b < a) & (b < c)) + if(sum(z) > 0) { + stop("Error in deriving M matrix") + } + return(M) } From e232ca115ee63a513b644950a04f533542888407 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Thu, 12 Sep 2024 21:10:13 -0400 Subject: [PATCH 08/16] move M matrix test to validation and print any failures --- R/ExternalImportFactors.R | 9 --------- R/ValidateModel.R | 13 +++++++++++++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/R/ExternalImportFactors.R b/R/ExternalImportFactors.R index 552b44b1..6aedcb77 100644 --- a/R/ExternalImportFactors.R +++ b/R/ExternalImportFactors.R @@ -149,14 +149,5 @@ deriveMMatrix <- function(model) { M <- model$M_d %*% diag(as.vector(dr)) + model$M_m %*% diag(as.vector(mr)) colnames(M) <- colnames(model$M_d) - # Validate that M is between M_m and M_d - a <- signif(model$M_m, 6) - b <- signif(M, 6) - c <- signif(model$M_d, 6) - z <- ((b > a) & (b > c)) | ((b < a) & (b < c)) - if(sum(z) > 0) { - stop("Error in deriving M matrix") - } - return(M) } diff --git a/R/ValidateModel.R b/R/ValidateModel.R index 4b41c142..2c95753c 100644 --- a/R/ValidateModel.R +++ b/R/ValidateModel.R @@ -474,6 +474,19 @@ validateImportFactorsApproach <- function(model, demand = "Consumption"){ cat("assuming model$M = model$M_m.\n") print(all.equal(LCIA_dm, LCIA)) + cat("\nValidating that the derived M matrix has all values between M_d and M_m\n") + + # Validate that M is between M_m and M_d + a <- signif(model$M_m, 6) + b <- signif(model$M, 6) + c <- signif(model$M_d, 6) + z <- ((b > a) & (b > c)) | ((b < a) & (b < c)) + if(sum(z) == 0) { + print(TRUE) + } else { + comm <- colSums(z) > 0 + print(paste0("Failures: ", names(comm)[comm == TRUE])) + } } #' Validate the calculation of household_emissions From e9256a8f5f2b48a45e0dad4ff1d849e4a32d685b Mon Sep 17 00:00:00 2001 From: Ben Young Date: Thu, 31 Oct 2024 09:33:39 -0400 Subject: [PATCH 09/16] move two region model spec (v1.0) out of tests --- {tests => inst/extdata}/modelspecs/GAEEIOv1.0-GHG-19.yml | 0 tests/test_model_build.R | 5 ++--- 2 files changed, 2 insertions(+), 3 deletions(-) rename {tests => inst/extdata}/modelspecs/GAEEIOv1.0-GHG-19.yml (100%) diff --git a/tests/modelspecs/GAEEIOv1.0-GHG-19.yml b/inst/extdata/modelspecs/GAEEIOv1.0-GHG-19.yml similarity index 100% rename from tests/modelspecs/GAEEIOv1.0-GHG-19.yml rename to inst/extdata/modelspecs/GAEEIOv1.0-GHG-19.yml diff --git a/tests/test_model_build.R b/tests/test_model_build.R index a0af581b..bab449ff 100644 --- a/tests/test_model_build.R +++ b/tests/test_model_build.R @@ -131,13 +131,12 @@ printValidationResults(model) ## StateEEIOv1.0 Two-region Summary model m <- "GAEEIOv1.0-GHG-19" -cfg <- paste0("modelspecs/", m, ".yml") -model <- buildModel(m, configpaths = file.path(cfg)) +model <- buildModel(m) printValidationResults(model) writeModeltoXLSX(model, ".") ## StateEEIOv1.0 Two-region Summary model (Economic only) -model <- buildIOModel(m, configpaths = file.path(cfg)) +model <- buildIOModel(m) printValidationResults(model) writeModeltoXLSX(model, ".") From 5c5c18e0fd20299c3777d92f62bdbe2380e513f4 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Thu, 31 Oct 2024 09:56:37 -0400 Subject: [PATCH 10/16] include additional warnings for functions that don't work for specific model types --- R/AdjustPrice.R | 8 ++++++-- R/VisualizationFunctions.R | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/R/AdjustPrice.R b/R/AdjustPrice.R index 3170f08a..8a473a84 100644 --- a/R/AdjustPrice.R +++ b/R/AdjustPrice.R @@ -19,8 +19,12 @@ adjustResultMatrixPrice <- function(matrix_name, currency_year, purchaser_price= } # Adjust price type of multiplier if (purchaser_price) { - logging::loginfo(paste("Adjusting", matrix_name, "matrix from producer to purchaser price...")) - mat <- adjustMultiplierPriceType(mat, currency_year, model) + if(is.null(model$Phi)) { + logging::logwarn("Model does not contain margins, purchaser price can not be calculated") + } else { + logging::loginfo(paste("Adjusting", matrix_name, "matrix from producer to purchaser price...")) + mat <- adjustMultiplierPriceType(mat, currency_year, model) + } } else { logging::loginfo(paste("Keeping", matrix_name, "matrix in producer price...")) } diff --git a/R/VisualizationFunctions.R b/R/VisualizationFunctions.R index 7a2df283..cb757585 100644 --- a/R/VisualizationFunctions.R +++ b/R/VisualizationFunctions.R @@ -237,6 +237,9 @@ heatmapSatelliteTableCoverage <- function(model, form="Commodity") { #' @export heatmapSectorRanking <- function(model, matrix, indicators, sector_to_remove, N_sector, x_title = NULL, use_codes = TRUE) { + if(model$specs$IODataSource == "stateior") { + stop("heatmapSectorRanking not available for two-region models.") + } # Generate BEA sector color mapping mapping <- getBEASectorColorMapping(model) mapping$GroupName <- mapping$SectorName From bea22ec94299b9598fef416293f55d42d434a739 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Thu, 31 Oct 2024 10:12:48 -0400 Subject: [PATCH 11/16] adds result and visualization tests to a number of models, #320 --- R/ValidateModel.R | 88 +++++++++++++++++++++++++++++++ man/testCalculationFunctions.Rd | 24 +++++++++ man/testVisualizationFunctions.Rd | 20 +++++++ tests/test_model_build.R | 12 +++-- 4 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 man/testCalculationFunctions.Rd create mode 100644 man/testVisualizationFunctions.Rd diff --git a/R/ValidateModel.R b/R/ValidateModel.R index 2c95753c..8aa2a445 100644 --- a/R/ValidateModel.R +++ b/R/ValidateModel.R @@ -507,3 +507,91 @@ validateHouseholdEmissions <- function(model) { result <- r$LCI_f[codes, names(flows)] all.equal(flows, result) } + +#' Test that model calculation functions are successful +#' Includes tests for the following functions: +#' adjustResultMatrixPrice, calculateFlowContributiontoImpact, +#' calculateSectorContributiontoImpact, disaggregateTotalToDirectAndTier1, +#' calculateSectorPurchasedbySectorSourcedImpact, aggregateResultMatrix, +#' calculateMarginSectorImpacts +#' +#' @param model, A fully built EEIO model object +testCalculationFunctions <- function(model) { + target_year <- ifelse(model$specs$IOYear != 2019, 2019, 2020) + sector <- model$Commodities$Code_Loc[[10]] + indicator <- model$Indicators$meta$Name[[1]] + + matrix <- adjustResultMatrixPrice(matrix_name = "N", + currency_year = target_year, + purchaser_price = TRUE, + model) + if(!all(dim(model$N) == dim(matrix)) && !all(model$N == matrix)) { + print("Error in adjustResultMatrixPrice()") + } + + flow_contrib <- calculateFlowContributiontoImpact(model, sector, indicator) + if(!all.equal(sum(flow_contrib$contribution), 1)) { + print("Error in calculateFlowContributiontoImpact()") + } + + sector_contrib <- calculateSectorContributiontoImpact(model, sector, indicator) + if(!all.equal(sum(sector_contrib$contribution), 1)) { + print("Error in calculateSectorContributiontoImpact()") + } + + demand = model$DemandVectors$vectors[[1]] + result <- calculateSectorPurchasedbySectorSourcedImpact(y=demand, model, indicator) + if(model$specs$IODataSource != "stateior") { + # not working for 2R mode + agg_result <- aggregateResultMatrix(result, "Sector", model$crosswalk) + } + + result <- disaggregateTotalToDirectAndTier1(model, indicator) + + if(model$specs$IODataSource != "stateior") { + margins <- calculateMarginSectorImpacts(model) + } + +} + +#' Test that visualization functions are successful +#' Includes tests for the following functions: +#' barplotFloworImpactFractionbyRegion, barplotIndicatorScoresbySector, +#' heatmapSatelliteTableCoverage, heatmapSectorRanking, plotMatrixCoefficient +#' +#' @param model, A fully built EEIO model object +testVisualizationFunctions <- function(model) { + model_list <- list("model" = model) + loc <- model$specs$ModelRegionAcronyms[[1]] + indicator <- model$Indicators$meta$Name[[1]] + + fullcons <- calculateEEIOModel(model, perspective='DIRECT', demand="Consumption", + location = loc) + domcons <- calculateEEIOModel(model, perspective='DIRECT', demand="Consumption", + location = loc, use_domestic_requirements = TRUE) + barplotFloworImpactFractionbyRegion(domcons$LCIA_d, + fullcons$LCIA_d, + "Domestic Proportion of Impact") + ## ^^ This may not be working correctly for 2R models + + barplotIndicatorScoresbySector(model_list, + totals_by_sector_name = "GHG", + indicator_name = "Greenhouse Gases", + sector = FALSE, y_title = "") + + heatmapSatelliteTableCoverage(model, form = "Industry") + # ^^ not working for form = "Commodity" + + indicators <- model$Indicators$meta$Code[1:min(5, length(model$Indicators$meta$Code))] + + if(model$specs$IODataSource != "stateior") { + # not working for 2R models + heatmapSectorRanking(model, matrix = fullcons$LCIA_d, indicators, + sector_to_remove = "", N_sector = 20) + } + + plotMatrixCoefficient(model_list, matrix_name = "D", + coefficient_name = indicator, + sector_to_remove = "", y_title = indicator, + y_label = "Name") +} diff --git a/man/testCalculationFunctions.Rd b/man/testCalculationFunctions.Rd new file mode 100644 index 00000000..b33dc432 --- /dev/null +++ b/man/testCalculationFunctions.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ValidateModel.R +\name{testCalculationFunctions} +\alias{testCalculationFunctions} +\title{Test that model calculation functions are successful +Includes tests for the following functions: +adjustResultMatrixPrice, calculateFlowContributiontoImpact, +calculateSectorContributiontoImpact, disaggregateTotalToDirectAndTier1, +calculateSectorPurchasedbySectorSourcedImpact, aggregateResultMatrix, +calculateMarginSectorImpacts} +\usage{ +testCalculationFunctions(model) +} +\arguments{ +\item{model, }{A fully built EEIO model object} +} +\description{ +Test that model calculation functions are successful +Includes tests for the following functions: +adjustResultMatrixPrice, calculateFlowContributiontoImpact, +calculateSectorContributiontoImpact, disaggregateTotalToDirectAndTier1, +calculateSectorPurchasedbySectorSourcedImpact, aggregateResultMatrix, +calculateMarginSectorImpacts +} diff --git a/man/testVisualizationFunctions.Rd b/man/testVisualizationFunctions.Rd new file mode 100644 index 00000000..4de6fbe3 --- /dev/null +++ b/man/testVisualizationFunctions.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ValidateModel.R +\name{testVisualizationFunctions} +\alias{testVisualizationFunctions} +\title{Test that visualization functions are successful +Includes tests for the following functions: +barplotFloworImpactFractionbyRegion, barplotIndicatorScoresbySector, +heatmapSatelliteTableCoverage, heatmapSectorRanking, plotMatrixCoefficient} +\usage{ +testVisualizationFunctions(model) +} +\arguments{ +\item{model, }{A fully built EEIO model object} +} +\description{ +Test that visualization functions are successful +Includes tests for the following functions: +barplotFloworImpactFractionbyRegion, barplotIndicatorScoresbySector, +heatmapSatelliteTableCoverage, heatmapSectorRanking, plotMatrixCoefficient +} diff --git a/tests/test_model_build.R b/tests/test_model_build.R index bab449ff..a441fa38 100644 --- a/tests/test_model_build.R +++ b/tests/test_model_build.R @@ -10,6 +10,8 @@ if (!interactive()) options(warn=2, error = function() { sink(stderr()) ; traceb m <- "USEEIOv2.0.1-411" model <- buildModel(m) printValidationResults(model) +testCalculationFunctions(model) +testVisualizationFunctions(model) ## USEEIOv2.0.1-411 Detail model with waste disaggregation (Economic only) m <- "USEEIOv2.0.1-411" @@ -128,12 +130,16 @@ writeModeltoXLSX(model, ".") m <- "USEEIOv2.3-s-GHG-19" model <- buildModel(m) printValidationResults(model) +testCalculationFunctions(model) +testVisualizationFunctions(model) ## StateEEIOv1.0 Two-region Summary model m <- "GAEEIOv1.0-GHG-19" model <- buildModel(m) printValidationResults(model) writeModeltoXLSX(model, ".") +testCalculationFunctions(model) +testVisualizationFunctions(model) ## StateEEIOv1.0 Two-region Summary model (Economic only) model <- buildIOModel(m) @@ -141,9 +147,7 @@ printValidationResults(model) writeModeltoXLSX(model, ".") ## StateEEIOv1.1 Two-region Summary model with Import Factors -cfg <- c(paste0("modelspecs/", m, ".yml"), - "US_summary_import_factors_exio_2019_12sch.csv" - ) +cfg <- c("US_summary_import_factors_exio_2019_12sch.csv") model <- useeior:::initializeModel(m, configpaths = file.path(cfg)) model$specs$Model <- "GAEEIOv1.1-GHG-19-IF" model$specs$ExternalImportFactors <- TRUE @@ -156,6 +160,8 @@ model <- useeior:::loadandbuildIndicators(model) model <- useeior:::loadDemandVectors(model) model <- useeior:::constructEEIOMatrices(model, file.path(cfg)) printValidationResults(model) +testCalculationFunctions(model) +testVisualizationFunctions(model) # ## StateEEIOv1.0 Two-region Summary model with Utility disaggregation # model <- useeior:::initializeModel(m, configpaths = file.path(cfg)) From 87a0d0b2decc71327b16a18408cd475e5db548e0 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Thu, 31 Oct 2024 10:19:49 -0400 Subject: [PATCH 12/16] export validation functions --- NAMESPACE | 2 ++ R/ValidateModel.R | 2 ++ 2 files changed, 4 insertions(+) diff --git a/NAMESPACE b/NAMESPACE index 7f42189c..c504c06d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -22,6 +22,8 @@ export(normalizeResultMatrixByTotalImpacts) export(plotMatrixCoefficient) export(printValidationResults) export(seeAvailableModels) +export(testCalculationFunctions) +export(testVisualizationFunctions) export(writeModelMatrices) export(writeModelforAPI) export(writeModeltoXLSX) diff --git a/R/ValidateModel.R b/R/ValidateModel.R index 8aa2a445..caac8648 100644 --- a/R/ValidateModel.R +++ b/R/ValidateModel.R @@ -516,6 +516,7 @@ validateHouseholdEmissions <- function(model) { #' calculateMarginSectorImpacts #' #' @param model, A fully built EEIO model object +#' @export testCalculationFunctions <- function(model) { target_year <- ifelse(model$specs$IOYear != 2019, 2019, 2020) sector <- model$Commodities$Code_Loc[[10]] @@ -560,6 +561,7 @@ testCalculationFunctions <- function(model) { #' heatmapSatelliteTableCoverage, heatmapSectorRanking, plotMatrixCoefficient #' #' @param model, A fully built EEIO model object +#' @export testVisualizationFunctions <- function(model) { model_list <- list("model" = model) loc <- model$specs$ModelRegionAcronyms[[1]] From 13d78eb905997a2757049e95d489b22b3749e5c1 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Thu, 31 Oct 2024 10:50:14 -0400 Subject: [PATCH 13/16] warnings not converted to errors --- tests/test_model_build.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_model_build.R b/tests/test_model_build.R index a441fa38..8f36d433 100644 --- a/tests/test_model_build.R +++ b/tests/test_model_build.R @@ -4,7 +4,7 @@ # setwd("tests") library(useeior) # library(unittest, quietly = TRUE) -if (!interactive()) options(warn=2, error = function() { sink(stderr()) ; traceback(3) ; q(status = 1) }) +if (!interactive()) options(warn=1, error = function() { sink(stderr()) ; traceback(3) ; q(status = 1) }) ## USEEIOv2.0.1-411 Detail model with waste disaggregation m <- "USEEIOv2.0.1-411" From 031e992e15b8c3d452d23a3c0a386a628c17d6a9 Mon Sep 17 00:00:00 2001 From: Wesley Ingwersen Date: Fri, 1 Nov 2024 08:39:17 -0400 Subject: [PATCH 14/16] Revert "derive an M matrix for IEF models" --- R/ExternalImportFactors.R | 25 +------------------------ R/ValidateModel.R | 13 ------------- man/deriveMMatrix.Rd | 17 ----------------- 3 files changed, 1 insertion(+), 54 deletions(-) delete mode 100644 man/deriveMMatrix.Rd diff --git a/R/ExternalImportFactors.R b/R/ExternalImportFactors.R index 6aedcb77..5eb01866 100644 --- a/R/ExternalImportFactors.R +++ b/R/ExternalImportFactors.R @@ -100,7 +100,7 @@ castImportFactors <- function(IFTable, model) { buildModelwithImportFactors <- function(model, configpaths = NULL) { # (see Palm et al. 2019) - logging::loginfo("Building A_m (import requirements) accounting for international trade adjustment in domestic final demand.\n") + logging::loginfo("Building Import A (A_m) accounting for ITA in Domestic FD.\n") # Re-derive import values in Use and final demand # _m denotes import-related structures model$UseTransactions_m <- model$UseTransactions - model$DomesticUseTransactions @@ -126,28 +126,5 @@ buildModelwithImportFactors <- function(model, configpaths = NULL) { model$M_m <- M_m - model$M <- deriveMMatrix(model) - return(model) } - -#' Derives an aggregate M matrix from M_d and M_m based on the ratio of commodity output to total imports. -#' @param model, An EEIO model object with model specs and crosswalk table loaded -#' @return An M matrix of flows x sector -deriveMMatrix <- function(model) { - logging::loginfo("Deriving M matrix (total emissions and resource use per dollar) ...") - q <- model$q - import_code <- model$FinalDemandMeta[model$FinalDemandMeta$Group=="Import", "Code_Loc"] - # derive total imports (m) from the Use table - U_m <- model$U - model$U_d - # Exclude imports col when calculating total imports - m <- rowSums(U_m[model$Commodities$Code_Loc, !(colnames(U_m) %in% import_code)]) # drop VA - - dr <- q / (q + m) - mr <- 1 - dr - # Derive M by taking the ratio of domestic vs imported goods - M <- model$M_d %*% diag(as.vector(dr)) + model$M_m %*% diag(as.vector(mr)) - colnames(M) <- colnames(model$M_d) - - return(M) -} diff --git a/R/ValidateModel.R b/R/ValidateModel.R index 2c95753c..4b41c142 100644 --- a/R/ValidateModel.R +++ b/R/ValidateModel.R @@ -474,19 +474,6 @@ validateImportFactorsApproach <- function(model, demand = "Consumption"){ cat("assuming model$M = model$M_m.\n") print(all.equal(LCIA_dm, LCIA)) - cat("\nValidating that the derived M matrix has all values between M_d and M_m\n") - - # Validate that M is between M_m and M_d - a <- signif(model$M_m, 6) - b <- signif(model$M, 6) - c <- signif(model$M_d, 6) - z <- ((b > a) & (b > c)) | ((b < a) & (b < c)) - if(sum(z) == 0) { - print(TRUE) - } else { - comm <- colSums(z) > 0 - print(paste0("Failures: ", names(comm)[comm == TRUE])) - } } #' Validate the calculation of household_emissions diff --git a/man/deriveMMatrix.Rd b/man/deriveMMatrix.Rd deleted file mode 100644 index c56ac74e..00000000 --- a/man/deriveMMatrix.Rd +++ /dev/null @@ -1,17 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/ExternalImportFactors.R -\name{deriveMMatrix} -\alias{deriveMMatrix} -\title{Derives an aggregate M matrix from M_d and M_m based on the ratio of commodity output to total imports.} -\usage{ -deriveMMatrix(model) -} -\arguments{ -\item{model, }{An EEIO model object with model specs and crosswalk table loaded} -} -\value{ -An M matrix of flows x sector -} -\description{ -Derives an aggregate M matrix from M_d and M_m based on the ratio of commodity output to total imports. -} From 70ea6d4906557506ad1d7c3936fe0664e5c5a888 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Fri, 1 Nov 2024 09:41:13 -0400 Subject: [PATCH 15/16] add new calculation for M matrix with IEFs, #311 --- R/ExternalImportFactors.R | 18 +++++++++++++++++- man/calculateMwithImportFactors.Rd | 17 +++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 man/calculateMwithImportFactors.Rd diff --git a/R/ExternalImportFactors.R b/R/ExternalImportFactors.R index 5eb01866..2a8f8b73 100644 --- a/R/ExternalImportFactors.R +++ b/R/ExternalImportFactors.R @@ -100,7 +100,7 @@ castImportFactors <- function(IFTable, model) { buildModelwithImportFactors <- function(model, configpaths = NULL) { # (see Palm et al. 2019) - logging::loginfo("Building Import A (A_m) accounting for ITA in Domestic FD.\n") + logging::loginfo("Building A_m (import requirements) accounting for international trade adjustment in domestic final demand.\n") # Re-derive import values in Use and final demand # _m denotes import-related structures model$UseTransactions_m <- model$UseTransactions - model$DomesticUseTransactions @@ -126,5 +126,21 @@ buildModelwithImportFactors <- function(model, configpaths = NULL) { model$M_m <- M_m + model$M <- calculateMwithImportFactors(model) + return(model) } + +#' Derives an M matrix for total embodied flows from domestic and imported supply chains. +#' @param model, An EEIO model object with model specs and crosswalk table loaded +#' @return An M matrix of flows x sector +calculateMwithImportFactors <- function(model) { + logging::loginfo("Calculating M matrix (total emissions and resource use per dollar) ...") + + # embodied flows from the use of imports by industries to make their commodities + # both directly (from A_m) and indirectly (by scaling it to total requirements using L_d) + M_mi <- model$M_m %*% model$A_m %*% model$L_d + + M <- model$M_d + M_mi + return(M) +} diff --git a/man/calculateMwithImportFactors.Rd b/man/calculateMwithImportFactors.Rd new file mode 100644 index 00000000..d6725db0 --- /dev/null +++ b/man/calculateMwithImportFactors.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ExternalImportFactors.R +\name{calculateMwithImportFactors} +\alias{calculateMwithImportFactors} +\title{Derives an M matrix for total embodied flows from domestic and imported supply chains.} +\usage{ +calculateMwithImportFactors(model) +} +\arguments{ +\item{model, }{An EEIO model object with model specs and crosswalk table loaded} +} +\value{ +An M matrix of flows x sector +} +\description{ +Derives an M matrix for total embodied flows from domestic and imported supply chains. +} From 13854b4a8a4c8965fe15bcb0907d9758337914d5 Mon Sep 17 00:00:00 2001 From: Ben Young Date: Mon, 4 Nov 2024 13:56:51 -0500 Subject: [PATCH 16/16] :bookmark: bump to v1.6.1 --- DESCRIPTION | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 42bbf678..b703a37c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Package: useeior Type: Package Title: USEEIO R modeling software -Version: 1.6.0 -Date: 2024-8-6 +Version: 1.6.1 +Date: 2024-11-4 Authors@R: c( person("Ben","Young", email="ben.young@erg.com", role="aut"), person("Jorge","Vendries", email="jvendries@gmail.com", role="aut"),