Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added appropriate exception catching for SBML errors when exproting to SEDML. #937

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7ebc703
Added appropriate exception catching for SBML errors when exproting t…
CodeByDrescher Jul 11, 2023
47af614
Patched unnecessary throw statement
CodeByDrescher Jul 11, 2023
1881451
Changed Exception to SEDMLExportException
CodeByDrescher Jul 12, 2023
76001b6
Added clearer exception catching, and small tweaks
CodeByDrescher Jul 12, 2023
0dfb1d1
Adding missing exception infrastructure
CodeByDrescher Jul 12, 2023
2dd266b
Added new exception for non-error raising failures
CodeByDrescher Jul 12, 2023
bb1eb15
Cleaning commit
CodeByDrescher Jul 13, 2023
7856b29
Added handling for mapping exception
CodeByDrescher Jul 13, 2023
b26c92f
expanded unsupported sbml exceptions
CodeByDrescher Jul 13, 2023
7e4e842
Added cbit's XMLParseException exception handling
CodeByDrescher Jul 13, 2023
7612358
Added NumberFormatException exception handling
CodeByDrescher Jul 14, 2023
143c2ce
Testing state in GitHub Action
CodeByDrescher Jul 17, 2023
0b23d8a
Fixed bug with OmexPythonUtils
CodeByDrescher Jul 18, 2023
943faf2
Added system property to MathOverrideRoundTipTest
CodeByDrescher Jul 18, 2023
4e6272f
Testing using install dir as reference
CodeByDrescher Jul 18, 2023
8f7dd33
Second attempt at a fix
CodeByDrescher Jul 18, 2023
59b643d
Used canonical file to fix pathing
CodeByDrescher Jul 18, 2023
ef156b3
Cleaned up Batch mode, still a bug with Export calls
CodeByDrescher Jul 21, 2023
60cc476
Reverted some changes to get working result
CodeByDrescher Jul 21, 2023
22d6929
Added more needed property updates
CodeByDrescher Jul 25, 2023
b9ca278
removed debug session
CodeByDrescher Jul 25, 2023
861296b
Needing to check debug again
CodeByDrescher Jul 26, 2023
eb771e3
Removed tmate check, and added code to restore joblob.txt
CodeByDrescher Aug 3, 2023
393b929
Fixed Workflow to not create already existing directory, and to print…
CodeByDrescher Aug 4, 2023
71070c1
Fixed path to processed export results
CodeByDrescher Aug 4, 2023
eaa1e30
Added new test and correlated helper classes; need to test prototype …
CodeByDrescher Aug 15, 2023
2784e40
Fleshed out new tests, and changed github action to use test
CodeByDrescher Aug 17, 2023
2cbc9de
Fixed mkdirs
CodeByDrescher Aug 17, 2023
eb6ab0c
Removed skipping tests
CodeByDrescher Aug 18, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
433 changes: 223 additions & 210 deletions .github/workflows/nightly-model-testing.yml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public static void writeHdf5(Hdf5DataContainer hdf5DataWrapper, File outDirForCu
masterHdf5.insertNumericAttributes(currentDatasetId, "times", Hdf5DataPreparer.getSpatialHdf5Attribute_Times(data));
}
masterHdf5.insertFixedStringAttribute(currentDatasetId, "_type", data.datasetMetadata._type);
masterHdf5.insertFixedStringAttributes(currentDatasetId, "scanParameterNames", Arrays.asList(data.dataSource.scanParameterNames));
//masterHdf5.insertFixedStringAttributes(currentDatasetId, "scanParameterNames", Arrays.asList(data.dataSource.scanParameterNames));
masterHdf5.insertFixedStringAttributes(currentDatasetId, "sedmlDataSetDataTypes", data.datasetMetadata.sedmlDataSetDataTypes);
masterHdf5.insertFixedStringAttributes(currentDatasetId, "sedmlDataSetIds", data.datasetMetadata.sedmlDataSetIds);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.vcell.cli.vcml;

import org.vcell.cli.vcml.ExportOmexCommand;
import cbit.vcell.resource.PropertyLoader;

import org.apache.logging.log4j.Level;
Expand All @@ -10,12 +11,18 @@
import org.vcell.admin.cli.CLIDatabaseService;
import org.vcell.cli.CLIRecorder;
import org.vcell.sedml.ModelFormat;
import org.vcell.sedml.SEDMLEventLog;
import org.vcell.sedml.SEDMLEventLogFile;
import org.vcell.util.DataAccessException;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

import java.io.File;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.SQLException;
import java.util.concurrent.Callable;

Expand Down Expand Up @@ -64,23 +71,88 @@ public class ExportOmexBatchCommand implements Callable<Integer> {
private boolean help;

public Integer call() {
Level logLevel = bDebug ? Level.DEBUG : logger.getLevel();
Level logLevel = this.bDebug ? Level.DEBUG : logger.getLevel();

LoggerContext config = (LoggerContext)(LogManager.getContext(false));
config.getConfiguration().getLoggerConfig(LogManager.getLogger("org.vcell").getName()).setLevel(logLevel);
config.getConfiguration().getLoggerConfig(LogManager.getLogger("cbit").getName()).setLevel(logLevel);
config.updateLoggers();

final SEDMLEventLog sedmlEventLog;
try {

logger.debug("Batch export of omex files requested");
PropertyLoader.loadProperties();
if (inputFilePath == null || !inputFilePath.exists() || !inputFilePath.isDirectory())
throw new RuntimeException("inputFilePath '" + (inputFilePath == null ? "" : inputFilePath) + "' is not a 'valid directory'");

if (outputFilePath.exists() && !outputFilePath.isDirectory())
throw new RuntimeException("outputFilePath '" + outputFilePath + "' is not a 'valid directory'");
File parentDir = new File(outputFilePath.getParent()).getCanonicalFile();
if (this.inputFilePath == null || !this.inputFilePath.exists() || !this.inputFilePath.isDirectory())
throw new RuntimeException("inputFilePath '" + (this.inputFilePath == null ? "" : this.inputFilePath) + "' is not a valid VCML archive");
if (this.outputFilePath == null || !this.outputFilePath.isDirectory())
throw new RuntimeException("outputFilePath '" + (this.outputFilePath == null ? "" : this.outputFilePath) + "' is not a valid target for OMEX archive");
if (parentDir.exists() && !parentDir.isDirectory()) {
throw new RuntimeException("directory for output '" + parentDir.getCanonicalPath() + "' is not a valid directory for OMEX archive");
}
if (!parentDir.exists())
if (!parentDir.mkdirs())
throw new RuntimeException("Output dir doesn't exist and could not be made!");


if (bWriteLogFiles) {
sedmlEventLog = new SEDMLEventLogFile(new File(outputFilePath, "jobLog.txt"));
} else {
sedmlEventLog = (String entry) -> {};
}
} catch (IOException e){
throw new RuntimeException("Error in setting up batch execution:\n\t", e);
}

try {
PropertyLoader.loadProperties();

logger.debug("Batch export of omex files requested");
int numSuccessfulExports = 0, numTotalFiles = 0;
Path inputDirPath = this.inputFilePath.getCanonicalFile().toPath();
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(inputDirPath)){
for (Path child : dirStream){
// Begin Setup
File childFile, targetOutputFile;
try {
childFile = child.toFile();
if (childFile.isDirectory()){
continue;
}
if (!child.toString().endsWith(".vcml")){
continue;
}
numTotalFiles++;

String childFileFullName = childFile.getName();
String outputFileName = childFileFullName.substring(0, childFileFullName.length() - 5);
targetOutputFile = Paths.get(this.outputFilePath.getCanonicalPath(), outputFileName).toFile();
} catch (IOException e){
logger.error("Error setting up '" + child.getFileName() + "':\n\t", e);
continue;
}

// Setup Complete, Begin Conversion.
try {
ExportOmexCommand.exportVCMLFile(childFile, targetOutputFile, this.outputModelFormat, sedmlEventLog,
this.bWriteLogFiles, this.bValidateOmex, this.bSkipUnsupportedApps);
logger.info("Conversion from '" + child.getFileName()
+ "' to '" + targetOutputFile.getName() + "' succeeded");
numSuccessfulExports++;
} catch (Exception e){
logger.error("Conversion for '" + child.getFileName() + "' failed:\n\t", e);
}
logger.error("Continuing to next file to convert.\n\n");
}
logger.info(String.format("Batch mode complete.\n\t"
+ " %d/%d exports were successful.", numSuccessfulExports, numTotalFiles));
}

} catch (Exception e){
logger.error("Unexpected IO Error occurred, ending batch conversion");
throw new RuntimeException("Unexpected IO error occurred:\n\t", e);
}
return 0;
/* old methodology
if (bOffline) this.runInOfflineMode();
else this.run();

Expand All @@ -91,6 +163,7 @@ public Integer call() {
} finally {
logger.debug("Batch export completed");
}
*/
}

private void runInOfflineMode() throws IOException {
Expand Down
41 changes: 31 additions & 10 deletions vcell-cli/src/main/java/org/vcell/cli/vcml/ExportOmexCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.vcell.sedml.ModelFormat;
import org.vcell.sedml.SEDMLEventLog;
import org.vcell.util.DataAccessException;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
Expand Down Expand Up @@ -42,8 +43,8 @@ public class ExportOmexCommand implements Callable<Integer> {
boolean bValidateOmex;

public Integer call() {
Level logLevel = bDebug ? Level.DEBUG : logger.getLevel();
Level logLevel = bDebug ? Level.DEBUG : logger.getLevel();

LoggerContext config = (LoggerContext)(LogManager.getContext(false));
config.getConfiguration().getLoggerConfig(LogManager.getLogger("org.vcell").getName()).setLevel(logLevel);
config.getConfiguration().getLoggerConfig(LogManager.getLogger("cbit").getName()).setLevel(logLevel);
Expand All @@ -52,15 +53,35 @@ public Integer call() {
try {
PropertyLoader.loadProperties();

logger.debug("Beginning export");
VcmlOmexConverter.convertOneFile(
inputFilePath, outputFilePath, outputModelFormat, bWriteLogFiles, bValidateOmex, bSkipUnsupportedApps);
return 0;
if (inputFilePath == null || !inputFilePath.exists() || !inputFilePath.isDirectory())
throw new RuntimeException("inputFilePath '" + (inputFilePath == null ? "" : inputFilePath) + "' is not a valid VCML archive");

if (outputFilePath == null || outputFilePath.isDirectory())
throw new RuntimeException("outputFilePath '" + (outputFilePath == null ? "" : outputFilePath) + "' is not a valid target for OMEX archive");

if (outputFilePath.exists())
this.logger.warn(String.format("File '%s' already exists."));

return ExportOmexCommand.exportVCMLFile(this.inputFilePath, this.outputFilePath,
this.outputModelFormat, null, this.bWriteLogFiles, this.bValidateOmex, this.bSkipUnsupportedApps);

} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
} finally {
logger.debug("Completed all exports");
throw new RuntimeException("Export failed with message:\n\t" + e.getMessage(), e);
}
}

public static int exportVCMLFile(File inputFilePath, File outputFilePath, ModelFormat outputModelFormat, SEDMLEventLog sedmlEventLog,
boolean bWriteLogFiles, boolean bValidateOmex, boolean bSkipUnsupportedApps)
throws Exception {
try {
logger.debug(String.format("Beginning export of '%s'", inputFilePath.getName()));
VcmlOmexConverter.convertOneFile(inputFilePath, outputFilePath, outputModelFormat, sedmlEventLog,
bWriteLogFiles, bValidateOmex, bSkipUnsupportedApps);
logger.debug(String.format("Finished export of '%s'", inputFilePath.getName()));
} catch (Exception e){
logger.error(String.format("Error while exporting '%s'", inputFilePath.getName())); // We throw, no need to print error here
throw e;
}
return 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.vcell.cli.vcml;

public class VCMLConversionException extends Exception {
public VCMLConversionException(String message){
super(message);
}

public VCMLConversionException(String message, Throwable cause){
super(message, cause);
}

public VCMLConversionException(Throwable cause){
super(cause);
}

public VCMLConversionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace){
super(message, cause, enableSuppression, writableStackTrace);
}
}
20 changes: 14 additions & 6 deletions vcell-cli/src/main/java/org/vcell/cli/vcml/VcmlOmexConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.apache.logging.log4j.Logger;
import org.vcell.admin.cli.CLIDatabaseService;
import org.vcell.sbml.OmexPythonUtils;
import org.vcell.sbml.UnsupportedSbmlExportException;
import org.vcell.sedml.*;
import org.vcell.util.DataAccessException;
import org.vcell.util.document.BioModelInfo;
Expand Down Expand Up @@ -42,6 +43,7 @@ public class VcmlOmexConverter {
public static void convertOneFile(File input,
File outputDir,
ModelFormat modelFormat,
SEDMLEventLog passedInSedmlEventLog,
boolean bWriteLogFiles,
boolean bValidateOmex,
boolean bSkipUnsupportedApps)
Expand All @@ -53,12 +55,15 @@ public static void convertOneFile(File input,
logger.debug("Beginning conversion of `" + input + "`");
Predicate<Simulation> simulationExportFilter = simulation -> true;
BioModelInfo bioModelInfo = null;
final SEDMLEventLog sedmlEventLog;
if (bWriteLogFiles) {
SEDMLEventLog sedmlEventLog;
if (passedInSedmlEventLog != null){
sedmlEventLog = passedInSedmlEventLog;
} else if (bWriteLogFiles) {
sedmlEventLog = new SEDMLEventLogFile(new File(outputDir, jobLogFileName));
} else {
sedmlEventLog = (String entry) -> {};
}

boolean bHasPython = true;
List<SEDMLTaskRecord> sedmlTaskRecords = SEDMLExporter.writeBioModel(
input,
Expand Down Expand Up @@ -204,19 +209,22 @@ public static void convertFilesNoDatabase(File inputDir, File outputDir, ModelFo
bSkipUnsupportedApps,
bHasPython,
bValidateOmex);
if (!sedmlTaskRecords.stream().anyMatch((SEDMLTaskRecord r) -> r.getTaskResult() == TaskResult.FAILED)) {
if (sedmlTaskRecords.stream().noneMatch((SEDMLTaskRecord r) -> r.getTaskResult() == TaskResult.FAILED)) {
logger.info("Combine archive created for `" + inputFileName + "`");
} else {
List<String> errorList = sedmlTaskRecords.stream()
.filter((SEDMLTaskRecord r) -> r.getTaskResult() == TaskResult.FAILED)
.map((SEDMLTaskRecord r) -> r.getCSV())
.map(SEDMLTaskRecord::getCSV)
.collect(Collectors.toList());
String msg = "Failed converting VCML to OMEX archive for `" + inputFileName + "`, errors: " + errorList;
logger.error(msg);
throw new RuntimeException(msg);
throw new VCMLConversionException(msg);
}
} catch (SEDMLExporter.SEDMLExportException | OmexPythonUtils.OmexValidationException e) {
} catch (SEDMLExporter.SEDMLExportException | OmexPythonUtils.OmexValidationException | VCMLConversionException e) {
logger.error("Failed converting VCML to OMEX archive for `" + inputFileName + "`", e);
} catch (Exception e){
logger.error("Unexpected Exception occurred while converting VCML:\n\t", e);
throw e;
}
}
logger.debug("Completed conversion of files in `" + inputDir + "`");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ public class PropertyLoader {
public static final String cmdSrvcSshCmdRestoreTimeoutFactor = record("vcell.ssh.cmd.restoretimeout", ValueType.GEN);

public static final String cliWorkingDir = record("cli.workingDir", ValueType.DIR);

public static final String vcellVcmlLocation = record("vcell.vcmlLocation", ValueType.DIR);

public static final String enableSpringSaLaD = record("vcell.enableSpringSaLaD", ValueType.BOOL);

Expand Down
3 changes: 1 addition & 2 deletions vcell-core/src/main/java/org/vcell/sbml/OmexPythonUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ private static List<OmexValidationError> getErrorsFromReport(JsonObject reportRo
}

private static int callCLIPython(String command, Path omexFile, Path tempDir, Path reportJsonFile) throws InterruptedException, IOException {
File installDir = PropertyLoader.getRequiredDirectory(PropertyLoader.installationRoot);
File cliPythonDir = Paths.get(installDir.getAbsolutePath(), "vcell-cli-utils").toAbsolutePath().toFile();
File cliPythonDir = PropertyLoader.getRequiredDirectory(PropertyLoader.cliWorkingDir).getCanonicalFile();
ProcessBuilder pb = new ProcessBuilder(
"poetry", "run", "python",
"-m", "vcell_cli_utils.wrapper",
Expand Down
Loading