diff --git a/src/main/java/Enums/State.java b/src/main/java/Enums/State.java new file mode 100644 index 0000000000000000000000000000000000000000..3193f10a203d8a9bc3d6068c17bce34ed3d42035 --- /dev/null +++ b/src/main/java/Enums/State.java @@ -0,0 +1,12 @@ +package Enums; + +public enum State { + Empty, + Hydrophobic, + Hydrophilic, + HydrophobicMulti, + HydrophilicMulti, + Mixed, + ConnectionVertical, + ConnectionHorizontal +} diff --git a/src/main/java/Interfaces/Visualizer.java b/src/main/java/Interfaces/Visualizer.java index f93e288b9162a71a72e181d32872202f994d8e78..50dbf16ba7fdcfcbd12de2d221f30794f38cfb05 100644 --- a/src/main/java/Interfaces/Visualizer.java +++ b/src/main/java/Interfaces/Visualizer.java @@ -1,4 +1,91 @@ package Interfaces; +import Enums.State; +import MainClasses.Vertex; +import Visualization.Cell; + +import java.util.ArrayList; +import java.util.List; + public interface Visualizer { + + void drawProtein(ArrayList<Vertex> vertexListOriginal, double fit, int bond, int over, int gen); + + static ArrayList<Vertex> deepCopyVertexList (List<Vertex> vertexListOriginal) { + ArrayList<Vertex> vertexList = new ArrayList<>(); + for (Vertex v : vertexListOriginal) { + Vertex vNew = new Vertex(v.x, v.y, v.isHydrophobic, v.outgoingDirection); + vertexList.add(vNew); + } + return vertexList; + } + + static Cell[][] convertProteinTo2DArray(ArrayList<Vertex> vertexList) { + // Determine size + int minX = 0; + int maxX = 0; + int minY = 0; + int maxY = 0; + for (Vertex vertex : vertexList) { + if (vertex.x < minX) { + minX = vertex.x; + } + if (vertex.x > maxX) { + maxX = vertex.x; + } + if (vertex.y < minY) { + minY = vertex.y; + } + if (vertex.y > maxY) { + maxY = vertex.y; + } + } + + // Fix min values to 0 and double vertex coordinates to make room for connections + maxX += Math.abs(minX); + maxY += Math.abs(minY); + for (Vertex vertex : vertexList) { + vertex.x += Math.abs(minX); + vertex.x *= 2; + vertex.y += Math.abs(minY); + vertex.y *= 2; + } + + // Add vertexes and connections to 2d array + Cell[][] cellArray = new Cell[maxY * 2 + 1][maxX * 2 + 1]; + for (int yIndex = 0; yIndex < maxY * 2 + 1; yIndex++) { + for (int xIndex = 0; xIndex < maxX * 2 + 1; xIndex++) { + cellArray[yIndex][xIndex] = new Cell(); + } + } + + for (int i = 0; i < vertexList.size(); i++) { + Vertex vertex = vertexList.get(i); + if (vertex.isHydrophobic) { + cellArray[vertex.y][vertex.x].addState(State.Hydrophobic); + } else { + cellArray[vertex.y][vertex.x].addState(State.Hydrophilic); + } + cellArray[vertex.y][vertex.x].addAminoIndex(i); + + // Add connection, except on the last one + if (i + 1 != vertexList.size()) { + if (vertex.outgoingDirection == 0) { + cellArray[vertex.y + 1][vertex.x].addState(State.ConnectionVertical); + } else if (vertex.outgoingDirection == 1) { + cellArray[vertex.y][vertex.x + 1].addState(State.ConnectionHorizontal); + } else if (vertex.outgoingDirection == 2) { + cellArray[vertex.y - 1][vertex.x].addState(State.ConnectionVertical); + } else if (vertex.outgoingDirection == 3) { + cellArray[vertex.y][vertex.x - 1].addState(State.ConnectionHorizontal); + } + } + } + + return cellArray; + } + + void setFilename(String filename); + int getMaxH(); + int getMaxW(); } diff --git a/src/main/java/MainClasses/Config.java b/src/main/java/MainClasses/Config.java index 515e320959ff7bc643de9845488c6e733bdf0e62..42dbc7e4b2ab9ab926d43991d3f5325d93afb0aa 100644 --- a/src/main/java/MainClasses/Config.java +++ b/src/main/java/MainClasses/Config.java @@ -2,6 +2,7 @@ package MainClasses; import Enums.Selection; +import java.awt.*; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; @@ -25,6 +26,27 @@ public class Config { static int K; // Number of selected Candidates to face off in a tournament selection static String IMAGE_SEQUENCE_PATH; + // For images + public static final Font font = new Font("Sans-Serif", Font.PLAIN, 15); + public static final Color imageBackground = new Color(255, 255, 255); + public static final Color imageConnection = new Color(0, 0, 0); + public static final Color imageOutline = new Color(0, 0, 0); + public static final Color imageHydrophobic = new Color(205, 0, 0); + public static final Color imageHydrophilic = new Color(0, 0, 255); + public static final Color imageMixed = new Color(205, 0, 205); + public static final Color imageAminoText = new Color(0, 190, 190); + public static final Color imageText = new Color(0,0,0); + + // For console output + public static final String consoleEmpty = " "; + public static final String consoleHydrophobic = "(o)"; + public static final String consoleHydrophilic = "(i)"; + public static final String consoleHydrophobicMulti = "{o}"; + public static final String consoleHydrophilicMulti = "{i}"; + public static final String consoleMixed = "{z}"; + public static final String consoleConnectionVertical = " | "; + public static final String consoleConnectionHorizontal = "---"; + // Points per hydrophobic bond static int POINTS_PER_BOND; diff --git a/src/main/java/MainClasses/GeneticAlgorithm.java b/src/main/java/MainClasses/GeneticAlgorithm.java index b6951761aab2e365ac4f868842664e7936bfbcb0..6ba204f0307813411c91dcf603d560c5a7e4019c 100644 --- a/src/main/java/MainClasses/GeneticAlgorithm.java +++ b/src/main/java/MainClasses/GeneticAlgorithm.java @@ -3,14 +3,12 @@ package MainClasses; import Enums.DirectionNESW; import Evaluators.EvaluatorNESW; import InitialGenerationCreators.Curl; -import Interfaces.Evaluator; -import Interfaces.InitialGenerationCreator; -import Interfaces.Mutator; -import Interfaces.Selector; +import Interfaces.*; import Mutators.Crossover; import Mutators.SinglePoint; import Selectors.OnlyBest; -import Visualization.ProteinDrawer; +import Visualization.Visualizers.VisualizerNESWtoConsole; +import Visualization.Visualizers.VisualizerNESWtoFile; import java.io.IOException; import java.nio.file.Files; @@ -20,7 +18,7 @@ import java.util.Random; public class GeneticAlgorithm { Random rand = new Random(); - ProteinDrawer pdraw; + Visualizer visualizer; int[] isHydrophobic; Candidate[] population; @@ -40,7 +38,8 @@ public class GeneticAlgorithm { // Initialize with protein public GeneticAlgorithm (int[] protein) { this.isHydrophobic = protein; - this.pdraw = new ProteinDrawer(Config.IMAGE_SEQUENCE_PATH); +// this.visualizer = new VisualizerNESWtoConsole(); + this.visualizer = new VisualizerNESWtoFile(Config.IMAGE_SEQUENCE_PATH); // this.initialGenCreator = new RandomDirection<>(this.rand, DirectionNESW.class); // this.initialGenCreator = new StraightLine(); @@ -106,8 +105,8 @@ public class GeneticAlgorithm { int bonds = this.evaluator.evaluateBonds(this.population[bestIndex]); int overlaps = this.evaluator.evaluateOverlaps(this.population[bestIndex]); - this.pdraw.setFilename(String.format("gen_%07d.jpg",gen)); - this.pdraw.drawProteinToFile(this.population[bestIndex].getVertexList(), bestFitness, bonds, overlaps, gen); + this.visualizer.setFilename(String.format("gen_%07d.jpg",gen)); + this.visualizer.drawProtein(this.population[bestIndex].getVertexList(), bestFitness, bonds, overlaps, gen); System.out.println("The fitness is: " + bestFitness + " [hydrophobicBonds = " + bonds + " | overlaps = " + overlaps + "]"); @@ -134,4 +133,12 @@ public class GeneticAlgorithm { return bestIndex; } + + public int getMaxH() { + return this.visualizer.getMaxH(); + } + + public int getMaxW() { + return this.visualizer.getMaxH(); + } } diff --git a/src/main/java/MainClasses/Main.java b/src/main/java/MainClasses/Main.java index 76b68ab4dfa0ce6fa53c7e8d904486c6948d90c7..8d21429f453ef2fd437bcb6fec336a0b7f029750 100644 --- a/src/main/java/MainClasses/Main.java +++ b/src/main/java/MainClasses/Main.java @@ -15,8 +15,9 @@ public class Main { GeneticAlgorithm ga = new GeneticAlgorithm(protein); ga.simulateGenerations(); +// if (Config.isVidoable && Config.doVideo) try { - VideoCreator.createVideo(config.getProperties()); + VideoCreator.createVideo(config.getProperties(), ga.getMaxH(), ga.getMaxW()); } catch (IOException e) { e.printStackTrace(); } diff --git a/src/main/java/Visualization/Cell.java b/src/main/java/Visualization/Cell.java new file mode 100644 index 0000000000000000000000000000000000000000..c801e7051ea5865bd9be72ac658db473c2d883ae --- /dev/null +++ b/src/main/java/Visualization/Cell.java @@ -0,0 +1,48 @@ +package Visualization; + +import Enums.State; + +import java.util.ArrayList; + +public class Cell { + public ArrayList<State> states = new ArrayList<>(); + public ArrayList<Integer> aminoIndexes = new ArrayList<>(); + + public Cell() { + states.add(State.Empty); + } + + public void addState (State state) { + if (states.get(0).equals(State.Empty)) { + states.clear(); + } + states.add(state); + } + + public void addAminoIndex (int aminoIndex) { + aminoIndexes.add(aminoIndex); + } + + public State getRelevantDrawState () { + State rc = states.get(0); + if (states.size() > 1) { + if (rc.equals(State.Hydrophobic)) { + for (State s : states) { + if (s.equals(State.Hydrophilic)) { + return State.Mixed; + } + } + return State.HydrophobicMulti; + + } else if (rc.equals(State.Hydrophilic)) { + for (State s : states) { + if (s.equals(State.Hydrophobic)) { + return State.Mixed; + } + } + return State.HydrophilicMulti; + } + } + return rc; + } +} diff --git a/src/main/java/Visualization/ProteinDrawer.java b/src/main/java/Visualization/ProteinDrawer.java deleted file mode 100644 index 4a95ee9fb2dd7bc825a3a15b1a313c44be897197..0000000000000000000000000000000000000000 --- a/src/main/java/Visualization/ProteinDrawer.java +++ /dev/null @@ -1,354 +0,0 @@ -package Visualization; - -import MainClasses.Vertex; - -import javax.imageio.ImageIO; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -public class ProteinDrawer { - - String folder; - String filename; - - // Used only for the console output - String consoleEmpty = " "; - String consoleHydrophobic = "(o)"; - String consoleHydrophilic = "(i)"; - String consoleHydrophobicMulti = "{o}"; - String consoleHydrophilicMulti = "{i}"; - String consoleMixed = "{z}"; - String consoleConnectionVertical = " | "; - String consoleConnectionHorizontal = "---"; - - // For image - int pixelsPerCell = 40; - int margin = pixelsPerCell * 2; - int outline = 2; - public static final Font font = new Font("Sans-Serif", Font.PLAIN, 15); - public static final Color imageBackground = new Color(255, 255, 255); - public static final Color imageConnection = new Color(0, 0, 0); - public static final Color imageOutline = new Color(0, 0, 0); - public static final Color imageHydrophobic = new Color(205, 0, 0); - public static final Color imageHydrophilic = new Color(0, 0, 255); - public static final Color imageMixed = new Color(205, 0, 205); - public static final Color imageAminoText = new Color(180, 180, 180); - public static final Color imageText = new Color(0,0,0); - - public static int maxHeight; - public static int maxWidth; - - public ProteinDrawer(String folder) { - this.folder = folder; - this.filename = "image.jpg"; // Default - - maxHeight = 0; - maxWidth = 0; - } - - public void drawProteinToFile(ArrayList<Vertex> vertexListOriginal, double fit, int bond, int over, int gen) { - // Copy VertexList to be able to manipulate it - ArrayList<Vertex> vertexList = deepCopyVertexList(vertexListOriginal); - - Cell[][] cellArray = convertProteinTo2DArray(vertexList); - - int height = (cellArray.length * pixelsPerCell) + margin * 2; - int width = (cellArray[0].length * pixelsPerCell) + margin * 2; - - if (height > maxHeight) { - maxHeight = height; - } - if (width > maxWidth) { - maxWidth = width; - } - - BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); - Graphics2D g2 = image.createGraphics(); - g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - g2.setFont(font); - FontMetrics metrics = g2.getFontMetrics(); - int ascent = metrics.getAscent(); - - // Background - g2.setColor(imageBackground); - g2.fillRect(0, 0, width, height); - - for (int yIndex = cellArray.length-1; yIndex >= 0; yIndex--) { - int yIndexPosition = cellArray.length-1 - yIndex; - - for (int xIndex = 0; xIndex < cellArray[0].length; xIndex++) { - Color aminoColor = null; - - State cellState = cellArray[yIndex][xIndex].getRelevantDrawState(); - - switch (cellState) { - case Empty: - break; - - case Hydrophobic: - case HydrophobicMulti: - aminoColor = imageHydrophobic; - break; - - case Hydrophilic: - case HydrophilicMulti: - aminoColor = imageHydrophilic; - break; - - case Mixed: - aminoColor = imageMixed; - break; - - case ConnectionVertical: - g2.setColor(imageConnection); - g2.fillRect((xIndex * pixelsPerCell) + margin + (pixelsPerCell/2)-outline, - (yIndexPosition * pixelsPerCell) + margin, - outline * 2, pixelsPerCell); - break; - - case ConnectionHorizontal: - g2.setColor(imageConnection); - g2.fillRect((xIndex * pixelsPerCell) + margin, - (yIndexPosition * pixelsPerCell) + margin + (pixelsPerCell/2)-outline, - pixelsPerCell, outline * 2); - break; - } - - if (aminoColor != null) { - g2.setColor(imageOutline); - g2.fillRect((xIndex * pixelsPerCell) + margin, (yIndexPosition * pixelsPerCell) + margin, - pixelsPerCell, pixelsPerCell); - g2.setColor(aminoColor); - g2.fillRect((xIndex * pixelsPerCell) + outline + margin, (yIndexPosition * pixelsPerCell) + outline + margin, - pixelsPerCell - (outline * 2), pixelsPerCell - (outline * 2)); - - g2.setColor(imageAminoText); - String label = ""; - for (int aminoIndex : cellArray[yIndex][xIndex].aminoIndexes) { - label += aminoIndex + " "; - } - int labelWidth = metrics.stringWidth(label); - int x = (xIndex * pixelsPerCell) + margin + (pixelsPerCell/2) - (labelWidth/2) + outline; - int y = (yIndexPosition * pixelsPerCell) + margin + (pixelsPerCell/2) + (ascent/2) - outline; - g2.drawString(label, x, y); - } - } - } - - g2.setColor(imageText); - String label = "Gen: " + gen - + " Fitness: " + String.format("%.4f", fit) - + " H/H Bonds: " + bond - + " Overlaps: " + over; - int labelWidth = metrics.stringWidth(label); - int x = margin / 4; - int y = margin / 4; - g2.drawString(label, x, y); - - if (!new File(folder).exists()) new File(folder).mkdirs(); - - try { - ImageIO.write(image, "jpg", new File(folder + File.separator + filename)); - } catch (IOException e) { - e.printStackTrace(); - System.exit(0); - } - } - - public void printProtein(ArrayList<Vertex> vertexListOriginal) { - // Copy VertexList to be able to manipulate it - ArrayList<Vertex> vertexList = deepCopyVertexList(vertexListOriginal); - - Cell[][] cellArray = convertProteinTo2DArray(vertexList); - - for (int yIndex = cellArray.length-1; yIndex >= 0; yIndex--) { - for (int xIndex = 0; xIndex < cellArray[0].length; xIndex++) { - System.out.print(convertCellToString(cellArray[yIndex][xIndex])); - } - System.out.println(); - } - System.out.println(); - } - - private ArrayList<Vertex> deepCopyVertexList (List<Vertex> vertexListOriginal) { - ArrayList<Vertex> vertexList = new ArrayList<>(); - for (Vertex v : vertexListOriginal) { - Vertex vNew = new Vertex(v.x, v.y, v.isHydrophobic, v.outgoingDirection); - vertexList.add(vNew); - } - return vertexList; - } - - private Cell[][] convertProteinTo2DArray(ArrayList<Vertex> vertexList) { - // Determine size - int minX = 0; - int maxX = 0; - int minY = 0; - int maxY = 0; - for (Vertex vertex : vertexList) { - if (vertex.x < minX) { - minX = vertex.x; - } - if (vertex.x > maxX) { - maxX = vertex.x; - } - if (vertex.y < minY) { - minY = vertex.y; - } - if (vertex.y > maxY) { - maxY = vertex.y; - } - } - - // Fix min values to 0 and double vertex coordinates to make room for connections - maxX += Math.abs(minX); - maxY += Math.abs(minY); - for (Vertex vertex : vertexList) { - vertex.x += Math.abs(minX); - vertex.x *= 2; - vertex.y += Math.abs(minY); - vertex.y *= 2; - } - - // Add vertexes and connections to 2d array - Cell[][] cellArray = new Cell[maxY * 2 + 1][maxX * 2 + 1]; - for (int yIndex = 0; yIndex < maxY * 2 + 1; yIndex++) { - for (int xIndex = 0; xIndex < maxX * 2 + 1; xIndex++) { - cellArray[yIndex][xIndex] = new Cell(); - } - } - - for (int i = 0; i < vertexList.size(); i++) { - Vertex vertex = vertexList.get(i); - if (vertex.isHydrophobic) { - cellArray[vertex.y][vertex.x].addState(State.Hydrophobic); - } else { - cellArray[vertex.y][vertex.x].addState(State.Hydrophilic); - } - cellArray[vertex.y][vertex.x].addAminoIndex(i); - - // Add connection, except on the last one - if (i + 1 != vertexList.size()) { - if (vertex.outgoingDirection == 0) { - cellArray[vertex.y + 1][vertex.x].addState(State.ConnectionVertical); - } else if (vertex.outgoingDirection == 1) { - cellArray[vertex.y][vertex.x + 1].addState(State.ConnectionHorizontal); - } else if (vertex.outgoingDirection == 2) { - cellArray[vertex.y - 1][vertex.x].addState(State.ConnectionVertical); - } else if (vertex.outgoingDirection == 3) { - cellArray[vertex.y][vertex.x - 1].addState(State.ConnectionHorizontal); - } - } - } - - return cellArray; - } - - private String convertCellToString(Cell cell) { - - State cellState = cell.getRelevantDrawState (); - - switch (cellState) { - case Empty: - return consoleEmpty; - - case Hydrophobic: - return consoleHydrophobic; - - case Hydrophilic: - return consoleHydrophilic; - - case HydrophobicMulti: - return consoleHydrophobicMulti; - - case HydrophilicMulti: - return consoleHydrophilicMulti; - - case Mixed: - return consoleMixed; - - case ConnectionVertical: - return consoleConnectionVertical; - - case ConnectionHorizontal: - return consoleConnectionHorizontal; - - } - // Fallback - return consoleEmpty; - } - - public String getFolder() { - return folder; - } - - public void setFolder(String folder) { - this.folder = folder; - } - - public String getFilename() { - return filename; - } - - public void setFilename(String filename) { - this.filename = filename; - } -} - -class Cell { - ArrayList<State> states = new ArrayList<>(); - ArrayList<Integer> aminoIndexes = new ArrayList<>(); - - public Cell() { - states.add(State.Empty); - } - - public void addState (State state) { - if (states.get(0).equals(State.Empty)) { - states.clear(); - } - states.add(state); - } - - public void addAminoIndex (int aminoIndex) { - aminoIndexes.add(aminoIndex); - } - - public State getRelevantDrawState () { - State rc = states.get(0); - if (states.size() > 1) { - if (rc.equals(State.Hydrophobic)) { - for (State s : states) { - if (s.equals(State.Hydrophilic)) { - return State.Mixed; - } - } - return State.HydrophobicMulti; - - } else if (rc.equals(State.Hydrophilic)) { - for (State s : states) { - if (s.equals(State.Hydrophobic)) { - return State.Mixed; - } - } - return State.HydrophilicMulti; - } - } - return rc; - } -} - -enum State { - Empty, - Hydrophobic, - Hydrophilic, - HydrophobicMulti, - HydrophilicMulti, - Mixed, - ConnectionVertical, - ConnectionHorizontal -} \ No newline at end of file diff --git a/src/main/java/Visualization/VideoCreator.java b/src/main/java/Visualization/VideoCreator.java index f3041c35b8927030fecdb9d337c9775630e12b8d..af4ddb9981a921c993308195eebe7b68e63eab75 100644 --- a/src/main/java/Visualization/VideoCreator.java +++ b/src/main/java/Visualization/VideoCreator.java @@ -1,5 +1,7 @@ package Visualization; +import MainClasses.Config; + import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.File; @@ -28,14 +30,14 @@ public class VideoCreator{ } }; - private static int[] resizeImages(String imagesPath) throws IOException { + private static int[] resizeImages(String imagesPath, int maxH, int maxW) throws IOException { dir = new File(imagesPath); int[] widthHeight = new int[2]; if (dir.isDirectory()) { // reads input images and determines maximum required size - int maxHeight = ProteinDrawer.maxHeight; - int maxWidth = ProteinDrawer.maxWidth; + int maxHeight = maxH; + int maxWidth = maxW; if (maxHeight <= 0 || maxWidth <= 0) { int counter = 1; @@ -71,7 +73,7 @@ public class VideoCreator{ // draws input image to the top left corner Graphics2D g2d = outputImage.createGraphics(); - g2d.setColor(ProteinDrawer.imageBackground); + g2d.setColor(Config.imageBackground); g2d.fillRect(0,0, maxWidth, maxHeight); g2d.drawImage(inputImage, 0, 0, inputImage.getWidth(), inputImage.getHeight(), null); g2d.dispose(); @@ -85,13 +87,13 @@ public class VideoCreator{ } // MainClasses.Main function - public static void createVideo(Properties properties) throws IOException { + public static void createVideo(Properties properties, int maxH, int maxW) throws IOException { String imagesPath = properties.getProperty("imageSequencePath"); String videoPathAndFile = properties.getProperty("videoPathAndFile"); int imgInterval = Integer.parseInt(properties.getProperty("imgInterval")); dir = new File(imagesPath); - int[] widthHeight = VideoCreator.resizeImages(imagesPath); + int[] widthHeight = VideoCreator.resizeImages(imagesPath, maxH, maxW); File file = new File(videoPathAndFile); if (!file.exists()) { diff --git a/src/main/java/Visualization/Visualizers/VisualizerNESWtoConsole.java b/src/main/java/Visualization/Visualizers/VisualizerNESWtoConsole.java new file mode 100644 index 0000000000000000000000000000000000000000..22af4d1bcd05f8687644ed651c6443a795ba3616 --- /dev/null +++ b/src/main/java/Visualization/Visualizers/VisualizerNESWtoConsole.java @@ -0,0 +1,90 @@ +package Visualization.Visualizers; + +import Enums.State; +import Interfaces.Visualizer; +import MainClasses.Config; +import MainClasses.Vertex; +import Visualization.Cell; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; + +public class VisualizerNESWtoConsole implements Visualizer { + + int maxHeight; + int maxWidth; + + public VisualizerNESWtoConsole() { + this.maxHeight = 0; + this.maxWidth = 0; + } + + public void drawProtein(ArrayList<Vertex> vertexListOriginal, double fit, int bond, int over, int gen) { + // Copy VertexList to be able to manipulate it + ArrayList<Vertex> vertexList = Visualizer.deepCopyVertexList(vertexListOriginal); + + Cell[][] cellArray = Visualizer.convertProteinTo2DArray(vertexList); + + for (int yIndex = cellArray.length-1; yIndex >= 0; yIndex--) { + for (int xIndex = 0; xIndex < cellArray[0].length; xIndex++) { + System.out.print(convertCellToString(cellArray[yIndex][xIndex])); + } + System.out.println(); + } + System.out.println(); + } + + private String convertCellToString(Cell cell) { + + State cellState = cell.getRelevantDrawState (); + + switch (cellState) { + case Empty: + return Config.consoleEmpty; + + case Hydrophobic: + return Config.consoleHydrophobic; + + case Hydrophilic: + return Config.consoleHydrophilic; + + case HydrophobicMulti: + return Config.consoleHydrophobicMulti; + + case HydrophilicMulti: + return Config.consoleHydrophilicMulti; + + case Mixed: + return Config.consoleMixed; + + case ConnectionVertical: + return Config.consoleConnectionVertical; + + case ConnectionHorizontal: + return Config.consoleConnectionHorizontal; + + } + // Fallback + return Config.consoleEmpty; + } + + + @Override + public void setFilename(String format) { + // Only here so file based visualizers work + } + + @Override + public int getMaxH() { + return this.maxHeight; + } + + @Override + public int getMaxW() { + return this.maxWidth; + } +} diff --git a/src/main/java/Visualization/Visualizers/VisualizerNESWtoFile.java b/src/main/java/Visualization/Visualizers/VisualizerNESWtoFile.java new file mode 100644 index 0000000000000000000000000000000000000000..0300a1a50edf19187b46cb5f8f04f9d3576a9727 --- /dev/null +++ b/src/main/java/Visualization/Visualizers/VisualizerNESWtoFile.java @@ -0,0 +1,160 @@ +package Visualization.Visualizers; + +import Enums.State; +import Interfaces.Visualizer; +import MainClasses.Config; +import MainClasses.Vertex; +import Visualization.Cell; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; + +public class VisualizerNESWtoFile implements Visualizer { + + String folder; + String filename; + + int maxHeight; + int maxWidth; + + // For image sizing + int pixelsPerCell = 40; + int margin = pixelsPerCell * 2; + int outline = 2; + + public VisualizerNESWtoFile(String folder) { + this.folder = folder; + this.filename = "image.jpg"; // Default + + this.maxHeight = 0; + this.maxWidth = 0; + } + + public void drawProtein(ArrayList<Vertex> vertexListOriginal, double fit, int bond, int over, int gen) { + // Copy VertexList to be able to manipulate it + ArrayList<Vertex> vertexList = Visualizer.deepCopyVertexList(vertexListOriginal); + + Cell[][] cellArray = Visualizer.convertProteinTo2DArray(vertexList); + + int height = (cellArray.length * pixelsPerCell) + margin * 2; + int width = (cellArray[0].length * pixelsPerCell) + margin * 2; + + if (height > maxHeight) { + maxHeight = height; + } + if (width > maxWidth) { + maxWidth = width; + } + + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics2D g2 = image.createGraphics(); + g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g2.setFont(Config.font); + FontMetrics metrics = g2.getFontMetrics(); + int ascent = metrics.getAscent(); + + // Background + g2.setColor(Config.imageBackground); + g2.fillRect(0, 0, width, height); + + for (int yIndex = cellArray.length-1; yIndex >= 0; yIndex--) { + int yIndexPosition = cellArray.length-1 - yIndex; + + for (int xIndex = 0; xIndex < cellArray[0].length; xIndex++) { + Color aminoColor = null; + + State cellState = cellArray[yIndex][xIndex].getRelevantDrawState(); + + switch (cellState) { + case Empty: + break; + + case Hydrophobic: + case HydrophobicMulti: + aminoColor = Config.imageHydrophobic; + break; + + case Hydrophilic: + case HydrophilicMulti: + aminoColor = Config.imageHydrophilic; + break; + + case Mixed: + aminoColor = Config.imageMixed; + break; + + case ConnectionVertical: + g2.setColor(Config.imageConnection); + g2.fillRect((xIndex * pixelsPerCell) + margin + (pixelsPerCell/2)-outline, + (yIndexPosition * pixelsPerCell) + margin, + outline * 2, pixelsPerCell); + break; + + case ConnectionHorizontal: + g2.setColor(Config.imageConnection); + g2.fillRect((xIndex * pixelsPerCell) + margin, + (yIndexPosition * pixelsPerCell) + margin + (pixelsPerCell/2)-outline, + pixelsPerCell, outline * 2); + break; + } + + if (aminoColor != null) { + g2.setColor(Config.imageOutline); + g2.fillRect((xIndex * pixelsPerCell) + margin, (yIndexPosition * pixelsPerCell) + margin, + pixelsPerCell, pixelsPerCell); + g2.setColor(aminoColor); + g2.fillRect((xIndex * pixelsPerCell) + outline + margin, (yIndexPosition * pixelsPerCell) + outline + margin, + pixelsPerCell - (outline * 2), pixelsPerCell - (outline * 2)); + + g2.setColor(Config.imageAminoText); + String label = ""; + for (int aminoIndex : cellArray[yIndex][xIndex].aminoIndexes) { + label += aminoIndex + " "; + } + int labelWidth = metrics.stringWidth(label); + int x = (xIndex * pixelsPerCell) + margin + (pixelsPerCell/2) - (labelWidth/2) + outline; + int y = (yIndexPosition * pixelsPerCell) + margin + (pixelsPerCell/2) + (ascent/2) - outline; + g2.drawString(label, x, y); + } + } + } + + g2.setColor(Config.imageText); + String label = "Gen: " + gen + + " Fitness: " + String.format("%.4f", fit) + + " H/H Bonds: " + bond + + " Overlaps: " + over; + int labelWidth = metrics.stringWidth(label); + int x = margin / 4; + int y = margin / 4; + g2.drawString(label, x, y); + + if (!new File(folder).exists()) new File(folder).mkdirs(); + + try { + ImageIO.write(image, "jpg", new File(folder + File.separator + filename)); + } catch (IOException e) { + e.printStackTrace(); + System.exit(0); + } + } + + @Override + public void setFilename(String filename) { + this.filename = filename; + } + + @Override + public int getMaxH() { + return this.maxHeight; + } + + @Override + public int getMaxW() { + return this.maxWidth; + } +}