-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add sim state pipeline * update filename
- Loading branch information
Showing
13 changed files
with
418 additions
and
4 deletions.
There are no files selected for viewing
134 changes: 134 additions & 0 deletions
134
src/main/java/gov/hhs/aspr/ms/gcm/pipeline/pipelines/SimulationStatePipeline.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package gov.hhs.aspr.ms.gcm.pipeline.pipelines; | ||
|
||
import java.nio.file.Path; | ||
import java.time.LocalDate; | ||
import java.time.format.DateTimeFormatter; | ||
import java.time.format.DateTimeParseException; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import gov.hhs.aspr.ms.gcm.pipeline.input.SimulationStatePipelineInput; | ||
import gov.hhs.aspr.ms.gcm.pipeline.support.GCMPipelineFileHeaders; | ||
import gov.hhs.aspr.ms.gcm.pipeline.IPipeline; | ||
import gov.hhs.aspr.ms.gcm.simulation.nucleus.SimulationState; | ||
import gov.hhs.aspr.ms.gcm.taskit.protobuf.nucleus.NucleusTranslator; | ||
import gov.hhs.aspr.ms.gcm.taskit.protobuf.nucleus.input.SimulationStateInput; | ||
import gov.hhs.aspr.ms.gcm.taskit.protobuf.nucleus.translationSpecs.SimulationStateTranslationSpec; | ||
import gov.hhs.aspr.ms.taskit.core.TranslationController; | ||
import gov.hhs.aspr.ms.taskit.core.TranslationEngineType; | ||
import gov.hhs.aspr.ms.taskit.protobuf.ProtobufTranslationEngine; | ||
import gov.hhs.aspr.ms.util.errors.ContractException; | ||
import gov.hhs.aspr.ms.util.readers.TextTableReader; | ||
import gov.hhs.aspr.ms.util.resourcehelper.ResourceError; | ||
import gov.hhs.aspr.ms.util.resourcehelper.ResourceHelper; | ||
|
||
/** | ||
* A utility for constructing the SimulationState file from the | ||
* simStateSettingsFile | ||
*/ | ||
public class SimulationStatePipeline implements IPipeline { | ||
|
||
/** | ||
* Given a {@link SimulationStatePipelineInput}, an input directory path and an | ||
* output directory path, return a {@link SimulationStatePipeline} | ||
* | ||
* @throws ContractException | ||
* <ul> | ||
* <li>{@link ResourceError#UNKNOWN_FILE} if any of | ||
* the input paths are not valid</li> | ||
* <li>{@link ResourceError#FILE_PATH_IS_DIRECTORY} if | ||
* any of the input paths or output path point to a directory</li> | ||
* </ul> | ||
*/ | ||
public static SimulationStatePipeline from(SimulationStatePipelineInput pipelineInput, Path inputDirectory, | ||
Path outputDirectory) { | ||
String simStateSettingsFile = inputDirectory.resolve(pipelineInput.getSimulationSettingsFile()).toString(); | ||
String simStateFile = outputDirectory.resolve(pipelineInput.getSimulationStateFile()).toString(); | ||
|
||
Path simStateSettingsPath = ResourceHelper.validateFile(simStateSettingsFile); | ||
|
||
Path simStatePath = ResourceHelper.validateFilePath(simStateFile); | ||
|
||
return new SimulationStatePipeline(simStateSettingsPath, simStatePath); | ||
} | ||
|
||
private final Path simStateSettingsFile; | ||
|
||
private final Path simStateFile; | ||
|
||
private SimulationStatePipeline(Path simStateSettingsFile, Path simStateDataFile) { | ||
this.simStateSettingsFile = simStateSettingsFile; | ||
this.simStateFile = simStateDataFile; | ||
} | ||
|
||
/** | ||
* Executes the pipeline with the given input files | ||
* <p> | ||
* writes out the resulting simState file to the path provided | ||
*/ | ||
public void execute() { | ||
SimulationState.Builder builder = SimulationState.builder(); | ||
|
||
System.out.println("SimulationState Pipeline::loading simulation state settings file"); | ||
loadSimStateSettingsFile(builder); | ||
|
||
System.out.println("SimulationState Pipeline::translating simulation state"); | ||
// create the translation engine and have it use the nucleus translator and | ||
ProtobufTranslationEngine protobufTranslationEngine = ProtobufTranslationEngine.builder()// | ||
.addTranslator(NucleusTranslator.getTranslator())// | ||
.build();// | ||
|
||
SimulationStateTranslationSpec translationSpec = new SimulationStateTranslationSpec(); | ||
translationSpec.init(protobufTranslationEngine); | ||
|
||
SimulationStateInput input = translationSpec.convert(builder.build()); | ||
builder = null; | ||
|
||
System.out.println("SimulationState Pipeline::writing simulation state"); | ||
// build the translation controller and have it write the SimulationState file | ||
TranslationController.builder() | ||
.addTranslationEngine(protobufTranslationEngine)// | ||
.build()// | ||
.writeOutput(input, simStateFile, TranslationEngineType.PROTOBUF);// | ||
|
||
System.out.println("SimulationState Pipeline::done"); | ||
|
||
} | ||
|
||
private void loadSimStateSettingsFile(SimulationState.Builder builder) { | ||
List<DateTimeFormatter> formatters = new ArrayList<>(); | ||
|
||
formatters.add(DateTimeFormatter.ofPattern("M-d-uuuu")); | ||
formatters.add(DateTimeFormatter.ofPattern("M/d/uuuu")); | ||
formatters.add(DateTimeFormatter.ofPattern("uuuu-M-d")); | ||
formatters.add(DateTimeFormatter.ofPattern("uuuu/M/d")); | ||
|
||
TextTableReader.read(",", GCMPipelineFileHeaders.SIM_STATE_SETTINGS, simStateSettingsFile, (values) -> { | ||
switch (values[0]) { | ||
case "start_time": | ||
builder.setStartTime(Double.parseDouble(values[1])); | ||
break; | ||
case "base_date": | ||
LocalDate localDate; | ||
RuntimeException runtimeException = null; | ||
for (DateTimeFormatter formatter : formatters) { | ||
try { | ||
localDate = LocalDate.parse(values[1], formatter); | ||
builder.setBaseDate(localDate); | ||
runtimeException = null; | ||
break; | ||
} catch (DateTimeParseException e) { | ||
runtimeException = new RuntimeException(e); | ||
} | ||
} | ||
|
||
if (runtimeException != null) { | ||
throw runtimeException; | ||
} | ||
|
||
break; | ||
// plans are not currently supported | ||
} | ||
}); | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
src/main/java/gov/hhs/aspr/ms/gcm/pipeline/support/GCMPipelineFileHeaders.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package gov.hhs.aspr.ms.gcm.pipeline.support; | ||
|
||
public class GCMPipelineFileHeaders { | ||
|
||
private GCMPipelineFileHeaders() { | ||
} | ||
|
||
public static String SIM_STATE_SETTINGS = "property,value"; | ||
} |
10 changes: 10 additions & 0 deletions
10
src/main/proto/gov/hhs/aspr/ms/gcm/pipeline/pipeline.proto
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
syntax = "proto3"; | ||
package gov.hhs.aspr.ms.gcm.pipeline; | ||
|
||
option java_multiple_files = true; | ||
option java_package = "gov.hhs.aspr.ms.gcm.pipeline.input"; | ||
|
||
message SimulationStatePipelineInput { | ||
string simulationSettingsFile = 1; | ||
string simulationStateFile = 2; | ||
} |
35 changes: 35 additions & 0 deletions
35
src/test/java/gov/hhs/aspr/ms/gcm/pipeline/PipelineTestHelper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package gov.hhs.aspr.ms.gcm.pipeline; | ||
|
||
import gov.hhs.aspr.ms.gcm.taskit.protobuf.nucleus.NucleusTranslator; | ||
import gov.hhs.aspr.ms.gcm.taskit.protobuf.plugins.groups.GroupsTranslator; | ||
import gov.hhs.aspr.ms.gcm.taskit.protobuf.plugins.people.PeopleTranslator; | ||
import gov.hhs.aspr.ms.gcm.taskit.protobuf.plugins.personproperties.PersonPropertiesTranslator; | ||
import gov.hhs.aspr.ms.gcm.taskit.protobuf.plugins.properties.PropertiesTranslator; | ||
import gov.hhs.aspr.ms.gcm.taskit.protobuf.plugins.regions.RegionsTranslator; | ||
import gov.hhs.aspr.ms.gcm.taskit.protobuf.plugins.reports.ReportsTranslator; | ||
import gov.hhs.aspr.ms.gcm.taskit.protobuf.plugins.stochastics.StochasticsTranslator; | ||
import gov.hhs.aspr.ms.taskit.protobuf.ProtobufTranslationEngine; | ||
|
||
/** | ||
* This class is to help test the pipelines | ||
*/ | ||
public class PipelineTestHelper { | ||
|
||
/* | ||
* static method to return a new protobuf translation engine. | ||
* | ||
* used in a method due to nature of static access | ||
*/ | ||
public static ProtobufTranslationEngine getProtobufTranslationEngine() { | ||
return ProtobufTranslationEngine.builder() | ||
.addTranslator(PeopleTranslator.getTranslator()) | ||
.addTranslator(PersonPropertiesTranslator.getTranslator()) | ||
.addTranslator(GroupsTranslator.getTranslator()) | ||
.addTranslator(RegionsTranslator.getTranslator()) | ||
.addTranslator(ReportsTranslator.getTranslator()) | ||
.addTranslator(StochasticsTranslator.getTranslator()) | ||
.addTranslator(PropertiesTranslator.getTranslator()) | ||
.addTranslator(NucleusTranslator.getTranslator()) | ||
.build(); | ||
} | ||
} |
92 changes: 92 additions & 0 deletions
92
src/test/java/gov/hhs/aspr/ms/gcm/pipeline/PipelineTestPaths.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package gov.hhs.aspr.ms.gcm.pipeline; | ||
|
||
import java.nio.file.Path; | ||
|
||
import gov.hhs.aspr.ms.util.resourcehelper.ResourceHelper; | ||
|
||
/** | ||
* This is a class that contains all of the paths for all pipeline test output | ||
* files and the test resource directory. | ||
* | ||
* When adding a new dimension or plugin data, first add the file name in the | ||
* respective section, and then add the path in the respective section. | ||
*/ | ||
public class PipelineTestPaths { | ||
// name of expected output directory | ||
private static final String EXPECTED_OUTPUT_DIR_NAME = "expectedOutput"; | ||
|
||
// name of test output directory | ||
private static final String TEST_OUTPUT_DIR_NAME = "testOutput"; | ||
|
||
// name of pipelineInput directory | ||
private static final String PIPELINE_INPUT_DIR_NAME = "pipelineInput"; | ||
|
||
// name of each of the pipeline input files | ||
private static final String SIM_STATE_PIPELINE_INPUT_F_NAME = "simulationStatePipeline.json"; | ||
|
||
// name of each the plugin data files | ||
private static final String POPULATION_P_DATA_F_NAME = "populationPluginData.json"; | ||
private static final String PEOPLE_P_DATA_F_NAME = "peoplePluginData.json"; | ||
private static final String PEOPLE_P_DATA_EMPTY_F_NAME = "peoplePluginData_empty.json"; | ||
private static final String PERSON_PROPS_P_DATA_F_NAME = "personPropertiesPluginData.json"; | ||
private static final String GROUPS_P_DATA_F_NAME = "groupsPluginData.json"; | ||
private static final String REGIONS_P_DATA_F_NAME = "regionsPluginData.json"; | ||
private static final String STOCHASTICS_P_DATA_F_NAME = "stochasticsPluginData.json"; | ||
|
||
// name of gcm experiment params and sim state files | ||
private static final String EXPERIMENT_PARAMS_F_NAME = "experimentParameterData.json"; | ||
private static final String SIM_STATE_F_NAME = "simulationState.json"; | ||
|
||
// Absolute path to the resource directory used in testing | ||
public static final Path RESOURCE_DIR = ResourceHelper.getResourceDir(PipelineTestPaths.class); | ||
|
||
// absolute path to the expected output directory based on the resource dir | ||
// above | ||
public static final Path EXPECTED_OUTPUT_DIR = getResolvedResourcePath(EXPECTED_OUTPUT_DIR_NAME); | ||
|
||
// absolute path to the test output directory based on the resource dir above | ||
public static final Path TEST_OUTPUT_DIR = getResolvedResourcePath(TEST_OUTPUT_DIR_NAME); | ||
|
||
// absolute path to the pipeline input directory based on the resource dir above | ||
public static final Path PIPELINE_INPUT_DIR = getResolvedResourcePath(PIPELINE_INPUT_DIR_NAME); | ||
|
||
// absolute paths to each of the pipeline input files | ||
public static final Path SIM_STATE_PIPELINE = getResolvedPipelineInputPath(SIM_STATE_PIPELINE_INPUT_F_NAME); | ||
|
||
// absolute paths to each of the expected output plugin data files | ||
public static final Path EXPECTED_POPULATION_PLUGIN_DATA = getResolvedOutputPath(POPULATION_P_DATA_F_NAME); | ||
public static final Path EXPECTED_PEOPLE_PLUGIN_DATA = getResolvedOutputPath(PEOPLE_P_DATA_F_NAME); | ||
public static final Path EXPECTED_PEOPLE_PLUGIN_DATA_EMPTY = getResolvedOutputPath(PEOPLE_P_DATA_EMPTY_F_NAME); | ||
public static final Path EXPECTED_PERSON_PROPS_PLUGIN_DATA = getResolvedOutputPath(PERSON_PROPS_P_DATA_F_NAME); | ||
public static final Path EXPECTED_GROUPS_PLUGIN_DATA = getResolvedOutputPath(GROUPS_P_DATA_F_NAME); | ||
public static final Path EXPECTED_REGIONS_PLUGIN_DATA = getResolvedOutputPath(REGIONS_P_DATA_F_NAME); | ||
public static final Path EXPECTED_STOCHASTICS_PLUGIN_DATA = getResolvedOutputPath(STOCHASTICS_P_DATA_F_NAME); | ||
|
||
// absolute paths to the gcm experiment params and sim state files | ||
public static final Path EXPECTED_EXPERIMENT_PARAMETER_DATA = getResolvedOutputPath(EXPERIMENT_PARAMS_F_NAME); | ||
public static final Path EXPECTED_SIMULATION_STATE = getResolvedOutputPath(SIM_STATE_F_NAME); | ||
|
||
private PipelineTestPaths() { | ||
} | ||
|
||
/** | ||
* Given a path, return it resolved against the resource directory path | ||
*/ | ||
public static Path getResolvedResourcePath(String path) { | ||
return RESOURCE_DIR.resolve(path).toAbsolutePath(); | ||
} | ||
|
||
/** | ||
* Given a path, return it resolved against the expected output directory path | ||
*/ | ||
public static Path getResolvedOutputPath(String path) { | ||
return EXPECTED_OUTPUT_DIR.resolve(path); | ||
} | ||
|
||
/** | ||
* Given a path, return it resolved against the pipeline input directory path | ||
*/ | ||
public static Path getResolvedPipelineInputPath(String path) { | ||
return PIPELINE_INPUT_DIR.resolve(path); | ||
} | ||
} |
98 changes: 98 additions & 0 deletions
98
src/test/java/gov/hhs/aspr/ms/gcm/pipeline/pipelines/AT_SimulationStatePipeline.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package gov.hhs.aspr.ms.gcm.pipeline.pipelines; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertNotNull; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
import static org.junit.jupiter.api.Assertions.assertTrue; | ||
|
||
import java.nio.file.Path; | ||
import java.time.format.DateTimeParseException; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
import gov.hhs.aspr.ms.gcm.pipeline.PipelineTestHelper; | ||
import gov.hhs.aspr.ms.gcm.pipeline.PipelineTestPaths; | ||
import gov.hhs.aspr.ms.gcm.pipeline.input.SimulationStatePipelineInput; | ||
import gov.hhs.aspr.ms.gcm.pipeline.testsupport.PipelineTestSupport; | ||
import gov.hhs.aspr.ms.gcm.simulation.nucleus.SimulationState; | ||
import gov.hhs.aspr.ms.gcm.taskit.protobuf.nucleus.input.SimulationStateInput; | ||
import gov.hhs.aspr.ms.util.annotations.UnitTestMethod; | ||
import gov.hhs.aspr.ms.util.errors.ContractException; | ||
import gov.hhs.aspr.ms.util.resourcehelper.ResourceError; | ||
import gov.hhs.aspr.ms.util.resourcehelper.ResourceHelper; | ||
|
||
public class AT_SimulationStatePipeline { | ||
PipelineTestSupport<SimulationStatePipelineInput> pipelineInputTestSupport = new PipelineTestSupport<>( | ||
PipelineTestHelper.getProtobufTranslationEngine(), | ||
SimulationStatePipelineInput.getDefaultInstance(), SimulationStatePipelineInput.class, | ||
PipelineTestPaths::getResolvedResourcePath, PipelineTestPaths.TEST_OUTPUT_DIR); | ||
|
||
SimulationStatePipelineInput unresolvedPipelineInput = pipelineInputTestSupport | ||
.getUnresolvedPipelineInput(PipelineTestPaths.SIM_STATE_PIPELINE.toString()); | ||
|
||
SimulationStatePipelineInput resolvedPipelineInput = pipelineInputTestSupport | ||
.getResolvedPipelineInput(unresolvedPipelineInput, false, false); | ||
|
||
@Test | ||
@UnitTestMethod(target = SimulationStatePipeline.class, name = "from", args = { | ||
SimulationStatePipelineInput.class, | ||
Path.class, Path.class }) | ||
public void testFrom() { | ||
|
||
Path inputPath = Path.of(""); | ||
Path outputPath = Path.of(""); | ||
|
||
SimulationStatePipelineInput pipelineInput = resolvedPipelineInput; | ||
|
||
SimulationStatePipeline pipeline = SimulationStatePipeline.from(pipelineInput, inputPath, outputPath); | ||
|
||
assertNotNull(pipeline); | ||
|
||
// preconditions | ||
// simStateSettingsFile is invalid | ||
ContractException contractException = assertThrows(ContractException.class, () -> { | ||
SimulationStatePipeline.from( | ||
pipelineInput.toBuilder().setSimulationSettingsFile("invalidPath").build(), | ||
inputPath, outputPath); | ||
}); | ||
|
||
assertEquals(ResourceError.UNKNOWN_FILE, contractException.getErrorType()); | ||
} | ||
|
||
@Test | ||
@UnitTestMethod(target = SimulationStatePipeline.class, name = "execute", args = {}) | ||
public void testExecute() { | ||
|
||
Path resourceDir = PipelineTestPaths.RESOURCE_DIR; | ||
|
||
Path inputPath = Path.of(""); | ||
Path outputPath = Path.of(""); | ||
|
||
SimulationStatePipelineInput pipelineInput = resolvedPipelineInput; | ||
|
||
Path dataFile = resourceDir.resolve(pipelineInput.getSimulationStateFile()); | ||
|
||
ResourceHelper.createDirectory(dataFile.getParent()); | ||
ResourceHelper.createFile(dataFile.getParent(), dataFile.getFileName().toString()); | ||
|
||
SimulationStatePipeline pipeline = SimulationStatePipeline.from(pipelineInput, inputPath, outputPath); | ||
|
||
pipeline.execute(); | ||
|
||
assertTrue(pipelineInputTestSupport.filesAreSame(SimulationStateInput.class, | ||
SimulationState.class, PipelineTestPaths.EXPECTED_SIMULATION_STATE, dataFile)); | ||
|
||
// preconditions | ||
// base date is invalid | ||
SimulationStatePipelineInput badDate = pipelineInput.toBuilder() | ||
.setSimulationSettingsFile(pipelineInput.getSimulationSettingsFile() | ||
.replace("simulation_settings.csv", "simulation_settings_bad_date.csv")) | ||
.build(); | ||
|
||
RuntimeException runtimeException = assertThrows(RuntimeException.class, () -> { | ||
SimulationStatePipeline.from(badDate, inputPath, outputPath).execute(); | ||
}); | ||
|
||
assertEquals(DateTimeParseException.class, runtimeException.getCause().getClass()); | ||
} | ||
} |
Oops, something went wrong.