Skip to content

Commit

Permalink
Merge branch 'master' into repair-nightly-testing
Browse files Browse the repository at this point in the history
  • Loading branch information
CodeByDrescher committed Dec 17, 2024
2 parents a8d5b3e + 4b1ed10 commit e9b055a
Show file tree
Hide file tree
Showing 76 changed files with 3,204 additions and 1,241 deletions.
35 changes: 0 additions & 35 deletions .github/workflows/objective-c-xcode-debug.yml

This file was deleted.

2 changes: 2 additions & 0 deletions vcell-cli/src/main/java/org/vcell/cli/CLIStandalone.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.vcell.cli.biosimulation.BiosimulationsCommand;
import org.vcell.cli.run.ExecuteCommand;
import org.vcell.cli.run.ExecuteOmexCommand;
import org.vcell.cli.sbml.ModelCommand;
import org.vcell.cli.vcml.*;

Expand All @@ -22,6 +23,7 @@
ExportOmexBatchCommand.class,
ImportOmexCommand.class,
ImportOmexBatchCommand.class,
ExecuteOmexCommand.class,
ExecuteCommand.class,
VersionCommand.class,
ModelCommand.class,
Expand Down
31 changes: 31 additions & 0 deletions vcell-cli/src/main/java/org/vcell/cli/CliTracer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.vcell.cli;

import org.vcell.trace.Tracer;

public class CliTracer implements CLIRecordable {

@Override
public void writeDetailedErrorList(Exception e, String message) {
Tracer.failure(e, "writeDetailedErrorList(): "+message);
}
@Override
public void writeFullSuccessList(String message) {
Tracer.success("writeFullSuccessList(): " + message);
}
@Override
public void writeErrorList(Exception e, String message) {
Tracer.failure(e, "writeErrorList(): " + message);
}
@Override
public void writeDetailedResultList(String message) {
Tracer.log("writeDetailedResultList(): "+message);
}
@Override
public void writeSpatialList(String message) {
Tracer.log("writeSpatialList(): "+message);
}
@Override
public void writeImportErrorList(Exception e, String message) {
Tracer.failure(e, "writeImportErrorList(): " + message);
}
}
49 changes: 27 additions & 22 deletions vcell-cli/src/main/java/org/vcell/cli/run/ExecuteImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import cbit.vcell.solver.ode.ODESolverResultSet;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jlibsedml.XMLException;
import org.vcell.cli.CLIRecordable;
import org.vcell.cli.PythonStreamException;
import org.vcell.cli.exceptions.ExecutionException;
Expand Down Expand Up @@ -40,45 +39,47 @@ 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;
} finally {
if (span != null) {
span.close();
}
BiosimulationLog.instance().close();
}
}
if (failedFiles.isEmpty()){
Expand Down Expand Up @@ -138,10 +139,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 {
Expand Down Expand Up @@ -232,7 +237,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);
Expand Down
132 changes: 132 additions & 0 deletions vcell-cli/src/main/java/org/vcell/cli/run/ExecuteOmexCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package org.vcell.cli.run;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.vcell.cli.CLIPythonManager;
import org.vcell.cli.CLIRecordable;
import org.vcell.cli.CliTracer;
import org.vcell.cli.testsupport.OmexExecSummary;
import org.vcell.cli.testsupport.OmexTestingDatabase;
import org.vcell.trace.Tracer;
import org.vcell.util.FileUtils;
import org.vcell.util.exe.Executable;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Date;
import java.util.concurrent.Callable;

@Command(name = "execute-omex", description = "run a single .omex file and log into exec_summary.json and tracer.json")
public class ExecuteOmexCommand implements Callable<Integer> {

private final static Logger logger = LogManager.getLogger(ExecuteOmexCommand.class);

@Option(names = { "-i", "--inputFilePath" }, required = true, description = "Path to a COMBINE/OMEX archive file")
private File inputFilePath;

@Option(names = { "-o", "--outputFilePath"}, required = true, description = "Directory to save outputs")
private File outputFilePath;

@Option(names = {"--keepTempFiles"}, defaultValue = "false")
private boolean bKeepTempFiles = false;

@Option(names = {"--exactMatchOnly"}, defaultValue = "false")
private boolean bExactMatchOnly = false;

@Option(names = "--small-mesh", defaultValue = "false", description = "force spatial simulations to have a very small mesh to make execution faster")
private boolean bSmallMeshOverride = false;

@Option(names = {"--encapsulateOutput"}, defaultValue = "true", description =
"VCell will encapsulate output results in a sub directory when executing with a single input archive; has no effect when providing an input directory")
private boolean bEncapsulateOutput = true;

@Option(names = {"--timeout_ms"}, defaultValue = "600000", description = "executable wall clock timeout in milliseconds")
// timeout for compiled solver running long jobs; default 10 minutes
private long EXECUTABLE_MAX_WALLCLOCK_MILLIS = 10 * 60 * 1000;

@Option(names = {"-h", "--help"}, description = "show this help message and exit", usageHelp = true)
private boolean help = false;

@Option(names = {"-d", "--debug"}, description = "full application debug mode")
private boolean bDebug = false;

@Option(names = {"-q", "--quiet"}, description = "suppress all console output")
private boolean bQuiet = false;


public Integer call() {

CLIRecordable cliTracer = new CliTracer();
try {
if (bDebug && bQuiet) {
System.err.println("cannot specify both debug and quiet, try --help for usage");
return 1;
}
Level logLevel;
if (!bQuiet && bDebug) {
logLevel = Level.DEBUG;
} else if (bQuiet) {
logLevel = Level.OFF;
} else {
logLevel = logger.getLevel();
}

if (this.inputFilePath.exists() && !this.inputFilePath.isFile()) {
System.err.println("Input path must be a file");
return 1;
}
if (this.outputFilePath.exists() && !this.outputFilePath.isDirectory()) {
System.err.println("Output path must be a directory");
return 1;
}

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();


CLIPythonManager.getInstance().instantiatePythonProcess();

Executable.setGlobalTimeoutMS(EXECUTABLE_MAX_WALLCLOCK_MILLIS);
logger.info("Beginning execution");
File tmpDir = Files.createTempDirectory("VCell_CLI_" + Long.toHexString(new Date().getTime())).toFile();

Tracer.clearTraceEvents();
ExecuteImpl.singleMode(inputFilePath, tmpDir, cliTracer, bKeepTempFiles, bExactMatchOnly,
bEncapsulateOutput, bSmallMeshOverride);
CLIPythonManager.getInstance().closePythonProcess();
// WARNING: Python needs re-instantiation once the above line is called!
FileUtils.copyDirectoryContents(tmpDir, outputFilePath, true, null);
final OmexExecSummary omexExecSummary;
if (Tracer.hasErrors()){
omexExecSummary = OmexTestingDatabase.summarize(inputFilePath,(Exception)null,Tracer.getErrors());
} else {
omexExecSummary = new OmexExecSummary();
omexExecSummary.file_path = String.valueOf(inputFilePath);
omexExecSummary.status = OmexExecSummary.ActualStatus.PASSED;
}
new ObjectMapper().writeValue(new File(outputFilePath, "exec_summary.json"), omexExecSummary);
new ObjectMapper().writeValue(new File(outputFilePath, "tracer.json"), Tracer.getTraceEvents());
return 0;
} catch (Exception e) { ///TODO: Break apart into specific exceptions to maximize logging.
LogManager.getLogger(this.getClass()).error(e.getMessage(), e);
OmexExecSummary omexExecSummary = OmexTestingDatabase.summarize(inputFilePath,e,Tracer.getErrors());
try {
new ObjectMapper().writeValue(new File(outputFilePath, "exec_summary.json"), omexExecSummary);
new ObjectMapper().writeValue(new File(outputFilePath, "tracer.json"), Tracer.getTraceEvents());
} catch (IOException ex) {
logger.error("Failed to write exec summary and structured logs", ex);
}
return 1;
} finally {
logger.debug("Completed all execution");
}
}
}
Loading

0 comments on commit e9b055a

Please sign in to comment.