diff --git a/.github/workflows/objective-c-xcode-debug.yml b/.github/workflows/objective-c-xcode-debug.yml deleted file mode 100644 index 7d157ee9a0..0000000000 --- a/.github/workflows/objective-c-xcode-debug.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Xcode - Test and debug - -on: - workflow_dispatch: - inputs: - debug_enabled: - description: 'Run the build with tmate debugging enabled?' - required: false - default: 'true' -jobs: - build: - name: Build and analyse default scheme using xcodebuild command - runs-on: macos-latest - - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set Default Scheme - run: | - scheme_list=$(xcodebuild -list -json | tr -d "\n") - default=$(echo $scheme_list | ruby -e "require 'json'; puts JSON.parse(STDIN.gets)['project']['targets'][0]") - echo $default | cat >default - echo Using default scheme: $default -# - name: Build -# env: -# scheme: ${{ 'default' }} -# run: | -# if [ $scheme = default ]; then scheme=$(cat default); fi -# if [ "`ls -A | grep -i \\.xcworkspace\$`" ]; then filetype_parameter="workspace" && file_to_build="`ls -A | grep -i \\.xcworkspace\$`"; else filetype_parameter="project" && file_to_build="`ls -A | grep -i \\.xcodeproj\$`"; fi -# file_to_build=`echo $file_to_build | awk '{$1=$1;print}'` -# xcodebuild clean build analyze -scheme "$scheme" -"$filetype_parameter" "$file_to_build" | xcpretty && exit ${PIPESTATUS[0]} - - - name: Setup tmate session 2 - uses: mxschmitt/action-tmate@v3 - if: ${{ failure() || github.event.inputs.debug_enabled }} diff --git a/vcell-cli/src/main/java/org/vcell/cli/run/ExecuteImpl.java b/vcell-cli/src/main/java/org/vcell/cli/run/ExecuteImpl.java index b78dfe3c43..9e08a57d14 100644 --- a/vcell-cli/src/main/java/org/vcell/cli/run/ExecuteImpl.java +++ b/vcell-cli/src/main/java/org/vcell/cli/run/ExecuteImpl.java @@ -40,38 +40,39 @@ public static void batchMode(File dirOfArchivesToProcess, File outputDir, CLIRec for (File inputFile : inputFiles){ String bioModelBaseName = FileUtils.getBaseName(inputFile.getName()); String outputBaseDir = outputDir.getAbsolutePath(); // bioModelBaseName = input file without the path - String targetOutputDir = Paths.get(outputBaseDir, bioModelBaseName).toString(); - File adjustedOutputDir = new File(targetOutputDir); - + File targetOutputDir = Paths.get(outputBaseDir, bioModelBaseName).toFile(); logger.info("Preparing output directory..."); // we don't want to accidentally delete the input... // if the output is a subset of the input file's housing directory, we shouldn't delete!! - if (!inputFile.getParentFile().getCanonicalPath().contains(adjustedOutputDir.getCanonicalPath())) - RunUtils.removeAndMakeDirs(adjustedOutputDir); - try { - BiosimulationLog.generateStatusYaml(inputFile.getAbsolutePath(), targetOutputDir); // generate Status YAML - } catch (XMLException e){ - throw new RuntimeException("Python call did not process correctly:", e); + if (!inputFile.getParentFile().getCanonicalPath().contains(targetOutputDir.getCanonicalPath())) { + RunUtils.removeAndMakeDirs(targetOutputDir); } } try { for (File inputFile : inputFiles) { String inputFileName = inputFile.getName(); - System.out.println("\n\n"); - logger.info("Processing " + inputFileName + "(" + inputFile + ")"); + String bioModelBaseName = FileUtils.getBaseName(inputFile.getName()); + String outputBaseDir = outputDir.getAbsolutePath(); // bioModelBaseName = input file without the path + String targetOutputDir = Paths.get(outputBaseDir, bioModelBaseName).toString(); + Span span = null; try { span = Tracer.startSpan(Span.ContextType.OMEX_EXECUTE, inputFileName, Map.of("filename", inputFileName)); - if (inputFileName.endsWith("vcml")) + BiosimulationLog.initialize(inputFile.getAbsolutePath(), targetOutputDir); // generate Status YAML + + System.out.println("\n\n"); + logger.info("Processing " + inputFileName + "(" + inputFile + ")"); + + if (inputFileName.endsWith("vcml")) { singleExecVcml(inputFile, outputDir, cliLogger); - if (inputFileName.endsWith("omex")) - runSingleExecOmex(inputFile, outputDir, cliLogger, - bKeepTempFiles, bExactMatchOnly, bSmallMeshOverride); - } catch (ExecutionException e){ + } else if (inputFileName.endsWith("omex")) { + runSingleExecOmex(inputFile, outputDir, cliLogger, bKeepTempFiles, bExactMatchOnly, bSmallMeshOverride); + } + } catch (ExecutionException e) { logger.error("Error caught executing batch mode", e); Tracer.failure(e, "Error caught executing batch mode"); failedFiles.add(inputFileName); - } catch (Exception e){ + } catch (Exception e) { Tracer.failure(e, "Error caught executing batch mode"); failedFiles.add(inputFileName); throw e; @@ -79,6 +80,7 @@ public static void batchMode(File dirOfArchivesToProcess, File outputDir, CLIRec if (span != null) { span.close(); } + BiosimulationLog.instance().close(); } } if (failedFiles.isEmpty()){ @@ -138,10 +140,14 @@ public static void singleMode(File inputFile, File rootOutputDir, CLIRecordable if (!inputFile.getParentFile().getCanonicalPath().contains(adjustedOutputDir.getCanonicalPath())) RunUtils.removeAndMakeDirs(adjustedOutputDir); - BiosimulationLog.generateStatusYaml(inputFile.getAbsolutePath(), targetOutputDir); // generate Status YAML + try { + BiosimulationLog.initialize(inputFile.getAbsolutePath(), targetOutputDir); // generate Status YAML - ExecuteImpl.singleExecOmex(inputFile, rootOutputDir, cliLogger, bKeepTempFiles, bExactMatchOnly, - bEncapsulateOutput, bSmallMeshOverride, bBioSimMode); + ExecuteImpl.singleExecOmex(inputFile, rootOutputDir, cliLogger, bKeepTempFiles, bExactMatchOnly, + bEncapsulateOutput, bSmallMeshOverride, bBioSimMode); + } finally { + BiosimulationLog.instance().close(); + } } public static void singleMode(File inputFile, File outputDir, CLIRecordable cliLogger) throws Exception { @@ -232,7 +238,7 @@ public static void singleExecVcml(File vcmlFile, File outputDir, CLIRecordable c private static void singleExecOmex(File inputFile, File rootOutputDir, CLIRecordable cliRecorder, boolean bKeepTempFiles, boolean bExactMatchOnly, boolean bEncapsulateOutput, boolean bSmallMeshOverride, boolean bBioSimMode) - throws ExecutionException, PythonStreamException, IOException, InterruptedException, BiosimulationsHdfWriterException { + throws ExecutionException, PythonStreamException, IOException, BiosimulationsHdfWriterException { ExecutionJob requestedExecution = new ExecutionJob(inputFile, rootOutputDir, cliRecorder, bKeepTempFiles, bExactMatchOnly, bEncapsulateOutput, bSmallMeshOverride); diff --git a/vcell-cli/src/main/java/org/vcell/cli/run/ExecutionJob.java b/vcell-cli/src/main/java/org/vcell/cli/run/ExecutionJob.java index bee9e04e1d..2585dfe1f3 100644 --- a/vcell-cli/src/main/java/org/vcell/cli/run/ExecutionJob.java +++ b/vcell-cli/src/main/java/org/vcell/cli/run/ExecutionJob.java @@ -12,6 +12,7 @@ import java.io.File; import java.io.IOException; +import java.math.BigDecimal; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; @@ -25,10 +26,12 @@ public class ExecutionJob { private final static Logger logger = LogManager.getLogger(ExecutionJob.class); - private long startTime, endTime; + private long startTime_ms, endTime_ms; private boolean bExactMatchOnly, bSmallMeshOverride, bKeepTempFiles; private StringBuilder logOmexMessage; - private String inputFilePath, bioModelBaseName, outputBaseDir, outputDir; + private String inputFilePath; + private String bioModelBaseName; + private String outputDir; private boolean anySedmlDocumentHasSucceeded = false; // set to true if at least one sedml document run is successful private boolean anySedmlDocumentHasFailed = false; // set to true if at least one sedml document run fails @@ -58,7 +61,7 @@ public ExecutionJob(File inputFile, File rootOutputDir, CLIRecordable cliRecorde this.inputFilePath = inputFile.getAbsolutePath(); this.bioModelBaseName = FileUtils.getBaseName(inputFile.getName()); // input file without the path - this.outputBaseDir = rootOutputDir.getAbsolutePath(); + String outputBaseDir = rootOutputDir.getAbsolutePath(); this.outputDir = bEncapsulateOutput ? Paths.get(outputBaseDir, bioModelBaseName).toString() : outputBaseDir; this.bKeepTempFiles = bKeepTempFiles; this.bExactMatchOnly = bExactMatchOnly; @@ -78,7 +81,7 @@ private ExecutionJob(){ */ public void preprocessArchive() throws PythonStreamException, IOException { // Start the clock - this.startTime = System.currentTimeMillis(); + this.startTime_ms = System.currentTimeMillis(); // Beginning of Execution logger.info("Executing OMEX archive `{}`", this.inputFile.getName()); @@ -108,7 +111,7 @@ public void preprocessArchive() throws PythonStreamException, IOException { } // Update Status - BiosimulationLog.updateOmexStatusYml(BiosimulationLog.Status.RUNNING, outputDir, "0"); + BiosimulationLog.instance().updateOmexStatusYml(BiosimulationLog.Status.RUNNING, 0.0); } /** @@ -128,7 +131,7 @@ public void executeArchive(boolean isBioSimSedml) throws BiosimulationsHdfWriter this.queueAllSedml(); for (String sedmlLocation : this.sedmlLocations){ - SedmlJob job = new SedmlJob(sedmlLocation, this.omexHandler, this.inputFile, new File(this.outputBaseDir), + SedmlJob job = new SedmlJob(sedmlLocation, this.omexHandler, this.inputFile, this.outputDir, this.sedmlPath2d3d.toString(), this.cliRecorder, this.bKeepTempFiles, this.bExactMatchOnly, this.bSmallMeshOverride, this.logOmexMessage); if (!job.preProcessDoc()){ @@ -166,13 +169,13 @@ public void executeArchive(boolean isBioSimSedml) throws BiosimulationsHdfWriter * @throws PythonStreamException if calls to the python-shell instance are not working correctly * @throws IOException if there are system I/O issues */ - public void postProcessessArchive() throws InterruptedException, PythonStreamException, IOException { + public void postProcessessArchive() throws IOException { omexHandler.deleteExtractedOmex(); - this.endTime = System.currentTimeMillis(); - long elapsedTime = this.endTime - this.startTime; - int duration = (int) Math.ceil(elapsedTime / 1000.0); - logger.info("Omex " + inputFile.getName() + " processing completed (" + Integer.toString(duration) + "s)"); + this.endTime_ms = System.currentTimeMillis(); + long elapsedTime_ms = this.endTime_ms - this.startTime_ms; + double duration_s = elapsedTime_ms / 1000.0; + logger.info("Omex " + inputFile.getName() + " processing completed (" + duration_s + "s)"); // // failure if at least one of the documents in the omex archive fails // @@ -181,24 +184,24 @@ public void postProcessessArchive() throws InterruptedException, PythonStreamExc if (anySedmlDocumentHasSucceeded) { // some succeeded, some failed error = " At least one document in this archive failed to execute"; } - BiosimulationLog.updateOmexStatusYml(BiosimulationLog.Status.FAILED, outputDir, duration + ""); + BiosimulationLog.instance().updateOmexStatusYml(BiosimulationLog.Status.FAILED, duration_s); logger.error(error); logOmexMessage.append(error); cliRecorder.writeErrorList(new Exception("exception not recorded"), bioModelBaseName); } else { - BiosimulationLog.updateOmexStatusYml(BiosimulationLog.Status.SUCCEEDED, outputDir, duration + ""); + BiosimulationLog.instance().updateOmexStatusYml(BiosimulationLog.Status.SUCCEEDED, duration_s); cliRecorder.writeFullSuccessList(bioModelBaseName); logOmexMessage.append(" Done"); } - BiosimulationLog.setOutputMessage("null", "null", outputDir, "omex", logOmexMessage.toString()); + BiosimulationLog.instance().setOutputMessage("null", "null", "omex", logOmexMessage.toString()); logger.debug("Finished Execution of Archive: " + bioModelBaseName); } private void queueAllSedml() throws PythonStreamException, InterruptedException, IOException { for (String sedmlLocation: sedmlLocations){ - BiosimulationLog.updateSedmlDocStatusYml(sedmlLocation, BiosimulationLog.Status.QUEUED, outputDir); + BiosimulationLog.instance().updateSedmlDocStatusYml(sedmlLocation, BiosimulationLog.Status.QUEUED); } } diff --git a/vcell-cli/src/main/java/org/vcell/cli/run/SedmlJob.java b/vcell-cli/src/main/java/org/vcell/cli/run/SedmlJob.java index 9793bf87b8..e76c935a69 100644 --- a/vcell-cli/src/main/java/org/vcell/cli/run/SedmlJob.java +++ b/vcell-cli/src/main/java/org/vcell/cli/run/SedmlJob.java @@ -39,7 +39,7 @@ public class SedmlJob { private final String SEDML_LOCATION, BIOMODEL_BASE_NAME, RESULTS_DIRECTORY_PATH; private final StringBuilder LOG_OMEX_MESSAGE; private final SedmlStatistics DOC_STATISTICS; - private final File MASTER_OMEX_ARCHIVE, ROOT_OUTPUT_DIR, PLOTS_DIRECTORY, OUTPUT_DIRECTORY_FOR_CURRENT_SEDML; + private final File MASTER_OMEX_ARCHIVE, PLOTS_DIRECTORY, OUTPUT_DIRECTORY_FOR_CURRENT_SEDML; private final CLIRecordable CLI_RECORDER; private boolean somethingFailed, hasScans, hasOverrides; private String logDocumentMessage, logDocumentError, sedmlName; @@ -55,7 +55,6 @@ public class SedmlJob { * @param sedmlLocation location of the sedml document with the model to process * @param omexHandler object to deal with omex archive related utilities * @param masterOmexArchive the archive containing the sedml file - * @param rootOutputDir the top-level directory for all the output of omex execution * @param resultsDirPath path to where the results should be placed * @param sedmlPath2d3dString path to where 2D and 3D plots are stored * @param cliRecorder recorder object used for CLI applications @@ -64,7 +63,7 @@ public class SedmlJob { * @param bSmallMeshOverride whether to use small meshes or standard meshes. * @param logOmexMessage a string-builder to contain progress updates of omex execution */ - public SedmlJob(String sedmlLocation, OmexHandler omexHandler, File masterOmexArchive, File rootOutputDir, + public SedmlJob(String sedmlLocation, OmexHandler omexHandler, File masterOmexArchive, String resultsDirPath, String sedmlPath2d3dString, CLIRecordable cliRecorder, boolean bKeepTempFiles, boolean bExactMatchOnly, boolean bSmallMeshOverride, StringBuilder logOmexMessage){ @@ -73,7 +72,6 @@ public SedmlJob(String sedmlLocation, OmexHandler omexHandler, File masterOmexAr this.OUTPUT_DIRECTORY_FOR_CURRENT_SEDML = new File(omexHandler.getOutputPathFromSedml(sedmlLocation)); this.DOC_STATISTICS = new SedmlStatistics(); this.BIOMODEL_BASE_NAME = FileUtils.getBaseName(masterOmexArchive.getName()); - this.ROOT_OUTPUT_DIR = rootOutputDir; this.RESULTS_DIRECTORY_PATH = resultsDirPath; this.LOG_OMEX_MESSAGE = logOmexMessage; this.PLOTS_DIRECTORY = new File(sedmlPath2d3dString); @@ -109,6 +107,7 @@ public boolean preProcessDoc() throws PythonStreamException, InterruptedExceptio final String SAFE_WINDOWS_FILE_SEPARATOR = "\\\\"; final String SAFE_UNIX_FILE_SEPARATOR = "/"; logger.info("Initializing SED-ML document..."); + BiosimulationLog biosimLog = BiosimulationLog.instance(); Span span = null; try { @@ -124,7 +123,7 @@ public boolean preProcessDoc() throws PythonStreamException, InterruptedExceptio this.sedmlName = sedmlNameSplit[sedmlNameSplit.length - 1]; this.LOG_OMEX_MESSAGE.append("Processing ").append(this.sedmlName).append(". "); logger.info("Processing SED-ML: " + this.sedmlName); - BiosimulationLog.updateSedmlDocStatusYml(this.SEDML_LOCATION, BiosimulationLog.Status.RUNNING, this.RESULTS_DIRECTORY_PATH); + biosimLog.updateSedmlDocStatusYml(this.SEDML_LOCATION, BiosimulationLog.Status.RUNNING); this.DOC_STATISTICS.setNumModels(sedmlFromOmex.getModels().size()); for(Model m : sedmlFromOmex.getModels()) { @@ -200,8 +199,7 @@ public boolean preProcessDoc() throws PythonStreamException, InterruptedExceptio Tracer.failure(e, prefix); this.reportProblem(e); this.somethingFailed = somethingDidFail(); - BiosimulationLog.updateSedmlDocStatusYml(this.SEDML_LOCATION, BiosimulationLog.Status.FAILED, this.RESULTS_DIRECTORY_PATH); - BiosimulationLog.validate(this.RESULTS_DIRECTORY_PATH); + biosimLog.updateSedmlDocStatusYml(this.SEDML_LOCATION, BiosimulationLog.Status.FAILED); return false; } finally { if (span != null) { @@ -264,7 +262,7 @@ private void runSimulations(SolverHandler solverHandler, ExternalDocInfo externa this.logDocumentMessage += str; solverHandler.simulateAllTasks(externalDocInfo, this.sedml, this.CLI_RECORDER, this.OUTPUT_DIRECTORY_FOR_CURRENT_SEDML, this.RESULTS_DIRECTORY_PATH, - this.ROOT_OUTPUT_DIR.getAbsolutePath(), this.SEDML_LOCATION, this.SHOULD_KEEP_TEMP_FILES, + this.SEDML_LOCATION, this.SHOULD_KEEP_TEMP_FILES, this.ACCEPT_EXACT_MATCH_ONLY, this.SHOULD_OVERRIDE_FOR_SMALL_MESH); } catch (Exception e) { Throwable currentTierOfException = e; @@ -347,9 +345,9 @@ private boolean evaluateResults() throws PythonStreamException, InterruptedExcep org.apache.commons.io.FileUtils.deleteDirectory(this.PLOTS_DIRECTORY); // removing sedml dir which stages results. // Declare success! - BiosimulationLog.setOutputMessage(this.SEDML_LOCATION, this.sedmlName, this.RESULTS_DIRECTORY_PATH, "sedml", this.logDocumentMessage); - BiosimulationLog.updateSedmlDocStatusYml(this.SEDML_LOCATION, BiosimulationLog.Status.SUCCEEDED, this.RESULTS_DIRECTORY_PATH); - BiosimulationLog.validate(this.RESULTS_DIRECTORY_PATH); + BiosimulationLog biosimLog = BiosimulationLog.instance(); + biosimLog.setOutputMessage(this.SEDML_LOCATION, this.sedmlName, "sedml", this.logDocumentMessage); + biosimLog.updateSedmlDocStatusYml(this.SEDML_LOCATION, BiosimulationLog.Status.SUCCEEDED); logger.info("SED-ML : " + this.sedmlName + " successfully completed"); return true; } @@ -385,7 +383,7 @@ private void generatePlots() throws PythonStreamException, InterruptedException, // We assume if no exception is returned that the plots pass for (Output output : this.sedml.getOutputs()){ if (!(output instanceof Plot2D plot)) continue; - BiosimulationLog.updatePlotStatusYml(this.SEDML_LOCATION, plot.getId(), BiosimulationLog.Status.SUCCEEDED, this.RESULTS_DIRECTORY_PATH); + BiosimulationLog.instance().updatePlotStatusYml(this.SEDML_LOCATION, plot.getId(), BiosimulationLog.Status.SUCCEEDED); } } @@ -393,7 +391,7 @@ private void generateHDF5(SolverHandler solverHandler, HDF5ExecutionResults mast this.logDocumentMessage += "Generating HDF5 file... "; logger.info("Generating HDF5 file... "); - Hdf5DataExtractor hdf5Extractor = new Hdf5DataExtractor(this.sedml, solverHandler.taskToTempSimulationMap, this.RESULTS_DIRECTORY_PATH); + Hdf5DataExtractor hdf5Extractor = new Hdf5DataExtractor(this.sedml, solverHandler.taskToTempSimulationMap); Hdf5DataContainer partialHdf5File = hdf5Extractor.extractHdf5RelevantData(solverHandler.nonSpatialResults, solverHandler.spatialResults, masterHdf5File.isBioSimHdf5); masterHdf5File.addResults(this.sedml, partialHdf5File); @@ -467,11 +465,11 @@ private static SedML repairSedML(SedML brokenSedML, String[] tokenizedPath){ private void reportProblem(Exception e) throws PythonStreamException, InterruptedException, IOException{ logger.error(e.getMessage(), e); String type = e.getClass().getSimpleName(); - BiosimulationLog.setOutputMessage(this.SEDML_LOCATION, this.sedmlName, this.RESULTS_DIRECTORY_PATH, "sedml", this.logDocumentMessage); - BiosimulationLog.setExceptionMessage(this.SEDML_LOCATION, this.sedmlName, this.RESULTS_DIRECTORY_PATH, "sedml", type, this.logDocumentError); + BiosimulationLog biosimLog = BiosimulationLog.instance(); + biosimLog.setOutputMessage(this.SEDML_LOCATION, this.sedmlName, "sedml", this.logDocumentMessage); + biosimLog.setExceptionMessage(this.SEDML_LOCATION, this.sedmlName, "sedml", type, this.logDocumentError); this.CLI_RECORDER.writeDetailedErrorList(e, this.BIOMODEL_BASE_NAME + ", doc: " + type + ": " + this.logDocumentError); - BiosimulationLog.updateSedmlDocStatusYml(this.SEDML_LOCATION, BiosimulationLog.Status.FAILED, this.RESULTS_DIRECTORY_PATH); - BiosimulationLog.validate(this.RESULTS_DIRECTORY_PATH); + biosimLog.updateSedmlDocStatusYml(this.SEDML_LOCATION, BiosimulationLog.Status.FAILED); } private void recordRunDetails(SolverHandler solverHandler) throws IOException { diff --git a/vcell-cli/src/main/java/org/vcell/cli/run/SolverHandler.java b/vcell-cli/src/main/java/org/vcell/cli/run/SolverHandler.java index 5cd403376d..2ee172159d 100644 --- a/vcell-cli/src/main/java/org/vcell/cli/run/SolverHandler.java +++ b/vcell-cli/src/main/java/org/vcell/cli/run/SolverHandler.java @@ -54,6 +54,7 @@ import org.apache.logging.log4j.Logger; import java.io.*; +import java.math.BigDecimal; import java.util.*; import java.util.stream.Collectors; @@ -314,7 +315,7 @@ public TempSimulation getTempSimulation() { } public void simulateAllTasks(ExternalDocInfo externalDocInfo, SedML sedml, CLIRecordable cliLogger, - File outputDirForSedml, String outDir, String outputBaseDir, String sedmlLocation, + File outputDirForSedml, String outDir, String sedmlLocation, boolean keepTempFiles, boolean exactMatchOnly, boolean bSmallMeshOverride ) throws Exception { // create the VCDocument(s) (bioModel(s) + application(s) + simulation(s)), do sanity checks @@ -359,7 +360,7 @@ public void simulateAllTasks(ExternalDocInfo externalDocInfo, SedML sedml, CLIRe tempSims = Arrays.stream(bioModel.getSimulations()).map(s -> origSimulationToTempSimulationMap.get(s)).collect(Collectors.toList()); Map simStatusMap = new LinkedHashMap<>(); - Map simDurationMap = new LinkedHashMap<>(); + Map simDurationMap_ms = new LinkedHashMap<>(); List simJobsList = new ArrayList<>(); for (TempSimulation tempSimulation : tempSims) { if (tempSimulation.getImportedTaskID() == null) { @@ -368,9 +369,9 @@ public void simulateAllTasks(ExternalDocInfo externalDocInfo, SedML sedml, CLIRe AbstractTask task = tempSimulationToTaskMap.get(tempSimulation); simStatusMap.put(tempSimulation, BiosimulationLog.Status.RUNNING); - BiosimulationLog.updateTaskStatusYml(sedmlLocation, task.getId(), BiosimulationLog.Status.RUNNING, outDir, - "0", tempSimulation.getSolverTaskDescription().getSolverDescription().getKisao()); - simDurationMap.put(tempSimulation, 0); + BiosimulationLog.instance().updateTaskStatusYml(sedmlLocation, task.getId(), BiosimulationLog.Status.RUNNING, + 0.0, tempSimulation.getSolverTaskDescription().getSolverDescription().getKisao()); + simDurationMap_ms.put(tempSimulation, 0); if (bSmallMeshOverride && tempSimulation.getMeshSpecification() != null) { int maxSize = 11; @@ -393,7 +394,7 @@ public void simulateAllTasks(ExternalDocInfo externalDocInfo, SedML sedml, CLIRe logger.debug("Initializing simulation job... "); String logTaskMessage = "Initializing simulation job " + tempSimulationJob.getJobIndex() + " ... "; String logTaskError = ""; - long startTimeTask = System.currentTimeMillis(); + long startTimeTask_ms = System.currentTimeMillis(); AbstractTask task = tempSimulationToTaskMap.get(tempSimulationJob.getTempSimulation()); @@ -477,22 +478,22 @@ public void simulateAllTasks(ExternalDocInfo externalDocInfo, SedML sedml, CLIRe logTaskMessage += "done. "; logger.info("Succesful execution: Model '" + docName + "' Task '" + sim.getDescription() + "'."); - long endTimeTask = System.currentTimeMillis(); - long elapsedTime = endTimeTask - startTimeTask; - int duration = (int) Math.ceil(elapsedTime / 1000.0); + long endTimeTask_ms = System.currentTimeMillis(); + long elapsedTime_ms = endTimeTask_ms - startTimeTask_ms; + int duration_ms = (int) elapsedTime_ms; TempSimulation originalSim = tempSimulationJob.getSimulation(); - int simDuration = simDurationMap.get(originalSim); - simDuration += duration; - simDurationMap.put(originalSim, simDuration); + int simDuration_ms = simDurationMap_ms.get(originalSim); + simDuration_ms += duration_ms; + simDurationMap_ms.put(originalSim, simDuration_ms); - String msg = "Running simulation " + simTask.getSimulation().getName() + ", " + elapsedTime + " ms"; + String msg = "Running simulation " + simTask.getSimulation().getName() + ", " + elapsedTime_ms + " ms"; logger.info(msg); countSuccessfulSimulationRuns++; // we only count the number of simulations (tasks) that succeeded if (simStatusMap.get(originalSim) != BiosimulationLog.Status.ABORTED && simStatusMap.get(originalSim) != BiosimulationLog.Status.FAILED) { simStatusMap.put(originalSim, BiosimulationLog.Status.SUCCEEDED); } - BiosimulationLog.setOutputMessage(sedmlLocation, sim.getImportedTaskID(), outDir, "task", logTaskMessage); + BiosimulationLog.instance().setOutputMessage(sedmlLocation, sim.getImportedTaskID(), "task", logTaskMessage); RunUtils.drawBreakLine("-", 100); } else { String error = solver.getSolverStatus().getSimulationMessage().getDisplayMessage(); @@ -507,10 +508,9 @@ public void simulateAllTasks(ExternalDocInfo externalDocInfo, SedML sedml, CLIRe logger.error(error); Tracer.failure(e, error); - long endTime = System.currentTimeMillis(); - long elapsedTime = endTime - startTimeTask; - int duration = (int) Math.ceil(elapsedTime / 1000.0); - String msg = "Running simulation for " + elapsedTime + " ms"; + long endTime_ms = System.currentTimeMillis(); + long elapsedTime_ms = endTime_ms - startTimeTask_ms; + String msg = "Running simulation for " + elapsedTime_ms + " ms"; logger.info(msg); if (sim.getImportedTaskID() == null) { @@ -534,8 +534,8 @@ public void simulateAllTasks(ExternalDocInfo externalDocInfo, SedML sedml, CLIRe logTaskError += (error + ". "); } String type = e.getClass().getSimpleName(); - BiosimulationLog.setOutputMessage(sedmlLocation, sim.getImportedTaskID(), outDir, "task", logTaskMessage); - BiosimulationLog.setExceptionMessage(sedmlLocation, sim.getImportedTaskID(), outDir, "task", type, logTaskError); + BiosimulationLog.instance().setOutputMessage(sedmlLocation, sim.getImportedTaskID(), "task", logTaskMessage); + BiosimulationLog.instance().setExceptionMessage(sedmlLocation, sim.getImportedTaskID(), "task", type, logTaskError); String sdl = ""; if (sd != null && sd.getShortDisplayLabel() != null && !sd.getShortDisplayLabel().isEmpty()) { sdl = sd.getShortDisplayLabel(); @@ -593,15 +593,15 @@ public void simulateAllTasks(ExternalDocInfo externalDocInfo, SedML sedml, CLIRe } AbstractTask task = tempSimulationToTaskMap.get(tempSimulation); // assert task != null; - int duration = simDurationMap.get(tempSimulation); + double duration_s = simDurationMap_ms.get(tempSimulation)/1000.0; SolverTaskDescription std = tempSimulation.getSolverTaskDescription(); SolverDescription sd = std.getSolverDescription(); String kisao = sd.getKisao(); - BiosimulationLog.updateTaskStatusYml(sedmlLocation, task.getId(), status, outDir, duration + "", kisao); + BiosimulationLog.instance().updateTaskStatusYml(sedmlLocation, task.getId(), status, duration_s, kisao); List children = taskToListOfSubTasksMap.get(task); for (AbstractTask rt : children) { - BiosimulationLog.updateTaskStatusYml(sedmlLocation, rt.getId(), status, outDir, duration + "", kisao); + BiosimulationLog.instance().updateTaskStatusYml(sedmlLocation, rt.getId(), status, duration_s, kisao); } } bioModelCount++; diff --git a/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/Hdf5DataExtractor.java b/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/Hdf5DataExtractor.java index 5283456905..1e4e3cebf2 100644 --- a/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/Hdf5DataExtractor.java +++ b/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/Hdf5DataExtractor.java @@ -23,7 +23,7 @@ public class Hdf5DataExtractor { private SedML sedml; private Map taskToSimulationMap; - private String sedmlLocation, sedmlRoot, outputDirectory; + private String sedmlLocation, sedmlRoot; private final static Logger logger = LogManager.getLogger(Hdf5DataExtractor.class); @@ -32,14 +32,12 @@ public class Hdf5DataExtractor { * * @param sedml the sedml object to get outputs, datasets, and data generators from. * @param taskToSimulationMap mapping of task to its simulation data - * @param outputDirectory path to where the outputs should go */ - public Hdf5DataExtractor(SedML sedml, Map taskToSimulationMap, String outputDirectory){ + public Hdf5DataExtractor(SedML sedml, Map taskToSimulationMap){ this.sedml = sedml; this.taskToSimulationMap = taskToSimulationMap; this.sedmlRoot = Paths.get(sedml.getPathForURI()).toString(); this.sedmlLocation = Paths.get(this.sedmlRoot, this.sedml.getFileName()).toString(); - this.outputDirectory = outputDirectory; } /** @@ -57,7 +55,7 @@ public Hdf5DataContainer extractHdf5RelevantData(Map> nonspatialWrappers = NonspatialResultsConverter.convertNonspatialResultsToSedmlFormat( - this.sedml, nonSpatialResults, this.taskToSimulationMap, this.sedmlLocation, this.outputDirectory); + this.sedml, nonSpatialResults, this.taskToSimulationMap, this.sedmlLocation); Hdf5DataExtractor.addWrappers(wrappers, nonspatialWrappers); } catch (Exception e){ logger.warn("Collection of nonspatial datasets failed for " + this.sedml.getFileName(), e); @@ -66,7 +64,7 @@ public Hdf5DataContainer extractHdf5RelevantData(Map> spatialWrappers = SpatialResultsConverter.convertSpatialResultsToSedmlFormat( - this.sedml, spatialResults, this.taskToSimulationMap, this.sedmlLocation, this.outputDirectory); + this.sedml, spatialResults, this.taskToSimulationMap, this.sedmlLocation); Hdf5DataExtractor.addWrappers(wrappers, spatialWrappers); } catch (Exception e){ diff --git a/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/NonspatialResultsConverter.java b/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/NonspatialResultsConverter.java index 02ac4457d1..a9a0854b18 100644 --- a/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/NonspatialResultsConverter.java +++ b/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/NonspatialResultsConverter.java @@ -21,7 +21,7 @@ public class NonspatialResultsConverter { private final static Logger logger = LogManager.getLogger(NonspatialResultsConverter.class); - public static Map> convertNonspatialResultsToSedmlFormat(SedML sedml, Map nonspatialResultsHash, Map taskToSimulationMap, String sedmlLocation, String outDir) throws ExpressionException, IOException { + public static Map> convertNonspatialResultsToSedmlFormat(SedML sedml, Map nonspatialResultsHash, Map taskToSimulationMap, String sedmlLocation) throws ExpressionException { Map> results = new LinkedHashMap<>(); for (Report report : NonspatialResultsConverter.getReports(sedml.getOutputs())){ @@ -139,7 +139,7 @@ public static Map> convertNonspatialResultsToSedm } dataSetValues.put(dataset, synthesizedResults); - BiosimulationLog.updateDatasetStatusYml(sedmlLocation, report.getId(), dataset.getId(), BiosimulationLog.Status.SUCCEEDED, outDir); + BiosimulationLog.instance().updateDatasetStatusYml(sedmlLocation, report.getId(), dataset.getId(), BiosimulationLog.Status.SUCCEEDED); } // end of current dataset processing if (dataSetValues.isEmpty()) { diff --git a/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/SpatialResultsConverter.java b/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/SpatialResultsConverter.java index 16445929e5..1624627afa 100644 --- a/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/SpatialResultsConverter.java +++ b/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/SpatialResultsConverter.java @@ -23,7 +23,7 @@ public class SpatialResultsConverter { private final static Logger lg = LogManager.getLogger(SpatialResultsConverter.class); - public static Map> convertSpatialResultsToSedmlFormat(SedML sedml, Map spatialResultsHash, Map taskToSimulationMap, String sedmlLocation, String outDir) throws IOException { + public static Map> convertSpatialResultsToSedmlFormat(SedML sedml, Map spatialResultsHash, Map taskToSimulationMap, String sedmlLocation) { Map> results = new LinkedHashMap<>(); if (spatialResultsHash.isEmpty()) return results; ReorganizedSpatialResults sourceOfTruth = new ReorganizedSpatialResults(spatialResultsHash, taskToSimulationMap); @@ -40,7 +40,7 @@ public static Map> convertSpatialResultsToSedmlFo if (!returnedGoodResult) continue; if (!dataGenToDataSets.containsKey(dataGen)) dataGenToDataSets.put(dataGen, new ArrayList<>()); dataGenToDataSets.get(dataGen).add(dataSet); - BiosimulationLog.updateDatasetStatusYml(sedmlLocation, report.getId(), dataSet.getId(), BiosimulationLog.Status.SUCCEEDED, outDir); + BiosimulationLog.instance().updateDatasetStatusYml(sedmlLocation, report.getId(), dataSet.getId(), BiosimulationLog.Status.SUCCEEDED); } // end of dataset // Fill out DatasetWrapper Values diff --git a/vcell-core/src/main/java/org/vcell/sedml/log/BiosimulationLog.java b/vcell-core/src/main/java/org/vcell/sedml/log/BiosimulationLog.java index 09b07291d0..87366a8506 100644 --- a/vcell-core/src/main/java/org/vcell/sedml/log/BiosimulationLog.java +++ b/vcell-core/src/main/java/org/vcell/sedml/log/BiosimulationLog.java @@ -32,19 +32,66 @@ public LogValidationException(String message) { public static final Logger lg = LogManager.getLogger(BiosimulationLog.class); public static final String LOG_YML = "log.yml"; - public static final boolean VALIDATE_LOG = true; + public static final boolean VALIDATE_LOG = false; + private static final ThreadLocal instanceThreadLocal = new ThreadLocal<>(); - public static void validate(String sedmlLocation) throws LogValidationException { - if (!VALIDATE_LOG) { - lg.debug("Skipping log validation"); + final ArchiveLog archiveLog; + final String outDir; + boolean dirty = false; + + private BiosimulationLog(Path omexFilePath, Path outDir) throws XMLException, IOException { + this.archiveLog = initializeLogFromOmex(omexFilePath.toString());; + this.outDir = outDir.toString(); + this.dirty = true; + } +// ArchiveLog readCopyFromDisk() throws IOException { +// // may be used for testing, but shouldn't have to read from disk, only write. +// ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); +// return mapper.readValue(this.logFilePath.toFile(), ArchiveLog.class); +// } + + void write() throws IOException { + if (!this.dirty) { return; } + ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); + mapper.writeValue(new File(this.outDir, LOG_YML), this.archiveLog); + this.dirty = false; + } + + public void setDirty() { + this.dirty = true; + } + + public void close() throws IOException { + if (this.dirty) { + write(); + } + if (VALIDATE_LOG) { + validate(); + } + if (instanceThreadLocal.get() == this) { + instanceThreadLocal.remove(); + } + } + + public static BiosimulationLog instance() { + if (instanceThreadLocal.get() == null) { + throw new RuntimeException("LogSession not initialized"); + } + return instanceThreadLocal.get(); + } + + public static BiosimulationLog initialize(String omexFilePath, String outDir) throws XMLException, IOException { + BiosimulationLog log = new BiosimulationLog(Paths.get(omexFilePath), Paths.get(outDir)); + instanceThreadLocal.set(log); + return log; + } + + public void validate() throws LogValidationException { try { // prepare HTTP POST to https://api.biosimulations.org/logs/validate with content type application/json - ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); - File yamlFile = new File(sedmlLocation, LOG_YML); - ArchiveLog log = mapper.readValue(yamlFile, ArchiveLog.class); - String jsonText = writeArchiveLogToJson(log); + String jsonText = this.archiveLog.writeToJson(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://api.biosimulations.org/logs/validate")) .header("Content-Type", "application/json") @@ -72,23 +119,23 @@ public enum Status { ABORTED, SKIPPED } - public static class ExceptionLog { + static class ExceptionLog { public String type; public String message; } - public static class DataSetLog { + static class DataSetLog { public String id; public Status status; } - public static class CurveLog { + static class CurveLog { public String id; public Status status; } - public static class SkipReason { + static class SkipReason { public String type; public String message; } - public static class OutputLog { + static class OutputLog { public String id; public Status status; public ExceptionLog exception; @@ -98,7 +145,7 @@ public static class OutputLog { @JsonInclude(JsonInclude.Include.NON_NULL) public List dataSets; @JsonInclude(JsonInclude.Include.NON_NULL) public List curves; } - public static class TaskLog { + static class TaskLog { public String id; public Status status; public ExceptionLog exception; @@ -108,7 +155,7 @@ public static class TaskLog { public String algorithm; public String simulatorDetails; } - public static class SedDocumentLog { + static class SedDocumentLog { public String location; public Status status; public ExceptionLog exception; @@ -118,48 +165,33 @@ public static class SedDocumentLog { public List tasks = new ArrayList<>(); public List outputs = new ArrayList<>(); } - public static class ArchiveLog { + static class ArchiveLog { public Status status; public ExceptionLog exception; public SkipReason skipReason; public String output; public BigDecimal duration; public List sedDocuments = new ArrayList<>(); - } - - public static ArchiveLog readArchiveLogFromJsonFile(Path path) throws IOException { - ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(path.toFile(), ArchiveLog.class); - } - - public static ArchiveLog readArchiveLogFromJson(String json) throws IOException { - ObjectMapper objectMapper = new ObjectMapper(); - return objectMapper.readValue(json.getBytes(StandardCharsets.UTF_8), ArchiveLog.class); - } - public static void writeArchiveLogToJsonFile(ArchiveLog archiveLog, Path path) throws IOException { - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.enable(SerializationFeature.INDENT_OUTPUT); - objectMapper.writeValue(path.toFile(), archiveLog); - } + static ArchiveLog fromJson(String json) throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(json.getBytes(StandardCharsets.UTF_8), ArchiveLog.class); + } - public static String writeArchiveLogToJson(ArchiveLog archiveLog) throws IOException { - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.enable(SerializationFeature.INDENT_OUTPUT); - return objectMapper.writeValueAsString(archiveLog); + String writeToJson() throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.enable(SerializationFeature.INDENT_OUTPUT); + return objectMapper.writeValueAsString(this); + } } - public static void updateTaskStatusYml(String sedmlName, String taskName, Status taskStatus, String outDir, String duration, String algorithm) throws IOException { - ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); - File yamlFile = new File(outDir, LOG_YML); - ArchiveLog log = mapper.readValue(yamlFile, ArchiveLog.class); - - for (SedDocumentLog sedDocument : log.sedDocuments) { + public void updateTaskStatusYml(String sedmlName, String taskName, Status taskStatus, double duration_s, String algorithm) { + for (SedDocumentLog sedDocument : this.archiveLog.sedDocuments) { if (sedmlName.endsWith(sedDocument.location)) { for (TaskLog taskItem : sedDocument.tasks) { if (taskItem.id.equals(taskName)) { taskItem.status = taskStatus; - taskItem.duration = new BigDecimal(duration); + taskItem.duration = BigDecimal.valueOf(duration_s); taskItem.algorithm = algorithm != null ? algorithm.replace("KISAO:","KISAO_") : null; // // update individual task status // if ( taskItem.status == BiosimulationLog.Status.QUEUED || taskItem.status == BiosimulationLog.Status.SUCCEEDED){ @@ -171,32 +203,22 @@ public static void updateTaskStatusYml(String sedmlName, String taskName, Status } } } - - mapper.writeValue(yamlFile, log); + setDirty(); } - public static void updateSedmlDocStatusYml(String sedmlName, Status sedmlDocStatus, String outDir) throws IOException { - ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); - File yamlFile = new File(outDir, LOG_YML); - ArchiveLog log = mapper.readValue(yamlFile, ArchiveLog.class); - - for (SedDocumentLog sedDocument : log.sedDocuments) { + public void updateSedmlDocStatusYml(String sedmlName, Status sedmlDocStatus) { + for (SedDocumentLog sedDocument : this.archiveLog.sedDocuments) { if (sedmlName.endsWith(sedDocument.location)) { sedDocument.status = sedmlDocStatus; } } - mapper.writeValue(yamlFile, log); + setDirty(); } - public static void updateOmexStatusYml(Status simStatus, String outDir, String duration) throws IOException { - ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); - File yamlFile = new File(outDir, LOG_YML); - ArchiveLog log = mapper.readValue(yamlFile, ArchiveLog.class); - - log.status = simStatus; - log.duration = new BigDecimal(duration); - - mapper.writeValue(yamlFile, log); + public void updateOmexStatusYml(Status simStatus, double duration_s) { + this.archiveLog.status = simStatus; + this.archiveLog.duration = BigDecimal.valueOf(duration_s); + setDirty(); } // sedmlAbsolutePath - full path to location of the actual sedml file (document) used as input @@ -204,15 +226,11 @@ public static void updateOmexStatusYml(Status simStatus, String outDir, String d // outDir - path to directory where the log files will be placed // entityType - string describing the entity type ex "task" for a task, or "sedml" for sedml document // message - useful info about the execution of the entity (ex: task), could be human readable or concatenation of stdout and stderr - public static void setOutputMessage(String sedmlAbsolutePath, String entityId, String outDir, String entityType, String message) throws IOException { - ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); - File yamlFile = new File(outDir, LOG_YML); - ArchiveLog log = mapper.readValue(yamlFile, ArchiveLog.class); - + public void setOutputMessage(String sedmlAbsolutePath, String entityId, String entityType, String message) { if (entityType.equals("omex")) { - log.output = message; + this.archiveLog.output = message; } else { - for (SedDocumentLog sedDocument : log.sedDocuments) { + for (SedDocumentLog sedDocument : this.archiveLog.sedDocuments) { if (sedmlAbsolutePath.endsWith(sedDocument.location)) { if (entityType.equals("sedml") && sedDocument.location.equals(entityId)) { sedDocument.output = message; @@ -226,18 +244,13 @@ public static void setOutputMessage(String sedmlAbsolutePath, String entityId, S } } } - - mapper.writeValue(yamlFile, log); + setDirty(); } // type - exception class, ex RuntimeException // message - exception message - public static void setExceptionMessage(String sedmlAbsolutePath, String entityId, String outDir, String entityType, String type, String message) throws IOException { - ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); - File yamlFile = new File(outDir, LOG_YML); - ArchiveLog log = mapper.readValue(yamlFile, ArchiveLog.class); - - for (SedDocumentLog sedDocument : log.sedDocuments) { + public void setExceptionMessage(String sedmlAbsolutePath, String entityId, String entityType, String type, String message) { + for (SedDocumentLog sedDocument : this.archiveLog.sedDocuments) { if (sedmlAbsolutePath.endsWith(sedDocument.location)) { if (entityType.equals("sedml") && sedDocument.location.equals(entityId)) { ExceptionLog exceptionLog = new ExceptionLog(); @@ -256,17 +269,15 @@ public static void setExceptionMessage(String sedmlAbsolutePath, String entityId } } } - - mapper.writeValue(yamlFile, log); - System.out.println("Success!"); + setDirty(); } - public static void generateStatusYaml(String omexFile, String outDir) throws IOException, XMLException { - List sedDocumentLogs = new ArrayList<>(); - // read sedml file + private static ArchiveLog initializeLogFromOmex(String omexFile) throws IOException, XMLException { + // read sedml files from omex ArchiveComponents ac = Libsedml.readSEDMLArchive(new FileInputStream(omexFile)); List sedmlDocs = ac.getSedmlDocuments(); + List sedDocumentLogs = new ArrayList<>(); for (SEDMLDocument sedmlDoc : sedmlDocs) { SedML sedmlModel = sedmlDoc.getSedMLModel(); @@ -318,17 +329,11 @@ public static void generateStatusYaml(String omexFile, String outDir) throws IOE archiveLog.sedDocuments = sedDocumentLogs; archiveLog.status = Status.QUEUED; - String statusYamlPath = Paths.get(outDir, LOG_YML).toString(); - ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); - mapper.writeValue(new File(statusYamlPath), archiveLog); + return archiveLog; } - public static void updateDatasetStatusYml(String sedmlName, String report, String dataset, Status simStatus, String outDir) throws IOException { - ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); - File yamlFile = new File(outDir, LOG_YML); - ArchiveLog log = mapper.readValue(yamlFile, ArchiveLog.class); - - for (SedDocumentLog sedDocument : log.sedDocuments) { + public void updateDatasetStatusYml(String sedmlName, String report, String dataset, Status simStatus) { + for (SedDocumentLog sedDocument : this.archiveLog.sedDocuments) { if (sedmlName.endsWith(sedDocument.location)) { for (OutputLog output : sedDocument.outputs) { if (output.id.equals(report)) { @@ -346,16 +351,11 @@ public static void updateDatasetStatusYml(String sedmlName, String report, Strin } } } - - mapper.writeValue(yamlFile, log); + setDirty(); } - public static void updatePlotStatusYml(String sedmlName, String plotId, Status simStatus, String outDir) throws IOException { - ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); - File yamlFile = new File(outDir, LOG_YML); - ArchiveLog log = mapper.readValue(yamlFile, ArchiveLog.class); - - for (SedDocumentLog sedDocument : log.sedDocuments) { + public void updatePlotStatusYml(String sedmlName, String plotId, Status simStatus) { + for (SedDocumentLog sedDocument : this.archiveLog.sedDocuments) { if (sedmlName.endsWith(sedDocument.location)) { for (OutputLog output : sedDocument.outputs) { if (output.id.equals(plotId)) { @@ -371,7 +371,7 @@ public static void updatePlotStatusYml(String sedmlName, String plotId, Status s } } } - - mapper.writeValue(yamlFile, log); + setDirty(); } + } diff --git a/vcell-core/src/test/java/org/vcell/sedml/log/BiosimulationLogTest.java b/vcell-core/src/test/java/org/vcell/sedml/log/BiosimulationLogTest.java index c3e49f2178..6227f2cd08 100644 --- a/vcell-core/src/test/java/org/vcell/sedml/log/BiosimulationLogTest.java +++ b/vcell-core/src/test/java/org/vcell/sedml/log/BiosimulationLogTest.java @@ -279,10 +279,10 @@ public static Collection testCases() { @MethodSource("testCases") public void testArchiveLogRead(String expectedJson) throws IOException { // create ArchiveLog from given JSON - BiosimulationLog.ArchiveLog archiveLog = BiosimulationLog.readArchiveLogFromJson(expectedJson); + BiosimulationLog.ArchiveLog archiveLog = BiosimulationLog.ArchiveLog.fromJson(expectedJson); // generate new JSON string from ArchiveLog - String newJson = BiosimulationLog.writeArchiveLogToJson(archiveLog); + String newJson = archiveLog.writeToJson(); // compare the original JSON string with the new JSON string - normalize by pretty printing assertEquals(prettyPrintJson(expectedJson), prettyPrintJson(newJson));