org.structnetalign.util.GraphImageWriter.java Source code

Java tutorial

Introduction

Here is the source code for org.structnetalign.util.GraphImageWriter.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
 * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 * 
 * @author dmyersturnbull
 */
package org.structnetalign.util;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Properties;

import javax.imageio.ImageIO;

import org.apache.commons.collections15.Transformer;
import org.structnetalign.CleverGraph;
import org.structnetalign.Edge;
import org.structnetalign.HomologyEdge;
import org.structnetalign.InteractionEdge;
import org.structnetalign.PipelineProperties;

import edu.uci.ics.jung.algorithms.layout.KKLayout;
import edu.uci.ics.jung.graph.UndirectedGraph;
import edu.uci.ics.jung.visualization.Layer;
import edu.uci.ics.jung.visualization.VisualizationImageServer;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import edu.uci.ics.jung.visualization.renderers.Renderer.VertexLabel.Position;

public class GraphImageWriter {

    private static Properties props;
    static {
        props = new Properties();
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        InputStream stream = loader.getResourceAsStream("graph_image.properties");
        try {
            props.load(stream);
        } catch (IOException e) {
            throw new RuntimeException("Couldn't open graph image property file", e);
        }
    }

    private int vertexFontSize = Integer.parseInt(props.getProperty("vertex_font_size"));

    private int interactionFontSize = Integer.parseInt(props.getProperty("interaction_font_size"));

    private int homologyFontSize = Integer.parseInt(props.getProperty("homology_font_size"));

    private int height = Integer.parseInt(props.getProperty("height"));

    private Color homologyColor = parseColor(props.getProperty("homology_color"));

    private float homologyDash[] = { Float.parseFloat(props.getProperty("homology_dash")) };

    private Color interactionColor = parseColor(props.getProperty("interaction_color"));

    private float interactionDash[] = { Float.parseFloat(props.getProperty("interaction_dash")) };

    private int labelOffset = Integer.parseInt(props.getProperty("edge_label_offset"));

    private Color vertexColor = parseColor(props.getProperty("vertex_color"));

    private int vertexSize = Integer.parseInt(props.getProperty("vertex_size"));

    private int width = Integer.parseInt(props.getProperty("width"));

    private int xMargin = Integer.parseInt(props.getProperty("x_margin"));

    private int yMargin = Integer.parseInt(props.getProperty("y_margin"));

    private float interactionThicknessCoeff = Float.parseFloat(props.getProperty("interaction_thickness_coeff"));

    private float homologyThicknessCoeff = Float.parseFloat(props.getProperty("homology_thickness_coeff"));

    public void setInteractionThicknessCoeff(float interactionThicknessCoeff) {
        this.interactionThicknessCoeff = interactionThicknessCoeff;
    }

    public void setHomologyThicknessCoeff(float homologyThicknessCoeff) {
        this.homologyThicknessCoeff = homologyThicknessCoeff;
    }

    public void setVertexFontSize(int vertexFontSize) {
        this.vertexFontSize = vertexFontSize;
    }

    public void setHomologyFontSize(int homologyFontSize) {
        this.homologyFontSize = homologyFontSize;
    }

    private static Color parseColor(String s) {
        String[] p = s.split(",");
        int red = Integer.parseInt(p[0]);
        int blue = Integer.parseInt(p[1]);
        int green = Integer.parseInt(p[2]);
        return new Color(red, blue, green);
    }

    @Override
    public String toString() {
        return "GraphImageWriter [vertexFontSize=" + vertexFontSize + ", interactionFontSize=" + interactionFontSize
                + ", homologyFontSize=" + homologyFontSize + ", height=" + height + ", homologyColor="
                + homologyColor + ", homologyDash=" + Arrays.toString(homologyDash) + ", interactionColor="
                + interactionColor + ", interactionDash=" + Arrays.toString(interactionDash) + ", labelOffset="
                + labelOffset + ", vertexColor=" + vertexColor + ", vertexSize=" + vertexSize + ", width=" + width
                + ", xMargin=" + xMargin + ", yMargin=" + yMargin + ", interactionThicknessCoeff="
                + interactionThicknessCoeff + ", homologyThicknessCoeff=" + homologyThicknessCoeff + "]";
    }

    public static void main(String[] args) throws IOException {
        if (args.length != 3) {
            System.err.println(
                    "Usage: GraphImageWriter input-interaction-graphml-file input-homology-graphml-file output-png-file");
            return;
        }
        writeImage(new File(args[0]), new File(args[1]), new File(args[2]), 1800, 1800);
    }

    public static void writeImage(File interaction, File homology, File output, int width, int height) {
        CleverGraph graph = GraphMLAdaptor.readGraph(interaction, homology);
        GraphImageWriter writer = new GraphImageWriter(width, height);
        try {
            writer.writeGraph(graph, output);
        } catch (IOException e) {
            throw new RuntimeException("Couldn't write graph image to " + output, e);
        }
    }

    private static BufferedImage getImage(VisualizationImageServer<Integer, Edge> vv, Point2D center, Dimension d) {
        int width = vv.getWidth();
        int height = vv.getHeight();

        float scalex = (float) width / d.width;
        float scaley = (float) height / d.height;
        try {
            vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).scale(scalex, scaley,
                    center);

            BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D graphics = bi.createGraphics();
            graphics.setRenderingHints(vv.getRenderingHints());
            vv.paint(graphics);
            graphics.dispose();
            return bi;
        } finally {
            vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).setToIdentity();
        }
    }

    public GraphImageWriter() {
        this(4000, 4000);
    }

    public GraphImageWriter(int width, int height) {
        super();
        this.width = width;
        this.height = height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public void setHomologyColor(Color homologyColor) {
        this.homologyColor = homologyColor;
    }

    public void setHomologyDash(float[] homologyDash) {
        this.homologyDash = homologyDash;
    }

    public void setInteractionColor(Color interactionColor) {
        this.interactionColor = interactionColor;
    }

    public void setInteractionDash(float[] interactionDash) {
        this.interactionDash = interactionDash;
    }

    public void setLabelOffset(int labelOffset) {
        this.labelOffset = labelOffset;
    }

    public void setVertexColor(Color vertexColor) {
        this.vertexColor = vertexColor;
    }

    public void setVertexSize(int vertexSize) {
        this.vertexSize = vertexSize;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public void setXMargin(int xMargin) {
        this.xMargin = xMargin;
    }

    public void setYMargin(int yMargin) {
        this.yMargin = yMargin;
    }

    public void writeGraph(CleverGraph graph, File file) throws IOException {
        UndirectedGraph<Integer, Edge> combined = graph.buildCombinedGraph();
        writeGraph(combined, file);
    }

    public void writeGraph(UndirectedGraph<Integer, Edge> graph, File file) throws IOException {

        Dimension dim = new Dimension(width, height);

        KKLayout<Integer, Edge> layout = new KKLayout<>(graph);
        // layout.setAttractionMultiplier(attraction);
        // layout.setRepulsionMultiplier(repulsion);
        // layout.setMaxIterations(1000);
        layout.setSize(new Dimension(width - xMargin, height - yMargin));

        VisualizationImageServer<Integer, Edge> vv = new VisualizationImageServer<>(layout, dim);

        vv.setPreferredSize(dim);

        Transformer<Integer, Paint> vertexPaint = new Transformer<Integer, Paint>() {
            @Override
            public Paint transform(Integer i) {
                return vertexColor;
            }
        };
        vv.getRenderContext().setVertexFillPaintTransformer(vertexPaint);

        Transformer<Edge, Stroke> edgeStrokeTransformer = new Transformer<Edge, Stroke>() {
            @Override
            public Stroke transform(Edge edge) {
                if (edge instanceof HomologyEdge) {
                    final float thickness = (float) edge.getWeight() * homologyThicknessCoeff;
                    return new BasicStroke(thickness, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f,
                            homologyDash, 0.0f);
                } else if (edge instanceof InteractionEdge) {
                    final float thickness = (float) edge.getWeight() * interactionThicknessCoeff;
                    return new BasicStroke(thickness, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f,
                            interactionDash, 0.0f);
                }
                throw new IllegalArgumentException("Unknown edge type");
            }
        };
        vv.getRenderContext().setEdgeStrokeTransformer(edgeStrokeTransformer);

        Transformer<Edge, String> edgeLabeler = new Transformer<Edge, String>() {
            @Override
            public String transform(Edge edge) {
                String color = "";
                if (edge instanceof InteractionEdge) {
                    color = "rgb(" + interactionColor.getRed() + "," + interactionColor.getGreen() + ","
                            + interactionColor.getBlue() + ")";
                } else if (edge instanceof HomologyEdge) {
                    color = "rgb(" + homologyColor.getRed() + "," + homologyColor.getGreen() + ","
                            + homologyColor.getBlue() + ")";
                } else {
                    throw new IllegalArgumentException("Unknown edge type");
                }
                String prefix = "<html><font color=\"" + color + "\">";
                String suffix = "</font></html>";
                return prefix + PipelineProperties.getInstance().getOutputFormatter().format(edge.getWeight())
                        + suffix;
            }
        };
        vv.getRenderContext().setEdgeLabelTransformer(edgeLabeler);

        Transformer<Integer, Font> vertexFont = new Transformer<Integer, Font>() {
            private final Font font = new Font("Serif", Font.BOLD, vertexFontSize);

            @Override
            public Font transform(Integer edge) {
                return font;
            }
        };
        vv.getRenderContext().setVertexFontTransformer(vertexFont);

        Transformer<Edge, Font> edgeFont = new Transformer<Edge, Font>() {
            private final Font homologyFont = new Font("Serif", Font.BOLD, homologyFontSize);
            private final Font interactionFont = new Font("Serif", Font.BOLD, interactionFontSize);

            @Override
            public Font transform(Edge edge) {
                if (edge instanceof InteractionEdge) {
                    return interactionFont;
                } else if (edge instanceof HomologyEdge) {
                    return homologyFont;
                }
                throw new IllegalArgumentException("Unknown edge type");
            }
        };
        vv.getRenderContext().setEdgeFontTransformer(edgeFont);

        Transformer<Integer, Shape> vertexShape = new Transformer<Integer, Shape>() {
            private final Ellipse2D CIRCLE = new Ellipse2D.Double(-vertexSize / 2.0, -vertexSize / 2.0, vertexSize,
                    vertexSize);

            @Override
            public Shape transform(Integer i) {
                return CIRCLE;
            }
        };
        vv.getRenderContext().setVertexShapeTransformer(vertexShape);

        Transformer<Edge, Paint> edgeDrawPaint = new Transformer<Edge, Paint>() {
            @Override
            public Paint transform(Edge edge) {
                if (edge instanceof InteractionEdge) {
                    return interactionColor;
                } else if (edge instanceof HomologyEdge) {
                    return homologyColor;
                }
                throw new IllegalArgumentException("Unknown edge type");
            }
        };
        vv.getRenderContext().setEdgeDrawPaintTransformer(edgeDrawPaint);

        vv.getRenderContext().setLabelOffset(labelOffset);
        vv.getRenderer().getVertexLabelRenderer().setPosition(Position.CNTR);
        vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<Integer>());
        vv.getRenderContext().getEdgeLabelRenderer().setRotateEdgeLabels(false);
        vv.setOpaque(false);
        vv.setBackground(new Color(255, 255, 255, 0));

        writeImage(vv, file);

    }

    private void writeImage(VisualizationImageServer<Integer, Edge> vv, File file) throws IOException {
        Dimension dim = new Dimension(width, height);
        Point2D center = new Point2D.Double(width / 2.0 - xMargin / 2.0, height / 2.0 - yMargin / 2.0);
        BufferedImage image = getImage(vv, center, dim);
        ImageIO.write(image, "png", file);
    }
}