Commit 3d0d99d6 authored by Marek Ostaszewski's avatar Marek Ostaszewski
Browse files

XGMML converter

parent b9e554f9
##################################################
## Project: Disease Maps
## Script purpose: Translate Cytoscape networks to a Systems Biology format using GPML as an intermediate
## Date: 20.07.2021
## Author: Marek Ostaszewski
##################################################
library(xml2)
### XGMML namespaces to use
ns_xgmml <- xml_ns_rename(xml_ns(read_xml("<root>
<dc xmlns = 'http://purl.org/dc/elements/1.1/'/>
<xlink xmlns = 'http://www.w3.org/1999/xlink' />
<rdf xmlns = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#' />
<cy xmlns = 'http://www.cytoscape.org' />
<xgmml xmlns='http://www.cs.rpi.edu/XGMML' />
</root>")),
d1 = "dc", d2 = "xlink", d3 = "rdf", d4 = "cy", d5 = "xgmml")
### GPML namespaces to use
ns_gpml <- xml_ns_rename(xml_ns(read_xml("<root>
<gpml xmlns = 'http://pathvisio.org/GPML/2013a' />
</root>")), d1 = "gpml")
### Initialise a GPML::Pathway
create_Pathway <- function(name, version = date(), organism = "Homo sapiens") {
return(read_xml(paste0("<Pathway xmlns='http://pathvisio.org/GPML/2013a' Name='", name,
"' Version='", version,"' Organism='", organism, "'>",
"<Graphics BoardWidth='0.0' BoardHeight='0.0' />",
"</Pathway>")))
}
### Create a GPML::DataNode object, with given label, id, type position and size
create_DataNode <- function(label, id, type, x, y, w, h,
zorder = "32768", fontsize="12", valign="Middle") {
return(read_xml(paste0("<DataNode TextLabel='", label, "' GraphId='", id, "' Type='", type, "'>",
"<Graphics CenterX='", x, "' CenterY='", y, "' Width='", w,
"' Height='", h,"' ZOrder='", zorder,"' FontSize='", fontsize,"' Valign='", valign,"' />",
"<Xref Database='' ID='' />",
"</DataNode>")))
}
### Add a GPML::DataNode to a GPML::Pathway
add_DataNode_to_Pathway <- function(gpml_pathway, gpml_node) {
xml_add_child(gpml_pathway, gpml_node)
canvas <- xml_find_first(gpml_pathway, "//gpml:Pathway/gpml:Graphics", ns_gpml)
node_graphics <- xml_find_first(gpml_node, "./Graphics")
### Resize the canvas if needed
xml_attr(canvas, "BoardWidth") <- max(as.numeric(xml_attr(canvas, "BoardWidth")),
as.numeric(xml_attr(node_graphics, "CenterX")) +
as.numeric(xml_attr(node_graphics, "Width")))
xml_attr(canvas, "BoardHeight") <- max(as.numeric(xml_attr(canvas, "BoardHeight")),
as.numeric(xml_attr(node_graphics, "CenterY")) +
as.numeric(xml_attr(node_graphics, "Height")))
invisible(0)
}
### Add a GPML::Interaction to a GPML::Pathway, based on the ids of two GPML::DataNodes
add_Interaction_to_Pathway <- function(gpml_pathway, id_source, id_target) {
dn_src <- xml_find_first(gpml_pathway, paste0("//DataNode[@GraphId='", id_source, "']"))
dn_trg <- xml_find_first(gpml_pathway, paste0("//DataNode[@GraphId='", id_target, "']"))
### Identify anchor points
gpml_ps <- read_xml(paste0("<Point X='", as.numeric(xml_attr(xml_child(dn_src),"CenterX")),# + as.numeric(xml_attr(xml_child(dn_src),"Width"))/2,
"' Y='", xml_attr(xml_child(dn_src),"CenterY"),
"' GraphRef='", xml_attr(dn_src,"GraphId"), "' RelX='1.0' RelY='0.0' />"))
gpml_pt <- read_xml(paste0("<Point X='", as.numeric(xml_attr(xml_child(dn_trg),"CenterX")),# - as.numeric(xml_attr(xml_child(dn_trg),"Width"))/2,
"' Y='", xml_attr(xml_child(dn_trg),"CenterY"),
"' GraphRef='", xml_attr(dn_trg,"GraphId"), "' RelX='-1.0' RelY='0.0' ArrowHead='Arrow'/>"))
gpml_gr <- read_xml("<Graphics ZOrder='12288' LineThickness='1.0'/>")
xml_add_child(gpml_gr, gpml_ps)
xml_add_child(gpml_gr, gpml_pt)
gpml_ix <- read_xml("<Interaction/>")
xml_add_child(gpml_ix, gpml_gr)
xml_add_child(gpml_ix, read_xml("<Xref Database='' ID='' />"))
xml_add_child(gpml_pathway, gpml_ix)
invisible(0)
}
### Save GPML::Pathway to file
write_Pathway <- function(gpml_pathway, filename) {
### InfoBox needs to go to the end of the file
xml_add_child(gpml_pathway, read_xml("<InfoBox CenterX='0.0' CenterY='0.0' />"))
write_xml(gpml_pathway, file = filename)
invisible(0)
}
### Read node information from the CytoScape XGMML file
cys_nodedata <- function(cys_node_xgmml) {
nd_attrs <- xml_attrs(cys_node_xgmml)
gr_attrs <- xml_attrs(xml_find_first(cys_node_xgmml, "./xgmml:graphics", ns = ns_xgmml))
return(data.frame(id = nd_attrs["id"], label = nd_attrs["label"],
x = as.numeric(gr_attrs["x"]), y = as.numeric(gr_attrs["y"]),
w = as.numeric(gr_attrs["w"]), h = as.numeric(gr_attrs["h"]), fill = gr_attrs["fill"]))
}
### Read edge information from the CytoScape XGMML file
cys_edgedata <- function(cys_edge_xgmml) {
eg_attrs <- xml_attrs(cys_edge_xgmml)
return(data.frame(id = eg_attrs["id"], label = eg_attrs["label"],
source = eg_attrs["source"], target = eg_attrs["target"]))
}
### The main function to call, optionally generating an image of the created diagram
### and runs a translation to a desired format, with syntax matching
### the MINERVA Conversion API: https://minerva.pages.uni.lu/doc/api/15.1/converter/
xgmml_gpml <- function(xgmml_file, output,
curl_image = T, target_output = "") {
xgmml <- read_xml(xgmml_file)
nodedata <- do.call("rbind", lapply(xml_find_all(xgmml, "//xgmml:node", ns = ns_xgmml), cys_nodedata))
### Purely numeric ids are a problem, adding a letter
nodedata$id <- paste0("p_",nodedata$id)
### Correct for x,y negative values, add 100 margin
nodedata$x <- nodedata$x + abs(min(nodedata$x)) + 100
nodedata$y <- nodedata$y + abs(min(nodedata$y)) + 100
nodedata <- cbind(nodedata, type = "Pathway")
nodedata$type[grep("^[A-Z0-9]{3,}$",nodedata$label)] <- "Protein"
nodedata$type[grep("_[1-9]",nodedata$label)] <- "Metabolite"
edgedata <- do.call("rbind", lapply(xml_find_all(xgmml, "//xgmml:edge", ns = ns_xgmml), cys_edgedata))
### Purely numeric ids are a problem, adding a letter
edgedata$id <- paste0("p_",edgedata$id)
edgedata$source <- paste0("p_",edgedata$source)
edgedata$target <- paste0("p_",edgedata$target)
xgmml_P <- create_Pathway("from xgmml")
apply(nodedata, 1, function(x)
add_DataNode_to_Pathway(xgmml_P,
create_DataNode(label = x["label"], id = x["id"], type = x["type"],
x = x["x"], y = x["y"], w = x["w"], h = x["h"])))
apply(edgedata, 1, function(x)
add_Interaction_to_Pathway(xgmml_P, x["source"], x["target"]))
write_Pathway(xgmml_P, filename = output)
if(curl_image) {
message("Creating image ...")
system(paste0("curl -X POST --data-binary @", output," -H 'Content-Type: text/plain'",
" https://minerva-dev.lcsb.uni.lu/minerva/api/convert/image/GPML:png > ",
paste0(output,".png")))
}
if(target_output != "") {
message("Translating to ...")
system(paste0("curl -X POST --data-binary @", output," -H 'Content-Type: text/plain'",
" https://minerva-dev.lcsb.uni.lu/minerva/api/convert/GPML:", target_output," > ",
paste0(output,target_output,".xml")))
}
invisible(0)
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment