APE as a Java Library
Run APE from a Java environment
The APE library relies on a configuration file or object that references the domain ontology, tool annotations, workflow specification and execution parameters. All the parameters can either be set by a JSONObject/JSON file or be set programmatically. The guidelines how to create domain configuration (and annotation) were provided on the previous page.
APE API functions
Environment Setup
Setup the APE framework with a JSON file or provide the required information programmatically:
// JSON
APE framework1 = new APE("path/to/setup-configuration.json");
// programmatically
APECoreConfig config = new APECoreConfig(
new File("GeoGMT/GMT_UseCase_taxonomy.owl"),
"http://www.co-ode.org/ontologies/ont.owl#",
"ToolsTaxonomy",
Arrays.asList("TypesTaxonomy"),
new File("GeoGMT/tool_annotations.json")
);
APE framework2 = new APE(config);
Domain information retreval
After setting up the environment, APE will process the domain data (Taxonomies and Tool annotations). This includes creating object that correspond to tool and data terms provided, with the corresponding subclass relations. In addition, the library will filter out the terms that are not used in the domain (e.g. data formats that cannot be used nor generated by any of the tools), and thus trimming the ontology.
APE provides a domain model object that contains all the mentioned information.
// get domain setup from the APE object
APEDomainSetup domainSetup = framework.getDomainSetup();
APEDomainSetup provides all the available information regarding: 1. The annotated tools and their structure. The user can fetch the root of the tool taxonomy and extract the whole ontology structure recursivlty (using the getSubPredicates() method) , or simply retreive a single tool annotation.
//get the root operation and its subclasses
TaxonomyPredicate rootOperation = domainOperations.getRootModule();
Set<TaxonomyPredicate> subOperations = rootOperation.getSubPredicates();
// get a specific tool from the domain
AbstractModule operation = domainOperations.get("operationID");
List<Type> inputs = operation.getModuleInput();
List<Type> outputs = operation.getModuleOutput();
Structure of the domain types, for each of the dimensions.
AllTypes domainTypes = domainSetup.getAllTypes();
// get all dimensions in the domain
List<TaxonomyPredicate> dataDimensionRoots = domainTypes.getRootPredicates();
for(TaxonomyPredicate dataDimensionRoot : dataDimensionRoots) {
// print dimension in human readable format
System.out.println("Processing data dimension: " + dataDimensionRoot.getPredicateLabel());
Set<TaxonomyPredicate> subDataTypes = dataDimensionRoot.getSubPredicates();
}
Run Specifications Setup
After setting up the framework, create a Run configuration with a JSON file or provide the required information programmatically:
// JSON
APERunConfig runConfig1 = new APERunConfig("path/to/run-configuration.json");
// programmatically
APERunConfig runConfig2 = APERunConfig.builder()
.withSolutionMinLength(1)
.withSolutionMaxLength(10)
.withMaxNoSolutions(100)
.withApeDomainSetup(framework.getDomainSetup())
.build();
Run the Synthesis
APE framework = new APE( .. );
APERunConfig runConfig = .. ;
SATsolutionsList solutions = framework.runSynthesis(runConfig);
// write the solutions to the file system
APE.writeSolutionToFile(solutions); // write solutions to ./sat_solutions.txt
APE.writeDataFlowGraphs(solutions, Rank.RankDir.TOP_TO_BOTTOM); // save images to ./Figures/, alternatively APE.writeTavernaDesignGraphs() method can be used to generate workflows that follow the visual design of Taverna workflows
APE.writeExecutableWorkflows(solutions); // save scripts to ./Executables/
APE.writeCWLWorkflows(solutions); // save CWL files to ./CWL/
The API allows to generate and edit the configuration file programmatically between runs:
// set up the framework
APE framework = new APE( .. );
APERunConfig runConfig = .. ;
// run the synthesis
SATsolutionsList solutions1 = framework.runSynthesis(runConfig);
// run the synthesis again with altered parameters
runConfig.setUseWorkflowInput(ConfigEnum.ONE);
SATsolutionsList solutions2 = ape.runSynthesis(runConfig);
SATsolutionsList
Functions to retrieve data (that can be visualized).
SATsolutionsList: The solution set retrieved from the synthesis execution.
int getNumberOfSolutions()
Amount of solutions.SolutionWorkflow get(int index)
Get solution i.
SolutionWorkFlow: One solution workflow.
int getSolutionlength()
The length of the solution.List<ModuleNode> getModuleNodes()
The tools represented in the workflow.List<TypeNode> getWorkflowInputTypeStates()
Data instances used as input of the workflow.List<TypeNode> getWorkflowOutputTypeStates()
Data instances representing the output of the workflow.
ModuleNode: contains information about a tool in a workflow.
String getNodeID()
The ID of the tool.String getNodeLabel()
The name of the tool.boolean hasNextModule()
The output of this tool is used as input for another tool (outgoing arrow).ModuleNode getNextModuleNode()
Get the next tool.boolean hasPrevModule()
The input of this tool was the output of another tool (incoming arrow).ModuleNode getPrevModuleNode()
Get the previous tool.List<TypeNode> getInputTypes()
Data instances used as input of the tool.List<TypeNode> getOutputTypes()
Data instances used as output of the tool.
TypeNode: a data instance
String getNodeID()
The ID of the data instance.String getShortNodeID()
The name of the data instance (e.g. node12345).SortedSet<Type> getTypes()
Containing n values for the n-dimensions.
The following example prints a SolutionWorkflow to the console.
/**
* Print SolutionWorkflow to the console
*/
public static void printReadableWorkflowSolution(SolutionWorkflow solution) {
System.out.println("INPUT:" + inputTypesToString(solution.getWorkflowInputTypeStates()) + "\n");
// print the first solution
solution.getModuleNodes().forEach(node -> {
System.out.printf("Tool %s" +
"\n\tInput data: %s" +
"\n\tOutput data %s" +
"\n\tNext tool: %s" +
"\n\tPrevious tool: %s\n\n",
node.getNodeLabel(),
inputTypesToString(node.getInputTypes()),
inputTypesToString(node.getOutputTypes()),
node.hasNextModule() ? node.getNextModuleNode().getNodeLabel() : "",
node.hasPrevModule() ? node.getPrevModuleNode().getNodeLabel() : ""
);
});
System.out.println("\nOUTPUT:" + inputTypesToString(solution.getWorkflowOutputTypeStates()));
}
/**
* If a type node is a PNG as well as an Image (2 dimensions) and has id node12345,
* this method returns "(node12345[PNG, Image])"
* SortedSet Type can be obtained from typeNode.getTypes();
*/
private static String inputTypesToString(List<TypeNode> types){
return types.stream()
.map(data -> "(" + data.getShortNodeID() + typeToString(data.getTypes()) + ")")
.collect(Collectors.toList())
.toString();
}
/**
* If a data instance is a PNG as well as an Image (2 dimensions),
* this method returns "[PNG, Image]"
* SortedSet Type can be obtained from typeNode.getTypes();
*/
private static String typeToString(SortedSet<Type> dimensions){
return dimensions.stream()
.map(Type::getPredicateLabel)
.collect(Collectors.toList())
.toString();
}
INPUT:[(node579867570[PNG, Image]), (node1548883689[String, Content])]
Tool generate_color
Input data: []
Output data [(node173380607[String, Color]), (node676323030[])]
Next tool: generate_font
Previous tool:
Tool generate_font
Input data: []
Output data [(node1695080704[String, FontFamily]), (node676323991[])]
Next tool: add_small_border
Previous tool: generate_color
Tool add_small_border
Input data: [(node579867570[PNG, Image]), (node173380607[String, Color])]
Output data [(node579870453[PNG, Image]), (node676324952[])]
Next tool: add_title
Previous tool: generate_font
Tool add_title
Input data: [(node579870453[PNG, Image]), (node173380607[String, Color]), (node1695080704[String, FontFamily]), (node1548883689[String, Content])]
Output data [(node579871414[PNG, Image]), (node676325913[])]
Next tool:
Previous tool: add_small_border
OUTPUT:[(node579871414[PNG, Image])]
APE as a Web plug-in
Note
The following documentation is for APE 2.3.0.
Use APE-executable.jar
.
Tag information
Tag Types
Tags can have the following type enumerations:
Type |
Description |
---|---|
|
A path to a file |
|
A path to a folder |
|
URI of the ontology file |
|
One integer with boundaries |
|
Two integers with boundaries |
|
Yes/No, True/False |
|
A setting |
|
Root names of the data dimensions |
|
Data instances based on the data dimensions |
|
A class from the ontology (in this case a tool) |
Info by JSON
Request information about the (run)configuration fields in JSON format.
Note that "type"
is one of the enumerations mentioned above:
JSONObject tag_info = APERunConfig.TAGS.toJSON();
System.out.println(tag_info.toString(2));
This results in the following (partial) JSON:
{"tags": [
{
"default": true,
"description": "",
"optional": true,
"tag": "shared_memory",
"label": "Use shared memory",
"type": "BOOLEAN"
},
{
"description": "",
"optional": false,
"tag": "solutions",
"label": "Maximum number of solutions",
"type": "INTEGER",
"constraints": {
"min": 0,
"max": 2147483647
}
},
{
"default": "ONE",
"description": "",
"optional": true,
"tag": "use_all_generated_data",
"label": "Use all generated data",
"type": "ENUM",
"constraints": {"options": [
"NONE",
"ONE",
"ALL"
]}
}
]}
tags[] (JSONArray)
├── tag (String)
├── label (String)
├── description (String)
├── type (String)
├── optional (Boolean)
├──? default (Type) (depending on `optional` and `type`)
└──? constraints (JSONObject) (depending on `type`)
├──? min (int) (depending on `type`)
├──? max (int) (depending on `type`)
└──? options (String[]) (depending on `type`)
Info by API
Request information about the (run)configuration fields by calling TAGS statically.
This will return a list of Info
’s that can be queried. At the moment,
constraints.tags
returns a JSONObject and can contain the following tags:
min
, min
, options
.
for(APEConfigTag.Info<?> tag : APERunConfig.TAGS.getAll()){
if(tag.type == APEConfigTag.TagType.INTEGER){
System.out.printf("`%s` needs a value from %s to %s\n",
tag.label,
tag.constraints.getInt("min"),
tag.constraints.getInt("max")
);
}
else if(tag.type == APEConfigTag.TagType.ENUM){
JSONArray arr = tag.constraints.getJSONArray("options");
String[] options = new String[arr.length()];
for(int i = 0; i < arr.length(); i++){
options[i] = arr.get(i).toString();
}
System.out.printf("`%s` needs a setting from this list: %s\n",
tag.label,
Arrays.toString(options)
);
}
else if(tag.type == APEConfigTag.TagType.FILE_PATH){
System.out.printf("`%s` needs a file.\n", tag.label);
}
}
`Constraints` needs a file.
`Maximum number of solutions` needs a value from 0 to 2147483647
`Number of executions scripts` needs a value from 0 to 2147483647
`Number of generated graphs` needs a value from 0 to 2147483647
`Use workflow input` needs a setting from this list: [NONE, ONE, ALL]
`Use all generated data` needs a setting from this list: [NONE, ONE, ALL]
Evaluating a configuration object
Use APERunConfig
and APECoreConfig
statically to check if
your configuration file is correct.
In this first example, the number of solutions "-10"
is
not checked as it is not part of the core configuration setup.
JSONObject config = ..;
config.put("tool_annotations_path", "does/not/exist.json");
config.put("solutions", "-10");
ValidationResults results = APECoreConfig.validate(config);
System.out.println("Configuration file is correct: " + results.success());
for(ValidationResult result : results.getFails()){
System.out.println(result.getTag() + ": " + result.getRuleDescription());
}
Configuration file is correct: false
tool_annotations_path: Provided path 'does/not/exist.json' for tag 'tool_annotations_path' does not exist.
To check the run configuration tags, you will need a valid framework instance of APE
,
because the run configuration setup is based on a valid domain.
JSONObject config = ..;
config.put("solutions", "-10");
ValidationResults results = APECoreConfig.validate(config);
System.out.println("Core configuration file is correct: " + results.success());
APE framework = new APE(config);
results = APERunConfig.validate(config, framework.getDomainSetup());
System.out.println("Run configuration file is correct: " + results.success());
for(ValidationResult result : results.getFails()){
System.out.println(result.getTag() + ": " + result.getRuleDescription());
}
Core configuration file is correct: true
Run configuration file is correct: false
solutions: The maximum number of generated solutions should be greater or equal to 0.
To make things easier, you could also call APE
statically
to check both the run and core configuration setup.
JSONObject config = ..;
config.put("solutions", "-10");
ValidationResults results = APE.validate(config);
System.out.println("Configuration file is correct: " + results.success());
for(ValidationResult result : results.getFails()){
System.out.println(result.getTag() + ": " + result.getRuleDescription());
}
Configuration file is correct: false
solutions: The maximum number of generated solutions should be greater or equal to 0.