diff --git a/pom.xml b/pom.xml index 4ba3ce8500a387d3918c6485775fdb346426a4e8..71f538e311e61860f506d47fa82eac78d591d1a8 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>beamline</groupId> <artifactId>framework</artifactId> - <version>0.0.1-SNAPSHOT</version> + <version>0.0.1</version> <properties> <maven.compiler.source>11</maven.compiler.source> @@ -49,29 +49,15 @@ <artifactId>org.eclipse.paho.client.mqttv3</artifactId> <version>1.2.0</version> </dependency> - <dependency> - <groupId>com.github.beamline</groupId> - <artifactId>graphviz</artifactId> - <version>0.0.2</version> - </dependency> - <dependency> <groupId>io.reactivex.rxjava3</groupId> <artifactId>rxjava</artifactId> <version>3.1.3</version> </dependency> - <dependency> - <groupId>com.opencsv</groupId> - <artifactId>opencsv</artifactId> - <version>5.5</version> - </dependency> - - - <dependency> - <groupId>org.apache.commons</groupId> - <artifactId>commons-lang3</artifactId> - <version>3.10</version> + <groupId>com.github.beamline</groupId> + <artifactId>graphviz</artifactId> + <version>0.0.2</version> </dependency> </dependencies> </project> \ No newline at end of file diff --git a/src/main/java/beamline/miners/DiscoveryMiner.java b/src/main/java/beamline/miners/DiscoveryMiner.java deleted file mode 100644 index f853ae17e50ca068db01fd4fc0584e1e793aa609..0000000000000000000000000000000000000000 --- a/src/main/java/beamline/miners/DiscoveryMiner.java +++ /dev/null @@ -1,94 +0,0 @@ -package beamline.miners; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; -import org.deckfour.xes.extension.std.XConceptExtension; -import org.deckfour.xes.model.XTrace; - -import beamline.models.algorithms.StreamMiningAlgorithm; - -public class DiscoveryMiner extends StreamMiningAlgorithm<XTrace, ProcessMap> { - - private Map<String, String> latestActivityInCase = new HashMap<String, String>(); - private Map<Pair<String, String>, Double> relations = new HashMap<Pair<String, String>, Double>(); - private Map<String, Double> activities = new HashMap<String, Double>(); - private Double maxActivityFreq = Double.MIN_VALUE; - private Double maxRelationsFreq = Double.MIN_VALUE; - private double minDependency = 1d; - private int modelRefreshRate = 0; - - public DiscoveryMiner() { - - } - - public void setMinDependency(double minDependency) { - this.minDependency = minDependency; - } - - public void setModelRefreshRate(int modelRefreshRate) { - this.modelRefreshRate = modelRefreshRate; - } - - @Override - public ProcessMap ingest(XTrace event) { - String caseID = XConceptExtension.instance().extractName(event); - String activityName = XConceptExtension.instance().extractName(event.get(0)); - - Double activityFreq = 1d; - if (activities.containsKey(activityName)) { - activityFreq += activities.get(activityName); - maxActivityFreq = Math.max(maxActivityFreq, activityFreq); - } - activities.put(activityName, activityFreq); - - if (latestActivityInCase.containsKey(caseID)) { - Pair<String, String> relation = new ImmutablePair<String, String>(latestActivityInCase.get(caseID), activityName); - Double relationFreq = 1d; - if (relations.containsKey(relation)) { - relationFreq += relations.get(relation); - maxRelationsFreq = Math.max(maxRelationsFreq, relationFreq); - } - relations.put(relation, relationFreq); - } - latestActivityInCase.put(caseID, activityName); - - if (getProcessedEvents() % modelRefreshRate == 0) { - setLatestResponse(mine(minDependency)); - } - - return getLatestResponse(); - } - - public ProcessMap mine(double threshold) { - ProcessMap process = new ProcessMap(); - for (String activity : activities.keySet()) { - process.addActivity(activity, activities.get(activity) / maxActivityFreq); - } - for (Pair<String, String> relation : relations.keySet()) { - double dependency = relations.get(relation) / maxRelationsFreq; - if (dependency >= threshold) { - process.addRelation(relation.getLeft(), relation.getRight(), dependency); - } - } - Set<String> toRemove = new HashSet<String>(); - Set<String> selfLoopsToRemove = new HashSet<String>(); - for (String activity : activities.keySet()) { - if (process.isStartActivity(activity) && process.isEndActivity(activity)) { - toRemove.add(activity); - } - if (process.isIsolatedNode(activity)) { - selfLoopsToRemove.add(activity); - } - } - for (String activity : toRemove) { - process.removeActivity(activity); - } - - return process; - } -} diff --git a/src/main/java/beamline/miners/ProcessMap.java b/src/main/java/beamline/miners/ProcessMap.java deleted file mode 100644 index cd0fa7c95ff8587fbbaae4cb7e5b3d4385702a82..0000000000000000000000000000000000000000 --- a/src/main/java/beamline/miners/ProcessMap.java +++ /dev/null @@ -1,93 +0,0 @@ -package beamline.miners; - -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; - -import beamline.graphviz.Dot; -import beamline.models.responses.GraphvizResponse; -import beamline.view.graph.PMDotModel; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -public class ProcessMap implements GraphvizResponse { - - private Map<String, Double> activities; - private Map<Pair<String, String>, Double> relations; - - @Override - public Dot generateDot() { - return new PMDotModel(this, beamline.view.graph.ColorPalette.Colors.BLUE); - } - - public ProcessMap() { - this.activities = new HashMap<String, Double>(); - this.relations = new HashMap<Pair<String, String>, Double>(); - } - - public void addActivity(String activityName, Double value) { - this.activities.put(activityName, value); - } - - public void removeActivity(String activityName) { - this.activities.remove(activityName); - } - - public void addRelation(String activitySource, String activityTarget, Double value) { - relations.put(new ImmutablePair<String, String>(activitySource, activityTarget), value); - } - - public void removeRelation(String activitySource, String activityTarget) { - relations.remove(new ImmutablePair<String, String>(activitySource, activityTarget)); - } - - public Set<String> getActivities() { - return activities.keySet(); - } - - public Set<Pair<String, String>> getRelations() { - return relations.keySet(); - } - - public Double getActivityValue(String activity) { - return this.activities.get(activity); - } - - public Double getRelationValue(Pair<String, String> relation) { - return this.relations.get(relation); - } - - public Set<String> getIncomingActivities(String candidate) { - Set<String> result = new HashSet<String>(); - for (Pair<String, String> relation : getRelations()) { - if (relation.getRight().equals(candidate)) { - result.add(relation.getLeft()); - } - } - return result; - } - - public Set<String> getOutgoingActivities(String candidate) { - Set<String> result = new HashSet<String>(); - for (Pair<String, String> relation : getRelations()) { - if (relation.getLeft().equals(candidate)) { - result.add(relation.getRight()); - } - } - return result; - } - - public boolean isStartActivity(String candidate) { - return getIncomingActivities(candidate).size() == 0; - } - - public boolean isEndActivity(String candidate) { - return getOutgoingActivities(candidate).size() == 0; - } - - public boolean isIsolatedNode(String candidate) { - return getOutgoingActivities(candidate).equals(getIncomingActivities(candidate)); - } -} \ No newline at end of file diff --git a/src/main/java/beamline/tester/Tester.java b/src/main/java/beamline/tester/Tester.java deleted file mode 100644 index 50c6a4e3b25ad79c3936d45d025eb20c04740c2a..0000000000000000000000000000000000000000 --- a/src/main/java/beamline/tester/Tester.java +++ /dev/null @@ -1,72 +0,0 @@ -package beamline.tester; - -import java.io.File; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import org.deckfour.xes.extension.std.XConceptExtension; -import org.deckfour.xes.extension.std.XTimeExtension; -import org.deckfour.xes.in.XParser; -import org.deckfour.xes.in.XesXmlParser; -import org.deckfour.xes.model.XEvent; -import org.deckfour.xes.model.XLog; -import org.deckfour.xes.model.XTrace; - -import beamline.filters.ExcludeActivitiesFilter; -import beamline.filters.RetainActivitiesFilter; -import beamline.miners.DiscoveryMiner; -import beamline.miners.ProcessMap; -import beamline.models.algorithms.HookEventProcessing; -import beamline.models.algorithms.StreamMiningAlgorithm; -import beamline.sources.XesLogSource; -import beamline.sources.XesSource; -import io.reactivex.rxjava3.annotations.NonNull; -import io.reactivex.rxjava3.core.Observable; -import io.reactivex.rxjava3.core.ObservableEmitter; -import io.reactivex.rxjava3.core.ObservableOnSubscribe; -import io.reactivex.rxjava3.functions.Consumer; -import io.reactivex.rxjava3.functions.Function; -import io.reactivex.rxjava3.functions.Predicate; -import jdk.jshell.execution.StreamingExecutionControl; - -public class Tester { - - public static void main(String[] args) throws Exception { - System.out.println("start"); - - XParser p = new XesXmlParser(); - XLog l = p.parse(new File("C:\\Users\\andbur\\Desktop\\input.xes")).get(0); - XesSource source = new XesLogSource(l); -// XesSource source = new MQTTXESSource(broker, topic, process); - source.prepare(); - - DiscoveryMiner miner = new DiscoveryMiner(); - miner.setMinDependency(0.3); - miner.setModelRefreshRate(1); - - Observable<XTrace> obs = source.getObservable(); - obs -// .filter(new RetainActivitiesFilter("A", "B", "C", "dummy-retain")) -// .filter(new ExcludeActivitiesFilter("A", "dummy-exclude")) -// .map(new DirectSuccessionMapper()) -// .combine(new SlidingWindow(1000)) -// .map(new Miner(1, 0.5)) - .subscribe(miner); -// .subscribe(new Consumer<XTrace>() { -// @Override -// public void accept(@NonNull XTrace t) throws Throwable { -// System.out.println( -// XConceptExtension.instance().extractName(t) + " - " + -// XConceptExtension.instance().extractName(t.get(0)) + " - " + -// XTimeExtension.instance().extractTimestamp(t.get(0)) -// ); -// } -// }); - - miner.getLatestResponse().generateDot().exportToSvg(new File("C:\\Users\\andbur\\Desktop\\output.svg")); - - System.out.println("done"); - } - -} diff --git a/src/main/java/beamline/view/graph/ColorPalette.java b/src/main/java/beamline/view/graph/ColorPalette.java deleted file mode 100644 index 9ef89866dc71d0ed5fc01dc3cfab5883ecff5666..0000000000000000000000000000000000000000 --- a/src/main/java/beamline/view/graph/ColorPalette.java +++ /dev/null @@ -1,58 +0,0 @@ -package beamline.view.graph; - -import java.awt.Color; - -// see https://content.linkedin.com/content/dam/brand/site/img/color/color-palette-order.png -public class ColorPalette { - - public enum Colors { - BLUE ("#CFEDFB", "#0B4971"), - VIOLET("#F0E3EF", "#593482"), - RED ("#FFE2D2", "#98041B"), - ORANGE("#FFEBB6", "#933304"), - AQUA ("#D2ECEB", "#0E5C68"), - YELLOW("#FAF0B5", "#856A1D"), - PINK ("#FBE2ED", "#951343"), - GREEN ("#E5EFC7", "#3F652D"), - GRAY ("#E0E2E4", "#3A3C3E"), - DARK_GRAY("#86888A", "#252526"); - - public Color min; - public Color max; - - Colors(String min, String max) { - this.min = Color.decode(min); - this.max = Color.decode(max); - } - } - - public static Color getValue(Colors base, double value) { - float rMin = base.min.getRed() / 255f; - float gMin = base.min.getGreen() / 255f; - float bMin = base.min.getBlue() / 255f; - - float rMax = base.max.getRed() / 255f; - float gMax = base.max.getGreen() / 255f; - float bMax = base.max.getBlue() / 255f; - - float rOwn = (float) (rMin + (rMax - rMin) * value); - float gOwn = (float) (gMin + (gMax - gMin) * value); - float bOwn = (float) (bMin + (bMax - bMin) * value); - - rOwn = (rOwn > 1f)? 1 : (rOwn < 0? 0 : rOwn); - gOwn = (gOwn > 1f)? 1 : (gOwn < 0? 0 : gOwn); - bOwn = (bOwn > 1f)? 1 : (bOwn < 0? 0 : bOwn); - - return new Color(rOwn, gOwn, bOwn); - } - - public static Color getFontColor(Color background) { - double a = 1 - - (0.299 * background.getRed() + 0.587 * background.getGreen() + 0.114 * background.getBlue()) / 255; - return a < 0.5 ? Color.BLACK : Color.WHITE; - } - - public static String colorToString(Color color) { - return String.format("#%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue()); - } -} \ No newline at end of file diff --git a/src/main/java/beamline/view/graph/PMDotEdge.java b/src/main/java/beamline/view/graph/PMDotEdge.java deleted file mode 100644 index 345a6d4a6152b1ef8e5b1e1a6152db06c0ae221e..0000000000000000000000000000000000000000 --- a/src/main/java/beamline/view/graph/PMDotEdge.java +++ /dev/null @@ -1,47 +0,0 @@ -package beamline.view.graph; - -import beamline.graphviz.DotEdge; -import beamline.graphviz.DotNode; - -public class PMDotEdge extends DotEdge { - - public PMDotEdge(DotNode source, DotNode target, String edgeText, Double weight) { - super(source, target); - - setOption("decorate", "false"); - setOption("fontsize", "8"); - setOption("arrowsize", "0.5"); - setOption("fontname", "Arial"); - setOption("tailclip", "false"); - - if (edgeText != null) { - setLabel(" " + edgeText); - } - - if (weight != null) { - setOption("color", - ColorPalette.colorToString(ColorPalette.getValue(ColorPalette.Colors.DARK_GRAY, weight))); - if ((source instanceof PMDotStartNode) || (target instanceof PMDotEndNode)) { - setOption("penwidth", "" + (1 + (5 * weight))); - } else { - setOption("penwidth", "" + (1 + (8 * weight))); - } - } else { - if ((source instanceof PMDotStartNode) || (target instanceof PMDotEndNode)) { - setOption("penwidth", "2"); - } else { - setOption("penwidth", "3"); - } - } - - if (source instanceof PMDotStartNode) { - setOption("style", "dashed"); - setOption("color", "#ACB89C"); - } - - if (target instanceof PMDotEndNode) { - setOption("style", "dashed"); - setOption("color", "#C2B0AB"); - } - } -} \ No newline at end of file diff --git a/src/main/java/beamline/view/graph/PMDotEndNode.java b/src/main/java/beamline/view/graph/PMDotEndNode.java deleted file mode 100644 index bec9f8fc313e2105361b73ab7452d98e0e1e3ede..0000000000000000000000000000000000000000 --- a/src/main/java/beamline/view/graph/PMDotEndNode.java +++ /dev/null @@ -1,22 +0,0 @@ -package beamline.view.graph; - -import beamline.graphviz.DotNode; - -public class PMDotEndNode extends DotNode { - public PMDotEndNode() { - super("", null); - - setOption("shape", "circle"); - setOption("style", "filled"); - setOption("fillcolor", "#D8BBB9"); // #D8BBB9:#BC9F9D - setOption("gradientangle", "270"); - setOption("color", "#614847"); - setOption("height", "0.13"); - setOption("width", "0.13"); - } - - @Override - public String toString() { - return "{ rank = \"sink\"; " + super.toString() + "}"; - } -} \ No newline at end of file diff --git a/src/main/java/beamline/view/graph/PMDotModel.java b/src/main/java/beamline/view/graph/PMDotModel.java deleted file mode 100644 index 69e292ca32298deb453c4355a9eb73f5a47c74a5..0000000000000000000000000000000000000000 --- a/src/main/java/beamline/view/graph/PMDotModel.java +++ /dev/null @@ -1,123 +0,0 @@ -package beamline.view.graph; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - - -import org.apache.commons.lang3.tuple.Pair; - -import beamline.graphviz.Dot; -import beamline.graphviz.DotNode; -import beamline.miners.ProcessMap; - - -/** - * - * @author Andrea Burattin - */ -public class PMDotModel extends Dot { - - private ProcessMap model; - private ColorPalette.Colors activityColor; - - public PMDotModel(ProcessMap model, ColorPalette.Colors activityColor) { - this.model = model; - this.activityColor = activityColor; - - realize(); - } - - private void realize() { -// setOption("rankdir", "LR"); - setOption("ranksep", ".1"); - setOption("fontsize", "9"); - setOption("remincross", "true"); - setOption("margin", "0.0,0.0"); - setOption("outputorder", "edgesfirst"); - - Map<String, DotNode> activityToNode = new HashMap<String, DotNode>(); - Map<String, String> nodeToActivity = new HashMap<String, String>(); - - Set<DotNode> startNodes = new HashSet<DotNode>(); - Set<DotNode> endNodes = new HashSet<DotNode>(); - - // add all activities - for(String activity : model.getActivities()) { - DotNode node = addNodeIfNeeded(activity, activityToNode, nodeToActivity); - if (node instanceof PMDotNode) { - ((PMDotNode) node).setColorWeight(model.getActivityValue(activity), activityColor); - } - if (model.isStartActivity(activity)) { - startNodes.add(node); - } - if (model.isEndActivity(activity)) { - endNodes.add(node); - } - } - - // add all relations - for (Pair<String, String> relation : model.getRelations()) { - String sourceActivity = relation.getLeft(); - String targetActivity = relation.getRight(); - - // adding source nodes - DotNode sourceNode = addNodeIfNeeded(sourceActivity, activityToNode, nodeToActivity); - // adding target nodes - DotNode targetNode = addNodeIfNeeded(targetActivity, activityToNode, nodeToActivity); - - // adding relations - addRelation(sourceNode, targetNode, model.getRelationValue(relation)); - } - - // add relations from start and end - if (startNodes.size() > 0) { - PMDotStartNode start = new PMDotStartNode(); - addNode(start); - for (DotNode n : startNodes) { - addRelation(start, n, null); - } - } - if (endNodes.size() > 0) { - PMDotEndNode end = new PMDotEndNode(); - addNode(end); - for (DotNode n : endNodes) { - addRelation(n, end, null); - } - } - } - - private void addRelation(DotNode sourceNode, DotNode targetNode, Double value) { - addEdge(new PMDotEdge(sourceNode, targetNode, (value == null? null : String.format("%.2g%n", value)), value)); - } - - private DotNode addNodeIfNeeded(String activity, Map<String, DotNode> activityToNode, Map<String, String> nodeToActivity) { - DotNode existingNode = activityToNode.get(activity); - if (existingNode == null) { -// if (model.isStartActivity(activity)) { -// PMCEPDotStartNode startNode = new PMCEPDotStartNode(); -// addNode(startNode); -// activityToNode.put(activity, startNode); -// nodeToActivity.put(startNode.getId(), activity); -// return startNode; -// } else if (model.isEndActivity(activity)) { -// PMCEPDotEndNode endNode = new PMCEPDotEndNode(); -// addNode(endNode); -// activityToNode.put(activity, endNode); -// nodeToActivity.put(endNode.getId(), activity); -// return endNode; -// } else { - PMDotNode newNode = new PMDotNode(activity.toString()); - newNode.setColorWeight(model.getActivityValue(activity), activityColor); - newNode.setSecondLine(String.format("%.2g%n", model.getActivityValue(activity))); - addNode(newNode); - activityToNode.put(activity, newNode); - nodeToActivity.put(newNode.getId(), activity); - return newNode; -// } - } else { - return existingNode; - } - } -} \ No newline at end of file diff --git a/src/main/java/beamline/view/graph/PMDotNode.java b/src/main/java/beamline/view/graph/PMDotNode.java deleted file mode 100644 index 2626ef6ebc76acfa6adeb4be63cf1563d735739a..0000000000000000000000000000000000000000 --- a/src/main/java/beamline/view/graph/PMDotNode.java +++ /dev/null @@ -1,68 +0,0 @@ -package beamline.view.graph; - -import java.awt.Color; - -import beamline.graphviz.DotNode; - -public class PMDotNode extends DotNode { - - private String label; - - public PMDotNode(String label) { - this(label, null, null, null); - } - - public PMDotNode(String label, String secondLine, Double weight, ColorPalette.Colors activityColor) { - super(label, null); - - this.label = label; - - setOption("shape", "box"); - setOption("fixedsize", "true"); - setOption("height", "0.23"); - setOption("width", "1.2"); - setOption("style", "rounded,filled"); - setOption("fontname", "Arial"); - - setSecondLine(secondLine); - setColorWeight(weight, activityColor); - } - - public void setSecondLine(String secondLine) { - if (secondLine != null) { - setLabel("<<font point-size='22'>" + label + "</font> <br/><font point-size='16'>" + secondLine - + "</font>>"); - } - } - - public void setColorWeight(Double weight, ColorPalette.Colors activityColor) { - if (weight == null) { - setOption("fillcolor", "#FDEFD8"); // #FDEFD8:#E1D3BC - } else { - Color backgroundColor = ColorPalette.getValue(activityColor, weight); - Color fontColor = ColorPalette.getFontColor(backgroundColor); - setOption("fillcolor", ColorPalette - .colorToString(backgroundColor)/* + ":" + ColorPalette.colorToString(backgroundColor.darker()) */); - setOption("fontcolor", ColorPalette.colorToString(fontColor)); - setOption("fixedsize", "false"); - } - } - - public void setMovedIn() { - setOption("fillcolor", "white"); - } - - public void setMovedOut() { - setOption("fillcolor", "black"); - } - - @Override - public int hashCode() { - return getLabel().hashCode(); - } - - @Override - public boolean equals(Object object) { - return getLabel().equals(object); - } -} \ No newline at end of file diff --git a/src/main/java/beamline/view/graph/PMDotStartNode.java b/src/main/java/beamline/view/graph/PMDotStartNode.java deleted file mode 100644 index 690b8fa81aa4d8f7f59d5a1417961eae7919590b..0000000000000000000000000000000000000000 --- a/src/main/java/beamline/view/graph/PMDotStartNode.java +++ /dev/null @@ -1,22 +0,0 @@ -package beamline.view.graph; - -import beamline.graphviz.DotNode; - -public class PMDotStartNode extends DotNode { - public PMDotStartNode() { - super("", null); - - setOption("shape", "circle"); - setOption("style", "filled"); - setOption("fillcolor", "#CED6BD"); // #CED6BD:#B3BBA2 - setOption("gradientangle", "270"); - setOption("color", "#595F45"); - setOption("height", "0.13"); - setOption("width", "0.13"); - } - - @Override - public String toString() { - return "{ rank = \"source\"; " + super.toString() + " }"; - } -} \ No newline at end of file