Skip to content

Commit

Permalink
Merge pull request #29 from sanctuuary/taverna_workflow_design
Browse files Browse the repository at this point in the history
Introduce the Taverna workflow design
  • Loading branch information
vedran-kasalica authored Nov 19, 2023
2 parents 3bc6b3a + 468b906 commit 1ba85d2
Show file tree
Hide file tree
Showing 15 changed files with 502 additions and 247 deletions.
15 changes: 6 additions & 9 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This CITATION.cff file was generated with cffinit.
# Visit https://bit.ly/cffinit to generate yours today!
cff-version: 1.2.0
title: RESTful APE
title: 'RESTful APE'
message: >-
If you use this software, please cite it using the
metadata from this file.
Expand All @@ -16,22 +16,22 @@ authors:
given-names: Kok
email: [email protected]
affiliation: Netherlands eScience Center
orcid: https://orcid.org/0000-0002-6630-7326
orcid: 'https://orcid.org/0000-0002-6630-7326'
- family-names: Nauman
given-names: Ahmed
email: [email protected]
affiliation: Netherlands eScience Center
orcid: https://orcid.org/0000-0003-3559-9941
orcid: 'https://orcid.org/0000-0003-3559-9941'
- family-names: Anna-Lena
given-names: Lamprecht
email: vanna[email protected]
email: anna[email protected]
affiliation: University of Potsdam
orcid: https://orcid.org/0000-0003-1953-5606
orcid: 'https://orcid.org/0000-0003-1953-5606'
- family-names: Magnus
given-names: Palmblad
email: [email protected]
affiliation: Leiden University Medical Center
orcid: https://orcid.org/0000-0002-5865-8994
orcid: 'https://orcid.org/0000-0002-5865-8994'
identifiers:
- type: doi
value: 10.5281/zenodo.10048235
Expand Down Expand Up @@ -61,6 +61,3 @@ keywords:
- automated workflow composition
- RESTful API
license: Apache-2.0
commit: 2567159c68716c08e30f466a7079299e76216108
version: 0.3.0
date-released: '2023-10-28'
9 changes: 3 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</parent>
<groupId>nl.esciencecenter</groupId>
<artifactId>restape</artifactId>
<version>0.3.0</version>
<version>0.2.5</version>
<name>restape</name>
<description>RESTful API for the APE library</description>
<licenses>
Expand Down Expand Up @@ -89,16 +89,13 @@
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.2.220</version>
<version>2.2.224</version>
<scope>runtime</scope>
</dependency>



<dependency>
<groupId>io.github.sanctuuary</groupId>
<artifactId>APE</artifactId>
<version>2.1.8</version>
<version>2.2.2</version>
</dependency>

<dependency>
Expand Down
35 changes: 18 additions & 17 deletions src/main/java/nl/esciencecenter/models/BioToolsBenchmark.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import nl.esciencecenter.restape.ToolBenchmarkingAPIs;

@RequiredArgsConstructor
/**
Expand All @@ -20,7 +21,7 @@ public class BioToolsBenchmark {
@NonNull
private BenchmarkBase benchmarkTitle;
private String value;
private double Desirability_value;
private double desirabilityValue;
private List<WorkflowStepBench> workflow;

private static boolean emptyToolAnnotation(JSONObject toolAnnot) {
Expand Down Expand Up @@ -48,9 +49,9 @@ public static BioToolsBenchmark countEntries(List<JSONObject> biotoolsAnnotation
int workflowLength = biotoolsAnnotations.size();

benchmark.workflow = countEntries(biotoolsAnnotations);
int count = (int) benchmark.workflow.stream().filter(tool -> tool.getDesirability_value() > 0).count();
int count = (int) benchmark.workflow.stream().filter(tool -> tool.getDesirabilityValue() > 0).count();

benchmark.Desirability_value = strictDistribution(count, workflowLength);
benchmark.desirabilityValue = strictDistribution(count, workflowLength);
benchmark.value = ratioString(count, workflowLength);

return benchmark;
Expand All @@ -62,9 +63,9 @@ public static BioToolsBenchmark countLicencedEntries(List<JSONObject> biotoolsAn
int workflowLength = biotoolsAnnotations.size();

benchmark.workflow = countField(biotoolsAnnotations, benchmarkTitle.getExpectedField());
int count = (int) benchmark.workflow.stream().filter(tool -> tool.getDesirability_value() > 0).count();
int count = (int) benchmark.workflow.stream().filter(tool -> tool.getDesirabilityValue() > 0).count();

benchmark.Desirability_value = strictDistribution(count, workflowLength);
benchmark.desirabilityValue = strictDistribution(count, workflowLength);
benchmark.value = ratioString(count, workflowLength);

return benchmark;
Expand All @@ -77,9 +78,9 @@ public static BioToolsBenchmark countOSEntries(List<JSONObject> biotoolsAnnotati

benchmark.workflow = countArrayFieldVal(biotoolsAnnotations, benchmarkTitle.getExpectedField(),
benchmarkTitle.getExpectedValue());
int count = (int) benchmark.workflow.stream().filter(tool -> tool.getDesirability_value() > 0).count();
int count = (int) benchmark.workflow.stream().filter(tool -> tool.getDesirabilityValue() > 0).count();

benchmark.Desirability_value = normalDistribution(count, workflowLength);
benchmark.desirabilityValue = normalDistribution(count, workflowLength);

benchmark.value = ratioString(count, workflowLength);

Expand All @@ -97,12 +98,12 @@ private static List<WorkflowStepBench> countEntries(List<JSONObject> biotoolsAnn

biotoolsAnnotations.stream().forEach(toolAnnot -> {
WorkflowStepBench biotoolsEntryBenchmark = new WorkflowStepBench();
biotoolsEntryBenchmark.setDescription(toolAnnot.getString("toolID"));
biotoolsEntryBenchmark.setDescription(toolAnnot.getString(ToolBenchmarkingAPIs.restAPEtoolID));
if (emptyToolAnnotation(toolAnnot)) {
biotoolsEntryBenchmark.setDesirability_value(0);
biotoolsEntryBenchmark.setDesirabilityValue(0);
biotoolsEntryBenchmark.setValue("unavailable");
} else {
biotoolsEntryBenchmark.setDesirability_value(1);
biotoolsEntryBenchmark.setDesirabilityValue(1);
biotoolsEntryBenchmark.setValue("available");
}
biotoolsEntries.add(biotoolsEntryBenchmark);
Expand All @@ -124,12 +125,12 @@ private static List<WorkflowStepBench> countField(List<JSONObject> biotoolsAnnot

biotoolsAnnotations.stream().forEach(toolAnnot -> {
WorkflowStepBench biotoolsEntryBenchmark = new WorkflowStepBench();
biotoolsEntryBenchmark.setDescription(toolAnnot.getString("toolID"));
biotoolsEntryBenchmark.setDescription(toolAnnot.getString(ToolBenchmarkingAPIs.restAPEtoolID));
if (!inAvailable(toolAnnot, fieldName)) {
biotoolsEntryBenchmark.setDesirability_value(0);
biotoolsEntryBenchmark.setDesirabilityValue(0);
biotoolsEntryBenchmark.setValue("not available");
} else {
biotoolsEntryBenchmark.setDesirability_value(1);
biotoolsEntryBenchmark.setDesirabilityValue(1);
biotoolsEntryBenchmark.setValue("available");
}
biotoolsEntries.add(biotoolsEntryBenchmark);
Expand All @@ -153,12 +154,12 @@ private static List<WorkflowStepBench> countArrayFieldVal(List<JSONObject> bioto

biotoolsAnnotations.stream().forEach(toolAnnot -> {
WorkflowStepBench biotoolsEntryBenchmark = new WorkflowStepBench();
biotoolsEntryBenchmark.setDescription(toolAnnot.getString("toolID"));
biotoolsEntryBenchmark.setDescription(toolAnnot.getString(ToolBenchmarkingAPIs.restAPEtoolID));
if (!inStringArray(toolAnnot, fieldName, fieldValue)) {
biotoolsEntryBenchmark.setDesirability_value(0);
biotoolsEntryBenchmark.setDesirabilityValue(0);
biotoolsEntryBenchmark.setValue("not supported");
} else {
biotoolsEntryBenchmark.setDesirability_value(1);
biotoolsEntryBenchmark.setDesirabilityValue(1);
biotoolsEntryBenchmark.setValue("supported");
}
biotoolsEntries.add(biotoolsEntryBenchmark);
Expand Down Expand Up @@ -216,7 +217,7 @@ public JSONObject getJson() {
JSONObject benchmarkJson = this.benchmarkTitle.getTitleJson();

benchmarkJson.put("value", value);
benchmarkJson.put("desirability_value", Desirability_value);
benchmarkJson.put("desirability_value", desirabilityValue);
benchmarkJson.put("workflow", workflow);
return benchmarkJson;
}
Expand Down
35 changes: 35 additions & 0 deletions src/main/java/nl/esciencecenter/models/OpenEBenchmark.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package nl.esciencecenter.models;

import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import nl.esciencecenter.restape.ToolBenchmarkingAPIs;

@RequiredArgsConstructor
/**
* Class representing the design-time benchmarks for a workflow obtained from
* bio.tools API.
*/
public class OpenEBenchmark {

@NonNull
private BenchmarkBase benchmarkTitle;
private String value;
private double desirabilityValue;
private List<WorkflowStepBench> workflow;

public JSONObject getJson() {
JSONObject benchmarkJson = this.benchmarkTitle.getTitleJson();

benchmarkJson.put("value", value);
benchmarkJson.put("desirability_value", desirabilityValue);
benchmarkJson.put("workflow", workflow);
return benchmarkJson;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ public class WorkflowStepBench {
@NonNull
private String value;
@NonNull
private double desirability_value;
private double desirabilityValue;

@Override
public String toString() {
return "{ description:" + description + ", value:" + value + ", desirability_value:"
+ desirabilityValue + "]";
}

}
114 changes: 5 additions & 109 deletions src/main/java/nl/esciencecenter/restape/ApeAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,12 @@
import nl.uu.cs.ape.configuration.APECoreConfig;
import nl.uu.cs.ape.configuration.APERunConfig;
import nl.uu.cs.ape.constraints.ConstraintTemplate;
import nl.uu.cs.ape.core.solutionStructure.SolutionWorkflow;
import nl.uu.cs.ape.core.solutionStructure.SolutionsList;
import nl.uu.cs.ape.io.APEFiles;
import nl.uu.cs.ape.models.AllModules;
import nl.uu.cs.ape.models.AllPredicates;
import nl.uu.cs.ape.models.AllTypes;
import nl.uu.cs.ape.models.logic.constructs.TaxonomyPredicate;
import nl.uu.cs.ape.solver.solutionStructure.SolutionWorkflow;
import nl.uu.cs.ape.solver.solutionStructure.SolutionsList;
import nl.uu.cs.ape.utils.APEUtils;

import org.apache.commons.io.FileUtils;
Expand All @@ -32,6 +31,7 @@
import com.oracle.truffle.regex.tregex.util.json.JsonObject;

import guru.nidi.graphviz.attribute.Rank.RankDir;
import guru.nidi.graphviz.engine.Format;
import lombok.NoArgsConstructor;
import lombok.AccessLevel;

Expand Down Expand Up @@ -168,120 +168,16 @@ public static JSONArray runSynthesis(JSONObject configJson, boolean benchmark)

// Write solutions (as CWL files and figures) to the file system.
APE.writeCWLWorkflows(candidateSolutions);
APE.writeDataFlowGraphs(candidateSolutions, RankDir.TOP_TO_BOTTOM);
APE.writeTavernaDesignGraphs(candidateSolutions, Format.PNG);

// benchmark workflows if required
if (benchmark) {
computeBenchmarks(candidateSolutions, runID);
ToolBenchmarkingAPIs.computeBenchmarks(candidateSolutions, runID);
}

return workflowMetadataToJson(candidateSolutions, runID, benchmark);
}

/**
* Compute the benchmarks for the workflows.
*
* @param candidateSolutions - SolutionsList object, which contains the results
* of the synthesis as well as information about the
* synthesis run.
* @return - boolean to indicate if the benchmarks were computed successfully
*/
private static boolean computeBenchmarks(SolutionsList candidateSolutions, String runID) {
candidateSolutions.getParallelStream().forEach(workflow -> {
JSONObject workflowBenchmarks = computeBiotoolsBenchmark(workflow, runID);
String titleBenchmark = workflow.getFileName() + ".json";
Path solFolder = candidateSolutions.getRunConfiguration().getSolutionDirPath2CWL();
File script = solFolder.resolve(titleBenchmark).toFile();
try {
APEFiles.write2file(workflowBenchmarks.toString(2), script, false);
} catch (JSONException | IOException e) {
e.printStackTrace();
}

});

return true;
}

/**
* TODO: Delete
* Method reads the benchmark file and returns the JSON object.
*
* @param relativePath - relative path to the benchmark file
* @return - JSON object with the benchmark
*/
public static JSONObject getDummyBenchmark() {
String content;
try {
content = FileUtils.readFileToString(APEFiles.readPathToFile(
"https://raw.githubusercontent.com/sanctuuary/restape/d11a5f6f0f6de48361f383ba956040fbb5e90e54/src/main/resources/designtime_bench_v2.json"),
StandardCharsets.UTF_8);
return new JSONObject(content);
} catch (IOException e) {
e.printStackTrace();
return new JSONObject();
}

}

/**
* Compute the benchmarks for the workflows and return it in JSON format.
*
* @param workflow
* @return
*/
private static JSONObject computeBiotoolsBenchmark(SolutionWorkflow workflow, String runID) {
JSONObject benchmarkResult = new JSONObject();

// for each tool in the workflow, get the biotools annotations from bio.tool API
List<JSONObject> biotoolsAnnotations = new ArrayList<>();

workflow.getModuleNodes().forEach(toolNode -> {
String toolID = toolNode.getUsedModule().getPredicateLabel();
try {

JSONObject biotoolsEntry = BioTools.fetchToolFromBioTools(toolID);
biotoolsEntry.put("toolID", toolNode.getUsedModule().getPredicateLabel());
biotoolsAnnotations.add(biotoolsEntry);
} catch (JSONException | IOException e) {
JSONObject biotoolsEntry = new JSONObject();
biotoolsEntry.put("toolID", toolNode.getUsedModule().getPredicateLabel());
biotoolsAnnotations.add(biotoolsEntry);
e.printStackTrace();
}
});

// Set workflow specific fields
benchmarkResult.put("runID", runID);
benchmarkResult.put("domainID", "1");
benchmarkResult.put("workflowName", workflow.getFileName());

JSONArray benchmarks = new JSONArray();

BenchmarkBase bioToolBenchmark = new BenchmarkBase("bio.tool", "Available in bio.tools",
"Number of tools annotated in bio.tools.", null, null);
BenchmarkBase licensedBenchmark = new BenchmarkBase("Licensed", "Tools with a license",
"Number of tools which have a license specified.", "license", null);
BenchmarkBase linuxBenchmark = new BenchmarkBase("Linux", "Linux (OS) supported tools",
"Number of tools which support Linux OS.", "operatingSystem", "Linux");
BenchmarkBase macOSBenchmark = new BenchmarkBase("Mac OS", "Mac OS supported tools",
"Number of tools which support Mac OS.", "operatingSystem", "Mac");
BenchmarkBase windowsBenchmark = new BenchmarkBase("Windows", "Windows (OS) supported tools",
"Number of tools which support Windows OS.", "operatingSystem", "Windows");

benchmarks.put(BioToolsBenchmark.countEntries(biotoolsAnnotations, bioToolBenchmark).getJson());
benchmarks.put(BioToolsBenchmark.countLicencedEntries(biotoolsAnnotations, licensedBenchmark).getJson());
benchmarks.put(BioToolsBenchmark.countOSEntries(biotoolsAnnotations, linuxBenchmark).getJson());

benchmarks.put(BioToolsBenchmark.countOSEntries(biotoolsAnnotations, macOSBenchmark).getJson());
benchmarks.put(BioToolsBenchmark.countOSEntries(biotoolsAnnotations, windowsBenchmark).getJson());

benchmarkResult.put("benchmarks", benchmarks);

return benchmarkResult;

}

/**
*
* Method to execute the synthesis of workflows using the APE framework.
Expand Down
Loading

0 comments on commit 1ba85d2

Please sign in to comment.