Java tutorial
/** * This file is part of GeneMANIA. * Copyright (C) 2008-2011 University of Toronto. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package org.genemania.plugin.cytoscape; import java.io.IOException; import java.io.StringWriter; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.WeakHashMap; import org.apache.commons.beanutils.BeanUtils; import org.codehaus.jackson.JsonFactory; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.map.MappingJsonFactory; import org.genemania.domain.Attribute; import org.genemania.domain.AttributeGroup; import org.genemania.domain.Gene; import org.genemania.domain.GeneNamingSource; import org.genemania.domain.Interaction; import org.genemania.domain.InteractionNetwork; import org.genemania.domain.InteractionNetworkGroup; import org.genemania.domain.Node; import org.genemania.domain.Tag; import org.genemania.plugin.LogUtils; import org.genemania.plugin.NetworkUtils; import org.genemania.plugin.Strings; import org.genemania.plugin.data.DataSet; import org.genemania.plugin.model.AnnotationEntry; import org.genemania.plugin.model.Group; import org.genemania.plugin.model.Network; import org.genemania.plugin.model.SearchResult; import org.genemania.plugin.model.ViewState; import org.genemania.plugin.model.ViewStateBuilder; import org.genemania.plugin.proxies.EdgeProxy; import org.genemania.plugin.proxies.NetworkProxy; import org.genemania.plugin.proxies.NodeProxy; public abstract class AbstractCytoscapeUtils<NETWORK, NODE, EDGE> implements CytoscapeUtils<NETWORK, NODE, EDGE> { private static final String EDGE_TYPE_INTERACTION = "interaction"; //$NON-NLS-1$ protected static final double MINIMUM_NODE_SIZE = 10; protected static final double MAXIMUM_NODE_SIZE = 40; protected static final double MINIMUM_EDGE_WIDTH = 1; protected static final double MAXIMUM_EDGE_WIDTH = 6; private final Map<EDGE, EdgeProxy<EDGE, NODE>> edgeProxies; private final Map<NODE, NodeProxy<NODE>> nodeProxies; private final Map<NETWORK, NetworkProxy<NETWORK, NODE, EDGE>> networkProxies; private final Map<String, AttributeHandler> attributeHandlerRegistry = createHandlerRegistry(); protected final NetworkUtils networkUtils; public AbstractCytoscapeUtils(NetworkUtils networkUtils) { this.networkUtils = networkUtils; edgeProxies = new WeakHashMap<EDGE, EdgeProxy<EDGE, NODE>>(); nodeProxies = new WeakHashMap<NODE, NodeProxy<NODE>>(); networkProxies = new WeakHashMap<NETWORK, NetworkProxy<NETWORK, NODE, EDGE>>(); } @Override public EdgeProxy<EDGE, NODE> getEdgeProxy(EDGE edge, NETWORK network) { if (edge == null) { return null; } if (edgeProxies.containsKey(edge)) { return edgeProxies.get(edge); } EdgeProxy<EDGE, NODE> proxy = createEdgeProxy(edge, network); edgeProxies.put(edge, proxy); return proxy; } @Override public NetworkProxy<NETWORK, NODE, EDGE> getNetworkProxy(NETWORK network) { if (network == null) { return null; } if (networkProxies.containsKey(network)) { return networkProxies.get(network); } NetworkProxy<NETWORK, NODE, EDGE> proxy = createNetworkProxy(network); networkProxies.put(network, proxy); return proxy; } @Override public NodeProxy<NODE> getNodeProxy(NODE node, NETWORK network) { if (node == null) { return null; } if (nodeProxies.containsKey(node)) { return nodeProxies.get(node); } NodeProxy<NODE> proxy = createNodeProxy(node, network); nodeProxies.put(node, proxy); return proxy; } protected abstract NodeProxy<NODE> createNodeProxy(NODE node, NETWORK network); protected abstract NetworkProxy<NETWORK, NODE, EDGE> createNetworkProxy(NETWORK network); protected abstract EdgeProxy<EDGE, NODE> createEdgeProxy(EDGE edge, NETWORK network); @SuppressWarnings("unchecked") public void expandAttributes(NETWORK cyNetwork, ViewState options, List<String> attributes) { if (attributes.size() == 0) { return; } NetworkProxy<NETWORK, NODE, EDGE> networkProxy = getNetworkProxy(cyNetwork); for (EDGE edge : networkProxy.getEdges()) { EdgeProxy<EDGE, NODE> edgeProxy = getEdgeProxy(edge, cyNetwork); String edgeId = edgeProxy.getIdentifier(); Set<Network<?>> networks = options.getNetworksByEdge(edgeId); List<String> networkNames = edgeProxy.getAttribute(NETWORK_NAMES_ATTRIBUTE, List.class); for (String attribute : attributes) { List<Object> values = new ArrayList<Object>(); AttributeHandler handler = attributeHandlerRegistry.get(attribute); for (String networkName : networkNames) { InteractionNetwork network = findNetwork(networkName, networks); values.add(handler.getValue(network)); } edgeProxy.setAttribute(attribute, values); } } } private InteractionNetwork findNetwork(String networkName, Set<Network<?>> networks) { for (Network<?> network : networks) { InteractionNetwork adapted = network.adapt(InteractionNetwork.class); if (adapted == null) { continue; } if (adapted.getName().equals(networkName)) { return adapted; } } return null; } interface AttributeHandler { public abstract Object getValue(InteractionNetwork network); } static class TagAttributeHandler implements AttributeHandler { public Object getValue(InteractionNetwork network) { StringBuilder builder = new StringBuilder(); for (Tag tag : network.getTags()) { if (builder.length() > 0) { builder.append("|"); //$NON-NLS-1$ } builder.append(tag.getName()); } return builder.toString(); } } static class MetadataAttributeHandler implements AttributeHandler { private String name; public MetadataAttributeHandler(String attributeName) { name = attributeName; } public Object getValue(InteractionNetwork network) { try { return BeanUtils.getProperty(network.getMetadata(), name); } catch (IllegalAccessException e) { return null; } catch (InvocationTargetException e) { return null; } catch (NoSuchMethodException e) { return null; } } } private Map<String, AttributeHandler> createHandlerRegistry() { Map<String, AttributeHandler> map = new HashMap<String, AttributeHandler>(); map.put(TAGS, new TagAttributeHandler()); for (String name : new String[] { AUTHORS, INTERACTION_COUNT, PUBMED_ID, PROCESSING_DESCRIPTION, PUBLICATION_NAME, YEAR_PUBLISHED, SOURCE, SOURCE_URL, TITLE, URL, }) { map.put(name, new MetadataAttributeHandler(name)); } return map; } /** * Returns the <code>NODE</code> that corresponds to the given * <code>Node</code>. If the <code>NODE</code> does not already * exist, a new one is created. * * @param node * @param preferredSymbol * @return */ public NODE getNode(NETWORK network, Node node, String preferredSymbol) { String id = getNodeId(network, node); NODE target = getNode(id, network); if (target != null) { return target; } String name; if (preferredSymbol == null) { Gene gene = networkUtils.getPreferredGene(node); if (gene == null) { name = Strings.missingGeneName; } else { name = gene.getSymbol(); } } else { name = preferredSymbol; } target = createNode(id, network); NodeProxy<NODE> nodeProxy = getNodeProxy(target, network); nodeProxy.setAttribute(GENE_NAME_ATTRIBUTE, name); exportSynonyms(nodeProxy, node); return target; } protected String getNodeId(NETWORK network, Node node) { NetworkProxy<NETWORK, NODE, EDGE> proxy = getNetworkProxy(network); return String.format("%s-%s", filterTitle(proxy.getTitle()), node.getName()); //$NON-NLS-1$ } protected String getNodeId(NETWORK network, Attribute attribute) { NetworkProxy<NETWORK, NODE, EDGE> proxy = getNetworkProxy(network); return String.format("%s-%s", filterTitle(proxy.getTitle()), attribute.getName()); //$NON-NLS-1$ } private String filterTitle(String title) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < title.length(); i++) { char character = title.charAt(i); if (Character.isLetterOrDigit(character)) { builder.append(character); } else { builder.append("_"); //$NON-NLS-1$ } } return builder.toString(); } private void exportSynonyms(NodeProxy<NODE> proxy, Node node) { Collection<Gene> genes = node.getGenes(); for (Gene gene : genes) { GeneNamingSource source = gene.getNamingSource(); source.getName(); proxy.setAttribute(source.getName(), gene.getSymbol()); } } protected abstract NODE getNode(String id, NETWORK network); protected abstract NODE createNode(String id, NETWORK network); protected abstract NETWORK createNetwork(String title); protected abstract EDGE getEdge(NODE from, NODE to, String type, String label, NETWORK network); protected abstract EDGE getEdge(String id, NETWORK network); /** * Creates a Cytoscape network from the interaction network given by * <code>RelatedResult</code>. * * @param name the name of the new <code>NetworkProxy<NETWORK, NODE, EDGE></code> * @param result the results from running the GeneMANIA algorithm * @param queryGenes the genes used to * @return */ @Override public NETWORK createNetwork(DataSet data, String name, SearchResult options, ViewStateBuilder builder, EdgeAttributeProvider attributeProvider) { NETWORK currentNetwork = createNetwork(name); NetworkProxy<NETWORK, NODE, EDGE> networkProxy = getNetworkProxy(currentNetwork); networkProxy.setAttribute(TYPE_ATTRIBUTE, GENEMANIA_NETWORK_TYPE); networkProxy.setAttribute(DATA_VERSION_ATTRIBUTE, data.getVersion().toString()); networkProxy.setAttribute(ORGANISM_NAME_ATTRIBUTE, options.getOrganism().getName()); networkProxy.setAttribute(NETWORKS_ATTRIBUTE, serializeNetworks(options)); networkProxy.setAttribute(COMBINING_METHOD_ATTRIBUTE, options.getCombiningMethod().getCode()); networkProxy.setAttribute(GENE_SEARCH_LIMIT_ATTRIBUTE, options.getGeneSearchLimit()); networkProxy.setAttribute(ATTRIBUTE_SEARCH_LIMIT_ATTRIBUTE, options.getAttributeSearchLimit()); networkProxy.setAttribute(ANNOTATIONS_ATTRIBUTE, serializeAnnotations(options)); for (Group<?, ?> group : builder.getAllGroups()) { Group<InteractionNetworkGroup, InteractionNetwork> adapted = group.adapt(InteractionNetworkGroup.class, InteractionNetwork.class); if (adapted == null) { continue; } for (Network<InteractionNetwork> network : adapted.getNetworks()) { Collection<Interaction> sourceInteractions = network.getModel().getInteractions(); if (sourceInteractions == null || sourceInteractions.size() == 0) { continue; } buildGraph(currentNetwork, sourceInteractions, network, attributeProvider, options, builder); } } // Add all query genes in case they don't show up in the results for (Gene gene : options.getQueryGenes().values()) { Node node = gene.getNode(); getNode(currentNetwork, node, getSymbol(gene)); } // Create attributes Map<Long, Network<Attribute>> attributesById = new HashMap<Long, Network<Attribute>>(); for (Group<?, ?> group : builder.getAllGroups()) { Group<AttributeGroup, Attribute> adapted = group.adapt(AttributeGroup.class, Attribute.class); if (adapted == null) { continue; } for (Network<Attribute> network : adapted.getNetworks()) { attributesById.put(network.getModel().getId(), network); } } Map<Attribute, Double> weights = options.getAttributeWeights(); for (Entry<Long, Collection<Attribute>> entry : options.getAttributesByNodeId().entrySet()) { Gene gene = options.getGene(entry.getKey()); NODE to = getNode(currentNetwork, gene.getNode(), null); for (Attribute attribute : entry.getValue()) { String id = getNodeId(currentNetwork, attribute); Network<Attribute> network = attributesById.get(attribute.getId()); NODE from = getNode(id, currentNetwork); if (from == null) { from = createNode(id, currentNetwork); NodeProxy<NODE> nodeProxy = getNodeProxy(from, currentNetwork); nodeProxy.setAttribute(GENE_NAME_ATTRIBUTE, attribute.getName()); nodeProxy.setAttribute(NODE_TYPE_ATTRIBUTE, NODE_TYPE_ATTRIBUTE_NODE); nodeProxy.setAttribute(SCORE_ATTRIBUTE, weights.get(attribute)); builder.addSourceNetworkForNode(nodeProxy.getIdentifier(), network); } String edgeLabel = attribute.getName(); EDGE edge = getEdge(from, to, EDGE_TYPE_INTERACTION, edgeLabel, currentNetwork); EdgeProxy<EDGE, NODE> edgeProxy = getEdgeProxy(edge, currentNetwork); AttributeGroup group = options.getAttributeGroup(attribute.getId()); edgeProxy.setAttribute(NETWORK_GROUP_NAME_ATTRIBUTE, group.getName()); edgeProxy.setAttribute(ATTRIBUTE_NAME_ATTRIBUTE, edgeLabel); edgeProxy.setAttribute(HIGHLIGHT_ATTRIBUTE, 1); String edgeId = edgeProxy.getIdentifier(); builder.addEdge(builder.getGroup(network), edgeId); builder.addSourceNetworkForEdge(edgeId, network); } } decorateNodes(currentNetwork, options); return currentNetwork; } private String serializeAnnotations(SearchResult options) { StringWriter writer = new StringWriter(); JsonFactory jsonFactory = new MappingJsonFactory(); try { JsonGenerator generator = jsonFactory.createJsonGenerator(writer); generator.writeStartArray(); List<AnnotationEntry> enrichmentSummary = options.getEnrichmentSummary(); for (AnnotationEntry entry : enrichmentSummary) { generator.writeStartObject(); generator.writeFieldName("name"); //$NON-NLS-1$ generator.writeString(entry.getName()); generator.writeFieldName("description"); //$NON-NLS-1$ generator.writeString(entry.getDescription()); generator.writeFieldName("qValue"); //$NON-NLS-1$ generator.writeNumber(entry.getQValue()); generator.writeFieldName("sample"); //$NON-NLS-1$ generator.writeNumber(entry.getSampleOccurrences()); generator.writeFieldName("total"); //$NON-NLS-1$ generator.writeNumber(entry.getTotalOccurrences()); generator.writeEndObject(); } generator.writeEndArray(); generator.close(); } catch (IOException e) { LogUtils.log(getClass(), e); return ""; //$NON-NLS-1$ } return writer.toString(); } private String serializeNetworks(SearchResult options) { JsonFactory factory = new MappingJsonFactory(); StringWriter writer = new StringWriter(); try { JsonGenerator generator = factory.createJsonGenerator(writer); generator.writeStartArray(); Map<InteractionNetwork, Double> networkWeights = options.getNetworkWeights(); for (Entry<InteractionNetwork, Double> entry : networkWeights.entrySet()) { generator.writeStartObject(); InteractionNetwork network = entry.getKey(); generator.writeFieldName("group"); //$NON-NLS-1$ generator.writeString(options.getInteractionNetworkGroup(network.getId()).getName()); generator.writeFieldName("name"); //$NON-NLS-1$ generator.writeString(network.getName()); generator.writeFieldName("weight"); //$NON-NLS-1$ generator.writeNumber(entry.getValue()); generator.writeEndObject(); } generator.writeEndArray(); generator.close(); } catch (IOException e) { LogUtils.log(getClass(), e); return ""; //$NON-NLS-1$ } return writer.toString(); } @SuppressWarnings("unchecked") private void buildGraph(NETWORK currentNetwork, Collection<Interaction> interactions, Network<InteractionNetwork> network, EdgeAttributeProvider attributeProvider, SearchResult options, ViewStateBuilder builder) { Map<Long, Gene> queryGenes = options.getQueryGenes(); InteractionNetwork model = network.getModel(); for (Interaction interaction : interactions) { Node fromNode = interaction.getFromNode(); NODE from = getNode(currentNetwork, fromNode, getSymbol(queryGenes.get(fromNode.getId()))); Node toNode = interaction.getToNode(); NODE to = getNode(currentNetwork, toNode, getSymbol(queryGenes.get(toNode.getId()))); String edgeLabel = attributeProvider.getEdgeLabel(model); EDGE edge = getEdge(from, to, EDGE_TYPE_INTERACTION, edgeLabel, currentNetwork); EdgeProxy<EDGE, NODE> edgeProxy = getEdgeProxy(edge, currentNetwork); String edgeId = edgeProxy.getIdentifier(); Double rawWeight = (double) interaction.getWeight(); builder.addSourceNetworkForEdge(edgeId, network); Double weight = rawWeight * network.getWeight(); List<String> networkNames = edgeProxy.getAttribute(NETWORK_NAMES_ATTRIBUTE, List.class); if (networkNames == null) { networkNames = new ArrayList<String>(); } networkNames.add(network.getName()); edgeProxy.setAttribute(NETWORK_NAMES_ATTRIBUTE, networkNames); List<Double> edgeWeights = edgeProxy.getAttribute(RAW_WEIGHTS_ATTRIBUTE, List.class); if (edgeWeights == null) { edgeWeights = new ArrayList<Double>(); } edgeWeights.add((double) interaction.getWeight()); edgeProxy.setAttribute(RAW_WEIGHTS_ATTRIBUTE, edgeWeights); Double oldWeight = edgeProxy.getAttribute(MAX_WEIGHT_ATTRIBUTE, Double.class); if (oldWeight == null || oldWeight < weight) { edgeProxy.setAttribute(MAX_WEIGHT_ATTRIBUTE, weight); } edgeProxy.setAttribute(HIGHLIGHT_ATTRIBUTE, 1); for (Entry<String, Object> entry : attributeProvider.getAttributes(model).entrySet()) { edgeProxy.setAttribute(entry.getKey(), entry.getValue()); } } } /** * Returns the symbol for the given <code>Gene</code> or <code>null</code> * if the <code>Gene</code> is <code>null</code>. * * @param gene * @return */ private String getSymbol(Gene gene) { if (gene == null) { return null; } return gene.getSymbol(); } /** * Decorates the nodes in the active NETWORK with the results of * the GeneMANIA algorithm. For example, scores are assigned to the * nodes. * @param currentNetwork * * @param options * @param queryGenes */ private void decorateNodes(NETWORK currentNetwork, SearchResult options) { // Assign scores. Map<Long, Gene> queryGenes = options.getQueryGenes(); Map<Gene, Double> scores = options.getScores(); for (Entry<Gene, Double> entry : scores.entrySet()) { double score = entry.getValue(); Node node = entry.getKey().getNode(); NODE cyNode = getNode(currentNetwork, node, getSymbol(queryGenes.get(node))); NodeProxy<NODE> nodeProxy = getNodeProxy(cyNode, currentNetwork); nodeProxy.setAttribute(LOG_SCORE_ATTRIBUTE, Math.log(score)); nodeProxy.setAttribute(SCORE_ATTRIBUTE, score); String type; if (queryGenes.containsKey(node.getId())) { type = NODE_TYPE_QUERY; } else { type = NODE_TYPE_RESULT; } Collection<AnnotationEntry> nodeAnnotations = options.getAnnotations(node.getId()); if (nodeAnnotations != null) { List<String> annotationIds = new ArrayList<String>(); List<String> annotationNames = new ArrayList<String>(); for (AnnotationEntry annotation : nodeAnnotations) { annotationIds.add(annotation.getName()); annotationNames.add(annotation.getDescription()); } nodeProxy.setAttribute(ANNOTATION_ID_ATTRIBUTE, annotationIds); nodeProxy.setAttribute(ANNOTATION_NAME_ATTRIBUTE, annotationNames); } nodeProxy.setAttribute(NODE_TYPE_ATTRIBUTE, type); } } public void setHighlighted(ViewState options, NETWORK cyNetwork, boolean visible) { NetworkProxy<NETWORK, NODE, EDGE> networkProxy = getNetworkProxy(cyNetwork); for (EDGE edge : networkProxy.getEdges()) { EdgeProxy<EDGE, NODE> edgeProxy = getEdgeProxy(edge, cyNetwork); String groupName = (String) edgeProxy.getAttribute(NETWORK_GROUP_NAME_ATTRIBUTE, String.class); if (groupName == null) { continue; } Group<?, ?> group = options.getGroup(groupName); if (group == null) { continue; } Integer value = options.getEnabled(group) || visible ? 1 : 0; edgeProxy.setAttribute(HIGHLIGHT_ATTRIBUTE, value); } updateVisualStyles(cyNetwork); repaint(); } protected String getVisualStyleName(NETWORK network) { NetworkProxy<NETWORK, NODE, EDGE> proxy = getNetworkProxy(network); return proxy.getTitle().replace(".", ""); //$NON-NLS-1$ //$NON-NLS-2$; } public void setHighlight(ViewState config, Group<?, ?> source, NETWORK network, boolean selected) { Set<String> edgeIds = config.getEdgeIds(source); if (edgeIds == null) { return; } config.setEnabled(source, selected); if (selected) { for (String edgeId : edgeIds) { EDGE edge = getEdge(edgeId, network); EdgeProxy<EDGE, NODE> edgeProxy = getEdgeProxy(edge, network); edgeProxy.setAttribute(HIGHLIGHT_ATTRIBUTE, 1); } } else { for (String edgeId : edgeIds) { EDGE edge = getEdge(edgeId, network); EdgeProxy<EDGE, NODE> edgeProxy = getEdgeProxy(edge, network); edgeProxy.setAttribute(HIGHLIGHT_ATTRIBUTE, 0); } } updateVisualStyles(network); repaint(); } }