idekerlab / cy-rest-R

Example R script to use Cytoscape via RESTful API module.
MIT License
28 stars 13 forks source link

doubles printed as integers in JSON makes network upload fail #3

Closed thomaskelder closed 10 years ago

thomaskelder commented 10 years ago

Uploading a network to Cytoscape fails when there is a node/edge attribute with doubles, but the first occurence(s) are whole numbers (even when their storage mode is not "integer").

Here is a short R script to reproduce:

graphToCytoscape = function(g) {
  cygraph = toCytoscape(g)
  network.url = paste(base.url, "networks", sep="/")
  res = POST(url=network.url, body=cygraph, encode="json")
  print(res)
  unname(fromJSON(rawToChar(res$content))) ## Return network ID
}

library(igraph)
library(devtools)
library(RJSONIO)
library(httr)

port.number = 1234
base.url = paste("http://localhost:", toString(port.number), "/v1", sep="")

source_url("https://raw.githubusercontent.com/idekerlab/cy-rest-R/develop/toCytoscape.R")
test = ba.game(25)
E(test)$number = rep(0.1, ecount(test))
graphToCytoscape(test) ## Works fine!

E(test)$number[1] = 0  ## Now make first number whole
graphToCytoscape(test) ## Returns error 500

It gives me the following error on the final line:

Response [http://localhost:1234/v1/networks]
  Status: 500
  Content-type: text/html;charset=ISO-8859-1
  Size: 1.03 kB

 Show Traceback

 Rerun with Debug
 Error in file(con, "r") : cannot open the connection

When looking at the JSON output, is seems that the problem is that whole numbers are printed without decimals and hence parsed as integer by Cytoscape. Subsequent values that do have decimals, will then trigger an error (since the attribute type has been fixed as integer at that point).

I tried forcing the toJSON function to add decimals always in case of a numerical attribute, but couldn't find a way to do this.

thomaskelder commented 10 years ago

I read up a bit more about the options here, and I can't find a way to force any R json library to always print digits for a double (even if it's a round number). Both RJSONIO, rjson and jsonlite do not have an option for this. Besides, JSON doesn't distinguish between integers and doubles, the output is valid json. So I would argue to fix this on the Cytoscape part, e.g. by always treating numeric attributes as double in json (since JavaScript also only has doubles as number type, not integers). Alternatively, there could a an additional "type" option in the json format to force the type of the attribute?

keiono commented 10 years ago

Confirmed the bug. I think this can be resolved in Cytoscape side.

keiono commented 10 years ago

The actual parser is in the core, and need to be fixed in the next version (which will be released next month):

https://code.cytoscape.org/redmine/issues/2808

Also, an alternative is supporting GraphSON in addition to Cytoscape.js format.

https://github.com/tinkerpop/blueprints/wiki/GraphSON-Reader-and-Writer-Library

bdemchak commented 10 years ago

Is there any reason not to support GraphSON?? … at least via a format parameter on the REST request?

If this is the right approach, it can be implemented later.

From: Keiichiro Ono [mailto:notifications@github.com] Sent: Wednesday, August 27, 2014 7:23 PM To: idekerlab/cy-rest-R Subject: Re: [cy-rest-R] doubles printed as integers in JSON makes network upload fail (#3)

The actual parser is in the core, and need to be fixed in the next version (which will be released next month):

https://code.cytoscape.org/redmine/issues/2808

Also, an alternative is supporting GraphSON in addition to Cytoscape.js format.

https://github.com/tinkerpop/blueprints/wiki/GraphSON-Reader-and-Writer-Library

— Reply to this email directly or view it on GitHub https://github.com/idekerlab/cy-rest-R/issues/3#issuecomment-53666215 . https://github.com/notifications/beacon/3696094__eyJzY29wZSI6Ik5ld3NpZXM6QmVhY29uIiwiZXhwaXJlcyI6MTcyNDgxMTc1NSwiZGF0YSI6eyJpZCI6NDAxNjE0MDd9fQ==--377584332c79fca6b8618717c45ac967fe355d54.gif

keiono commented 10 years ago

There are two approaches for this problem:

  1. Add extra entries in Cytoscape.js JSON

Since there is no side-effect adding more information to the data object in Cytoscape.js JSON, we can add Cytoscape-dependent data in the JSON file like:

{
    "data": {
        "dataTables":[
            "nodeDefault": [
                { "columnName": "SUID", "type": "Long"}, ...
            ]
        ]
    },
    "elements": {
        "nodes":[...],
        "edges":[...]
    }
}
  1. Provide support for GraphSON

Also, there is no side effect for this solution, although the data is a bit redundant (all entries have its own data type tag). But I have no objection to adding support.

https://github.com/keiono/cy-rest/issues/17 https://github.com/keiono/cy-rest/issues/18

keiono commented 10 years ago

As a reasonably OK solution for now, I'll update the core code to handle numbers as double if no data type is available. This change is for the core (3.2.0).

https://code.cytoscape.org/redmine/issues/2808

keiono commented 10 years ago

By the way, this is not the complete solution, but even for current version, here is a workaround for R users:

  1. Create network data in igraph
  2. Write into GraphML file
  3. Send filelist to Cytoscape via REST

In R, it is this simple:

write.graph(test, "test.graphml", "graphml")
file.url <- paste(base.url, "networks?source=url", sep="/")
fullpath <- normalizePath("test.graphml")
file.list = paste("[\"file://", fullpath, "\"]", sep="")
res <- POST(url=file.url, body=file.list, encode="json")
result <- unname(fromJSON(rawToChar(res$content)))

Of course, you can send multiple files at once. This POST method DOES NOT send actual file contents. Just send a list of resources (URLs) and Cytoscape read the files from that resources.

keiono commented 10 years ago

Fixed in the core. By default, all numbers will be handed as Double. If optional columnTypes object is available as a network property, it will be used to set the data type.

See https://code.cytoscape.org/redmine/issues/2808

This fix will be available from Cytoscape 3.2.0.