diff --git a/vcell-cli/src/main/java/org/vcell/cli/exceptions/PreProcessingException.java b/vcell-cli/src/main/java/org/vcell/cli/exceptions/PreProcessingException.java new file mode 100644 index 0000000000..41b3a8b904 --- /dev/null +++ b/vcell-cli/src/main/java/org/vcell/cli/exceptions/PreProcessingException.java @@ -0,0 +1,20 @@ +package org.vcell.cli.exceptions; + +public class PreProcessingException extends RuntimeException { + public PreProcessingException(String message) { + super(message); + } + + public PreProcessingException(Throwable cause) { + super(cause); + } + + public PreProcessingException(String message, Throwable cause){ + super(message, cause); + } + + @Override + public int hashCode() { + return super.hashCode(); + } +} 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 e69d1242a8..f5757064a8 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 @@ -55,9 +55,9 @@ public static void batchMode(File dirOfArchivesToProcess, File outputDir, CLIRec String targetOutputDir = Paths.get(outputBaseDir, bioModelBaseName).toString(); Span span = null; - try { + // Initialization call generates Status YAML + try (BiosimulationLog bioSimLog = BiosimulationLog.initialize(inputFile.getAbsolutePath(), targetOutputDir)) { span = Tracer.startSpan(Span.ContextType.OMEX_EXECUTE, inputFileName, Map.of("filename", inputFileName)); - BiosimulationLog.initialize(inputFile.getAbsolutePath(), targetOutputDir); // generate Status YAML System.out.println("\n\n"); logger.info("Processing " + inputFileName + "(" + inputFile + ")"); @@ -79,7 +79,6 @@ public static void batchMode(File dirOfArchivesToProcess, File outputDir, CLIRec if (span != null) { span.close(); } - BiosimulationLog.instance().close(); } } if (failedFiles.isEmpty()){ @@ -134,19 +133,16 @@ public static void singleMode(File inputFile, File rootOutputDir, CLIRecordable String targetOutputDir = bEncapsulateOutput ? Paths.get(outputBaseDir, bioModelBaseName).toString() : outputBaseDir; File adjustedOutputDir = new File(targetOutputDir); - logger.info("Preparing output directory..."); + if (logger.isDebugEnabled()) logger.info("Preparing output directory..."); // we don't want to accidentally delete the input... // if the output directory 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.initialize(inputFile.getAbsolutePath(), targetOutputDir); // generate Status YAML - + // Initialization line generates Status YAML + try (BiosimulationLog bioSimLog = BiosimulationLog.initialize(inputFile.getAbsolutePath(), targetOutputDir)) { ExecuteImpl.singleExecOmex(inputFile, rootOutputDir, cliLogger, bKeepTempFiles, bExactMatchOnly, bEncapsulateOutput, bSmallMeshOverride, bBioSimMode); - } finally { - BiosimulationLog.instance().close(); } } 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 6619dc3f9e..218b2dfd4d 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 @@ -1,10 +1,12 @@ package org.vcell.cli.run; +import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.vcell.cli.CLIRecordable; import org.vcell.cli.PythonStreamException; import org.vcell.cli.exceptions.ExecutionException; +import org.vcell.cli.exceptions.PreProcessingException; import org.vcell.cli.run.hdf5.BiosimulationsHdf5Writer; import org.vcell.cli.run.hdf5.BiosimulationsHdfWriterException; import org.vcell.cli.run.hdf5.HDF5ExecutionResults; @@ -71,8 +73,7 @@ private ExecutionJob(){ /** * Run the neexed steps to prepare an archive for execution. * Follow-up call: `executeArchive()` - * - * @throws PythonStreamException if calls to the python-shell instance are not working correctly + * * @throws IOException if there are system I/O issues. */ public void preprocessArchive() throws IOException { @@ -81,7 +82,7 @@ public void preprocessArchive() throws IOException { // Beginning of Execution logger.info("Executing OMEX archive `{}`", this.inputFile.getName()); - logger.info("Archive location: {}", this.inputFile.getAbsolutePath()); + if (logger.isDebugEnabled()) logger.info("Archive location: {}", this.inputFile.getAbsolutePath()); RunUtils.drawBreakLine("-", 100); // Unpack the Omex Archive @@ -112,50 +113,43 @@ public void preprocessArchive() throws IOException { /** * Run solvers on all the models in the archive. - * + *
* Called after: `preprocessArchive()` * Called before: `postProcessArchive()` - * - * @throws InterruptedException if there is an issue with accessing data - * @throws PythonStreamException if calls to the python-shell instance are not working correctly - * @throws IOException if there are system I/O issues - * @throws ExecutionException if an execution specfic error occurs + * + * @throws ExecutionException if an execution specific error occurs */ - public void executeArchive(boolean isBioSimSedml) throws BiosimulationsHdfWriterException, PythonStreamException, ExecutionException { + public void executeArchive(boolean isBioSimSedml) throws BiosimulationsHdfWriterException, ExecutionException { + HDF5ExecutionResults cumulativeHdf5Results = new HDF5ExecutionResults(isBioSimSedml); + try { - HDF5ExecutionResults masterHdf5File = new HDF5ExecutionResults(isBioSimSedml); - this.queueAllSedml(); - - for (String sedmlLocation : this.sedmlLocations){ - 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()){ - SedmlStatistics stats = job.getDocStatistics(); // Must process document first - logger.error("Statistics of failed SedML:\n" + stats.toString()); + for (String sedmlLocation : this.sedmlLocations) { + try { + this.executeSedmlDocument(sedmlLocation, cumulativeHdf5Results); + } catch (PreProcessingException e) { this.anySedmlDocumentHasFailed = true; } - SedmlStatistics stats = job.getDocStatistics(); - boolean hasSucceeded = job.simulateSedml(masterHdf5File); - this.anySedmlDocumentHasSucceeded |= hasSucceeded; - this.anySedmlDocumentHasFailed &= hasSucceeded; - if (hasSucceeded){ - String formattedStats = stats.toFormattedString(); - logger.info("Processing of SedML succeeded.\n" + formattedStats); - } - else logger.error("Processing of SedML has failed.\n" + stats.toString()); } - BiosimulationsHdf5Writer.writeHdf5(masterHdf5File, new File(this.outputDir)); - - } catch(PythonStreamException e){ - logger.error("Python-processing encountered fatal error. Execution is unable to properly continue.", e); - throw e; - } catch(InterruptedException | IOException e){ + BiosimulationsHdf5Writer.writeHdf5(cumulativeHdf5Results, new File(this.outputDir)); + + } catch (IOException e){ logger.error("System IO encountered a fatal error"); throw new ExecutionException(e); } } + private void executeSedmlDocument(String sedmlLocation, HDF5ExecutionResults cumulativeHdf5Results) throws IOException, PreProcessingException { + BiosimulationLog.instance().updateSedmlDocStatusYml(sedmlLocation, BiosimulationLog.Status.QUEUED); + SedmlJob job = new SedmlJob(sedmlLocation, this.omexHandler, this.inputFile, + this.outputDir, this.sedmlPath2d3d.toString(), this.cliRecorder, + this.bKeepTempFiles, this.bExactMatchOnly, this.bSmallMeshOverride, this.logOmexMessage); + SedmlStatistics stats = job.preProcessDoc(); + boolean hasSucceeded = job.simulateSedml(cumulativeHdf5Results); + this.anySedmlDocumentHasSucceeded |= hasSucceeded; + this.anySedmlDocumentHasFailed &= hasSucceeded; + logger.log(hasSucceeded ? Level.INFO : Level.ERROR, "Processing of SedML ({}) {}", stats.getSedmlName(), hasSucceeded ? "succeeded." : "failed!"); + } + /** * Clean up and analyze the results of the archive's execution * @@ -171,7 +165,7 @@ public void postProcessessArchive() throws IOException { 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)"); + logger.info("Omex `" + inputFile.getName() + "` processing completed (" + duration_s + "s)"); // // failure if at least one of the documents in the omex archive fails // @@ -192,13 +186,7 @@ public void postProcessessArchive() throws IOException { } 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.instance().updateSedmlDocStatusYml(sedmlLocation, BiosimulationLog.Status.QUEUED); - } + if (logger.isDebugEnabled()) logger.info("Finished Execution of Archive: {}", this.bioModelBaseName); } } diff --git a/vcell-cli/src/main/java/org/vcell/cli/run/RunUtils.java b/vcell-cli/src/main/java/org/vcell/cli/run/RunUtils.java index 6efa37c67e..1fa6e16ed2 100644 --- a/vcell-cli/src/main/java/org/vcell/cli/run/RunUtils.java +++ b/vcell-cli/src/main/java/org/vcell/cli/run/RunUtils.java @@ -192,13 +192,13 @@ public static HashMap generateReportsAsCSV(SedML sedml, SolverHand for (Output sedmlOutput : allSedmlOutputs) { // We only want Reports if (!(sedmlOutput instanceof Report sedmlReport)) { - logger.info("Ignoring unsupported output `" + sedmlOutput.getId() + "` while CSV generation."); + if (logger.isDebugEnabled()) logger.info("Ignoring unsupported output `" + sedmlOutput.getId() + "` while CSV generation."); continue; } StringBuilder sb = new StringBuilder(); - logger.info("Generating report `" + sedmlReport.getId() +"`."); + if (logger.isDebugEnabled()) logger.info("Generating report `" + sedmlReport.getId() +"`."); /* * we go through each entry (dataset) in the list of datasets * for each dataset, we use the data reference to obtain the data generator @@ -371,16 +371,16 @@ public static HashMap generateReportsAsCSV(SedML sedml, SolverHand } // end of dataset - if (sb.length() > 0) { + if (!sb.isEmpty()) { File f = new File(outDirForCurrentSedml, sedmlReport.getId() + ".csv"); PrintWriter out = new PrintWriter(f); - out.print(sb.toString()); + out.print(sb); out.flush(); out.close(); - logger.info("created csv file for report " + sedmlReport.getId() + ": " + f.getAbsolutePath()); + if (logger.isDebugEnabled()) logger.info("created csv file for report " + sedmlReport.getId() + ": " + f.getAbsolutePath()); reportsHash.put(sedmlReport.getId(), f); } else { - logger.info("no csv file for report " + sedmlReport.getId()); + if (logger.isDebugEnabled()) logger.info("no csv file for report " + sedmlReport.getId()); } } catch (Exception e) { throw new RuntimeException("CSV generation failed: " + e.getMessage(), e); @@ -442,15 +442,13 @@ public static void zipResFiles(File dirPath) throws IOException { srcFiles = listFilesForFolder(dirPath, ext); if (srcFiles.isEmpty()) { - logger.warn("No " + ext.toUpperCase() + " files found, skipping archiving `" + extensionListMap.get(ext) + "` files"); + if (logger.isDebugEnabled()) logger.warn("No {} files found, skipping archiving `{}` files", ext.toUpperCase(), extensionListMap.get(ext)); } else { fileOutputStream = new FileOutputStream(Paths.get(dirPath.toString(), extensionListMap.get(ext)).toFile()); zipOutputStream = new ZipOutputStream(fileOutputStream); - if (!srcFiles.isEmpty()) logger.info("Archiving resultant " + ext.toUpperCase() + " files to `" + extensionListMap.get(ext) + "`."); + if (!srcFiles.isEmpty() && logger.isDebugEnabled()) logger.info("Archiving resultant {} files to `{}`.", ext.toUpperCase(), extensionListMap.get(ext)); for (File srcFile : srcFiles) { - fileInputstream = new FileInputStream(srcFile); - // get relative path relativePath = dirPath.toURI().relativize(srcFile.toURI()).toString(); zipEntry = new ZipEntry(relativePath); @@ -472,7 +470,7 @@ public static void zipResFiles(File dirPath) throws IOException { public static String getTempDir() throws IOException { String tempPath = String.valueOf(java.nio.file.Files.createTempDirectory( RunUtils.VCELL_TEMP_DIR_PREFIX + UUID.randomUUID()).toAbsolutePath()); - logger.info("TempPath Created: " + tempPath); + logger.trace("TempPath Created: " + tempPath); return tempPath; } 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 e54bd7cf91..127fc9822b 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 @@ -8,8 +8,8 @@ import org.apache.logging.log4j.Logger; import org.jlibsedml.*; import org.vcell.cli.CLIRecordable; -import org.vcell.cli.PythonStreamException; import org.vcell.cli.exceptions.ExecutionException; +import org.vcell.cli.exceptions.PreProcessingException; import org.vcell.cli.run.hdf5.HDF5ExecutionResults; import org.vcell.cli.run.hdf5.Hdf5DataContainer; import org.vcell.cli.run.hdf5.Hdf5DataExtractor; @@ -22,7 +22,6 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; @@ -36,15 +35,15 @@ public class SedmlJob { private final boolean SHOULD_KEEP_TEMP_FILES, ACCEPT_EXACT_MATCH_ONLY, SHOULD_OVERRIDE_FOR_SMALL_MESH; - private final String SEDML_LOCATION, BIOMODEL_BASE_NAME, RESULTS_DIRECTORY_PATH; + private final String SEDML_NAME, SEDML_LOCATION, BIOMODEL_BASE_NAME, RESULTS_DIRECTORY_PATH; + private final String[] SEDML_NAME_SPLIT; private final StringBuilder LOG_OMEX_MESSAGE; - private final SedmlStatistics DOC_STATISTICS; + private final SedmlStatistics DOC_STATISTICS; // We keep this in object memory for debugging 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; + private String logDocumentMessage, logDocumentError; private SedML sedml; - private File plotFile; private final static Logger logger = LogManager.getLogger(SedmlJob.class); @@ -67,10 +66,15 @@ public SedmlJob(String sedmlLocation, OmexHandler omexHandler, File masterOmexAr String resultsDirPath, String sedmlPath2d3dString, CLIRecordable cliRecorder, boolean bKeepTempFiles, boolean bExactMatchOnly, boolean bSmallMeshOverride, StringBuilder logOmexMessage){ + final String SAFE_WINDOWS_FILE_SEPARATOR = "\\\\"; + final String SAFE_UNIX_FILE_SEPARATOR = "/"; this.MASTER_OMEX_ARCHIVE = masterOmexArchive; this.SEDML_LOCATION = sedmlLocation; this.OUTPUT_DIRECTORY_FOR_CURRENT_SEDML = new File(omexHandler.getOutputPathFromSedml(sedmlLocation)); - this.DOC_STATISTICS = new SedmlStatistics(); + this.SEDML_NAME_SPLIT = this.SEDML_LOCATION.split(OperatingSystemInfo.getInstance().isWindows() ? + SAFE_WINDOWS_FILE_SEPARATOR : SAFE_UNIX_FILE_SEPARATOR, -2); + this.SEDML_NAME = this.SEDML_NAME_SPLIT[this.SEDML_NAME_SPLIT.length - 1]; + this.DOC_STATISTICS = new SedmlStatistics(this.SEDML_NAME); this.BIOMODEL_BASE_NAME = FileUtils.getBaseName(masterOmexArchive.getName()); this.RESULTS_DIRECTORY_PATH = resultsDirPath; this.LOG_OMEX_MESSAGE = logOmexMessage; @@ -81,143 +85,92 @@ public SedmlJob(String sedmlLocation, OmexHandler omexHandler, File masterOmexAr this.SHOULD_OVERRIDE_FOR_SMALL_MESH = bSmallMeshOverride; this.somethingFailed = false; - this.plotFile = null; this.logDocumentMessage = "Initializing SED-ML document... "; this.logDocumentError = ""; - } - /** - * Returns an object with variables containing useful information about the sedml document - * @return the statistics of the document - */ - public SedmlStatistics getDocStatistics(){ - return this.DOC_STATISTICS; - } /** * Prepare the SedML model for execution * Called before: `simulateSedml()` - * - * @throws InterruptedException if there is an issue with accessing data - * @throws PythonStreamException if calls to the python-shell instance are not working correctly + * * @throws IOException if there are system I/O issues */ - public boolean preProcessDoc() throws PythonStreamException, InterruptedException, IOException { - final String SAFE_WINDOWS_FILE_SEPARATOR = "\\\\"; - final String SAFE_UNIX_FILE_SEPARATOR = "/"; - logger.info("Initializing SED-ML document..."); + public SedmlStatistics preProcessDoc() throws IOException, PreProcessingException { BiosimulationLog biosimLog = BiosimulationLog.instance(); - Span span = null; - try { - span = Tracer.startSpan(Span.ContextType.PROCESSING_SEDML, "preProcessDoc", null); - SedML sedmlFromOmex, sedmlFromPython; - String[] sedmlNameSplit; - - RunUtils.removeAndMakeDirs(this.OUTPUT_DIRECTORY_FOR_CURRENT_SEDML); - - sedmlNameSplit = this.SEDML_LOCATION.split(OperatingSystemInfo.getInstance().isWindows() ? - SAFE_WINDOWS_FILE_SEPARATOR : SAFE_UNIX_FILE_SEPARATOR, -2); - sedmlFromOmex = SedmlJob.getSedMLFile(sedmlNameSplit, this.MASTER_OMEX_ARCHIVE); - this.sedmlName = sedmlNameSplit[sedmlNameSplit.length - 1]; - this.LOG_OMEX_MESSAGE.append("Processing ").append(this.sedmlName).append(". "); - logger.info("Processing SED-ML: " + this.sedmlName); - biosimLog.updateSedmlDocStatusYml(this.SEDML_LOCATION, BiosimulationLog.Status.RUNNING); - - this.DOC_STATISTICS.setNumModels(sedmlFromOmex.getModels().size()); - for(Model m : sedmlFromOmex.getModels()) { - List changes = m.getListOfChanges(); // change attribute caused by a math override - if(!changes.isEmpty()) { //m.getListOfChanges will never return null(?) - this.hasOverrides = true; - } - } - - for(AbstractTask at : sedmlFromOmex.getTasks()) { - if(at instanceof RepeatedTask) { - RepeatedTask rt = (RepeatedTask)at; - List changes = rt.getChanges(); - if(changes != null && !changes.isEmpty()) { - this.hasScans = true; - } - } - } - this.DOC_STATISTICS.setNumTasks(sedmlFromOmex.getTasks().size()); - List outputs = sedmlFromOmex.getOutputs(); - this.DOC_STATISTICS.setNumOutputs(outputs.size()); - for (Output output : outputs) { - if (output instanceof Report) this.DOC_STATISTICS.setReportsCount(this.DOC_STATISTICS.getReportsCount() + 1); - if (output instanceof Plot2D) this.DOC_STATISTICS.setPlots2DCount(this.DOC_STATISTICS.getPlots2DCount() + 1); - if (output instanceof Plot3D) this.DOC_STATISTICS.setPlots3DCount(this.DOC_STATISTICS.getPlots3DCount() + 1); - } - this.DOC_STATISTICS.setNumSimulations(sedmlFromOmex.getSimulations().size()); - String summarySedmlContentString = "Found one SED-ML document with " - + this.DOC_STATISTICS.getNumModels() + " model(s), " - + this.DOC_STATISTICS.getNumSimulations() + " simulation(s), " - + this.DOC_STATISTICS.getNumTasks() + " task(s), " - + this.DOC_STATISTICS.getReportsCount() + " report(s), " - + this.DOC_STATISTICS.getPlots2DCount() + " plot2D(s), and " - + this.DOC_STATISTICS.getPlots3DCount() + " plot3D(s)\n"; - logger.info(summarySedmlContentString); - - this.logDocumentMessage += "done. "; - String str = "Successful translation of SED-ML file"; - this.logDocumentMessage += str + ". "; - logger.info(str + " : " + this.sedmlName); - RunUtils.drawBreakLine("-", 100); - - // For appending data for SED Plot2D and Plot3D to HDF5 files following a temp convention - logger.info("Creating pseudo SED-ML for HDF5 conversion..."); - this.plotFile = new File(this.PLOTS_DIRECTORY, "simulation_" + this.sedmlName); - Path path = Paths.get(this.plotFile.getAbsolutePath()); - if (!Files.exists(path)){ - // SED-ML file generated by python VCell_cli_util - //PythonCalls.genSedmlForSed2DAnd3D(this.MASTER_OMEX_ARCHIVE.getAbsolutePath(), this.RESULTS_DIRECTORY_PATH); - } - if (!Files.exists(path)) { - String message = "Failed to create plot file " + this.plotFile.getAbsolutePath(); - this.CLI_RECORDER.writeDetailedResultList(this.BIOMODEL_BASE_NAME + "," + this.sedmlName + "," + message); - RuntimeException exception = new RuntimeException(message); - Tracer.failure(exception, this.BIOMODEL_BASE_NAME + "," + this.sedmlName + "," + message); - throw exception; - } - - // Converting pseudo SED-ML to biomodel - logger.info("Creating Biomodel from pseudo SED-ML"); - sedmlFromPython = Libsedml.readDocument(this.plotFile).getSedMLModel(); + Span span = Tracer.startSpan(Span.ContextType.PROCESSING_SEDML, "preProcessDoc", null); + RunUtils.removeAndMakeDirs(this.OUTPUT_DIRECTORY_FOR_CURRENT_SEDML); - /* If SED-ML has only plots as an output, we will use SED-ML that got generated from vcell_cli_util python code - * As of now, we are going to create a resultant dataSet for Plot output, using their respective data generators */ + this.LOG_OMEX_MESSAGE.append("Processing ").append(this.SEDML_NAME).append(". "); - // We need the name and path of the sedml file, which sedmlFromPseudo doesn't have! - - this.sedml = SedmlJob.repairSedML(sedmlFromPython, sedmlNameSplit); - + // Load SedML + logger.info("Initializing and Pre-Processing SedML document: {}", this.SEDML_NAME); + biosimLog.updateSedmlDocStatusYml(this.SEDML_LOCATION, BiosimulationLog.Status.RUNNING); + try { + this.sedml = SedmlJob.getSedMLFile(this.SEDML_NAME_SPLIT, this.MASTER_OMEX_ARCHIVE); } catch (Exception e) { - String prefix = "SED-ML processing for " + this.SEDML_LOCATION + " failed with error: "; - this.logDocumentError = prefix + e.getMessage(); + String prefix = "SedML pre-processing for " + this.SEDML_LOCATION + " failed"; + this.logDocumentError = prefix + ": " + e.getMessage(); Tracer.failure(e, prefix); this.reportProblem(e); - this.somethingFailed = somethingDidFail(); + this.somethingFailed = SedmlJob.somethingDidFail(); biosimLog.updateSedmlDocStatusYml(this.SEDML_LOCATION, BiosimulationLog.Status.FAILED); - return false; - } finally { - if (span != null) { - span.close(); - } + span.close(); + throw new PreProcessingException(prefix, e); } - return true; + + // If we got here, we have a successful load!! + this.logDocumentMessage += "done. "; + String resultString = String.format("Successfully loaded and translated SED-ML file: %s.\n", this.SEDML_NAME); + this.logDocumentMessage += resultString; + + // Generate Doc Statistics + this.DOC_STATISTICS.setNumModels(this.sedml.getModels().size()); + this.DOC_STATISTICS.setNumSimulations(this.sedml.getSimulations().size()); + this.DOC_STATISTICS.setNumTasks(this.sedml.getTasks().size()); + this.DOC_STATISTICS.setNumOutputs(this.sedml.getOutputs().size()); + + for (Output output : this.sedml.getOutputs()) { + if (output instanceof Report) this.DOC_STATISTICS.setReportsCount(this.DOC_STATISTICS.getReportsCount() + 1); + if (output instanceof Plot2D) this.DOC_STATISTICS.setPlots2DCount(this.DOC_STATISTICS.getPlots2DCount() + 1); + if (output instanceof Plot3D) this.DOC_STATISTICS.setPlots3DCount(this.DOC_STATISTICS.getPlots3DCount() + 1); + } + + String summarySedmlContentString = "Found:\n" + + "\t" + this.DOC_STATISTICS.getNumModels() + " model(s)\n" + + "\t" + this.DOC_STATISTICS.getNumSimulations() + " simulation(s)\n" + + "\t" + this.DOC_STATISTICS.getNumTasks() + " task(s)\n" + + "\t" + this.DOC_STATISTICS.getReportsCount() + " report(s)\n" + + "\t" + this.DOC_STATISTICS.getPlots2DCount() + " plot2D(s)\n" + + "\t" + this.DOC_STATISTICS.getPlots3DCount() + " plot3D(s)\n"; + logger.info("{}{}", resultString, summarySedmlContentString); + + // Check for overrides + for(Model m : this.sedml.getModels()) { + if (m.getListOfChanges().isEmpty()) continue; + this.hasOverrides = true; + break; + } + + // Check for parameter scans + for(AbstractTask at : this.sedml.getTasks()) { + if (!(at instanceof RepeatedTask rt)) continue; + List changes = rt.getChanges(); + if(changes == null || changes.isEmpty()) continue; + this.hasScans = true; + } + span.close(); + return this.DOC_STATISTICS; } /** * Prepare the SedML model for execution * Called after: `preProcessDoc()` - * - * @throws InterruptedException if there is an issue with accessing data - * @throws PythonStreamException if calls to the python-shell instance are not working correctly + * * @throws IOException if there are system I/O issues */ - public boolean simulateSedml(HDF5ExecutionResults masterHdf5File) throws InterruptedException, PythonStreamException, IOException { + public boolean simulateSedml(HDF5ExecutionResults masterHdf5File) throws IOException { /* temp code to test plot name correctness String idNamePlotsMap = utils.generateIdNamePlotsMap(sedml, outDirForCurrentSedml); utils.execPlotOutputSedDoc(inputFile, idNamePlotsMap, this.resultsDirPath); @@ -260,6 +213,7 @@ private void runSimulations(SolverHandler solverHandler, ExternalDocInfo externa String str = "Building solvers and starting simulation of all tasks... "; logger.info(str); this.logDocumentMessage += str; + RunUtils.drawBreakLine("-", 100); solverHandler.simulateAllTasks(externalDocInfo, this.sedml, this.CLI_RECORDER, this.OUTPUT_DIRECTORY_FOR_CURRENT_SEDML, this.RESULTS_DIRECTORY_PATH, this.SEDML_LOCATION, this.SHOULD_KEEP_TEMP_FILES, @@ -285,7 +239,7 @@ private void runSimulations(SolverHandler solverHandler, ExternalDocInfo externa this.recordRunDetails(solverHandler); } - private void processOutputs(SolverHandler solverHandler, HDF5ExecutionResults masterHdf5File) throws InterruptedException, ExecutionException, PythonStreamException { + private void processOutputs(SolverHandler solverHandler, HDF5ExecutionResults masterHdf5File) throws ExecutionException { // WARNING!!! Current logic dictates that if any task fails we fail the sedml document // change implemented on Nov 11, 2021 // Previous logic was that if at least one task produces some results we declare the sedml document status as successful @@ -294,8 +248,8 @@ private void processOutputs(SolverHandler solverHandler, HDF5ExecutionResults ma if (solverHandler.nonSpatialResults.containsValue(null) || solverHandler.spatialResults.containsValue(null)) { // some tasks failed, but not all this.somethingFailed = somethingDidFail(); this.logDocumentMessage += "Failed to execute one or more tasks. "; - Tracer.failure(new Exception("Failed to execute one or more tasks in " + this.sedmlName), "Failed to execute one or more tasks in " + this.sedmlName); - logger.info("Failed to execute one or more tasks in " + this.sedmlName); + Tracer.failure(new Exception("Failed to execute one or more tasks in " + this.SEDML_NAME), "Failed to execute one or more tasks in " + this.SEDML_NAME); + logger.info("Failed to execute one or more tasks in " + this.SEDML_NAME); } this.logDocumentMessage += "Generating outputs... "; @@ -322,7 +276,7 @@ private void processOutputs(SolverHandler solverHandler, HDF5ExecutionResults ma } } - private boolean evaluateResults() throws PythonStreamException, InterruptedException, IOException { + private boolean evaluateResults() throws IOException { if (this.somethingFailed) { // something went wrong but no exception was fired Exception e = new RuntimeException("Failure executing the sed document. "); this.logDocumentError += e.getMessage(); @@ -340,15 +294,15 @@ private boolean evaluateResults() throws PythonStreamException, InterruptedExcep //Files.copy(new File(outDirForCurrentSedml,"reports.h5").toPath(),Paths.get(this.resultsDirPath,"reports.h5")); // archiving result files - logger.info("Archiving result files"); + if (logger.isDebugEnabled()) logger.info("Archiving result files"); RunUtils.zipResFiles(new File(this.RESULTS_DIRECTORY_PATH)); org.apache.commons.io.FileUtils.deleteDirectory(this.PLOTS_DIRECTORY); // removing sedml dir which stages results. // Declare success! BiosimulationLog biosimLog = BiosimulationLog.instance(); - biosimLog.setOutputMessage(this.SEDML_LOCATION, this.sedmlName, "sedml", this.logDocumentMessage); + biosimLog.setOutputMessage(this.SEDML_LOCATION, this.SEDML_NAME, "sedml", this.logDocumentMessage); biosimLog.updateSedmlDocStatusYml(this.SEDML_LOCATION, BiosimulationLog.Status.SUCCEEDED); - logger.info("SED-ML : " + this.sedmlName + " successfully completed"); + logger.info("SED-ML : " + this.SEDML_NAME + " successfully completed"); return true; } @@ -377,7 +331,7 @@ private void generateCSV(SolverHandler solverHandler) throws DataAccessException } } - private void generatePlots() throws PythonStreamException, InterruptedException, IOException { + private void generatePlots() throws IOException { logger.info("Generating Plots... "); //PythonCalls.genPlotsPseudoSedml(this.SEDML_LOCATION, this.OUTPUT_DIRECTORY_FOR_CURRENT_SEDML.toString()); // generate the plots // We assume if no exception is returned that the plots pass @@ -388,8 +342,8 @@ private void generatePlots() throws PythonStreamException, InterruptedException, } private void generateHDF5(SolverHandler solverHandler, HDF5ExecutionResults masterHdf5File) { - this.logDocumentMessage += "Generating HDF5 file... "; - logger.info("Generating HDF5 file... "); + this.logDocumentMessage += "Indexing HDF5 data... "; + logger.info("Indexing HDF5 data... "); Hdf5DataExtractor hdf5Extractor = new Hdf5DataExtractor(this.sedml, solverHandler.taskToTempSimulationMap); @@ -407,27 +361,19 @@ private void generateHDF5(SolverHandler solverHandler, HDF5ExecutionResults mast } // This method is a bit weird; it uses a temp file as a reference to compare against while getting the file straight from the archive. - private static SedML getSedMLFile(String[] tokenizedPath, File inputFile) throws XMLException, IOException { - SedML file = null; - Path convertedPath = SedmlJob.getRelativePath(tokenizedPath); - if (convertedPath == null){ - RuntimeException exception = new RuntimeException("Was not able to get relative path to " + inputFile.getName()); - logger.error(exception); - throw exception; - } + private static SedML getSedMLFile(String[] tokenizedPathToSedml, File inputFile) throws XMLException, IOException { + Path convertedPath = SedmlJob.getRelativePath(tokenizedPathToSedml); + if (convertedPath == null) throw new RuntimeException("Was not able to get relative path to " + inputFile.getName()); String identifyingPath = FilenameUtils.separatorsToUnix(convertedPath.toString()); - FileInputStream omexStream = new FileInputStream(inputFile); - ArchiveComponents omexComponents = Libsedml.readSEDMLArchive(omexStream); - List sedmlDocuments = omexComponents.getSedmlDocuments(); - for (SEDMLDocument doc : sedmlDocuments){ - SedML potentiallyCorrectFile = doc.getSedMLModel(); - if (identifyingPath.equals(potentiallyCorrectFile.getPathForURI() + potentiallyCorrectFile.getFileName())){ - file = potentiallyCorrectFile; - break; + try (FileInputStream omexStream = new FileInputStream(inputFile)) { + for (SEDMLDocument doc : Libsedml.readSEDMLArchive(omexStream).getSedmlDocuments()){ + SedML potentiallyCorrectFile = doc.getSedMLModel(); + String potentiallyCorrectPath = potentiallyCorrectFile.getPathForURI() + potentiallyCorrectFile.getFileName(); + if (!identifyingPath.equals(potentiallyCorrectPath)) continue; + return potentiallyCorrectFile; } } - omexStream.close(); - return file; + throw new PreProcessingException("Unable to find desired SedML within path"); } private static Path getRelativePath(String[] tokenizedPath){ @@ -446,28 +392,12 @@ private static boolean somethingDidFail(){ return true; } - /** - * In its current state, the sed-ml generated with python is missing two important fields; - * this function fixes that. - */ - private static SedML repairSedML(SedML brokenSedML, String[] tokenizedPath){ - Path relativePath = getRelativePath(tokenizedPath); - if (relativePath == null) return null; - String name = relativePath.getFileName().toString(); - brokenSedML.setFileName(name); - // Take the relative path, remove the file name, and... - String source = relativePath.toString().substring(0, relativePath.toString().length() - name.length()); - // Convert to unix file separators (java URI does not do windows style) - brokenSedML.setPathForURI(FilenameUtils.separatorsToUnix(source)); - return brokenSedML; // now fixed! - } - - private void reportProblem(Exception e) throws PythonStreamException, InterruptedException, IOException{ + private void reportProblem(Exception e) throws IOException{ logger.error(e.getMessage(), e); String type = e.getClass().getSimpleName(); 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); + biosimLog.setOutputMessage(this.SEDML_LOCATION, this.SEDML_NAME, "sedml", this.logDocumentMessage); + biosimLog.setExceptionMessage(this.SEDML_LOCATION, this.SEDML_NAME, "sedml", type, this.logDocumentError); this.CLI_RECORDER.writeDetailedErrorList(e, this.BIOMODEL_BASE_NAME + ", doc: " + type + ": " + this.logDocumentError); biosimLog.updateSedmlDocStatusYml(this.SEDML_LOCATION, BiosimulationLog.Status.FAILED); } diff --git a/vcell-cli/src/main/java/org/vcell/cli/run/SedmlStatistics.java b/vcell-cli/src/main/java/org/vcell/cli/run/SedmlStatistics.java index cac38ab4ef..ef9d93e91f 100644 --- a/vcell-cli/src/main/java/org/vcell/cli/run/SedmlStatistics.java +++ b/vcell-cli/src/main/java/org/vcell/cli/run/SedmlStatistics.java @@ -14,11 +14,13 @@ * - hasScans :: if the sedml has parameter scans */ public class SedmlStatistics { + private String sedmlName; private Integer nModels, nSimulations, nTasks, nOutputs, nReportsCount, nPlots2DCount, nPlots3DCount; public boolean hasOverrides, hasScans; - public SedmlStatistics(){ + public SedmlStatistics(String sedmlName){ // -1 indicates the value has not been initialized. + this.sedmlName = sedmlName; this.nModels = null; this.nSimulations = null; this.nTasks = null; @@ -30,6 +32,10 @@ public SedmlStatistics(){ this.hasScans = false; } + public String getSedmlName(){ + return this.sedmlName; + } + public int getNumModels(){ return this.nModels == null ? 0 : this.nModels; } 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 ba9fb83167..5cf4a02e89 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 @@ -279,10 +279,10 @@ public void initialize(List bioModelList, SedML sedml) throws Expressi taskToChangeTargetMap.put(rt, targetIdSet); } } - System.out.println("taskToSimulationMap: " + this.taskToTempSimulationMap.size()); - System.out.println("taskToListOfSubTasksMap: " + taskToListOfSubTasksMap.size()); - System.out.println("taskToVariableMap: " + taskToVariableMap.size()); - System.out.println("topTaskToBaseTask: " + topTaskToBaseTask.size()); + if (logger.isDebugEnabled()){ + logger.info("Initialization Statistics:\n\t> taskToSimulationMap: {}\n\t> taskToListOfSubTasksMap: {}\n\t> taskToVariableMap: {}\n\t> topTaskToBaseTask: {}\n", + this.taskToTempSimulationMap.size(), this.taskToListOfSubTasksMap.size(), this.taskToVariableMap.size(), this.topTaskToBaseTask.size()); + } } private static class TempSimulationJob extends SimulationJob { @@ -326,7 +326,7 @@ public void simulateAllTasks(ExternalDocInfo externalDocInfo, SedML sedml, CLIRe String docName = null; List tempSims = null; //String outDirRoot = outputDirForSedml.toString().substring(0, outputDirForSedml.toString().lastIndexOf(System.getProperty("file.separator"))); - this.sedmlImporter = new SEDMLImporter(sedmlImportLogger, externalDocInfo, sedml, exactMatchOnly); + this.sedmlImporter = new SEDMLImporter(sedmlImportLogger, externalDocInfo.getFile(), sedml, exactMatchOnly); try { bioModelList = this.sedmlImporter.getBioModels(); } catch (Exception e) { @@ -431,22 +431,24 @@ public void simulateAllTasks(ExternalDocInfo externalDocInfo, SedML sedml, CLIRe } if (solver instanceof AbstractCompiledSolver) { ((AbstractCompiledSolver) solver).runSolver(); - logger.info("Solver: " + solver); - logger.info("Status: " + solver.getSolverStatus()); - if (solver instanceof ODESolver) { - odeSolverResultSet = ((ODESolver) solver).getODESolverResultSet(); - } else if (solver instanceof GibsonSolver) { - odeSolverResultSet = ((GibsonSolver) solver).getStochSolverResultSet(); - } else if (solver instanceof HybridSolver) { - odeSolverResultSet = ((HybridSolver) solver).getHybridSolverResultSet(); + if (logger.isDebugEnabled()){ + logger.info("Solver: " + solver); + logger.info("Status: " + solver.getSolverStatus()); + } + if (solver instanceof ODESolver odeSolver) { + odeSolverResultSet = odeSolver.getODESolverResultSet(); + } else if (solver instanceof GibsonSolver gibsonSolver) { + odeSolverResultSet = gibsonSolver.getStochSolverResultSet(); + } else if (solver instanceof HybridSolver hybridSolver) { + odeSolverResultSet = hybridSolver.getHybridSolverResultSet(); } else { - String str = "Solver results are not compatible with CSV format. "; + String str = "Solver results will not be compatible with CSV format. "; logger.warn(str); // keepTempFiles = true; // temp fix for Jasraj // throw new RuntimeException(str); } - } else if (solver instanceof AbstractJavaSolver) { - ((AbstractJavaSolver) solver).runSolver(); + } else if (solver instanceof AbstractJavaSolver abstractJavaSolver) { + abstractJavaSolver.runSolver(); odeSolverResultSet = ((ODESolver) solver).getODESolverResultSet(); // must interpolate data for uniform time course which is not supported natively by the Java solvers org.jlibsedml.Simulation sedmlSim = sedml.getSimulation(task.getSimulationReference()); @@ -478,8 +480,6 @@ public void simulateAllTasks(ExternalDocInfo externalDocInfo, SedML sedml, CLIRe if (solver.getSolverStatus().getStatus() == SolverStatus.SOLVER_FINISHED) { logTaskMessage += "done. "; - logger.info("Succesful execution: Model '" + docName + "' Task '" + sim.getDescription() + "'."); - long endTimeTask_ms = System.currentTimeMillis(); long elapsedTime_ms = endTimeTask_ms - startTimeTask_ms; int duration_ms = (int) elapsedTime_ms; @@ -489,14 +489,13 @@ public void simulateAllTasks(ExternalDocInfo externalDocInfo, SedML sedml, CLIRe simDuration_ms += duration_ms; simDurationMap_ms.put(originalSim, simDuration_ms); - String msg = "Running simulation " + simTask.getSimulation().getName() + ", " + elapsedTime_ms + " ms"; - logger.info(msg); + logger.info("Successful execution ({}s): Model '{}' Task '{}' ({}).", + ((double)elapsedTime_ms)/1000, docName, sim.getDescription(), simTask.getSimulation().getName()); 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.instance().setOutputMessage(sedmlLocation, sim.getImportedTaskID(), "task", logTaskMessage); - RunUtils.drawBreakLine("-", 100); } else { String error = solver.getSolverStatus().getSimulationMessage().getDisplayMessage(); solverStatus = solver.getSolverStatus().getStatus(); @@ -554,14 +553,15 @@ public void simulateAllTasks(ExternalDocInfo externalDocInfo, SedML sedml, CLIRe } else { cliLogger.writeDetailedErrorList(e,bioModelBaseName + ", solver: " + sdl + ": " + type + ": " + logTaskError); } - RunUtils.drawBreakLine("-", 100); } finally { if (sim_span != null) { sim_span.close(); } } + if (sd.isSpatial()) { + logger.info("Processing spatial results of execution..."); File hdf5Results = new File(outDir + System.getProperty("file.separator") + task.getId() + "_job_" + tempSimulationJob.getJobIndex() + "_results.h5"); try { RunUtils.exportPDE2HDF5(tempSimulationJob, outputDirForSedml, hdf5Results); @@ -573,6 +573,7 @@ public void simulateAllTasks(ExternalDocInfo externalDocInfo, SedML sedml, CLIRe spatialResults.put(new TaskJob(task.getId(), tempSimulationJob.getJobIndex()), null); } } else { + logger.info("Processing non-spatial results of execution..."); MathSymbolMapping mathMapping = (MathSymbolMapping) simTask.getSimulation().getMathDescription().getSourceSymbolMapping(); SBMLSymbolMapping sbmlMapping = this.sedmlImporter.getSBMLSymbolMapping(bioModel); @@ -581,9 +582,10 @@ public void simulateAllTasks(ExternalDocInfo externalDocInfo, SedML sedml, CLIRe this.nonSpatialResults.put(taskJob, nonspatialSimResults); } - if (keepTempFiles == false) { + if (!keepTempFiles) { RunUtils.removeIntermediarySimFiles(outputDirForSedml); } + RunUtils.drawBreakLine("-", 100); simulationJobCount++; } for (Map.Entry entry : simStatusMap.entrySet()) { diff --git a/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/BiosimulationsHdf5Writer.java b/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/BiosimulationsHdf5Writer.java index 9bf5c0135f..5febd21a5e 100644 --- a/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/BiosimulationsHdf5Writer.java +++ b/vcell-cli/src/main/java/org/vcell/cli/run/hdf5/BiosimulationsHdf5Writer.java @@ -36,7 +36,7 @@ public static void writeHdf5(HDF5ExecutionResults hdf5ExecutionResults, File out boolean didFail = false; // Create and open the Hdf5 file - logger.info("Creating hdf5 file `reports.h5` in {}", outDirForCurrentSedml.getAbsolutePath()); + logger.info("Creating HDF5 file `reports.h5` in {}", outDirForCurrentSedml.getAbsolutePath()); File tempFile = new File(outDirForCurrentSedml, "reports.h5"); try { try (WritableHdfFile hdf5File = HdfFile.write(tempFile.toPath())){ 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 a9a0854b18..b335c82bfa 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 @@ -201,7 +201,8 @@ private static List getReports(List outputs){ if (out instanceof Report){ reports.add((Report)out); } else { - logger.info("Ignoring unsupported output `" + out.getId() + "` while CSV generation."); + if (logger.isDebugEnabled()) + logger.info("Ignoring unsupported output `{}` while CSV generation.", out.getId()); } } return reports; diff --git a/vcell-core/src/main/java/cbit/vcell/geometry/surface/GeometrySurfaceUtils.java b/vcell-core/src/main/java/cbit/vcell/geometry/surface/GeometrySurfaceUtils.java index c2df955759..34b4e7aa4c 100644 --- a/vcell-core/src/main/java/cbit/vcell/geometry/surface/GeometrySurfaceUtils.java +++ b/vcell-core/src/main/java/cbit/vcell/geometry/surface/GeometrySurfaceUtils.java @@ -85,7 +85,7 @@ public static GeometricRegion[] getUpdatedGeometricRegions(GeometrySurfaceDescri cbit.vcell.geometry.RegionImage.RegionInfo regionInfos[] = regionImage.getRegionInfos(); for(int i = 0; i < regionInfos.length; i++){ cbit.vcell.geometry.RegionImage.RegionInfo regionInfo = regionInfos[i]; - lg.info(regionInfo); + if (lg.isDebugEnabled()) lg.info(regionInfo); cbit.vcell.geometry.SubVolume subVolume = geometrySpec.getSubVolume(regionInfo.getPixelValue()); String name = subVolume.getName() + regionInfo.getRegionIndex(); int numPixels = regionInfo.getNumPixels(); @@ -214,18 +214,16 @@ public static GeometricRegion[] getUpdatedGeometricRegions(GeometrySurfaceDescri } size -= sizeOfPixel * 0.125 * numOctantsToRemove; - if(lg.isInfoEnabled()){ - lg.info("size=" + size); - } + if(lg.isDebugEnabled()) lg.info("size={}", size); + break; } } VolumeGeometricRegion volumeRegion = new VolumeGeometricRegion(name, size, volumeUnit, subVolume, regionInfo.getRegionIndex()); regionList.add(volumeRegion); - if(lg.isInfoEnabled()){ - lg.info("added volumeRegion(" + volumeRegion.getName() + ")"); - } + if(lg.isDebugEnabled()) lg.info("added volumeRegion({})", volumeRegion.getName()); + } // // parse surfaceCollection into ResolvedMembraneLocations @@ -268,9 +266,8 @@ public static GeometricRegion[] getUpdatedGeometricRegions(GeometrySurfaceDescri } surfaceRegion.addAdjacentGeometricRegion(interiorVolumeRegion); interiorVolumeRegion.addAdjacentGeometricRegion(surfaceRegion); - if(lg.isInfoEnabled()){ - lg.info("added surfaceRegion(" + surfaceRegion.getName() + ")"); - } + if(lg.isDebugEnabled()) lg.info("added surfaceRegion({})", surfaceRegion.getName()); + } return regionList.toArray(GeometricRegion[]::new); diff --git a/vcell-core/src/main/java/cbit/vcell/mapping/DiffEquMathMapping.java b/vcell-core/src/main/java/cbit/vcell/mapping/DiffEquMathMapping.java index 6bda321e71..aa934c2a97 100644 --- a/vcell-core/src/main/java/cbit/vcell/mapping/DiffEquMathMapping.java +++ b/vcell-core/src/main/java/cbit/vcell/mapping/DiffEquMathMapping.java @@ -1454,7 +1454,7 @@ private void refreshMathDescription() throws MappingException, MatrixException, for(int i = 0; i < mappedSMs.length; i++){ if(mappedSMs[i] instanceof FeatureMapping){ if(mappedFM != null){ - lg.info("WARNING:::: MathMapping.refreshMathDescription() ... assigning boundary condition types not unique"); + if (lg.isDebugEnabled()) lg.warn("WARNING:::: MathMapping.refreshMathDescription() ... assigning boundary condition types not unique"); } mappedFM = (FeatureMapping) mappedSMs[i]; } diff --git a/vcell-core/src/main/java/cbit/vcell/mapping/LangevinMathMapping.java b/vcell-core/src/main/java/cbit/vcell/mapping/LangevinMathMapping.java index 55b000aa46..262aa576f7 100644 --- a/vcell-core/src/main/java/cbit/vcell/mapping/LangevinMathMapping.java +++ b/vcell-core/src/main/java/cbit/vcell/mapping/LangevinMathMapping.java @@ -415,7 +415,7 @@ protected void refreshMathDescription() throws MappingException, MatrixException for (int i = 0; i < mappedSMs.length; i++) { if (mappedSMs[i] instanceof FeatureMapping){ if (mappedFM!=null){ - lg.warn("WARNING:::: MathMapping.refreshMathDescription() ... assigning boundary condition types not unique"); + if (lg.isDebugEnabled()) lg.warn("WARNING:::: MathMapping.refreshMathDescription() ... assigning boundary condition types not unique"); } mappedFM = (FeatureMapping)mappedSMs[i]; } diff --git a/vcell-core/src/main/java/cbit/vcell/mapping/ParticleMathMapping.java b/vcell-core/src/main/java/cbit/vcell/mapping/ParticleMathMapping.java index 537216c22b..96fc17ef6f 100644 --- a/vcell-core/src/main/java/cbit/vcell/mapping/ParticleMathMapping.java +++ b/vcell-core/src/main/java/cbit/vcell/mapping/ParticleMathMapping.java @@ -487,7 +487,7 @@ private void refreshMathDescription() throws MappingException, MatrixException, for (int i = 0; i < mappedSMs.length; i++) { if (mappedSMs[i] instanceof FeatureMapping){ if (mappedFM!=null){ - lg.warn("WARNING:::: MathMapping.refreshMathDescription() ... assigning boundary condition types not unique"); + if (lg.isDebugEnabled()) lg.warn("WARNING:::: MathMapping.refreshMathDescription() ... assigning boundary condition types not unique"); } mappedFM = (FeatureMapping)mappedSMs[i]; } diff --git a/vcell-core/src/main/java/cbit/vcell/solver/SolverUtilities.java b/vcell-core/src/main/java/cbit/vcell/solver/SolverUtilities.java index 047f049b67..b42b6faf70 100644 --- a/vcell-core/src/main/java/cbit/vcell/solver/SolverUtilities.java +++ b/vcell-core/src/main/java/cbit/vcell/solver/SolverUtilities.java @@ -162,10 +162,10 @@ public static SolverDescription matchSolverWithKisaoId(String originalId, boolea private static List matchByKisaoId(KisaoTerm candidate) { List solverDescriptions = new ArrayList<>(); for (SolverDescription sd : SolverDescription.values()) { - if(sd.getKisao().contains(":") || sd.getKisao().contains("_")) { + if (sd.getKisao().contains(":") || sd.getKisao().contains("_")) { logger.trace(sd.getKisao()); } else { - logger.warn(sd.getKisao() + " - bad format, skipping"); + if (logger.isDebugEnabled()) logger.warn("`{}` is bad KiSAO formating, skipping", sd.getKisao()); continue; } String s1 = candidate.getId(); diff --git a/vcell-core/src/main/java/cbit/vcell/xml/XmlHelper.java b/vcell-core/src/main/java/cbit/vcell/xml/XmlHelper.java index 5f9ff632f8..4af94c50ac 100644 --- a/vcell-core/src/main/java/cbit/vcell/xml/XmlHelper.java +++ b/vcell-core/src/main/java/cbit/vcell/xml/XmlHelper.java @@ -501,7 +501,7 @@ public static List readOmex(File omexFile, VCLogger vcLogger) throws E public static List importSEDML(VCLogger transLogger, ExternalDocInfo externalDocInfo, SedML sedml, boolean exactMatchOnly) throws Exception { - SEDMLImporter sedmlImporter = new SEDMLImporter(transLogger, externalDocInfo, + SEDMLImporter sedmlImporter = new SEDMLImporter(transLogger, externalDocInfo.getFile(), sedml, exactMatchOnly); return sedmlImporter.getBioModels(); } diff --git a/vcell-core/src/main/java/cbit/vcell/xml/XmlReader.java b/vcell-core/src/main/java/cbit/vcell/xml/XmlReader.java index fdc9d4067a..b9eeda2ce8 100644 --- a/vcell-core/src/main/java/cbit/vcell/xml/XmlReader.java +++ b/vcell-core/src/main/java/cbit/vcell/xml/XmlReader.java @@ -4562,7 +4562,7 @@ public Model getModel(Element param) throws XmlParseException{ if(element != null){ getRbmModelContainer(element, newmodel); } else { - lg.info("RbmModelContainer is missing."); + if (lg.isDebugEnabled()) lg.info("RbmModelContainer is missing."); } //Add SpeciesContexts diff --git a/vcell-core/src/main/java/org/jlibsedml/SEDMLReader.java b/vcell-core/src/main/java/org/jlibsedml/SEDMLReader.java index 8b3973e1fd..a9d4cbd9b8 100644 --- a/vcell-core/src/main/java/org/jlibsedml/SEDMLReader.java +++ b/vcell-core/src/main/java/org/jlibsedml/SEDMLReader.java @@ -246,7 +246,7 @@ Algorithm getAlgorithm(Element algorithmElement) { if (eChild.getName().equals(SEDMLTags.ALGORITHM_PARAMETER_LIST)) { addAlgorithmParameters(alg, eChild); } else { - log.warn("Unexpected " + eChild); + if (log.isDebugEnabled()) log.warn("Unexpected " + eChild); } } return alg; diff --git a/vcell-core/src/main/java/org/jlibsedml/validation/SchemaValidatorImpl.java b/vcell-core/src/main/java/org/jlibsedml/validation/SchemaValidatorImpl.java index 2b10a4827b..43fc326c44 100644 --- a/vcell-core/src/main/java/org/jlibsedml/validation/SchemaValidatorImpl.java +++ b/vcell-core/src/main/java/org/jlibsedml/validation/SchemaValidatorImpl.java @@ -90,7 +90,7 @@ private String getSchema(String xmlAsString) throws JDOMException, return SEDML_L1_V2_SCHEMA; } else { // probably level 3, but trying anyway to interpret with level 2 - System.out.println("SED-ML version level not supported, import may fail"); + if (log.isDebugEnabled()) log.warn("SED-ML version level not supported, import may fail"); return SEDML_L1_V3_SCHEMA; // throw new IllegalArgumentException( // "Invalid level/version combingation - must be 1-1 or 1-2 but was " diff --git a/vcell-core/src/main/java/org/jlibsedml/validation/SchematronValidator.java b/vcell-core/src/main/java/org/jlibsedml/validation/SchematronValidator.java index fd72478d4a..fe9cc0d43f 100644 --- a/vcell-core/src/main/java/org/jlibsedml/validation/SchematronValidator.java +++ b/vcell-core/src/main/java/org/jlibsedml/validation/SchematronValidator.java @@ -116,7 +116,7 @@ private String getSchematronXSL() { } else if (sedml.isL1V2()) { return "validatorl1v2.xsl"; } else { - System.out.println("Unsupported version, import may fail"); + if (lg.isDebugEnabled()) lg.warn("Unsupported version, import may fail"); return "validatorl1v2.xsl"; // throw new UnsupportedOperationException(MessageFormat.format( // "Invalid level and version - {0}-{1}", sedml.getLevel(), diff --git a/vcell-core/src/main/java/org/vcell/sedml/SEDMLImporter.java b/vcell-core/src/main/java/org/vcell/sedml/SEDMLImporter.java index 2a27d5a876..bd2fa95e93 100644 --- a/vcell-core/src/main/java/org/vcell/sedml/SEDMLImporter.java +++ b/vcell-core/src/main/java/org/vcell/sedml/SEDMLImporter.java @@ -63,8 +63,7 @@ */ public class SEDMLImporter { private final static Logger logger = LogManager.getLogger(SEDMLImporter.class); - private final SedML sedml; - private final ExternalDocInfo externalDocInfo; + private SedML sedml; private final boolean exactMatchOnly; private final VCLogger transLogger; @@ -76,31 +75,47 @@ public class SEDMLImporter { private final HashMap importMap = new HashMap<>(); /** - * Prepares a sedml for import as biomodels + * Builds the importer for future initialization * * @param transLogger the VC logger to use - * @param externalDocInfo contextual information necessary for import - * @param sedml the sedml to import + * @param exactMatchOnly do not substitute for "compatible" kisao solvers, use the exact solver only. + */ + public SEDMLImporter(VCLogger transLogger, boolean exactMatchOnly) { + this.transLogger = transLogger; + this.sedml = null; + this.exactMatchOnly = exactMatchOnly; + } + + /** + * Prepares a sedml for import as biomodels + * + * @param transLogger the VC logger to use * @param exactMatchOnly do not substitute for "compatible" kisao solvers, use the exact solver only. * @throws FileNotFoundException if the sedml archive can not be found * @throws XMLException if the sedml has invalid xml. */ - public SEDMLImporter(VCLogger transLogger, ExternalDocInfo externalDocInfo, SedML sedml, boolean exactMatchOnly) + public SEDMLImporter(VCLogger transLogger, File fileWithSedmlToProcess, SedML sedml, boolean exactMatchOnly) throws XMLException, IOException { - this.transLogger = transLogger; - this.externalDocInfo = externalDocInfo; - this.sedml = sedml; - this.exactMatchOnly = exactMatchOnly; - - this.initialize(); + this(transLogger, exactMatchOnly); + this.initialize(fileWithSedmlToProcess, sedml); } - - private void initialize() throws XMLException, IOException { - // extract bioModel name from sedx (or sedml) file - this.bioModelBaseName = FileUtils.getBaseName(this.externalDocInfo.getFile().getAbsolutePath()); - if(this.externalDocInfo.getFile().getPath().toLowerCase().endsWith("sedx") - || this.externalDocInfo.getFile().getPath().toLowerCase().endsWith("omex")) { - this.ac = Libsedml.readSEDMLArchive(Files.newInputStream(this.externalDocInfo.getFile().toPath())); + + /** + * Initialize the importer to process a specific set of SedML within a document or archive. + * @param fileWithSedmlToProcess the file containing SedML + * @param sedml the SedML to be processed (since the file may have more than 1 sedml) + * @throws IOException if the sedml archive can not be found, or the IO stream reading it failed + * @throws XMLException if the sedml has invalid xml. + */ + public void initialize(File fileWithSedmlToProcess, SedML sedml) throws XMLException, IOException { + // extract bioModel name from sedml (or sedml) file + if (fileWithSedmlToProcess == null) throw new IllegalArgumentException("Source file of SedML can not be null!"); + if (sedml == null) throw new IllegalArgumentException("Provided SedML can not be null!"); + this.sedml = sedml; + this.bioModelBaseName = FileUtils.getBaseName(fileWithSedmlToProcess.getAbsolutePath()); + if(fileWithSedmlToProcess.getPath().toLowerCase().endsWith("sedx") + || fileWithSedmlToProcess.getPath().toLowerCase().endsWith("omex")) { + this.ac = Libsedml.readSEDMLArchive(Files.newInputStream(fileWithSedmlToProcess.toPath())); } this.resolver = new ModelResolver(this.sedml); if(this.ac != null) { @@ -109,7 +124,7 @@ private void initialize() throws XMLException, IOException { this.resolver.add(amr); } else { this.resolver.add(new FileModelResolver()); // assumes absolute paths - String sedmlRelativePrefix = this.externalDocInfo.getFile().getParent() + File.separator; + String sedmlRelativePrefix = fileWithSedmlToProcess.getParent() + File.separator; this.resolver.add(new RelativeFileModelResolver(sedmlRelativePrefix)); // in case model URIs are relative paths } this.sbmlSupport = new SBMLSupport(); @@ -180,7 +195,7 @@ public List getBioModels() { // try to find a match in the ontology tree SolverDescription solverDescription = SolverUtilities.matchSolverWithKisaoId(kisaoID, this.exactMatchOnly); if (solverDescription != null) { - logger.info("Task (id='{}') is compatible, solver match found in ontology: '{}' matched to {}", selectedTask.getId(), kisaoID, solverDescription); + if (logger.isDebugEnabled()) logger.info("Task (id='{}') is compatible, solver match found in ontology: '{}' matched to {}", selectedTask.getId(), kisaoID, solverDescription); } else { // give it a try anyway with our deterministic default solver solverDescription = SolverDescription.CombinedSundials; @@ -426,10 +441,12 @@ private List mergeBioModels(List bioModels) { BioModel bm0 = bioModels.get(0); for (int i = 1; i < bioModels.size(); i++) { - System.out.println("----comparing model from----"+bioModels.get(i)+" with model from "+bm0); + if (logger.isDebugEnabled()) + logger.info("--------------------\ncomparing model from `{}`\n with model from `{}`\n--------------------", + bioModels.get(i), bm0); RelationVisitor rvNotStrict = new ModelRelationVisitor(false); boolean equivalent = bioModels.get(i).getModel().relate(bm0.getModel(),rvNotStrict); - System.out.println(equivalent); + if (logger.isDebugEnabled()) logger.info("Equivalent => {}", equivalent); if (!equivalent) return bioModels; } // all have matchable model, try to merge by pooling SimContexts 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 87366a8506..7020ae1253 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 @@ -22,7 +22,7 @@ import java.util.ArrayList; import java.util.List; -public class BiosimulationLog { +public class BiosimulationLog implements AutoCloseable { public static class LogValidationException extends RuntimeException { public LogValidationException(String message) {