diff --git a/src/main/java/simpaths/data/Parameters.java b/src/main/java/simpaths/data/Parameters.java index ea8b52e66..1b1d18075 100644 --- a/src/main/java/simpaths/data/Parameters.java +++ b/src/main/java/simpaths/data/Parameters.java @@ -10,6 +10,8 @@ import org.apache.commons.io.FileUtils; import simpaths.data.startingpop.DataParser; import simpaths.model.AnnuityRates; +import simpaths.model.BenefitUnit; +import simpaths.model.Person; import simpaths.model.enums.*; import org.apache.commons.collections4.keyvalue.MultiKey; import org.apache.commons.collections4.map.LinkedMap; @@ -1138,6 +1140,8 @@ public static void loadParameters(Country country, int maxAgeModel, boolean enab coeffCovarianceHM2CaseMales = ExcelAssistant.loadCoefficientMap(Parameters.getInputDirectory() + "reg_health_mental.xlsx", countryString + "_HM2_Males_C", 1); coeffCovarianceHM2CaseFemales = ExcelAssistant.loadCoefficientMap(Parameters.getInputDirectory() + "reg_health_mental.xlsx", countryString + "_HM2_Females_C", 1); + validateRegressors(coeffCovarianceHM2CaseMales, "reg_health_mental.xlsx", "HM2_Males_C"); + //Health coeffCovarianceDHE_MCS1 = ExcelAssistant.loadCoefficientMap(Parameters.getInputDirectory() + "reg_health_wellbeing.xlsx", countryString + "_DHE_MCS1", 1); coeffCovarianceDHE_MCS2Males = ExcelAssistant.loadCoefficientMap(Parameters.getInputDirectory() + "reg_health_wellbeing.xlsx", countryString + "_DHE_MCS2_Males", 1); @@ -3230,6 +3234,55 @@ public static void setEuromodOutputDirectory(String euromodOutputDirectory) { EUROMOD_TRAINING_DIRECTORY = EUROMOD_OUTPUT_DIRECTORY + "training" + File.separator; } + public static void validateRegressors(MultiKeyCoefficientMap map, String excelFileName, String sheetName) { + if (map == null) return; + + // Get the values read from the REGRESSOR column by ExcelAssistant (excludes 'Constant') + Set regressorNames = map.keySet(); + + // Check across all + for (Object regressor : regressorNames) { + if (regressor instanceof MultiKey mk) { + String keyName = mk.getKey(0).toString(); + + // Test if a Person Enum + try { + Person.DoublesVariables.valueOf(keyName); + } catch (IllegalArgumentException e) { + try { + BenefitUnit.Regressors.valueOf(keyName); + } catch (IllegalArgumentException e2) { + + // This fires if the string isn't in the Enum + throw new RuntimeException("Validation failed for " + excelFileName + " in " + sheetName + + ": Regressor '" + keyName + "' not found in Person.DoublesVariables. " + + "Check for typos in Excel or missing Enums in Person.java."); + } + } + } + } + } + + public static MultiKeyCoefficientMap safeReadExcel(String excelFileName, String sheetName, int keyColumns) { + + MultiKeyCoefficientMap map = ExcelAssistant.loadCoefficientMap(excelFileName, sheetName, keyColumns); + + validateRegressors(map, excelFileName, sheetName); + + return map; + + } + + public static MultiKeyCoefficientMap safeReadExcel(String excelFileName, String sheetName, int keyColumns, int valueColumns) { + + MultiKeyCoefficientMap map = ExcelAssistant.loadCoefficientMap(excelFileName, sheetName, keyColumns, valueColumns); + + validateRegressors(map, excelFileName, sheetName); + + return map; + + } + public static String getInputDirectory() { return INPUT_DIRECTORY; } diff --git a/src/test/java/simpaths/data/ParametersTest.java b/src/test/java/simpaths/data/ParametersTest.java new file mode 100644 index 000000000..b0ead97d4 --- /dev/null +++ b/src/test/java/simpaths/data/ParametersTest.java @@ -0,0 +1,32 @@ +package simpaths.data; + +import microsim.data.MultiKeyCoefficientMap; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.*; + +class ParametersTest { + + /** + * Tests regressor validation logic using valid/invalid maps + */ + @Test + void validateRegressors() { + + String[] badValueVector = new String[] {"Dag", "Not_a_valid_value"}; + String[] goodValueVector = new String[] {"Dag", "D_Home_owner", "PovertyToNonPoverty"}; + String[] keyVector = new String[] {"REGRESSOR"}; + + MultiKeyCoefficientMap badMap = new MultiKeyCoefficientMap(keyVector, badValueVector); + for (String badValue : badValueVector) {badMap.putValue(badValue, 0);} + + MultiKeyCoefficientMap goodMap = new MultiKeyCoefficientMap(keyVector, goodValueVector); + for (String goodValue : goodValueVector) {goodMap.putValue(goodValue, 0);} + + assertThrows(RuntimeException.class, () -> Parameters.validateRegressors(badMap, "A map designed to contain invalid values", "Sheet1")); + assertDoesNotThrow(() -> Parameters.validateRegressors(goodMap, "A map designed to contain valid values", "Sheet1")); + + } +} \ No newline at end of file