From e14d040f5440bc2b86807df227a64eb7b81748ec Mon Sep 17 00:00:00 2001 From: tvheems Date: Mon, 5 Jun 2017 18:01:02 +0200 Subject: [PATCH 01/28] color encoded first base of a segment into the nodes which is compatible with zooming --- src/main/java/datastructure/NodeGraph.java | 24 +++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/main/java/datastructure/NodeGraph.java b/src/main/java/datastructure/NodeGraph.java index d35e9a5..5a65407 100644 --- a/src/main/java/datastructure/NodeGraph.java +++ b/src/main/java/datastructure/NodeGraph.java @@ -196,7 +196,7 @@ public void generateDrawNodes(int center, int radius) { addEdges(current, q, visited); drawNode = new DrawNode(current); drawNode.setWidth(nodes.get(current).getLength()); - drawNode.setFill(Color.CRIMSON); + colorDrawNode(drawNode); drawNode.setHeight(10); drawNodes.addLast(drawNode); } @@ -622,7 +622,7 @@ public Pair, LinkedList> addAtRoot() { nodes.get(newNodes.get(i).getIndex()).computeLength(); newNodes.get(i).setWidth(nodes.get(newNodes.get(i).getIndex()).getLength()); newNodes.get(i).setHeight(10); - newNodes.get(i).setFill(Color.CRIMSON); + colorDrawNode(newNodes.get(i)); newDrawNodes.add(newNodes.get(i)); } else { Node dummyIn = nodes.get(newNodes.get(i).getIndex()); @@ -688,7 +688,7 @@ public Pair, LinkedList> addAtLeaf() { nodes.get(newNodes.get(i).getIndex()).computeLength(); newNodes.get(i).setWidth(nodes.get(newNodes.get(i).getIndex()).getLength()); newNodes.get(i).setHeight(10); - newNodes.get(i).setFill(Color.CRIMSON); + colorDrawNode(newNodes.get(i)); newDrawNodes.add(newNodes.get(i)); } else { Node dummyOut = nodes.get(newNodes.get(i).getIndex()); @@ -814,4 +814,22 @@ protected LinkedList getRootNodes() { protected LinkedList getLeafNodes() { return leafNodes; } + + private void colorDrawNode(DrawNode drawNode) { + String segment = getSegment(drawNode.getIndex()).substring(0,1); + switch (segment) { + case "A": drawNode.setStroke(Color.CRIMSON); + break; + case "T": drawNode.setStroke(Color.BLUE); + break; + case "C": drawNode.setStroke(Color.CYAN); + break; + case "G": drawNode.setStroke(Color.YELLOW); + break; + default: drawNode.setStroke(Color.PURPLE); + break; + } + drawNode.setFill(Color.BLACK); + drawNode.setStrokeWidth(2.0); + } } From d0f82a94ef3d606829b5e1cb31980feff86c8e99 Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Tue, 6 Jun 2017 11:02:00 +0200 Subject: [PATCH 02/28] Add weight attribute to node corresponding to number of genome paths going through the node --- src/main/java/datastructure/Node.java | 22 ++++++++++++++++++++++ src/main/java/parsing/Parser.java | 18 +++++++++++++++--- src/main/java/screens/Window.java | 2 +- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/main/java/datastructure/Node.java b/src/main/java/datastructure/Node.java index 71b050a..2f69397 100644 --- a/src/main/java/datastructure/Node.java +++ b/src/main/java/datastructure/Node.java @@ -23,6 +23,12 @@ public class Node { */ private int[] from; + /** + * The ratio of the number of genome paths going through this nodes compared to the total number + * of genome paths. + */ + private double weight; + /** * Empty constructor for Node. */ @@ -163,4 +169,20 @@ public void computeLength() { public void setLength(int length) { this.length = length; } + + /** + * Getter for the weight of a node. + * @return the weight of a node. + */ + public double getWeight() { + return this.weight; + } + + /** + * Setter for the weight of a node. + * @param newWeight the new weight a node will be set to. + */ + public void setWeight(double newWeight) { + this.weight = newWeight; + } } diff --git a/src/main/java/parsing/Parser.java b/src/main/java/parsing/Parser.java index 138d4cf..8aa3e3b 100644 --- a/src/main/java/parsing/Parser.java +++ b/src/main/java/parsing/Parser.java @@ -5,6 +5,7 @@ import datastructure.SegmentDB; import javafx.application.Platform; import screens.Window; +import window.FileSelector; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -113,13 +114,14 @@ public NodeGraph parse(final File file, NodeGraph graph) { id = Integer.parseInt(line2.substring(0, line2.indexOf('\t'))) - 1; line2 = line2.substring(line2.indexOf('\t') + 1); segment = line2.substring(0, line2.indexOf('\t')); - graph.addNode(id, new Node(segment.length(), new int[0], new int[0])); + Node node = new Node(segment.length(), new int[0], new int[0]); + graph.addNode(id, node); out.write(segment + "\n"); out.flush(); line2 = line2.substring(line2.indexOf('\t') + 1); line2 = line2.substring(line2.indexOf('\t') + 1); String nodeGenomes = line2.substring(0, line2.indexOf('\t')); - addGenomes(gw, nodeGenomes); + node.setWeight(addGenomes(gw, nodeGenomes)); line2 = in.readLine(); lineCounter++; while (line2 != null && line2.startsWith("L")) { @@ -264,7 +266,7 @@ private void createCache(String filename, NodeGraph graph) { * @param gw Writer that writes the string. * @param str String with the genomes. */ - private void addGenomes(BufferedWriter gw, String str) { + private int addGenomes(BufferedWriter gw, String str) { str = str.substring(str.indexOf(':') + 1); str = str.substring(str.indexOf(':') + 1); String[] genomeTemp = str.split(";"); @@ -279,6 +281,7 @@ private void addGenomes(BufferedWriter gw, String str) { e.printStackTrace(); System.out.println("adding genomes failed"); } + return genomeTemp.length; } /** @@ -314,4 +317,13 @@ private void updateProgressBar(int lineCount, int nol) { public static Thread getThread() { return parser; } + + public void setWeights(NodeGraph ng) { + try { +// BufferedReader br = new BufferedReader(new FileInputStream()) + } catch (Exception e) { + System.out.println("Error when reading in genome cache"); + e.printStackTrace(); + } + } } diff --git a/src/main/java/screens/Window.java b/src/main/java/screens/Window.java index 661c7fb..7c27942 100644 --- a/src/main/java/screens/Window.java +++ b/src/main/java/screens/Window.java @@ -1,6 +1,7 @@ package screens; import datastructure.DrawNode; +import datastructure.Node; import datastructure.NodeGraph; import filesystem.FileSystem; import javafx.application.Application; @@ -214,7 +215,6 @@ private Menu addFileSelector(Stage stage) { if (file != null && file.exists()) { pB.setVisible(true); NodeGraph.setCurrentInstance(Parser.getInstance().parse(file)); - new Thread() { public void run () { try { From a80024321257b01a866c36f62b2f6dfc7b06070f Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Tue, 6 Jun 2017 11:40:41 +0200 Subject: [PATCH 03/28] Correctly set weights to nodes when parsing the files --- src/main/java/parsing/Parser.java | 31 +++++++++++++++++++++----- src/main/java/window/FileSelector.java | 4 ++-- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/main/java/parsing/Parser.java b/src/main/java/parsing/Parser.java index 8aa3e3b..2712dbb 100644 --- a/src/main/java/parsing/Parser.java +++ b/src/main/java/parsing/Parser.java @@ -34,6 +34,16 @@ public class Parser { */ private static Thread parser; + /** + * The name of the currently selected file. + */ + private String currentFile; + + /** + * The number of genome paths contained in the file. + */ + private double noOfGenomes; + /** * Constructor of the parser. */ @@ -58,7 +68,7 @@ public static Parser getInstance() { */ public NodeGraph parse(File file) { NodeGraph graph = new NodeGraph(); - + currentFile = file.getName().substring(0, file.getName().length() - 4); String cacheName = file.getAbsolutePath().substring(0, file.getAbsolutePath().length() - 4); graph.setSegmentDB(new SegmentDB(cacheName + "Segments.txt")); File cache = new File(cacheName + ".txt"); @@ -98,7 +108,7 @@ public NodeGraph parse(final File file, NodeGraph graph) { BufferedWriter out = new BufferedWriter(new FileWriter(segments)); BufferedWriter gw = new BufferedWriter(new FileWriter(genomes)); - addGenomes(gw, line); + noOfGenomes = (double) addGenomes(gw, line); parser = new Thread(() -> { try { @@ -121,7 +131,8 @@ public NodeGraph parse(final File file, NodeGraph graph) { line2 = line2.substring(line2.indexOf('\t') + 1); line2 = line2.substring(line2.indexOf('\t') + 1); String nodeGenomes = line2.substring(0, line2.indexOf('\t')); - node.setWeight(addGenomes(gw, nodeGenomes)); + node.setWeight(addGenomes(gw, nodeGenomes) / noOfGenomes); + System.out.println(node.getWeight()); line2 = in.readLine(); lineCounter++; while (line2 != null && line2.startsWith("L")) { @@ -189,6 +200,8 @@ public NodeGraph parseCache(NodeGraph graph, File cache) { int lineCounter = 0; try { int nol = getNumberOfLine(cache); + BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(FileSelector.getDirectory() + currentFile + "Genomes.txt"))); + noOfGenomes = Double.parseDouble(br.readLine().split("\t")[0]); for (int i = 0; i < graphSize; i++) { int length = Integer.parseInt(in.readLine()); int outLength = Integer.parseInt(in.readLine()); @@ -206,9 +219,10 @@ public NodeGraph parseCache(NodeGraph graph, File cache) { Node temp = new Node(length, outgoing, incoming); graph.addNodeCache(i, temp); lineCounter = lineCounter + 5; - + setWeights(br, temp); updateProgressBar(lineCounter, nol); } + br.close(); in.close(); } catch (IOException e) { e.printStackTrace(); @@ -318,9 +332,14 @@ public static Thread getThread() { return parser; } - public void setWeights(NodeGraph ng) { + /** + * Sets the weights of nodes when reading in from the cache file. + * @param br the reader that reads the cached file. + * @param node the node a weight is being set to. + */ + private void setWeights(BufferedReader br, Node node) { try { -// BufferedReader br = new BufferedReader(new FileInputStream()) + node.setWeight(Double.parseDouble(br.readLine().split("\t")[0]) / noOfGenomes); } catch (Exception e) { System.out.println("Error when reading in genome cache"); e.printStackTrace(); diff --git a/src/main/java/window/FileSelector.java b/src/main/java/window/FileSelector.java index 224fb9c..2e574aa 100644 --- a/src/main/java/window/FileSelector.java +++ b/src/main/java/window/FileSelector.java @@ -72,7 +72,7 @@ public static File showOpenDialog(Window ownerWindow) { } if (chosenFile != null) { - saveDirectory(chosenFile.getParentFile().getAbsolutePath()); + saveDirectory(chosenFile.getParentFile().getAbsolutePath() + "\\"); } return chosenFile; } @@ -81,7 +81,7 @@ public static File showOpenDialog(Window ownerWindow) { * Finds the last used directory from which a file was chosen. * @return the path of the directory. */ - private static String getDirectory() { + public static String getDirectory() { try { BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("directory.txt"))); String dir = br.readLine(); From 310570b5e43f6b5eaee26e3f44e135e1d3feab43 Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Tue, 6 Jun 2017 12:38:07 +0200 Subject: [PATCH 04/28] Update tests to be working again --- src/main/java/parsing/Parser.java | 5 +++-- src/main/java/screens/GraphScene.java | 7 +++++++ src/test/java/parsing/ParserTest.java | 9 +++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main/java/parsing/Parser.java b/src/main/java/parsing/Parser.java index 2712dbb..8a0d4ba 100644 --- a/src/main/java/parsing/Parser.java +++ b/src/main/java/parsing/Parser.java @@ -132,7 +132,6 @@ public NodeGraph parse(final File file, NodeGraph graph) { line2 = line2.substring(line2.indexOf('\t') + 1); String nodeGenomes = line2.substring(0, line2.indexOf('\t')); node.setWeight(addGenomes(gw, nodeGenomes) / noOfGenomes); - System.out.println(node.getWeight()); line2 = in.readLine(); lineCounter++; while (line2 != null && line2.startsWith("L")) { @@ -200,7 +199,9 @@ public NodeGraph parseCache(NodeGraph graph, File cache) { int lineCounter = 0; try { int nol = getNumberOfLine(cache); - BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(FileSelector.getDirectory() + currentFile + "Genomes.txt"))); + String path = cache.getAbsolutePath(); + path = path.substring(0, path.length() - 4); + BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(path + "Genomes.txt"))); noOfGenomes = Double.parseDouble(br.readLine().split("\t")[0]); for (int i = 0; i < graphSize; i++) { int length = Integer.parseInt(in.readLine()); diff --git a/src/main/java/screens/GraphScene.java b/src/main/java/screens/GraphScene.java index ed80bfd..badbfbc 100644 --- a/src/main/java/screens/GraphScene.java +++ b/src/main/java/screens/GraphScene.java @@ -328,4 +328,11 @@ public INodeHandler getInfo() { return this.info; } + private void determineEdgeWidth(Node incNode) { + double outgoingWeight = 0; + for (Integer i : incNode.getOutgoingEdges()) { + NodeGraph.getCurrentInstance().getNode(i); + } + } + } diff --git a/src/test/java/parsing/ParserTest.java b/src/test/java/parsing/ParserTest.java index f8d5162..4b2f0c3 100644 --- a/src/test/java/parsing/ParserTest.java +++ b/src/test/java/parsing/ParserTest.java @@ -145,6 +145,7 @@ public void parseCache() { String workingDirectory = System.getProperty("user.dir"); String absoluteFilePath = workingDirectory + File.separator; File file = new File(absoluteFilePath + "/src/test/resources/testCache.txt"); + File file2 = new File(absoluteFilePath + "/src/test/resources/testCacheGenomes.txt"); try { BufferedWriter bw = new BufferedWriter(new FileWriter(file)); bw.write("4\n" + @@ -169,6 +170,13 @@ public void parseCache() { "2\n" + "1\t2"); bw.close(); + BufferedWriter bw2 = new BufferedWriter(new FileWriter(file2)); + bw2.write("3\n" + + "1\n" + + "1\n" + + "3\n" + + "2\n"); + bw2.close(); NodeGraph graph = new NodeGraph(); Node node1 = new Node(); Node node2 = new Node(); @@ -200,6 +208,7 @@ public void parseCache() { } file.delete(); + file2.delete(); assertEquals(graph.getSize(), testGraph.getSize()); Node testNode1; Node testNode2; From f7dd36edda0a09982ce20de8975b27b24eb5c83c Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Wed, 7 Jun 2017 15:13:20 +0200 Subject: [PATCH 05/28] Edge thickness gets set to edges --- src/main/java/parsing/Parser.java | 25 ++++++++++-- src/main/java/screens/GraphScene.java | 59 +++++++++++++++++++++++---- src/main/java/screens/Window.java | 3 +- 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/src/main/java/parsing/Parser.java b/src/main/java/parsing/Parser.java index dedc86a..8683376 100644 --- a/src/main/java/parsing/Parser.java +++ b/src/main/java/parsing/Parser.java @@ -43,6 +43,11 @@ public class Parser { */ private double noOfGenomes; + /** + * All paths of the genomes specified in the file. + */ + private static int[][] paths; + /** * Constructor of the parser. */ @@ -215,6 +220,7 @@ public NodeGraph parseCache(NodeGraph graph, File cache) { path = path.substring(0, path.length() - 4); BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(path + "Genomes.txt"))); noOfGenomes = Double.parseDouble(br.readLine().split("\t")[0]); + paths = new int[graphSize][]; for (int i = 0; i < graphSize; i++) { int length = Integer.parseInt(in.readLine()); int outLength = Integer.parseInt(in.readLine()); @@ -232,7 +238,7 @@ public NodeGraph parseCache(NodeGraph graph, File cache) { Node temp = new Node(length, outgoing, incoming); graph.addNodeCache(i, temp); lineCounter = lineCounter + 5; - setWeights(br, temp); + setWeights(br, temp, i); updateProgressBar(lineCounter, nol); } br.close(); @@ -358,9 +364,14 @@ public static Thread getThread() { * @param br the reader that reads the cached file. * @param node the node a weight is being set to. */ - private void setWeights(BufferedReader br, Node node) { + private void setWeights(BufferedReader br, Node node, int id) { try { - node.setWeight(Double.parseDouble(br.readLine().split("\t")[0]) / noOfGenomes); + String[] line = br.readLine().split("\\t"); + node.setWeight(Double.parseDouble(line[0]) / noOfGenomes); + paths[id] = new int[Integer.parseInt(line[0])]; + for (int i = 1; i < line.length; i++) { + paths[id][i - 1] = Integer.parseInt(line[i]); + } } catch (Exception e) { System.out.println("Error when reading in genome cache"); e.printStackTrace(); @@ -412,4 +423,12 @@ private boolean determineBasis(String line, String[] allGenomes) { } return result; } + + public static int[][] getPaths() { + return paths; + } + + public double getNoOfGenomes() { + return noOfGenomes; + } } diff --git a/src/main/java/screens/GraphScene.java b/src/main/java/screens/GraphScene.java index badbfbc..2a31bb7 100644 --- a/src/main/java/screens/GraphScene.java +++ b/src/main/java/screens/GraphScene.java @@ -8,6 +8,7 @@ import javafx.event.EventHandler; import javafx.scene.input.MouseEvent; import javafx.scene.layout.Pane; +import javafx.scene.paint.Color; import javafx.scene.shape.Line; import parsing.Parser; import javafx.scene.shape.Rectangle; @@ -105,6 +106,8 @@ private void drawGraphUtil(int center, int radius) { LinkedList drawNodes = nodeGraph.getDrawNodes(); LinkedList dummyNodes = nodeGraph.getDummyNodes(); for (DrawNode dNode : drawNodes) { + int count = 0; + double[] widths = determineEdgeWidth(NodeGraph.getCurrentInstance().getNode(dNode.getIndex()), dNode.getIndex()); dNode.setX(dNode.getX() - dNode.getWidth() / 2); dNode.setOnMousePressed(click); Platform.runLater(() -> this.getChildren().add(dNode)); @@ -112,11 +115,11 @@ private void drawGraphUtil(int center, int radius) { for (int i : nodes.get(dNode.getIndex()).getOutgoingEdges()) { nOut = nodeGraph.getDrawNode(i); if (nOut != null && nOut.getBoundsInLocal().getMinX() - dNode.getBoundsInLocal().getMaxX() <= 100) { - drawLine(dNode.getIndex() + "-" + i, 2, dNode.getBoundsInLocal().getMaxX(), dNode.getBoundsInLocal().getMinY() + 5, nOut.getBoundsInLocal().getMinX(), nOut.getBoundsInLocal().getMinY() + 5); + drawLine(dNode.getIndex() + "-" + i, 5 * widths[count] / Parser.getInstance().getNoOfGenomes(), dNode.getBoundsInLocal().getMaxX(), dNode.getBoundsInLocal().getMinY() + 5, nOut.getBoundsInLocal().getMinX(), nOut.getBoundsInLocal().getMinY() + 5); } + count += 1; } } - DummyNode current; DummyNode current2; DrawNode dN; @@ -282,7 +285,7 @@ private void removeNodesLeaf(double maxX) { private void drawLine(String id, double width, double startX, double startY, double endX, double endY) { Line l = new Line(); l.setId(id); - l.setStrokeWidth(width); + l.setStrokeWidth(Math.ceil(width)); l.setStartX(startX); l.setStartY(startY); l.setEndX(endX); @@ -328,11 +331,53 @@ public INodeHandler getInfo() { return this.info; } - private void determineEdgeWidth(Node incNode) { - double outgoingWeight = 0; - for (Integer i : incNode.getOutgoingEdges()) { - NodeGraph.getCurrentInstance().getNode(i); + private double[] determineEdgeWidth(Node incNode, int id) { + NodeGraph ng = NodeGraph.getCurrentInstance(); + int[] outgoing = incNode.getOutgoingEdges(); + double[] widths = new double[outgoing.length]; + int[][] paths = Parser.getPaths(); + int maxInt = -1; + double maxX = -Double.MAX_VALUE; + for (int i = 0; i < outgoing.length; i++) { + double outgoingWeight = 0; + DrawNode out = ng.getDrawNode(outgoing[i]); + if (out != null && out.getX() > maxX) { + maxX = out.getX(); + maxInt = i; + } + for (int j = 0; j < paths[id].length; j++) { + for (int k = 0; k < paths[outgoing[i]].length; k++) { + if (paths[id][j] == paths[outgoing[i]][k]) { + outgoingWeight += 1; + } + } + } + widths[i] = outgoingWeight; + } + if (maxInt == -1) { + return widths; + } + int[] incoming = ng.getNode(outgoing[maxInt]).getIncomingEdges(); + if (incoming.length < 2 || outgoing.length < 2) { + return widths; + } + maxX = ng.getDrawNode(id).getX(); + for (int i = 0; i < incoming.length; i++) { + DrawNode dNode = ng.getDrawNode(incoming[i]); + if (dNode != null && Math.abs(maxX - dNode.getX()) >= 5.00001) { + for (int j = 0; j < paths[outgoing[maxInt]].length; j++) { + for (int k = 0; k < paths[incoming[i]].length; k++) { + if (paths[outgoing[maxInt]][j] == paths[incoming[i]][k]) { + widths[maxInt] -= 1; + } + } + } + } } +// for (int i = 0; i < widths.length; i++) { +// System.out.println(id + " " + widths[i] + " " + incNode.getOutgoingEdges()[i]); +// } + return widths; } } diff --git a/src/main/java/screens/Window.java b/src/main/java/screens/Window.java index 7c27942..6a84511 100644 --- a/src/main/java/screens/Window.java +++ b/src/main/java/screens/Window.java @@ -1,10 +1,10 @@ package screens; import datastructure.DrawNode; -import datastructure.Node; import datastructure.NodeGraph; import filesystem.FileSystem; import javafx.application.Application; +import javafx.application.Platform; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.Button; @@ -18,6 +18,7 @@ import javafx.scene.layout.BorderPane; import javafx.scene.layout.GridPane; import javafx.scene.paint.Color; +import javafx.scene.shape.Line; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; import javafx.stage.StageStyle; From 2304b2d4f77df9b5e488998c619956216253aa32 Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Wed, 7 Jun 2017 16:36:57 +0200 Subject: [PATCH 06/28] Refactor code used for edge thickness for a code base of better quality --- src/main/java/parsing/Parser.java | 40 ++++--------- .../{NavigationInfo.java => GraphInfo.java} | 60 +++++++++++++++---- src/main/java/screens/GraphScene.java | 52 +++++++++------- 3 files changed, 87 insertions(+), 65 deletions(-) rename src/main/java/screens/{NavigationInfo.java => GraphInfo.java} (50%) diff --git a/src/main/java/parsing/Parser.java b/src/main/java/parsing/Parser.java index 8683376..1ca2a35 100644 --- a/src/main/java/parsing/Parser.java +++ b/src/main/java/parsing/Parser.java @@ -4,6 +4,7 @@ import datastructure.NodeGraph; import datastructure.SegmentDB; import javafx.application.Platform; +import screens.GraphInfo; import screens.Window; import java.io.BufferedReader; @@ -33,21 +34,6 @@ public class Parser { */ private static Thread parser; - /** - * The name of the currently selected file. - */ - private String currentFile; - - /** - * The number of genome paths contained in the file. - */ - private double noOfGenomes; - - /** - * All paths of the genomes specified in the file. - */ - private static int[][] paths; - /** * Constructor of the parser. */ @@ -72,7 +58,6 @@ public static Parser getInstance() { */ public NodeGraph parse(File file) { NodeGraph graph = new NodeGraph(); - currentFile = file.getName().substring(0, file.getName().length() - 4); String cacheName = file.getAbsolutePath().substring(0, file.getAbsolutePath().length() - 4); graph.setSegmentDB(new SegmentDB(cacheName + "Segments.txt")); File cache = new File(cacheName + ".txt"); @@ -219,8 +204,8 @@ public NodeGraph parseCache(NodeGraph graph, File cache) { String path = cache.getAbsolutePath(); path = path.substring(0, path.length() - 4); BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(path + "Genomes.txt"))); - noOfGenomes = Double.parseDouble(br.readLine().split("\t")[0]); - paths = new int[graphSize][]; + GraphInfo.getInstance().setGenomesNum(Double.parseDouble(br.readLine().split("\t")[0])); + int[][] paths = new int[graphSize][]; for (int i = 0; i < graphSize; i++) { int length = Integer.parseInt(in.readLine()); int outLength = Integer.parseInt(in.readLine()); @@ -238,9 +223,10 @@ public NodeGraph parseCache(NodeGraph graph, File cache) { Node temp = new Node(length, outgoing, incoming); graph.addNodeCache(i, temp); lineCounter = lineCounter + 5; - setWeights(br, temp, i); + setWeights(br, temp, i, paths); updateProgressBar(lineCounter, nol); } + GraphInfo.getInstance().setPaths(paths); br.close(); in.close(); } catch (IOException e) { @@ -301,8 +287,8 @@ private void createCache(String filename, NodeGraph graph) { * @param hasInt true iff the genomes displayed as integers instead of names. * @param genomeList list of all genomes in the gfa file. * @throws IOException when the writer can't write to the file. + * @return the number of genome paths going through the node. */ - private int addGenomes(BufferedWriter gw, String str, boolean hasInt, String[] genomeList) throws IOException { str = str.substring(str.indexOf(':') + 1); str = str.substring(str.indexOf(':') + 1); @@ -363,11 +349,13 @@ public static Thread getThread() { * Sets the weights of nodes when reading in from the cache file. * @param br the reader that reads the cached file. * @param node the node a weight is being set to. + * @param id the id of the node. + * @param paths the paths of the genomes per node. */ - private void setWeights(BufferedReader br, Node node, int id) { + private void setWeights(BufferedReader br, Node node, int id, int[][] paths) { try { String[] line = br.readLine().split("\\t"); - node.setWeight(Double.parseDouble(line[0]) / noOfGenomes); + node.setWeight(Double.parseDouble(line[0]) / GraphInfo.getInstance().getGenomesNum()); paths[id] = new int[Integer.parseInt(line[0])]; for (int i = 1; i < line.length; i++) { paths[id][i - 1] = Integer.parseInt(line[i]); @@ -423,12 +411,4 @@ private boolean determineBasis(String line, String[] allGenomes) { } return result; } - - public static int[][] getPaths() { - return paths; - } - - public double getNoOfGenomes() { - return noOfGenomes; - } } diff --git a/src/main/java/screens/NavigationInfo.java b/src/main/java/screens/GraphInfo.java similarity index 50% rename from src/main/java/screens/NavigationInfo.java rename to src/main/java/screens/GraphInfo.java index bb0a05f..fc5ac52 100644 --- a/src/main/java/screens/NavigationInfo.java +++ b/src/main/java/screens/GraphInfo.java @@ -3,7 +3,7 @@ /** * Class that can store information about the current state on the drawn graph used for navigation. */ -public final class NavigationInfo { +public final class GraphInfo { /** * The radius of the currently drawn graph. @@ -15,32 +15,36 @@ public final class NavigationInfo { */ private int currentCenterNode; - private double xOffset; + /** + * The number of genomes paths that are specified. + */ + private double genomeNum; - private double yOffset; + /** + * All specified genome paths per node. + */ + private int[][] paths; /** - * A singleton instance of NavigationInfo. + * A singleton instance of GraphInfo. */ - private static NavigationInfo instance; + private static GraphInfo instance; /** * Constructor for the information. */ - private NavigationInfo() { + private GraphInfo() { this.currentCenterNode = 0; this.currentRadius = 200; - this.xOffset = 0; - this.yOffset = 0; } /** - * Getter for the instance of the NavigationInfo. - * @return the currrent instance of the NavigationInfo. + * Getter for the instance of the GraphInfo. + * @return the currrent instance of the GraphInfo. */ - public static NavigationInfo getInstance() { + public static GraphInfo getInstance() { if (instance == null) { - instance = new NavigationInfo(); + instance = new GraphInfo(); } return instance; } @@ -76,4 +80,36 @@ public void setCurrentRadius(int radius) { public void setCurrentCenterNode(int id) { this.currentCenterNode = id; } + + /** + * Setter for the number of genome paths specified in the file. + * @param num the number of genome paths specified in the file. + */ + public void setGenomesNum(double num) { + this.genomeNum = num; + } + + /** + * Getter for the number of genome paths specified in the file. + * @return the number of genome paths specified in the file. + */ + public double getGenomesNum() { + return this.genomeNum; + } + + /** + * Setter for the genome paths of the file. + * @param newPaths the genome paths to set. + */ + public void setPaths(int[][] newPaths) { + this.paths = newPaths; + } + + /** + * Getter for the genome paths of the file. + * @return the genome paths of the file per node. + */ + public int[][] getPaths() { + return this.paths; + } } diff --git a/src/main/java/screens/GraphScene.java b/src/main/java/screens/GraphScene.java index 2a31bb7..98fd1cf 100644 --- a/src/main/java/screens/GraphScene.java +++ b/src/main/java/screens/GraphScene.java @@ -8,7 +8,6 @@ import javafx.event.EventHandler; import javafx.scene.input.MouseEvent; import javafx.scene.layout.Pane; -import javafx.scene.paint.Color; import javafx.scene.shape.Line; import parsing.Parser; import javafx.scene.shape.Rectangle; @@ -115,7 +114,7 @@ private void drawGraphUtil(int center, int radius) { for (int i : nodes.get(dNode.getIndex()).getOutgoingEdges()) { nOut = nodeGraph.getDrawNode(i); if (nOut != null && nOut.getBoundsInLocal().getMinX() - dNode.getBoundsInLocal().getMaxX() <= 100) { - drawLine(dNode.getIndex() + "-" + i, 5 * widths[count] / Parser.getInstance().getNoOfGenomes(), dNode.getBoundsInLocal().getMaxX(), dNode.getBoundsInLocal().getMinY() + 5, nOut.getBoundsInLocal().getMinX(), nOut.getBoundsInLocal().getMinY() + 5); + drawLine(dNode.getIndex() + "-" + i, 5 * widths[count] / GraphInfo.getInstance().getGenomesNum(), dNode.getBoundsInLocal().getMaxX(), dNode.getBoundsInLocal().getMinY() + 5, nOut.getBoundsInLocal().getMinX(), nOut.getBoundsInLocal().getMinY() + 5); } count += 1; } @@ -331,28 +330,25 @@ public INodeHandler getInfo() { return this.info; } + /** + * Determine the number of genome paths going through an edge. + * @param incNode the node edges will be drawn from. + * @param id the id of the node. + * @return An array with the number of paths going through each outgoing edge of the node. + */ private double[] determineEdgeWidth(Node incNode, int id) { NodeGraph ng = NodeGraph.getCurrentInstance(); int[] outgoing = incNode.getOutgoingEdges(); double[] widths = new double[outgoing.length]; - int[][] paths = Parser.getPaths(); int maxInt = -1; double maxX = -Double.MAX_VALUE; for (int i = 0; i < outgoing.length; i++) { - double outgoingWeight = 0; DrawNode out = ng.getDrawNode(outgoing[i]); if (out != null && out.getX() > maxX) { maxX = out.getX(); maxInt = i; } - for (int j = 0; j < paths[id].length; j++) { - for (int k = 0; k < paths[outgoing[i]].length; k++) { - if (paths[id][j] == paths[outgoing[i]][k]) { - outgoingWeight += 1; - } - } - } - widths[i] = outgoingWeight; + widths[i] = getNumberOfDupes(id, outgoing[i]); } if (maxInt == -1) { return widths; @@ -364,20 +360,30 @@ private double[] determineEdgeWidth(Node incNode, int id) { maxX = ng.getDrawNode(id).getX(); for (int i = 0; i < incoming.length; i++) { DrawNode dNode = ng.getDrawNode(incoming[i]); - if (dNode != null && Math.abs(maxX - dNode.getX()) >= 5.00001) { - for (int j = 0; j < paths[outgoing[maxInt]].length; j++) { - for (int k = 0; k < paths[incoming[i]].length; k++) { - if (paths[outgoing[maxInt]][j] == paths[incoming[i]][k]) { - widths[maxInt] -= 1; - } - } - } + if (dNode != null && Math.abs(maxX - dNode.getX()) >= 5) { + widths[maxInt] -= getNumberOfDupes(outgoing[maxInt], incoming[i]); } } -// for (int i = 0; i < widths.length; i++) { -// System.out.println(id + " " + widths[i] + " " + incNode.getOutgoingEdges()[i]); -// } return widths; } + /** + * Get the number of paths going through node with id that also go through node outId. + * @param id the id of the node an edge will be drawn from. + * @param outId the id of the node an edge with be drawn to. + * @return the number of paths going through both nodes. + */ + private int getNumberOfDupes(int id, int outId) { + int count = 0; + int[][] paths = GraphInfo.getInstance().getPaths(); + for (int j = 0; j < paths[id].length; j++) { + for (int k = 0; k < paths[outId].length; k++) { + if (paths[id][j] == paths[outId][k]) { + count += 1; + } + } + } + return count; + } + } From 83202c7dfa338ca7e3473ab41d79108dfffcd204 Mon Sep 17 00:00:00 2001 From: tvheems Date: Wed, 7 Jun 2017 16:42:33 +0200 Subject: [PATCH 07/28] Drawnodes now have strokes of colors. --- src/main/java/datastructure/NodeGraph.java | 46 ++++++++++++---------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/main/java/datastructure/NodeGraph.java b/src/main/java/datastructure/NodeGraph.java index 5a65407..b37ca8c 100644 --- a/src/main/java/datastructure/NodeGraph.java +++ b/src/main/java/datastructure/NodeGraph.java @@ -7,6 +7,9 @@ import java.util.Iterator; import java.util.ListIterator; import javafx.scene.paint.Color; +import javafx.scene.paint.CycleMethod; +import javafx.scene.paint.LinearGradient; +import javafx.scene.paint.Stop; import javafx.util.Pair; @@ -196,7 +199,6 @@ public void generateDrawNodes(int center, int radius) { addEdges(current, q, visited); drawNode = new DrawNode(current); drawNode.setWidth(nodes.get(current).getLength()); - colorDrawNode(drawNode); drawNode.setHeight(10); drawNodes.addLast(drawNode); } @@ -205,6 +207,9 @@ public void generateDrawNodes(int center, int radius) { computeDummyNodes(); verticalSpacing(); retrieveEdgeNodes(); + for (DrawNode drawNode1 : drawNodes) { + colorDrawNode(drawNode1, new Color[]{Color.RED, Color.GREEN, Color.BLUE, Color.CYAN}); + } } /** @@ -259,7 +264,7 @@ private LinkedList newTopoSort(LinkedList dNodes) { } /** - * Recursive method for topological sorting + * Recursive method for topological sorting. * @param current current node. * @param sorted current list of sorted nodes. * @param dNodes current list of nodes to be sorted. @@ -314,7 +319,6 @@ private void assignLayers() { for (int i : nodes.get(current.getIndex()).getOutgoingEdges()) { for (int j = 0; j < size; j++) { DrawNode temp = drawNodes.get(j); - int ind2 = temp.getIndex(); if (temp.getIndex() == i && temp.getX() < layer) { layer = temp.getX(); } @@ -622,7 +626,7 @@ public Pair, LinkedList> addAtRoot() { nodes.get(newNodes.get(i).getIndex()).computeLength(); newNodes.get(i).setWidth(nodes.get(newNodes.get(i).getIndex()).getLength()); newNodes.get(i).setHeight(10); - colorDrawNode(newNodes.get(i)); + colorDrawNode(newNodes.get(i), new Color[]{Color.RED, Color.GREEN}); newDrawNodes.add(newNodes.get(i)); } else { Node dummyIn = nodes.get(newNodes.get(i).getIndex()); @@ -688,7 +692,7 @@ public Pair, LinkedList> addAtLeaf() { nodes.get(newNodes.get(i).getIndex()).computeLength(); newNodes.get(i).setWidth(nodes.get(newNodes.get(i).getIndex()).getLength()); newNodes.get(i).setHeight(10); - colorDrawNode(newNodes.get(i)); + colorDrawNode(newNodes.get(i), new Color[]{Color.RED, Color.GREEN}); newDrawNodes.add(newNodes.get(i)); } else { Node dummyOut = nodes.get(newNodes.get(i).getIndex()); @@ -756,7 +760,7 @@ public double removeAtRoot() { * @return the x-coordinate of the leaf nodes to be deleted. */ public double removeAtLeaf() { - ArrayList visited = new ArrayList();; + ArrayList visited = new ArrayList(); for (Double id : leafNodes) { if (id >= 0) { for (int m : NodeGraph.getCurrentInstance().getNodes().get(id.intValue()).getIncomingEdges()) { @@ -815,21 +819,21 @@ protected LinkedList getLeafNodes() { return leafNodes; } - private void colorDrawNode(DrawNode drawNode) { - String segment = getSegment(drawNode.getIndex()).substring(0,1); - switch (segment) { - case "A": drawNode.setStroke(Color.CRIMSON); - break; - case "T": drawNode.setStroke(Color.BLUE); - break; - case "C": drawNode.setStroke(Color.CYAN); - break; - case "G": drawNode.setStroke(Color.YELLOW); - break; - default: drawNode.setStroke(Color.PURPLE); - break; - } + /** + * Colors the node in even strokes. + * @param drawNode the node to be colored. + * @param colors the colors of the strokes. + */ + private void colorDrawNode(DrawNode drawNode, Color[] colors) { drawNode.setFill(Color.BLACK); - drawNode.setStrokeWidth(2.0); + Stop[] stops = new Stop[colors.length * 2]; + double offset = 1 / (double) colors.length; + + for (int i = 0; i < colors.length; i++) { + stops[2 * i] = new Stop((i * offset), colors[i]); + stops[(2 * i) + 1] = new Stop(((i + 1) * offset), colors[i]); + } + LinearGradient lg1 = new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE, stops); + drawNode.setFill(lg1); } } From 6d45b670bf971ca381f46bb14f1d8b2fb966b873 Mon Sep 17 00:00:00 2001 From: tvheems Date: Wed, 7 Jun 2017 18:58:34 +0200 Subject: [PATCH 08/28] Add skeleton of conditions. --- src/main/java/datastructure/Condition.java | 35 ++++++++++++ .../datastructure/GenomeCountCondition.java | 54 +++++++++++++++++++ .../java/datastructure/RegexCondition.java | 31 +++++++++++ 3 files changed, 120 insertions(+) create mode 100644 src/main/java/datastructure/Condition.java create mode 100644 src/main/java/datastructure/GenomeCountCondition.java create mode 100644 src/main/java/datastructure/RegexCondition.java diff --git a/src/main/java/datastructure/Condition.java b/src/main/java/datastructure/Condition.java new file mode 100644 index 0000000..842c574 --- /dev/null +++ b/src/main/java/datastructure/Condition.java @@ -0,0 +1,35 @@ +package datastructure; + + +import javafx.scene.paint.Color; + +/** + * Created by 101010. + */ +public abstract class Condition { + /** + * The color to be painted when condition holds. + */ + private Color color; + + /** + * Default constructor. + */ + public Condition(){} + + /** + *Constructor of the condition + * @param color the color of this condition. + */ + public Condition(Color color) { + this.color = color; + } + /** + * Derives if condition holds. + * @param drawNode the node to derive condition on. + * @return true iff the condition holds. + */ + public abstract boolean addColor(DrawNode drawNode); + + +} diff --git a/src/main/java/datastructure/GenomeCountCondition.java b/src/main/java/datastructure/GenomeCountCondition.java new file mode 100644 index 0000000..61d3dd0 --- /dev/null +++ b/src/main/java/datastructure/GenomeCountCondition.java @@ -0,0 +1,54 @@ +package datastructure; + +/** + * Created by 101010. + */ +public class GenomeCountCondition extends Condition{ + + /** + * The decision number of the condition. + */ + private int decisionNumber; + + /** + * True iff condition is greater than. + */ + private boolean greater; + + /** + * True iff condition in equal. + */ + private boolean equal; + + + /** + * Constructor of the condition + * @param decisionNumber the number that decides the condition. + * @param greater true iff condition is greater than the decisionNumber. + * @param equal true iff condition is equal to the decisionNumber. + */ + public GenomeCountCondition(int decisionNumber, boolean greater, boolean equal) { + this.decisionNumber = decisionNumber; + this.greater = greater; + this.equal = equal; + } + + @Override + public boolean addColor(DrawNode drawNode) { + int genomes = drawNode.getGenomes().length; + if (greater) { + if (equal) { + return decisionNumber >= genomes; + } else { + return decisionNumber > genomes; + } + } else { + if (equal) { + return decisionNumber <= genomes; + } else { + return decisionNumber < genomes; + } + } + + } +} diff --git a/src/main/java/datastructure/RegexCondition.java b/src/main/java/datastructure/RegexCondition.java new file mode 100644 index 0000000..6c1973b --- /dev/null +++ b/src/main/java/datastructure/RegexCondition.java @@ -0,0 +1,31 @@ +package datastructure; + +/** + * Created by 101010. + */ +public class RegexCondition extends Condition { + + /** + * the regex of the condition. + */ + private String regex; + + /** + * The constructor of the RegexCondition. + * @param regex the regex of the condition. + */ + public RegexCondition(String regex) { + this.regex = regex; + } + + @Override + public boolean addColor(DrawNode drawNode) { + String[] genomes = drawNode.getGenomes(); + for (int i = 0; i < genomes.length; i++) { + if (genomes[i].contains(regex)) { + return true; + } + } + return false; + } +} From 9991cc08b5942cc7377a47c7e0738402abded99c Mon Sep 17 00:00:00 2001 From: tvheems Date: Wed, 7 Jun 2017 20:56:17 +0200 Subject: [PATCH 09/28] All conditions now have a color in the constructor and can get this color. --- src/main/java/datastructure/Condition.java | 14 ++++++++++++-- .../java/datastructure/GenomeCountCondition.java | 8 ++++++-- src/main/java/datastructure/RegexCondition.java | 6 +++++- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/main/java/datastructure/Condition.java b/src/main/java/datastructure/Condition.java index 842c574..5c5bf27 100644 --- a/src/main/java/datastructure/Condition.java +++ b/src/main/java/datastructure/Condition.java @@ -10,12 +10,14 @@ public abstract class Condition { /** * The color to be painted when condition holds. */ - private Color color; + private final Color color; /** * Default constructor. */ - public Condition(){} + public Condition(){ + color = Color.BLACK; + } /** *Constructor of the condition @@ -31,5 +33,13 @@ public Condition(Color color) { */ public abstract boolean addColor(DrawNode drawNode); + /** + * Gets the color of the condition. + * @return the color of the condition. + */ + public Color getColor() { + return color; + } + } diff --git a/src/main/java/datastructure/GenomeCountCondition.java b/src/main/java/datastructure/GenomeCountCondition.java index 61d3dd0..3790263 100644 --- a/src/main/java/datastructure/GenomeCountCondition.java +++ b/src/main/java/datastructure/GenomeCountCondition.java @@ -1,9 +1,11 @@ package datastructure; +import javafx.scene.paint.Color; + /** * Created by 101010. */ -public class GenomeCountCondition extends Condition{ +public class GenomeCountCondition extends Condition { /** * The decision number of the condition. @@ -26,8 +28,10 @@ public class GenomeCountCondition extends Condition{ * @param decisionNumber the number that decides the condition. * @param greater true iff condition is greater than the decisionNumber. * @param equal true iff condition is equal to the decisionNumber. + * @param color the color of the condition. */ - public GenomeCountCondition(int decisionNumber, boolean greater, boolean equal) { + public GenomeCountCondition(int decisionNumber, boolean greater, boolean equal, Color color) { + super(color); this.decisionNumber = decisionNumber; this.greater = greater; this.equal = equal; diff --git a/src/main/java/datastructure/RegexCondition.java b/src/main/java/datastructure/RegexCondition.java index 6c1973b..ea3bd6c 100644 --- a/src/main/java/datastructure/RegexCondition.java +++ b/src/main/java/datastructure/RegexCondition.java @@ -1,5 +1,7 @@ package datastructure; +import javafx.scene.paint.Color; + /** * Created by 101010. */ @@ -13,8 +15,10 @@ public class RegexCondition extends Condition { /** * The constructor of the RegexCondition. * @param regex the regex of the condition. + * @param color the color of the condition. */ - public RegexCondition(String regex) { + public RegexCondition(String regex, Color color) { + super(color); this.regex = regex; } From 67ad5eec8cc7cd2321bd53c256e9a1d2ed5d9104 Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Wed, 7 Jun 2017 21:45:44 +0200 Subject: [PATCH 10/28] Add tests for determining the width of edges --- src/main/java/screens/GraphInfo.java | 12 +++- src/main/java/screens/GraphScene.java | 7 ++- src/test/java/screens/GraphSceneTest.java | 67 ++++++++++++++++++++++- 3 files changed, 80 insertions(+), 6 deletions(-) diff --git a/src/main/java/screens/GraphInfo.java b/src/main/java/screens/GraphInfo.java index fc5ac52..288203d 100644 --- a/src/main/java/screens/GraphInfo.java +++ b/src/main/java/screens/GraphInfo.java @@ -3,7 +3,7 @@ /** * Class that can store information about the current state on the drawn graph used for navigation. */ -public final class GraphInfo { +public class GraphInfo { /** * The radius of the currently drawn graph. @@ -33,7 +33,7 @@ public final class GraphInfo { /** * Constructor for the information. */ - private GraphInfo() { + public GraphInfo() { this.currentCenterNode = 0; this.currentRadius = 200; } @@ -49,6 +49,14 @@ public static GraphInfo getInstance() { return instance; } + /** + * Setter for the instance of the GraphInfo. + * @param gi the new GraphInfo. + */ + public static void setInstance(GraphInfo gi) { + instance = gi; + } + /** * Getter for the current radius. * @return the current radius. diff --git a/src/main/java/screens/GraphScene.java b/src/main/java/screens/GraphScene.java index 98fd1cf..a41ad69 100644 --- a/src/main/java/screens/GraphScene.java +++ b/src/main/java/screens/GraphScene.java @@ -348,12 +348,13 @@ private double[] determineEdgeWidth(Node incNode, int id) { maxX = out.getX(); maxInt = i; } - widths[i] = getNumberOfDupes(id, outgoing[i]); + widths[i] = getNumberOfDuplicates(id, outgoing[i]); } if (maxInt == -1) { return widths; } int[] incoming = ng.getNode(outgoing[maxInt]).getIncomingEdges(); + System.out.println(outgoing.length); if (incoming.length < 2 || outgoing.length < 2) { return widths; } @@ -361,7 +362,7 @@ private double[] determineEdgeWidth(Node incNode, int id) { for (int i = 0; i < incoming.length; i++) { DrawNode dNode = ng.getDrawNode(incoming[i]); if (dNode != null && Math.abs(maxX - dNode.getX()) >= 5) { - widths[maxInt] -= getNumberOfDupes(outgoing[maxInt], incoming[i]); + widths[maxInt] -= getNumberOfDuplicates(outgoing[maxInt], incoming[i]); } } return widths; @@ -373,7 +374,7 @@ private double[] determineEdgeWidth(Node incNode, int id) { * @param outId the id of the node an edge with be drawn to. * @return the number of paths going through both nodes. */ - private int getNumberOfDupes(int id, int outId) { + private int getNumberOfDuplicates(int id, int outId) { int count = 0; int[][] paths = GraphInfo.getInstance().getPaths(); for (int j = 0; j < paths[id].length; j++) { diff --git a/src/test/java/screens/GraphSceneTest.java b/src/test/java/screens/GraphSceneTest.java index 3371eec..47961bd 100644 --- a/src/test/java/screens/GraphSceneTest.java +++ b/src/test/java/screens/GraphSceneTest.java @@ -1,5 +1,6 @@ package screens; +import datastructure.DrawNode; import datastructure.Node; import datastructure.NodeGraph; import javafx.collections.ObservableList; @@ -17,11 +18,14 @@ import org.mockito.runners.MockitoJUnitRunner; import javax.swing.*; +import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.LinkedList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; import static org.mockito.Mockito.*; /** @@ -46,6 +50,8 @@ public class GraphSceneTest { @Mock ObservableList list = mock(ObservableList.class); + GraphInfo gi = new GraphInfo(); + ArrayList nodes = new ArrayList<>(); NodeGraph ngTest = new NodeGraph(); @@ -74,6 +80,12 @@ public void setUp() { n1.addOutgoingEdge(1); Node n2 = new Node(); n2.addIncomingEdge(0); + int[][] paths = new int[2][3]; + paths[0][0] = 1; + paths[0][1] = 2; + paths[0][2] = 3; + paths[1][0] = 1; + paths[1][1] = 3; nodes.add(n1); nodes.add(n2); ngTest = new NodeGraph(nodes, null, null, null); @@ -83,6 +95,8 @@ public void setUp() { when(group.getChildren()).thenReturn(list); when(fact.createScene(group, 150, 100)).thenReturn(scene); when(fact.setScene(stage, scene)).thenReturn(stage); + gi.setPaths(paths); + GraphInfo.setInstance(gi); NodeGraph.setCurrentInstance(ngTest); gs = new GraphScene(fact); } @@ -108,7 +122,7 @@ public void switchToInfo() { } @Test - public void drawGraphTestInRadius() { + public void drawGraphInRadius() { gs.drawGraph(0, 20); verify(fact, never()).createGroup(); verify(fact, never()).createLabel(anyString()); @@ -118,4 +132,55 @@ public void drawGraphTestInRadius() { verify(group, never()).getChildren(); verify(fact, never()).show(stage); } + + @Test + public void getNumberOfDuplicates() { + try { + Method method = GraphScene.class.getDeclaredMethod("getNumberOfDuplicates", int.class, int.class); + method.setAccessible(true); + int result = (int) method.invoke(gs, 0, 1); + assertEquals(2, result); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + } + + @Test + public void determineEdgeWidth() { + try { + int[] out0 = {1, 2}; + int[] out1 = {2}; + int[] in1 = {0}; + int[] in2 = {0, 1}; + int[][] paths = new int[3][3]; + paths[1][0] = 1; + paths[1][1] = 3; + ArrayList nodes = new ArrayList<>(); + nodes.add(new Node(0, out0, new int[0])); + nodes.add(new Node(0, out1, in1)); + nodes.add(new Node(0, new int[0], in2)); + LinkedList dNodes = new LinkedList<>(); + for (int i = 0; i < 3; i++) { + DrawNode dNode = new DrawNode(i); + dNode.setX(i); + dNodes.add(dNode); + paths[0][i] = i; + paths[2][i] = i; + } + gi.setPaths(paths); + GraphInfo.setInstance(gi); + NodeGraph ng = new NodeGraph(nodes, null, dNodes, null); + NodeGraph.setCurrentInstance(ng); + Method method = GraphScene.class.getDeclaredMethod("determineEdgeWidth", Node.class, int.class); + method.setAccessible(true); + double[] result = (double[]) method.invoke(gs, nodes.get(0), 0); + assertEquals(2, result[0], 0.00001); + assertEquals(3, result[1], 0.00001); + assertEquals(2, result.length); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + } } From 07eed38cb88aba8865487cfe285887529590115c Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Wed, 7 Jun 2017 21:46:20 +0200 Subject: [PATCH 11/28] Delete an unnecessary system out --- src/main/java/screens/GraphScene.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/screens/GraphScene.java b/src/main/java/screens/GraphScene.java index a41ad69..e3a7269 100644 --- a/src/main/java/screens/GraphScene.java +++ b/src/main/java/screens/GraphScene.java @@ -354,7 +354,6 @@ private double[] determineEdgeWidth(Node incNode, int id) { return widths; } int[] incoming = ng.getNode(outgoing[maxInt]).getIncomingEdges(); - System.out.println(outgoing.length); if (incoming.length < 2 || outgoing.length < 2) { return widths; } From 2fd076bfa3e997407ee3549202c06d54d9f6a688 Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Wed, 7 Jun 2017 23:27:54 +0200 Subject: [PATCH 12/28] Update parser to calculate paths during cold loads --- src/main/java/parsing/Parser.java | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/main/java/parsing/Parser.java b/src/main/java/parsing/Parser.java index 1ca2a35..4aed49f 100644 --- a/src/main/java/parsing/Parser.java +++ b/src/main/java/parsing/Parser.java @@ -156,6 +156,7 @@ public NodeGraph parse(final File file, NodeGraph graph) { e.printStackTrace(); } } + readGenomes(genomesName); in.close(); out.close(); gw.close(); @@ -181,7 +182,6 @@ public NodeGraph parse(final File file, NodeGraph graph) { System.out.println("Error while reading file"); e.printStackTrace(); } - return graph; } @@ -411,4 +411,31 @@ private boolean determineBasis(String line, String[] allGenomes) { } return result; } + + private void readGenomes(String path) { + try { + BufferedReader br = new BufferedReader(new FileReader(path)); + int nol = getNumberOfLine(new File(path)); + br.readLine(); + int[][] paths = new int[nol - 2][]; + for (int i = 0; i < nol - 2; i++) { + String line = br.readLine(); + String[] genomes = line.split("\t"); + int[] genPath = new int[Integer.parseInt(genomes[0])]; + for (int j = 0; j < Integer.parseInt(genomes[0]); j++) { + genPath[j] = Integer.parseInt(genomes[j + 1]); + } + paths[i] = genPath; + } +// for (int i = 0; i < paths.length; i++) { +// for (int j = 0; j < paths[i].length; j++) { +// System.out.print(paths[i][j] + " "); +// } +// System.out.println(""); +// } + GraphInfo.getInstance().setPaths(paths); + } catch (Exception e) { + e.printStackTrace(); + } + } } From dec7628ce1722bf5cbb58eb92ba3ce7195246e5f Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Wed, 7 Jun 2017 23:45:05 +0200 Subject: [PATCH 13/28] Fix determining edge thickness during cold load --- src/main/java/parsing/Parser.java | 8 +++++--- src/main/java/screens/GraphScene.java | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/parsing/Parser.java b/src/main/java/parsing/Parser.java index 4aed49f..64a3017 100644 --- a/src/main/java/parsing/Parser.java +++ b/src/main/java/parsing/Parser.java @@ -416,11 +416,13 @@ private void readGenomes(String path) { try { BufferedReader br = new BufferedReader(new FileReader(path)); int nol = getNumberOfLine(new File(path)); - br.readLine(); + String line = br.readLine(); + String[] genomes = line.split("\t"); + GraphInfo.getInstance().setGenomesNum(Integer.parseInt(genomes[0])); int[][] paths = new int[nol - 2][]; for (int i = 0; i < nol - 2; i++) { - String line = br.readLine(); - String[] genomes = line.split("\t"); + line = br.readLine(); + genomes = line.split("\t"); int[] genPath = new int[Integer.parseInt(genomes[0])]; for (int j = 0; j < Integer.parseInt(genomes[0]); j++) { genPath[j] = Integer.parseInt(genomes[j + 1]); diff --git a/src/main/java/screens/GraphScene.java b/src/main/java/screens/GraphScene.java index e3a7269..805a5f2 100644 --- a/src/main/java/screens/GraphScene.java +++ b/src/main/java/screens/GraphScene.java @@ -116,6 +116,7 @@ private void drawGraphUtil(int center, int radius) { if (nOut != null && nOut.getBoundsInLocal().getMinX() - dNode.getBoundsInLocal().getMaxX() <= 100) { drawLine(dNode.getIndex() + "-" + i, 5 * widths[count] / GraphInfo.getInstance().getGenomesNum(), dNode.getBoundsInLocal().getMaxX(), dNode.getBoundsInLocal().getMinY() + 5, nOut.getBoundsInLocal().getMinX(), nOut.getBoundsInLocal().getMinY() + 5); } + System.out.println(dNode.getIndex() + " " + 5 * widths[count] / GraphInfo.getInstance().getGenomesNum()); count += 1; } } From 29eac76a48c0dc2e4d03e5e75517037e8b4630bc Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Wed, 7 Jun 2017 23:45:40 +0200 Subject: [PATCH 14/28] Small code improvements --- src/main/java/parsing/Parser.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/parsing/Parser.java b/src/main/java/parsing/Parser.java index 64a3017..8bbd342 100644 --- a/src/main/java/parsing/Parser.java +++ b/src/main/java/parsing/Parser.java @@ -412,6 +412,10 @@ private boolean determineBasis(String line, String[] allGenomes) { return result; } + /** + * Reads the genome paths from the cache and puts these in an accessible array. + * @param path the path of the genome cache file. + */ private void readGenomes(String path) { try { BufferedReader br = new BufferedReader(new FileReader(path)); @@ -429,12 +433,6 @@ private void readGenomes(String path) { } paths[i] = genPath; } -// for (int i = 0; i < paths.length; i++) { -// for (int j = 0; j < paths[i].length; j++) { -// System.out.print(paths[i][j] + " "); -// } -// System.out.println(""); -// } GraphInfo.getInstance().setPaths(paths); } catch (Exception e) { e.printStackTrace(); From 7cabab8d834cfdc9a44bd616fcb6160eb6e2d392 Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Wed, 7 Jun 2017 23:46:33 +0200 Subject: [PATCH 15/28] Delete a system out that isn't needed anymore --- src/main/java/screens/GraphScene.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/screens/GraphScene.java b/src/main/java/screens/GraphScene.java index 805a5f2..e3a7269 100644 --- a/src/main/java/screens/GraphScene.java +++ b/src/main/java/screens/GraphScene.java @@ -116,7 +116,6 @@ private void drawGraphUtil(int center, int radius) { if (nOut != null && nOut.getBoundsInLocal().getMinX() - dNode.getBoundsInLocal().getMaxX() <= 100) { drawLine(dNode.getIndex() + "-" + i, 5 * widths[count] / GraphInfo.getInstance().getGenomesNum(), dNode.getBoundsInLocal().getMaxX(), dNode.getBoundsInLocal().getMinY() + 5, nOut.getBoundsInLocal().getMinX(), nOut.getBoundsInLocal().getMinY() + 5); } - System.out.println(dNode.getIndex() + " " + 5 * widths[count] / GraphInfo.getInstance().getGenomesNum()); count += 1; } } From 0f709e64cec91beb9202fece26a3c8e05bb88f03 Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Thu, 8 Jun 2017 10:39:31 +0200 Subject: [PATCH 16/28] Small code improvements --- src/main/java/parsing/Parser.java | 2 +- src/test/java/screens/GraphSceneTest.java | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/parsing/Parser.java b/src/main/java/parsing/Parser.java index 8bbd342..b7f21b5 100644 --- a/src/main/java/parsing/Parser.java +++ b/src/main/java/parsing/Parser.java @@ -132,7 +132,7 @@ public NodeGraph parse(final File file, NodeGraph graph) { if (line2.contains("\t")) { line2 = line2.substring(0, line2.indexOf("\t")); } - node.setWeight(addGenomes(gw, line2, threadIntegerBased, allGenomes)); + addGenomes(gw, line2, threadIntegerBased, allGenomes); line2 = in.readLine(); lineCounter++; diff --git a/src/test/java/screens/GraphSceneTest.java b/src/test/java/screens/GraphSceneTest.java index 47961bd..f83ed6a 100644 --- a/src/test/java/screens/GraphSceneTest.java +++ b/src/test/java/screens/GraphSceneTest.java @@ -9,6 +9,8 @@ import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.stage.Stage; + +import javax.swing.SwingUtilities; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; @@ -17,7 +19,6 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import javax.swing.*; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.LinkedList; @@ -26,7 +27,11 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.anyString; /** * Tests the GraphScene class. From 9ec48276576aeb7e1dd2f6ea3c2534b0fdf34bad Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Thu, 8 Jun 2017 10:41:51 +0200 Subject: [PATCH 17/28] Add GUI options for conditional color coding --- src/main/java/datastructure/DrawNode.java | 12 +++ src/main/java/screens/Window.java | 96 +++++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/src/main/java/datastructure/DrawNode.java b/src/main/java/datastructure/DrawNode.java index 26fce07..0441c6d 100644 --- a/src/main/java/datastructure/DrawNode.java +++ b/src/main/java/datastructure/DrawNode.java @@ -49,4 +49,16 @@ public int hashCode() { return id; } + /** + * Getter for the genome paths going through a DrawNode. + * @return all genomes that cross this DrawNode. + */ + public String[] getGenomes() { +// int[] genomes = GraphInfo.getPaths()[this.id]; +// String[] strGenomes = new String[genomes.length]; +// for (int i = 0; i < genomes.length; i++) { +// strGenomes = GraphInfo.getGenomes()[genomes[i]]; +// } + return null; + } } diff --git a/src/main/java/screens/Window.java b/src/main/java/screens/Window.java index 661c7fb..bbcfa7b 100644 --- a/src/main/java/screens/Window.java +++ b/src/main/java/screens/Window.java @@ -1,12 +1,17 @@ package screens; +import datastructure.Condition; import datastructure.DrawNode; +import datastructure.GenomeCountCondition; import datastructure.NodeGraph; +import datastructure.RegexCondition; import filesystem.FileSystem; import javafx.application.Application; +import javafx.collections.FXCollections; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.Button; +import javafx.scene.control.ChoiceBox; import javafx.scene.control.Label; import javafx.scene.control.Menu; import javafx.scene.control.MenuBar; @@ -329,10 +334,101 @@ private Menu addController() { } } ); + MenuItem item5 = new MenuItem("Number of Genomes"); + item5.setOnAction( + event -> { + if (NodeGraph.getCurrentInstance() != null) { + Stage newstage = new Stage(); + newstage.setTitle("Select the amount of genomes"); + GridPane box = new GridPane(); + TextField textField = new TextField(); + ChoiceBox choices = new ChoiceBox(FXCollections.observableArrayList( + ">", "<", ">=", "<=")); + Button btn = new Button("Submit"); + choices.getSelectionModel().getSelectedIndex(); + btn.setOnAction( + event2 -> { + if (textField.getText().length() == 0 || textField.getText().contains("\\D")) { + errorPopup("Please enter a number as number of genomes."); + } else { + int number = Integer.parseInt(textField.getText()); +// || number >= GraphInfo.getNoGenomes() + if (number < 0) { + errorPopup("Input center id is out of bounds, \nplease provide a different input id."); + } else { + int index = choices.getSelectionModel().getSelectedIndex(); + GenomeCountCondition gcc; + switch (index) { + case 0: + //gcc = new GenomeCountCondition(number, true, false, ?getColor()?); + break; + case 1: + //gcc = new GenomeCountCondition(number, false, false, ?getColor()?); + break; + case 2: + //gcc = new GenomeCountCondition(number, true, true, ?getColor()?); + break; + case 3: + //gcc = new GenomeCountCondition(number, false, true, ?getColor()?); + break; + default: + errorPopup("Please select a constraint."); + break; + } + newstage.close(); + } + } + } + ); + box.add(new Label("Number:"), 1, 1); + box.add(textField, 1, 2, 3, 1); + box.add(new Label("Constraint:"), 1, 3); + box.add(choices, 1, 4, 3, 1); + box.add(btn, 1, 5); + Scene scene = new Scene(box); + newstage.setScene(scene); + newstage.show(); + logger.info("state has been switched to centerId"); + } else { + errorPopup("Please load a graph."); + } + } + ); + MenuItem item6 = new MenuItem("Conditional Regex"); + item6.setOnAction( + event -> { + if (NodeGraph.getCurrentInstance() != null) { + Stage newstage = new Stage(); + newstage.setTitle("Select the regex"); + GridPane box = new GridPane(); + TextField textField = new TextField(); + Button btn = new Button("Submit"); + btn.setOnAction( + event2 -> { + String regex = textField.getText(); + Color color = newColor(); + RegexCondition regCond = new RegexCondition(regex, color); + newstage.close(); + } + ); + box.add(new Label("Regex:"), 1, 1); + box.add(textField, 1, 2, 3, 1); + box.add(btn, 1, 3); + Scene scene = new Scene(box); + newstage.setScene(scene); + newstage.show(); + logger.info("state has been switched to centerId"); + } else { + errorPopup("Please load a graph."); + } + } + ); menu.getItems().add(item1); menu.getItems().add(item2); menu.getItems().add(item3); menu.getItems().add(item4); + menu.getItems().add(item5); + menu.getItems().add(item6); return menu; } From 01d5874d8a567a2b1f39535e28b7254437fefd0c Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Thu, 8 Jun 2017 11:05:52 +0200 Subject: [PATCH 18/28] Requested code improvements --- src/main/java/datastructure/DrawNode.java | 4 ++-- src/main/java/datastructure/Node.java | 22 ---------------------- src/main/java/parsing/Parser.java | 9 ++++----- src/main/java/screens/GraphInfo.java | 10 +++++----- src/main/java/screens/GraphScene.java | 10 +++++----- src/main/java/screens/Window.java | 4 +--- src/main/java/window/FileSelector.java | 4 ++-- src/test/java/screens/GraphSceneTest.java | 4 ++-- 8 files changed, 21 insertions(+), 46 deletions(-) diff --git a/src/main/java/datastructure/DrawNode.java b/src/main/java/datastructure/DrawNode.java index 26fce07..2d36297 100644 --- a/src/main/java/datastructure/DrawNode.java +++ b/src/main/java/datastructure/DrawNode.java @@ -42,8 +42,8 @@ public boolean equals(Object other) { } /** - * Givens the hashcode of the DrawNode - * @return the hashcode + * Givens the hashcode of the DrawNode. + * @return the hashcode. */ public int hashCode() { return id; diff --git a/src/main/java/datastructure/Node.java b/src/main/java/datastructure/Node.java index 2f69397..71b050a 100644 --- a/src/main/java/datastructure/Node.java +++ b/src/main/java/datastructure/Node.java @@ -23,12 +23,6 @@ public class Node { */ private int[] from; - /** - * The ratio of the number of genome paths going through this nodes compared to the total number - * of genome paths. - */ - private double weight; - /** * Empty constructor for Node. */ @@ -169,20 +163,4 @@ public void computeLength() { public void setLength(int length) { this.length = length; } - - /** - * Getter for the weight of a node. - * @return the weight of a node. - */ - public double getWeight() { - return this.weight; - } - - /** - * Setter for the weight of a node. - * @param newWeight the new weight a node will be set to. - */ - public void setWeight(double newWeight) { - this.weight = newWeight; - } } diff --git a/src/main/java/parsing/Parser.java b/src/main/java/parsing/Parser.java index b7f21b5..f1475fe 100644 --- a/src/main/java/parsing/Parser.java +++ b/src/main/java/parsing/Parser.java @@ -205,7 +205,7 @@ public NodeGraph parseCache(NodeGraph graph, File cache) { path = path.substring(0, path.length() - 4); BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(path + "Genomes.txt"))); GraphInfo.getInstance().setGenomesNum(Double.parseDouble(br.readLine().split("\t")[0])); - int[][] paths = new int[graphSize][]; + int[][] genomes = new int[graphSize][]; for (int i = 0; i < graphSize; i++) { int length = Integer.parseInt(in.readLine()); int outLength = Integer.parseInt(in.readLine()); @@ -223,10 +223,10 @@ public NodeGraph parseCache(NodeGraph graph, File cache) { Node temp = new Node(length, outgoing, incoming); graph.addNodeCache(i, temp); lineCounter = lineCounter + 5; - setWeights(br, temp, i, paths); + setWeights(br, temp, i, genomes); updateProgressBar(lineCounter, nol); } - GraphInfo.getInstance().setPaths(paths); + GraphInfo.getInstance().setGenomes(genomes); br.close(); in.close(); } catch (IOException e) { @@ -355,7 +355,6 @@ public static Thread getThread() { private void setWeights(BufferedReader br, Node node, int id, int[][] paths) { try { String[] line = br.readLine().split("\\t"); - node.setWeight(Double.parseDouble(line[0]) / GraphInfo.getInstance().getGenomesNum()); paths[id] = new int[Integer.parseInt(line[0])]; for (int i = 1; i < line.length; i++) { paths[id][i - 1] = Integer.parseInt(line[i]); @@ -433,7 +432,7 @@ private void readGenomes(String path) { } paths[i] = genPath; } - GraphInfo.getInstance().setPaths(paths); + GraphInfo.getInstance().setGenomes(paths); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/main/java/screens/GraphInfo.java b/src/main/java/screens/GraphInfo.java index 288203d..1c41ab9 100644 --- a/src/main/java/screens/GraphInfo.java +++ b/src/main/java/screens/GraphInfo.java @@ -23,7 +23,7 @@ public class GraphInfo { /** * All specified genome paths per node. */ - private int[][] paths; + private int[][] genomes; /** * A singleton instance of GraphInfo. @@ -107,10 +107,10 @@ public double getGenomesNum() { /** * Setter for the genome paths of the file. - * @param newPaths the genome paths to set. + * @param newGenomes the genome paths to set. */ - public void setPaths(int[][] newPaths) { - this.paths = newPaths; + public void setGenomes(int[][] newGenomes) { + this.genomes = newGenomes; } /** @@ -118,6 +118,6 @@ public void setPaths(int[][] newPaths) { * @return the genome paths of the file per node. */ public int[][] getPaths() { - return this.paths; + return this.genomes; } } diff --git a/src/main/java/screens/GraphScene.java b/src/main/java/screens/GraphScene.java index e3a7269..866b3ea 100644 --- a/src/main/java/screens/GraphScene.java +++ b/src/main/java/screens/GraphScene.java @@ -105,7 +105,7 @@ private void drawGraphUtil(int center, int radius) { LinkedList drawNodes = nodeGraph.getDrawNodes(); LinkedList dummyNodes = nodeGraph.getDummyNodes(); for (DrawNode dNode : drawNodes) { - int count = 0; + int outgoingNum = 0; double[] widths = determineEdgeWidth(NodeGraph.getCurrentInstance().getNode(dNode.getIndex()), dNode.getIndex()); dNode.setX(dNode.getX() - dNode.getWidth() / 2); dNode.setOnMousePressed(click); @@ -114,9 +114,9 @@ private void drawGraphUtil(int center, int radius) { for (int i : nodes.get(dNode.getIndex()).getOutgoingEdges()) { nOut = nodeGraph.getDrawNode(i); if (nOut != null && nOut.getBoundsInLocal().getMinX() - dNode.getBoundsInLocal().getMaxX() <= 100) { - drawLine(dNode.getIndex() + "-" + i, 5 * widths[count] / GraphInfo.getInstance().getGenomesNum(), dNode.getBoundsInLocal().getMaxX(), dNode.getBoundsInLocal().getMinY() + 5, nOut.getBoundsInLocal().getMinX(), nOut.getBoundsInLocal().getMinY() + 5); + drawLine(dNode.getIndex() + "-" + i, 5 * widths[outgoingNum] / GraphInfo.getInstance().getGenomesNum(), dNode.getBoundsInLocal().getMaxX(), dNode.getBoundsInLocal().getMinY() + 5, nOut.getBoundsInLocal().getMinX(), nOut.getBoundsInLocal().getMinY() + 5); } - count += 1; + outgoingNum += 1; } } DummyNode current; @@ -357,10 +357,9 @@ private double[] determineEdgeWidth(Node incNode, int id) { if (incoming.length < 2 || outgoing.length < 2) { return widths; } - maxX = ng.getDrawNode(id).getX(); for (int i = 0; i < incoming.length; i++) { DrawNode dNode = ng.getDrawNode(incoming[i]); - if (dNode != null && Math.abs(maxX - dNode.getX()) >= 5) { + if (dNode != null) { widths[maxInt] -= getNumberOfDuplicates(outgoing[maxInt], incoming[i]); } } @@ -380,6 +379,7 @@ private int getNumberOfDuplicates(int id, int outId) { for (int k = 0; k < paths[outId].length; k++) { if (paths[id][j] == paths[outId][k]) { count += 1; + break; } } } diff --git a/src/main/java/screens/Window.java b/src/main/java/screens/Window.java index 6a84511..a643062 100644 --- a/src/main/java/screens/Window.java +++ b/src/main/java/screens/Window.java @@ -4,7 +4,6 @@ import datastructure.NodeGraph; import filesystem.FileSystem; import javafx.application.Application; -import javafx.application.Platform; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.Button; @@ -18,7 +17,6 @@ import javafx.scene.layout.BorderPane; import javafx.scene.layout.GridPane; import javafx.scene.paint.Color; -import javafx.scene.shape.Line; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; import javafx.stage.StageStyle; @@ -217,7 +215,7 @@ private Menu addFileSelector(Stage stage) { pB.setVisible(true); NodeGraph.setCurrentInstance(Parser.getInstance().parse(file)); new Thread() { - public void run () { + public void run() { try { Parser.getThread().join(); diff --git a/src/main/java/window/FileSelector.java b/src/main/java/window/FileSelector.java index 2e574aa..92bd16e 100644 --- a/src/main/java/window/FileSelector.java +++ b/src/main/java/window/FileSelector.java @@ -65,7 +65,7 @@ public static File showOpenDialog(Window ownerWindow) { File chosenFile = getInstance().showOpenDialog(ownerWindow); if (chosenFile != null && chosenFile.exists()) { logger.info("Selected file: " + chosenFile.getName()); - } else if (chosenFile != null){ + } else if (chosenFile != null) { logger.info("The selected file does not exist."); } else { logger.info("No file was selected."); @@ -81,7 +81,7 @@ public static File showOpenDialog(Window ownerWindow) { * Finds the last used directory from which a file was chosen. * @return the path of the directory. */ - public static String getDirectory() { + private static String getDirectory() { try { BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("directory.txt"))); String dir = br.readLine(); diff --git a/src/test/java/screens/GraphSceneTest.java b/src/test/java/screens/GraphSceneTest.java index f83ed6a..20ec030 100644 --- a/src/test/java/screens/GraphSceneTest.java +++ b/src/test/java/screens/GraphSceneTest.java @@ -100,7 +100,7 @@ public void setUp() { when(group.getChildren()).thenReturn(list); when(fact.createScene(group, 150, 100)).thenReturn(scene); when(fact.setScene(stage, scene)).thenReturn(stage); - gi.setPaths(paths); + gi.setGenomes(paths); GraphInfo.setInstance(gi); NodeGraph.setCurrentInstance(ngTest); gs = new GraphScene(fact); @@ -173,7 +173,7 @@ public void determineEdgeWidth() { paths[0][i] = i; paths[2][i] = i; } - gi.setPaths(paths); + gi.setGenomes(paths); GraphInfo.setInstance(gi); NodeGraph ng = new NodeGraph(nodes, null, dNodes, null); NodeGraph.setCurrentInstance(ng); From bb892939e9366a8875533830db7ce16e3a3544a5 Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Thu, 8 Jun 2017 11:12:53 +0200 Subject: [PATCH 19/28] Some more requested changes --- src/main/java/parsing/Parser.java | 31 +++++++++++++-------------- src/main/java/screens/GraphScene.java | 6 +++--- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/main/java/parsing/Parser.java b/src/main/java/parsing/Parser.java index f1475fe..716ee2a 100644 --- a/src/main/java/parsing/Parser.java +++ b/src/main/java/parsing/Parser.java @@ -223,7 +223,7 @@ public NodeGraph parseCache(NodeGraph graph, File cache) { Node temp = new Node(length, outgoing, incoming); graph.addNodeCache(i, temp); lineCounter = lineCounter + 5; - setWeights(br, temp, i, genomes); + setWeights(br, i, genomes); updateProgressBar(lineCounter, nol); } GraphInfo.getInstance().setGenomes(genomes); @@ -348,16 +348,15 @@ public static Thread getThread() { /** * Sets the weights of nodes when reading in from the cache file. * @param br the reader that reads the cached file. - * @param node the node a weight is being set to. * @param id the id of the node. - * @param paths the paths of the genomes per node. + * @param genomes the genomes going through each node. */ - private void setWeights(BufferedReader br, Node node, int id, int[][] paths) { + private void setWeights(BufferedReader br, int id, int[][] genomes) { try { String[] line = br.readLine().split("\\t"); - paths[id] = new int[Integer.parseInt(line[0])]; + genomes[id] = new int[Integer.parseInt(line[0])]; for (int i = 1; i < line.length; i++) { - paths[id][i - 1] = Integer.parseInt(line[i]); + genomes[id][i - 1] = Integer.parseInt(line[i]); } } catch (Exception e) { System.out.println("Error when reading in genome cache"); @@ -412,7 +411,7 @@ private boolean determineBasis(String line, String[] allGenomes) { } /** - * Reads the genome paths from the cache and puts these in an accessible array. + * Reads the genomes going through each node from the cache and puts these in an accessible array. * @param path the path of the genome cache file. */ private void readGenomes(String path) { @@ -420,19 +419,19 @@ private void readGenomes(String path) { BufferedReader br = new BufferedReader(new FileReader(path)); int nol = getNumberOfLine(new File(path)); String line = br.readLine(); - String[] genomes = line.split("\t"); - GraphInfo.getInstance().setGenomesNum(Integer.parseInt(genomes[0])); - int[][] paths = new int[nol - 2][]; + String[] nodeGenomes = line.split("\t"); + GraphInfo.getInstance().setGenomesNum(Integer.parseInt(nodeGenomes[0])); + int[][] genomes = new int[nol - 2][]; for (int i = 0; i < nol - 2; i++) { line = br.readLine(); - genomes = line.split("\t"); - int[] genPath = new int[Integer.parseInt(genomes[0])]; - for (int j = 0; j < Integer.parseInt(genomes[0]); j++) { - genPath[j] = Integer.parseInt(genomes[j + 1]); + nodeGenomes = line.split("\t"); + int[] genPath = new int[Integer.parseInt(nodeGenomes[0])]; + for (int j = 0; j < Integer.parseInt(nodeGenomes[0]); j++) { + genPath[j] = Integer.parseInt(nodeGenomes[j + 1]); } - paths[i] = genPath; + genomes[i] = genPath; } - GraphInfo.getInstance().setGenomes(paths); + GraphInfo.getInstance().setGenomes(genomes); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/main/java/screens/GraphScene.java b/src/main/java/screens/GraphScene.java index 866b3ea..6dcf164 100644 --- a/src/main/java/screens/GraphScene.java +++ b/src/main/java/screens/GraphScene.java @@ -106,7 +106,7 @@ private void drawGraphUtil(int center, int radius) { LinkedList dummyNodes = nodeGraph.getDummyNodes(); for (DrawNode dNode : drawNodes) { int outgoingNum = 0; - double[] widths = determineEdgeWidth(NodeGraph.getCurrentInstance().getNode(dNode.getIndex()), dNode.getIndex()); + int[] widths = determineEdgeWidth(NodeGraph.getCurrentInstance().getNode(dNode.getIndex()), dNode.getIndex()); dNode.setX(dNode.getX() - dNode.getWidth() / 2); dNode.setOnMousePressed(click); Platform.runLater(() -> this.getChildren().add(dNode)); @@ -336,10 +336,10 @@ public INodeHandler getInfo() { * @param id the id of the node. * @return An array with the number of paths going through each outgoing edge of the node. */ - private double[] determineEdgeWidth(Node incNode, int id) { + private int[] determineEdgeWidth(Node incNode, int id) { NodeGraph ng = NodeGraph.getCurrentInstance(); int[] outgoing = incNode.getOutgoingEdges(); - double[] widths = new double[outgoing.length]; + int[] widths = new int[outgoing.length]; int maxInt = -1; double maxX = -Double.MAX_VALUE; for (int i = 0; i < outgoing.length; i++) { From 115946cebd380056621be80955955045fca61a68 Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Thu, 8 Jun 2017 13:05:08 +0200 Subject: [PATCH 20/28] Edge thickness has a much more efficient memory usage --- src/main/java/parsing/Parser.java | 63 +++++++++++---------------- src/main/java/screens/GraphScene.java | 22 +++++++--- 2 files changed, 41 insertions(+), 44 deletions(-) diff --git a/src/main/java/parsing/Parser.java b/src/main/java/parsing/Parser.java index 716ee2a..0f1220e 100644 --- a/src/main/java/parsing/Parser.java +++ b/src/main/java/parsing/Parser.java @@ -1,8 +1,10 @@ package parsing; +import datastructure.DrawNode; import datastructure.Node; import datastructure.NodeGraph; import datastructure.SegmentDB; +import java.util.LinkedList; import javafx.application.Platform; import screens.GraphInfo; import screens.Window; @@ -34,6 +36,11 @@ public class Parser { */ private static Thread parser; + /** + * The file path to the cache files. + */ + private String path; + /** * Constructor of the parser. */ @@ -59,6 +66,7 @@ public static Parser getInstance() { public NodeGraph parse(File file) { NodeGraph graph = new NodeGraph(); String cacheName = file.getAbsolutePath().substring(0, file.getAbsolutePath().length() - 4); + path = cacheName; graph.setSegmentDB(new SegmentDB(cacheName + "Segments.txt")); File cache = new File(cacheName + ".txt"); @@ -156,7 +164,7 @@ public NodeGraph parse(final File file, NodeGraph graph) { e.printStackTrace(); } } - readGenomes(genomesName); + //readGenomes(genomesName); in.close(); out.close(); gw.close(); @@ -202,10 +210,6 @@ public NodeGraph parseCache(NodeGraph graph, File cache) { try { int nol = getNumberOfLine(cache); String path = cache.getAbsolutePath(); - path = path.substring(0, path.length() - 4); - BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(path + "Genomes.txt"))); - GraphInfo.getInstance().setGenomesNum(Double.parseDouble(br.readLine().split("\t")[0])); - int[][] genomes = new int[graphSize][]; for (int i = 0; i < graphSize; i++) { int length = Integer.parseInt(in.readLine()); int outLength = Integer.parseInt(in.readLine()); @@ -223,11 +227,8 @@ public NodeGraph parseCache(NodeGraph graph, File cache) { Node temp = new Node(length, outgoing, incoming); graph.addNodeCache(i, temp); lineCounter = lineCounter + 5; - setWeights(br, i, genomes); updateProgressBar(lineCounter, nol); } - GraphInfo.getInstance().setGenomes(genomes); - br.close(); in.close(); } catch (IOException e) { e.printStackTrace(); @@ -345,25 +346,6 @@ public static Thread getThread() { return parser; } - /** - * Sets the weights of nodes when reading in from the cache file. - * @param br the reader that reads the cached file. - * @param id the id of the node. - * @param genomes the genomes going through each node. - */ - private void setWeights(BufferedReader br, int id, int[][] genomes) { - try { - String[] line = br.readLine().split("\\t"); - genomes[id] = new int[Integer.parseInt(line[0])]; - for (int i = 1; i < line.length; i++) { - genomes[id][i - 1] = Integer.parseInt(line[i]); - } - } catch (Exception e) { - System.out.println("Error when reading in genome cache"); - e.printStackTrace(); - } - } - /** Reads all genomes of the gfa file and caches them. * @param gw the writer used to write to the cache. * @param line the line on which all genomes are listed. @@ -412,24 +394,29 @@ private boolean determineBasis(String line, String[] allGenomes) { /** * Reads the genomes going through each node from the cache and puts these in an accessible array. - * @param path the path of the genome cache file. + * @param drawNodes the path of the genome cache file. */ - private void readGenomes(String path) { + public void readGenomes(LinkedList drawNodes) { try { - BufferedReader br = new BufferedReader(new FileReader(path)); - int nol = getNumberOfLine(new File(path)); + BufferedReader br = new BufferedReader(new FileReader(path + "Genomes.txt")); + int nol = getNumberOfLine(new File(path + "Genomes.txt")); String line = br.readLine(); String[] nodeGenomes = line.split("\t"); GraphInfo.getInstance().setGenomesNum(Integer.parseInt(nodeGenomes[0])); - int[][] genomes = new int[nol - 2][]; + int[][] genomes = new int[drawNodes.size()][]; + int index = 0; for (int i = 0; i < nol - 2; i++) { - line = br.readLine(); - nodeGenomes = line.split("\t"); - int[] genPath = new int[Integer.parseInt(nodeGenomes[0])]; - for (int j = 0; j < Integer.parseInt(nodeGenomes[0]); j++) { - genPath[j] = Integer.parseInt(nodeGenomes[j + 1]); + if (NodeGraph.getCurrentInstance().getDrawNode(i) != null) { + line = br.readLine(); + nodeGenomes = line.split("\t"); + int[] genPath = new int[Integer.parseInt(nodeGenomes[0]) + 1]; + genPath[0] = i; + for (int j = 1; j < genPath.length; j++) { + genPath[j] = Integer.parseInt(nodeGenomes[j]); + } + genomes[index] = genPath; + index++; } - genomes[i] = genPath; } GraphInfo.getInstance().setGenomes(genomes); } catch (Exception e) { diff --git a/src/main/java/screens/GraphScene.java b/src/main/java/screens/GraphScene.java index 6dcf164..bf3387d 100644 --- a/src/main/java/screens/GraphScene.java +++ b/src/main/java/screens/GraphScene.java @@ -104,6 +104,7 @@ private void drawGraphUtil(int center, int radius) { ArrayList nodes = nodeGraph.getNodes(); LinkedList drawNodes = nodeGraph.getDrawNodes(); LinkedList dummyNodes = nodeGraph.getDummyNodes(); + Parser.getInstance().readGenomes(drawNodes); for (DrawNode dNode : drawNodes) { int outgoingNum = 0; int[] widths = determineEdgeWidth(NodeGraph.getCurrentInstance().getNode(dNode.getIndex()), dNode.getIndex()); @@ -374,12 +375,21 @@ private int[] determineEdgeWidth(Node incNode, int id) { */ private int getNumberOfDuplicates(int id, int outId) { int count = 0; - int[][] paths = GraphInfo.getInstance().getPaths(); - for (int j = 0; j < paths[id].length; j++) { - for (int k = 0; k < paths[outId].length; k++) { - if (paths[id][j] == paths[outId][k]) { - count += 1; - break; + int[][] genomes = GraphInfo.getInstance().getPaths(); + for (int i = 0; i < genomes.length; i++) { + if (genomes[i][0] == id) { + id = i; + } else if (genomes[i][0] == outId) { + outId = i; + } + } + if (outId < genomes.length) { + for (int j = 0; j < genomes[id].length; j++) { + for (int k = 0; k < genomes[outId].length; k++) { + if (genomes[id][j] == genomes[outId][k]) { + count += 1; + break; + } } } } From 8a717ae547f9d5b5738014543497ade2fbb91795 Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Thu, 8 Jun 2017 13:57:29 +0200 Subject: [PATCH 21/28] Fix the tests that were broken because of implementing the requested changes --- src/main/java/screens/GraphScene.java | 6 ++-- src/test/java/screens/GraphSceneTest.java | 44 +++++++++++++++-------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/main/java/screens/GraphScene.java b/src/main/java/screens/GraphScene.java index bf3387d..b08e35e 100644 --- a/src/main/java/screens/GraphScene.java +++ b/src/main/java/screens/GraphScene.java @@ -360,7 +360,7 @@ private int[] determineEdgeWidth(Node incNode, int id) { } for (int i = 0; i < incoming.length; i++) { DrawNode dNode = ng.getDrawNode(incoming[i]); - if (dNode != null) { + if (dNode != null && dNode.getIndex() != id) { widths[maxInt] -= getNumberOfDuplicates(outgoing[maxInt], incoming[i]); } } @@ -384,8 +384,8 @@ private int getNumberOfDuplicates(int id, int outId) { } } if (outId < genomes.length) { - for (int j = 0; j < genomes[id].length; j++) { - for (int k = 0; k < genomes[outId].length; k++) { + for (int j = 1; j < genomes[id].length; j++) { + for (int k = 1; k < genomes[outId].length; k++) { if (genomes[id][j] == genomes[outId][k]) { count += 1; break; diff --git a/src/test/java/screens/GraphSceneTest.java b/src/test/java/screens/GraphSceneTest.java index 20ec030..64e44ce 100644 --- a/src/test/java/screens/GraphSceneTest.java +++ b/src/test/java/screens/GraphSceneTest.java @@ -85,12 +85,16 @@ public void setUp() { n1.addOutgoingEdge(1); Node n2 = new Node(); n2.addIncomingEdge(0); - int[][] paths = new int[2][3]; - paths[0][0] = 1; - paths[0][1] = 2; - paths[0][2] = 3; + int[][] paths = new int[2][]; + paths[0] = new int[4]; + paths[1] = new int[3]; + paths[0][0] = 0; + paths[0][1] = 1; + paths[0][2] = 2; + paths[0][3] = 3; paths[1][0] = 1; - paths[1][1] = 3; + paths[1][1] = 1; + paths[1][2] = 3; nodes.add(n1); nodes.add(n2); ngTest = new NodeGraph(nodes, null, null, null); @@ -158,20 +162,32 @@ public void determineEdgeWidth() { int[] out1 = {2}; int[] in1 = {0}; int[] in2 = {0, 1}; - int[][] paths = new int[3][3]; + int[][] paths = new int[3][]; + paths[1] = new int[3]; paths[1][0] = 1; - paths[1][1] = 3; + paths[1][1] = 0; + paths[1][2] = 2; + paths[0] = new int[4]; + paths[2] = new int[4]; + paths[2][0] = 2; ArrayList nodes = new ArrayList<>(); nodes.add(new Node(0, out0, new int[0])); nodes.add(new Node(0, out1, in1)); nodes.add(new Node(0, new int[0], in2)); LinkedList dNodes = new LinkedList<>(); - for (int i = 0; i < 3; i++) { - DrawNode dNode = new DrawNode(i); + + for (int i = 1; i < 4; i++) { + DrawNode dNode = new DrawNode(i - 1); dNode.setX(i); dNodes.add(dNode); - paths[0][i] = i; - paths[2][i] = i; + paths[0][i] = i - 1; + paths[2][i] = i - 1; + } + for (int i = 0; i < paths.length; i++) { + for (int j = 0; j < paths[i].length; j++) { + System.out.print(paths[i][j] + " "); + } + System.out.println(); } gi.setGenomes(paths); GraphInfo.setInstance(gi); @@ -179,9 +195,9 @@ public void determineEdgeWidth() { NodeGraph.setCurrentInstance(ng); Method method = GraphScene.class.getDeclaredMethod("determineEdgeWidth", Node.class, int.class); method.setAccessible(true); - double[] result = (double[]) method.invoke(gs, nodes.get(0), 0); - assertEquals(2, result[0], 0.00001); - assertEquals(3, result[1], 0.00001); + int[] result = (int[]) method.invoke(gs, nodes.get(0), 0); + assertEquals(2, result[0]); + assertEquals(1, result[1]); assertEquals(2, result.length); } catch (Exception e) { e.printStackTrace(); From 37b276fc4f9a1a595e1d367bb260f9f724c469a0 Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Thu, 8 Jun 2017 18:35:58 +0200 Subject: [PATCH 22/28] Correctly colors nodes corresponding to conditionals --- src/main/java/datastructure/DrawNode.java | 23 ++++++++--- src/main/java/datastructure/NodeGraph.java | 22 +++++----- src/main/java/parsing/Parser.java | 5 +++ src/main/java/screens/GraphInfo.java | 48 ++++++++++++++++++++-- src/main/java/screens/GraphScene.java | 21 +++++++++- src/main/java/screens/Window.java | 24 +++++++---- src/test/java/screens/GraphSceneTest.java | 6 --- 7 files changed, 111 insertions(+), 38 deletions(-) diff --git a/src/main/java/datastructure/DrawNode.java b/src/main/java/datastructure/DrawNode.java index bd9e967..321de5c 100644 --- a/src/main/java/datastructure/DrawNode.java +++ b/src/main/java/datastructure/DrawNode.java @@ -1,6 +1,7 @@ package datastructure; import javafx.scene.shape.Rectangle; +import screens.GraphInfo; /** * Created by 101010. @@ -54,11 +55,21 @@ public int hashCode() { * @return all genomes that cross this DrawNode. */ public String[] getGenomes() { -// int[] genomes = GraphInfo.getPaths()[this.id]; -// String[] strGenomes = new String[genomes.length]; -// for (int i = 0; i < genomes.length; i++) { -// strGenomes = GraphInfo.getGenomes()[genomes[i]]; -// } - return null; + System.out.println(this.getIndex()); + int[][] allGenomes = GraphInfo.getInstance().getGenomes(); + int index = -1; + for (int i = 0; i < allGenomes.length; i++) { + if (allGenomes[i][0] == this.getIndex()) { + index = i; + break; + } + } + int[] genomes = GraphInfo.getInstance().getGenomes()[index]; + String[] strGenomes = new String[genomes.length - 1]; + for (int i = 1; i < genomes.length; i++) { + String name = GraphInfo.getInstance().getGenomeNames()[genomes[i]]; + strGenomes[i - 1] = name.substring(0, name.length() - 6); + } + return strGenomes; } } diff --git a/src/main/java/datastructure/NodeGraph.java b/src/main/java/datastructure/NodeGraph.java index b37ca8c..99b5cb1 100644 --- a/src/main/java/datastructure/NodeGraph.java +++ b/src/main/java/datastructure/NodeGraph.java @@ -207,9 +207,6 @@ public void generateDrawNodes(int center, int radius) { computeDummyNodes(); verticalSpacing(); retrieveEdgeNodes(); - for (DrawNode drawNode1 : drawNodes) { - colorDrawNode(drawNode1, new Color[]{Color.RED, Color.GREEN, Color.BLUE, Color.CYAN}); - } } /** @@ -626,7 +623,6 @@ public Pair, LinkedList> addAtRoot() { nodes.get(newNodes.get(i).getIndex()).computeLength(); newNodes.get(i).setWidth(nodes.get(newNodes.get(i).getIndex()).getLength()); newNodes.get(i).setHeight(10); - colorDrawNode(newNodes.get(i), new Color[]{Color.RED, Color.GREEN}); newDrawNodes.add(newNodes.get(i)); } else { Node dummyIn = nodes.get(newNodes.get(i).getIndex()); @@ -692,7 +688,6 @@ public Pair, LinkedList> addAtLeaf() { nodes.get(newNodes.get(i).getIndex()).computeLength(); newNodes.get(i).setWidth(nodes.get(newNodes.get(i).getIndex()).getLength()); newNodes.get(i).setHeight(10); - colorDrawNode(newNodes.get(i), new Color[]{Color.RED, Color.GREEN}); newDrawNodes.add(newNodes.get(i)); } else { Node dummyOut = nodes.get(newNodes.get(i).getIndex()); @@ -824,14 +819,17 @@ protected LinkedList getLeafNodes() { * @param drawNode the node to be colored. * @param colors the colors of the strokes. */ - private void colorDrawNode(DrawNode drawNode, Color[] colors) { - drawNode.setFill(Color.BLACK); - Stop[] stops = new Stop[colors.length * 2]; - double offset = 1 / (double) colors.length; + public void colorDrawNode(DrawNode drawNode, ArrayList colors) { + drawNode.setFill(Color.CRIMSON); + Stop[] stops = new Stop[colors.size() * 2]; + if (stops.length == 0) { + return; + } + double offset = 1 / (double) colors.size(); - for (int i = 0; i < colors.length; i++) { - stops[2 * i] = new Stop((i * offset), colors[i]); - stops[(2 * i) + 1] = new Stop(((i + 1) * offset), colors[i]); + for (int i = 0; i < colors.size(); i++) { + stops[2 * i] = new Stop((i * offset), colors.get(i)); + stops[(2 * i) + 1] = new Stop(((i + 1) * offset), colors.get(i)); } LinearGradient lg1 = new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE, stops); drawNode.setFill(lg1); diff --git a/src/main/java/parsing/Parser.java b/src/main/java/parsing/Parser.java index 0f1220e..c480177 100644 --- a/src/main/java/parsing/Parser.java +++ b/src/main/java/parsing/Parser.java @@ -403,6 +403,11 @@ public void readGenomes(LinkedList drawNodes) { String line = br.readLine(); String[] nodeGenomes = line.split("\t"); GraphInfo.getInstance().setGenomesNum(Integer.parseInt(nodeGenomes[0])); + String[] genomeNames = new String[Integer.parseInt(nodeGenomes[0])]; + for (int i = 1; i < nodeGenomes.length; i++) { + genomeNames[i - 1] = nodeGenomes[i]; + } + GraphInfo.getInstance().setGenomeNames(genomeNames); int[][] genomes = new int[drawNodes.size()][]; int index = 0; for (int i = 0; i < nol - 2; i++) { diff --git a/src/main/java/screens/GraphInfo.java b/src/main/java/screens/GraphInfo.java index 1c41ab9..6153519 100644 --- a/src/main/java/screens/GraphInfo.java +++ b/src/main/java/screens/GraphInfo.java @@ -1,5 +1,9 @@ package screens; +import datastructure.Condition; +import java.util.ArrayList; +import javafx.scene.paint.Color; + /** * Class that can store information about the current state on the drawn graph used for navigation. */ @@ -18,7 +22,7 @@ public class GraphInfo { /** * The number of genomes paths that are specified. */ - private double genomeNum; + private int genomeNum; /** * All specified genome paths per node. @@ -30,12 +34,25 @@ public class GraphInfo { */ private static GraphInfo instance; + private ArrayList colors; + + private ArrayList conditions; + + private String[] genomeNames; + /** * Constructor for the information. */ public GraphInfo() { this.currentCenterNode = 0; this.currentRadius = 200; + colors = new ArrayList<>(); + colors.add(Color.GREEN); + colors.add(Color.BLUE); + colors.add(Color.YELLOW); + colors.add(Color.MAGENTA); + colors.add(Color.CYAN); + conditions = new ArrayList<>(); } /** @@ -93,7 +110,7 @@ public void setCurrentCenterNode(int id) { * Setter for the number of genome paths specified in the file. * @param num the number of genome paths specified in the file. */ - public void setGenomesNum(double num) { + public void setGenomesNum(int num) { this.genomeNum = num; } @@ -101,7 +118,7 @@ public void setGenomesNum(double num) { * Getter for the number of genome paths specified in the file. * @return the number of genome paths specified in the file. */ - public double getGenomesNum() { + public int getGenomesNum() { return this.genomeNum; } @@ -117,7 +134,30 @@ public void setGenomes(int[][] newGenomes) { * Getter for the genome paths of the file. * @return the genome paths of the file per node. */ - public int[][] getPaths() { + public int[][] getGenomes() { return this.genomes; } + + public Color determineColor() { + if (colors.size() != 0) { + return colors.remove(0); + } + return Color.GRAY; + } + + public void addCondition(Condition cond) { + this.conditions.add(cond); + } + + public ArrayList getConditions() { + return this.conditions; + } + + public void setGenomeNames(String[] names) { + this.genomeNames = names; + } + + public String[] getGenomeNames() { + return this.genomeNames; + } } diff --git a/src/main/java/screens/GraphScene.java b/src/main/java/screens/GraphScene.java index b08e35e..9fa80c9 100644 --- a/src/main/java/screens/GraphScene.java +++ b/src/main/java/screens/GraphScene.java @@ -1,5 +1,6 @@ package screens; +import datastructure.Condition; import datastructure.DrawNode; import datastructure.DummyNode; import datastructure.Node; @@ -8,6 +9,8 @@ import javafx.event.EventHandler; import javafx.scene.input.MouseEvent; import javafx.scene.layout.Pane; +import javafx.scene.paint.Color; +import javafx.scene.paint.LinearGradient; import javafx.scene.shape.Line; import parsing.Parser; import javafx.scene.shape.Rectangle; @@ -109,6 +112,7 @@ private void drawGraphUtil(int center, int radius) { int outgoingNum = 0; int[] widths = determineEdgeWidth(NodeGraph.getCurrentInstance().getNode(dNode.getIndex()), dNode.getIndex()); dNode.setX(dNode.getX() - dNode.getWidth() / 2); + dNode.setFill(Color.CRIMSON); dNode.setOnMousePressed(click); Platform.runLater(() -> this.getChildren().add(dNode)); DrawNode nOut; @@ -375,7 +379,7 @@ private int[] determineEdgeWidth(Node incNode, int id) { */ private int getNumberOfDuplicates(int id, int outId) { int count = 0; - int[][] genomes = GraphInfo.getInstance().getPaths(); + int[][] genomes = GraphInfo.getInstance().getGenomes(); for (int i = 0; i < genomes.length; i++) { if (genomes[i][0] == id) { id = i; @@ -396,4 +400,19 @@ private int getNumberOfDuplicates(int id, int outId) { return count; } + public void drawConditions() { + LinkedList drawNodes = NodeGraph.getCurrentInstance().getDrawNodes(); + ArrayList colors = new ArrayList<>(); + for (DrawNode dNode: drawNodes) { + colors = new ArrayList<>(); + for (Condition cond : GraphInfo.getInstance().getConditions()) { + if (cond.addColor(dNode)) { + colors.add(cond.getColor()); + System.out.println("rip"); + } + } + NodeGraph.getCurrentInstance().colorDrawNode(dNode, colors); + } + } + } diff --git a/src/main/java/screens/Window.java b/src/main/java/screens/Window.java index 41b6364..e635830 100644 --- a/src/main/java/screens/Window.java +++ b/src/main/java/screens/Window.java @@ -351,29 +351,34 @@ private Menu addController() { errorPopup("Please enter a number as number of genomes."); } else { int number = Integer.parseInt(textField.getText()); -// || number >= GraphInfo.getNoGenomes() - if (number < 0) { - errorPopup("Input center id is out of bounds, \nplease provide a different input id."); + if (number < 0 || number >= GraphInfo.getInstance().getGenomesNum()) { + errorPopup("Input number is out of bounds, \nplease provide a different input between 0 and : " + GraphInfo.getInstance().getGenomesNum() + "."); } else { int index = choices.getSelectionModel().getSelectedIndex(); GenomeCountCondition gcc; + Color color = GraphInfo.getInstance().determineColor(); switch (index) { case 0: - //gcc = new GenomeCountCondition(number, true, false, ?getColor()?); + gcc = new GenomeCountCondition(number, true, false, color); + GraphInfo.getInstance().addCondition(gcc); break; case 1: - //gcc = new GenomeCountCondition(number, false, false, ?getColor()?); + gcc = new GenomeCountCondition(number, false, false, color); + GraphInfo.getInstance().addCondition(gcc); break; case 2: - //gcc = new GenomeCountCondition(number, true, true, ?getColor()?); + gcc = new GenomeCountCondition(number, true, true, color); + GraphInfo.getInstance().addCondition(gcc); break; case 3: - //gcc = new GenomeCountCondition(number, false, true, ?getColor()?); + gcc = new GenomeCountCondition(number, false, true, color); + GraphInfo.getInstance().addCondition(gcc); break; default: errorPopup("Please select a constraint."); break; } + graphScene.drawConditions(); newstage.close(); } } @@ -405,8 +410,9 @@ private Menu addController() { btn.setOnAction( event2 -> { String regex = textField.getText(); - Color color = newColor(); - RegexCondition regCond = new RegexCondition(regex, color); + RegexCondition regCond = new RegexCondition(regex, GraphInfo.getInstance().determineColor()); + GraphInfo.getInstance().addCondition(regCond); + graphScene.drawConditions(); newstage.close(); } ); diff --git a/src/test/java/screens/GraphSceneTest.java b/src/test/java/screens/GraphSceneTest.java index 64e44ce..498b803 100644 --- a/src/test/java/screens/GraphSceneTest.java +++ b/src/test/java/screens/GraphSceneTest.java @@ -183,12 +183,6 @@ public void determineEdgeWidth() { paths[0][i] = i - 1; paths[2][i] = i - 1; } - for (int i = 0; i < paths.length; i++) { - for (int j = 0; j < paths[i].length; j++) { - System.out.print(paths[i][j] + " "); - } - System.out.println(); - } gi.setGenomes(paths); GraphInfo.setInstance(gi); NodeGraph ng = new NodeGraph(nodes, null, dNodes, null); From 567e3b3a483cd93ba7ab985e1fd6113fa2a5106f Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Thu, 8 Jun 2017 22:20:35 +0200 Subject: [PATCH 23/28] Adapt color coding conditionals to new GUI --- .../datastructure/GenomeCountCondition.java | 8 +- src/main/java/screens/Window.java | 95 ------------------- src/main/java/screens/scenes/Controller.java | 82 +++++++++++++++- 3 files changed, 84 insertions(+), 101 deletions(-) diff --git a/src/main/java/datastructure/GenomeCountCondition.java b/src/main/java/datastructure/GenomeCountCondition.java index 3790263..b0b7259 100644 --- a/src/main/java/datastructure/GenomeCountCondition.java +++ b/src/main/java/datastructure/GenomeCountCondition.java @@ -42,15 +42,15 @@ public boolean addColor(DrawNode drawNode) { int genomes = drawNode.getGenomes().length; if (greater) { if (equal) { - return decisionNumber >= genomes; + return decisionNumber <= genomes; } else { - return decisionNumber > genomes; + return decisionNumber < genomes; } } else { if (equal) { - return decisionNumber <= genomes; + return decisionNumber >= genomes; } else { - return decisionNumber < genomes; + return decisionNumber > genomes; } } diff --git a/src/main/java/screens/Window.java b/src/main/java/screens/Window.java index 4ea6ca7..cf66b20 100644 --- a/src/main/java/screens/Window.java +++ b/src/main/java/screens/Window.java @@ -271,101 +271,6 @@ private Menu addController() { logger.info("console window has been opened"); } ); -// MenuItem item5 = new MenuItem("Number of Genomes"); -// item5.setOnAction( -// event -> { -// if (NodeGraph.getCurrentInstance() != null) { -// Stage newstage = new Stage(); -// newstage.setTitle("Select the amount of genomes"); -// GridPane box = new GridPane(); -// TextField textField = new TextField(); -// ChoiceBox choices = new ChoiceBox(FXCollections.observableArrayList( -// ">", "<", ">=", "<=")); -// Button btn = new Button("Submit"); -// choices.getSelectionModel().getSelectedIndex(); -// btn.setOnAction( -// event2 -> { -// if (textField.getText().length() == 0 || textField.getText().contains("\\D")) { -// errorPopup("Please enter a number as number of genomes."); -// } else { -// int number = Integer.parseInt(textField.getText()); -// if (number < 0 || number >= GraphInfo.getInstance().getGenomesNum()) { -// errorPopup("Input number is out of bounds, \nplease provide a different input between 0 and : " + GraphInfo.getInstance().getGenomesNum() + "."); -// } else { -// int index = choices.getSelectionModel().getSelectedIndex(); -// GenomeCountCondition gcc; -// Color color = GraphInfo.getInstance().determineColor(); -// switch (index) { -// case 0: -// gcc = new GenomeCountCondition(number, true, false, color); -// GraphInfo.getInstance().addCondition(gcc); -// break; -// case 1: -// gcc = new GenomeCountCondition(number, false, false, color); -// GraphInfo.getInstance().addCondition(gcc); -// break; -// case 2: -// gcc = new GenomeCountCondition(number, true, true, color); -// GraphInfo.getInstance().addCondition(gcc); -// break; -// case 3: -// gcc = new GenomeCountCondition(number, false, true, color); -// GraphInfo.getInstance().addCondition(gcc); -// break; -// default: -// errorPopup("Please select a constraint."); -// break; -// } -// graphScene.drawConditions(); -// newstage.close(); -// } -// } -// } -// ); -// box.add(new Label("Number:"), 1, 1); -// box.add(textField, 1, 2, 3, 1); -// box.add(new Label("Constraint:"), 1, 3); -// box.add(choices, 1, 4, 3, 1); -// box.add(btn, 1, 5); -// Scene scene = new Scene(box); -// newstage.setScene(scene); -// newstage.show(); -// logger.info("state has been switched to centerId"); -// } else { -// errorPopup("Please load a graph."); -// } -// } -// ); -// MenuItem item6 = new MenuItem("Conditional Regex"); -// item6.setOnAction( -// event -> { -// if (NodeGraph.getCurrentInstance() != null) { -// Stage newstage = new Stage(); -// newstage.setTitle("Select the regex"); -// GridPane box = new GridPane(); -// TextField textField = new TextField(); -// Button btn = new Button("Submit"); -// btn.setOnAction( -// event2 -> { -// String regex = textField.getText(); -// RegexCondition regCond = new RegexCondition(regex, GraphInfo.getInstance().determineColor()); -// GraphInfo.getInstance().addCondition(regCond); -// graphScene.drawConditions(); -// newstage.close(); -// } -// ); -// box.add(new Label("Regex:"), 1, 1); -// box.add(textField, 1, 2, 3, 1); -// box.add(btn, 1, 3); -// Scene scene = new Scene(box); -// newstage.setScene(scene); -// newstage.show(); -// logger.info("state has been switched to centerId"); -// } else { -// errorPopup("Please load a graph."); -// } -// } -// ); MenuItem item2 = new MenuItem("Open Interaction"); item2.setOnAction(event -> { if (mainPane.getLeft() == null) { diff --git a/src/main/java/screens/scenes/Controller.java b/src/main/java/screens/scenes/Controller.java index d1e1392..867bbdc 100644 --- a/src/main/java/screens/scenes/Controller.java +++ b/src/main/java/screens/scenes/Controller.java @@ -1,12 +1,18 @@ package screens.scenes; +import datastructure.GenomeCountCondition; import datastructure.NodeGraph; +import datastructure.RegexCondition; +import javafx.collections.FXCollections; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.control.Button; +import javafx.scene.control.ChoiceBox; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.layout.GridPane; +import javafx.scene.paint.Color; +import screens.GraphInfo; import screens.Window; import services.ServiceLocator; @@ -18,18 +24,24 @@ public class Controller extends GridPane { * Labels. */ @SuppressWarnings("FieldCanBeLocal") - private Label currentCenter, centerInput, radius; + private Label currentCenter, centerInput, radius, genomeNum, genomeRegex; /** * Input fields. */ - private static TextField centerInputField, radiusInputField, currentCenterField; + private static TextField centerInputField, radiusInputField, currentCenterField, numGenomesField, regexGenomesField; /** * Submit button to initiate center queries. */ private Button submitButton; + private Button submitButtonNoGen; + + private Button submitRegex; + + private ChoiceBox choices; + /** * Scene where the graph is drawn. */ @@ -44,6 +56,53 @@ public class Controller extends GridPane { } }; + private EventHandler regexAction = event -> { + String regex = regexGenomesField.getText(); + RegexCondition regCond = new RegexCondition(regex, GraphInfo.getInstance().determineColor()); + GraphInfo.getInstance().addCondition(regCond); + graphScene.drawConditions(); + }; + + private EventHandler numGenomeAction = event -> { + if (numGenomesField.getText().length() == 0 || numGenomesField.getText().contains("\\D")) { + Window.errorPopup("Please enter a number as number of genomes."); + } else { + int number = Integer.parseInt(numGenomesField.getText()); + if (number < 0 || number >= GraphInfo.getInstance().getGenomesNum()) { + Window.errorPopup("Input number is out of bounds, \nplease provide a different input between 0 and : " + GraphInfo.getInstance().getGenomesNum() + "."); + } else { + int index = choices.getSelectionModel().getSelectedIndex(); + GenomeCountCondition gcc; + Color color = GraphInfo.getInstance().determineColor(); + switch (index) { + case 0: + gcc = new GenomeCountCondition(number, true, false, color); + GraphInfo.getInstance().addCondition(gcc); + break; + case 1: + gcc = new GenomeCountCondition(number, false, false, color); + GraphInfo.getInstance().addCondition(gcc); + break; + case 2: + gcc = new GenomeCountCondition(number, true, true, color); + GraphInfo.getInstance().addCondition(gcc); + break; + case 3: + gcc = new GenomeCountCondition(number, false, true, color); + GraphInfo.getInstance().addCondition(gcc); + break; + default: + Window.errorPopup("Please select a constraint."); + break; + } + graphScene.drawConditions(); + } + } + }; + + + + /** * Constructor. * @param serviceLocator ServiceLocator for locating services registered in that object. @@ -53,10 +112,18 @@ public class Controller extends GridPane { currentCenter = serviceLocator.getFxElementsFactory().createLabel("Current center:"); centerInput = serviceLocator.getFxElementsFactory().createLabel("Search center:"); radius = serviceLocator.getFxElementsFactory().createLabel("Radius:"); + genomeNum = serviceLocator.getFxElementsFactory().createLabel("No. of\ngenomes:"); + genomeRegex = serviceLocator.getFxElementsFactory().createLabel("Genome\nregex:"); currentCenterField = new TextField(); centerInputField = new TextField(); radiusInputField = new TextField(); + numGenomesField = new TextField(); + regexGenomesField = new TextField(); + submitButton = new Button("Submit"); + submitButtonNoGen = new Button("Submit"); + submitRegex = new Button("Submit"); + choices = new ChoiceBox(FXCollections.observableArrayList(">", "<", ">=", "<=")); controllerSettings(); this.add(currentCenter, 1, 1); this.add(currentCenterField, 2, 1); @@ -65,6 +132,13 @@ public class Controller extends GridPane { this.add(radius, 1, 3); this.add(radiusInputField, 2, 3); this.add(submitButton, 1, 4); + this.add(genomeNum, 1, 6); + this.add(choices, 2, 6); + this.add(numGenomesField, 2, 7); + this.add(submitButtonNoGen, 1, 7); + this.add(genomeRegex, 1, 9); + this.add(regexGenomesField, 2, 9); + this.add(submitRegex, 1, 10); serviceLocator.setController(this); } @@ -75,8 +149,12 @@ private void controllerSettings() { centerInputField.setMaxWidth(75d); radiusInputField.setMaxWidth(75d); currentCenterField.setMaxWidth(75d); + numGenomesField.setMaxWidth(75d); + regexGenomesField.setMaxWidth(75d); currentCenterField.setEditable(false); submitButton.setOnAction(buttonAction); + submitButtonNoGen.setOnAction(numGenomeAction); + submitRegex.setOnAction(regexAction); this.getStyleClass().addAll("grid", "border_bottom"); } From 63dac20817f90b7da0a69958da1c6c20b31eec7e Mon Sep 17 00:00:00 2001 From: Martijn Straatman Date: Thu, 8 Jun 2017 23:25:55 +0200 Subject: [PATCH 24/28] Add a legend with a possibility to clear a selected conditional --- src/main/java/screens/GraphInfo.java | 4 ++ src/main/java/screens/scenes/Controller.java | 62 ++++++++++++++++++-- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/src/main/java/screens/GraphInfo.java b/src/main/java/screens/GraphInfo.java index 6153519..557e74b 100644 --- a/src/main/java/screens/GraphInfo.java +++ b/src/main/java/screens/GraphInfo.java @@ -145,6 +145,10 @@ public Color determineColor() { return Color.GRAY; } + public void addColor(Color color) { + colors.add(color); + } + public void addCondition(Condition cond) { this.conditions.add(cond); } diff --git a/src/main/java/screens/scenes/Controller.java b/src/main/java/screens/scenes/Controller.java index 867bbdc..c4b092a 100644 --- a/src/main/java/screens/scenes/Controller.java +++ b/src/main/java/screens/scenes/Controller.java @@ -1,15 +1,20 @@ package screens.scenes; +import datastructure.Condition; import datastructure.GenomeCountCondition; import datastructure.NodeGraph; import datastructure.RegexCondition; +import java.util.ArrayList; import javafx.collections.FXCollections; +import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.control.Button; import javafx.scene.control.ChoiceBox; import javafx.scene.control.Label; +import javafx.scene.control.ListView; import javafx.scene.control.TextField; +import javafx.scene.control.cell.ComboBoxListCell; import javafx.scene.layout.GridPane; import javafx.scene.paint.Color; import screens.GraphInfo; @@ -24,7 +29,7 @@ public class Controller extends GridPane { * Labels. */ @SuppressWarnings("FieldCanBeLocal") - private Label currentCenter, centerInput, radius, genomeNum, genomeRegex; + private Label currentCenter, centerInput, radius, genomeNum, genomeRegex, legend; /** * Input fields. @@ -40,8 +45,14 @@ public class Controller extends GridPane { private Button submitRegex; + private Button condClear; + private ChoiceBox choices; + private ListView