Basic Workflow 2: Working with igraph

by Kazuhiro Takemoto*

Updated by Keiichiro Ono

(The original tutorial was developed by Dr. Takemoto, and updated by Keiichiro Ono for cyREST)


Introduction

Welcome to part 2 of the R tutorial. In this section, you will learn how to use Cytoscape with igraph.

What is igraph?

igraph is one of the most popular network analysis toolkits for R/Python/C. It has a lot of graph analysis algorithms and utilities that Cytoscape does not have. If you use Cytoscape from igraph, you can use variety of network analysis functions in igraph and visualize the result with powerful visualization tools available in Cytoscape.

Basic Setup

# Basic setup
library(igraph)
library(RJSONIO)
library(httr)

port.number = 1234
base.url = paste("http://localhost:", toString(port.number), "/v1", sep="")
print(base.url)
## [1] "http://localhost:1234/v1"

Loading Networks

There are many ways to import network data into igraph. In this example, let’s try to load text data as Data Frame, and then convert it into igraph object.

# Load list of edges as Data Frame
network.df <- read.table("../data/eco_EM+TCA.txt")

# Convert it into igraph object
network <- graph.data.frame(network.df,directed=T)

# Remove duplicate edges & loops
g.tca <- simplify(network, remove.multiple=T, remove.loops=T)

# Name it
g.tca$name = "Ecoli TCA Cycle"

Convert igraph object into JSON

As you learned in the first tutorial, basic data exchange format between Cytoscape and external tools is Cytoscape.js JSON. To send igraph object to Cytoscape, you need to convert it into JSON:

# This function will be published as a part of utility package, but not ready yet.
source('../utility/cytoscape_util.R')

# Convert it into Cytosccape.js JSON
cygraph <- toCytoscape(g.tca)
## [1] "Done.  To json Start..."

Visualize it in Cytoscape

Now you are ready to visualize your data in Cytoscape. It’s very straightforward:

send2cy(cygraph, 'default%20black', 'circular')
## [1] 3372

If you want to visualize your network in igraph, obviously it is possible:

plot(g.tca,vertex.label=V(g.tca)$name)

This is a static image and there is no interactivity. In contrast, the result you see in the Cytoscape applicaiton window should look like this:

cy-ss1

You can tweak your result interactively with fully-featured network visualization workbench. And of course, you can modify your Visual Styles programmatically or manually.

…Which one do you like?

Find Shortest Path

Let’s find shortest path from D-Glucose to 2-Oxoglutarate. This is really easy with igraph:

PATH1 <- "path1"

paths <- get.all.shortest.paths(g.tca,"D-Glucose","2-Oxoglutarate",mode="out")

# Nodes in the first path
print(V(g.tca)[paths$res[[1]]])
## Vertex sequence:
##  [1] "D-Glucose"      "G6P"            "F6P"            "F16BP"         
##  [5] "GAP"            "BPG"            "3PG"            "2PG"           
##  [9] "PEP"            "Pyruvate"       "Acetyl-CoA"     "Citrate"       
## [13] "cis-Aconitate"  "Isocitrate"     "Oxalosuccinate" "2-Oxoglutarate"
# Add new attribute "path" and set value 1 for this path
V(g.tca)[paths$res[[1]]]$path <- PATH1

# Edges in the path
print(E(g.tca,path=paths$res[[1]]))
## Edge sequence:
##                                      
## [15] D-Glucose      -> G6P           
## [24] G6P            -> F6P           
## [19] F6P            -> F16BP         
## [17] F16BP          -> GAP           
## [26] GAP            -> BPG           
## [10] BPG            -> 3PG           
## [5]  3PG            -> 2PG           
## [4]  2PG            -> PEP           
## [41] PEP            -> Pyruvate      
## [42] Pyruvate       -> Acetyl-CoA    
## [7]  Acetyl-CoA     -> Citrate       
## [14] Citrate        -> cis-Aconitate 
## [50] cis-Aconitate  -> Isocitrate    
## [31] Isocitrate     -> Oxalosuccinate
## [38] Oxalosuccinate -> 2-Oxoglutarate
# Add path attribute
E(g.tca, path=paths$res[[1]])$path <- PATH1

Understanding Styles

In igraph plot function, you need to specify actual visual property values directly. For example, if you want to paint the path found in the previous section in red, you need to set actual color (red) for each edge in the path. Instead, Cytoscape used a mapping mechanism called Visual Style and you can reuse the mapping instructions for multiple networks. For more details, please read the manual.

Visualizing Paths

Because Style in Cytoscape is so flexible, there are many ways to visualize your The simplest way to visualize paths in Cytoscape is making a new attributes for the edges.

Design your Style

To understand basics of Style, let’s build a simple Style from scratch including the following instructions:

  • Paint nodes and edges on the path in red
  • Use red for node labels
  • Since this is a directed graph, add arrows to the edges

First, we need to set default values. This is just an example. Be creative to improve your visualizations!

# Name of this new style
style.name = "PathVisualization"

# Delete the existing style for fresh start...
style.url = paste(base.url, "styles", sep="/")
style.delete.url = paste(style.url, style.name, sep="/")
DELETE(url=style.delete.url)
## Response [http://localhost:1234/v1/styles/PathVisualization]
##   Date: 2015-06-17 12:13
##   Status: 204
##   Content-Type: <unknown>
## <EMPTY BODY>
# Define default values
def.node.color <- list(
  visualProperty = "NODE_FILL_COLOR",
  value = "#aaaaaa"
)

def.node.size <- list(
  visualProperty = "NODE_SIZE",
  value = 12
)

def.node.border.width <- list(
  visualProperty = "NODE_BORDER_WIDTH",
  value = 0
)

def.edge.width <- list(
  visualProperty = "EDGE_WIDTH",
  value = 2
)

def.edge.color <- list(
  visualProperty = "EDGE_STROKE_UNSELECTED_PAINT",
  value = "#aaaaaa"
)

def.edge.target.arrow.color = list(
  visualProperty="EDGE_TARGET_ARROW_UNSELECTED_PAINT",
  value = "#aaaaaa"
)

def.edge.transparency = list(
  visualProperty="EDGE_TRANSPARENCY",
  value = 100
)

def.node.transparency = list(
  visualProperty="NODE_TRANSPARENCY",
  value = 100
)

def.node.label.transparency = list(
  visualProperty="NODE_LABEL_TRANSPARENCY",
  value = 100
)

def.node.labelposition <- list(
  visualProperty = "NODE_LABEL_POSITION",
  value = "S,NW,c,7.00,0.00"  
)

def.edge.target.arrow <- list(
  visualProperty="EDGE_TARGET_ARROW_SHAPE",
  value="ARROW"
)

defaults <- list(def.node.color, def.node.size, def.node.labelposition, 
                 def.edge.color, def.node.border.width, def.edge.target.arrow, 
                 def.edge.width, def.edge.target.arrow.color,
                 def.node.transparency, def.node.label.transparency,
                 def.edge.transparency)
# Visual Mappings
mappings = list()

pair1 = list(
  key = PATH1,
  value = "red"
)

# This mapping object is also reusable!
discrete.mappings = list(pair1)

node.color = list(
  mappingType="discrete",
  mappingColumn="path",
  mappingColumnType="String",
  visualProperty="NODE_FILL_COLOR",
  map = discrete.mappings
)

node.label.color = list(
  mappingType="discrete",
  mappingColumn="path",
  mappingColumnType="String",
  visualProperty="NODE_LABEL_COLOR",
  map = discrete.mappings
)

edge.color = list(
  mappingType="discrete",
  mappingColumn="path",
  mappingColumnType="String",
  visualProperty="EDGE_STROKE_UNSELECTED_PAINT",
  map = discrete.mappings
)

edge.target.arrow.color = list(
  mappingType="discrete",
  mappingColumn="path",
  mappingColumnType="String",
  visualProperty="EDGE_TARGET_ARROW_UNSELECTED_PAINT",
  map = discrete.mappings
)

node.label = list(
  mappingType="passthrough",
  mappingColumn="name",
  mappingColumnType="String",
  visualProperty="NODE_LABEL"
)

pair.transparency = list(
  key = PATH1,
  value = "255"
)
discrete.transparency = list(pair.transparency)

node.transparency = list(
  mappingType="discrete",
  mappingColumn="path",
  mappingColumnType="String",
  visualProperty="NODE_TRANSPARENCY",
  map = discrete.transparency
)

edge.transparency = list(
  mappingType="discrete",
  mappingColumn="path",
  mappingColumnType="String",
  visualProperty="EDGE_TRANSPARENCY",
  map = discrete.transparency
)

node.label.transparency = list(
  mappingType="discrete",
  mappingColumn="path",
  mappingColumnType="String",
  visualProperty="NODE_LABEL_TRANSPARENCY",
  map = discrete.transparency
)

mappings = list(
  node.color, node.label, node.label.color, 
  edge.color, edge.target.arrow.color,
  node.label.transparency, node.transparency, edge.transparency)

style <- list(title=style.name, defaults = defaults, mappings = mappings)
style.JSON <- toJSON(style)

POST(url=style.url, body=style.JSON, encode = "json")
## Response [http://localhost:1234/v1/styles]
##   Date: 2015-06-17 12:13
##   Status: 201
##   Content-Type: application/json
##   Size: 30 B

Well, this may look a bit cumbersome for the first time because we make everything from scratch. However, in many cases, you can use preset Styles as your starting point and customize it for your purpose. But remember, you made a reusable set of instructions how to visualize your result controled by the data. Style object is just like a CSS for Cytoscape. It is reusable, and independent from your content (data).

In this section, you made a style programmatically, but of course, you can manually create Styles from GUI if you want.

cygraph.updated <- toCytoscape(g.tca)
## [1] "Done.  To json Start..."
send2cy(cygraph.updated, style.name, 'circular')
## [1] 3538

Final Result

And now you can see the network view like this:

You can use techniques you learned here for other data sets. The good news is, the code is re-usable. You can use the code segment above for other path visualization problems.