cytoscape / RCy3

New version of RCy3, redesigned and collaboratively maintained by Cytoscape developer community
MIT License
49 stars 20 forks source link

Exporting graphNEL into Cytoscape using RCy3 fails with 'arguments imply differing number of rows' #58

Closed methornton closed 5 years ago

methornton commented 5 years ago

Hello! I am trying to subset and import a graphNEL of GO terms made using the 'GOstats' package into Cytoscape using the 'RCy3' package and it isn't working. The data comes from the output of the 'termGraphs' function of GOstats

library(GOstats) ## from the vignette

params1 <- new("GOHyperGParams", geneIds=q_selectedEntrezIds, universeGeneIds=chipEntrezUniverse, annotation="org.Mm.eg.db", ontology="BP", pvalueCutoff=hgCutoff, conditional=FALSE, testDirection="over")
hgOver1 <- hyperGTest(params1)

y1 = termGraphs(hgOver1, use.terms=FALSE, pvalue=pbung)
a1 <- y1$`1`

I've got to truncate this for space

 library(Rgraphviz)
> str(y1$`1`)
    Formal class 'graphNEL' [package "graph"] with 6 slots
      ..@ nodes     : chr [1:60] "GO:0006952" "GO:0006955" "GO:0002376" "GO:0002252" ...
      ..@ edgeL     :List of 60
      .. ..$ GO:0006952:List of 1
      .. .. ..$ edges: int 13
      .. ..$ GO:0006955:List of 1
      .. .. ..$ edges: int [1:2] 3 8
      .. ..$ GO:0002376:List of 1
      .. .. ..$ edges: int(0) 
      .. ..$ GO:0002252:List of 1
      .. .. ..$ edges: int 3
      .. ..$ GO:0042221:List of 1

...

      ..@ edgeData  :Formal class 'attrData' [package "graph"] with 2 slots
      .. .. ..@ data    : Named list()
      .. .. ..@ defaults:List of 1
      .. .. .. ..$ weight: num 1
      ..@ nodeData  :Formal class 'attrData' [package "graph"] with 2 slots
      .. .. ..@ data    :List of 60
      .. .. .. ..$ GO:0006952:List of 4
      .. .. .. .. ..$ geneIds  : chr [1:810] "11419" "11421" "11465" "11477" ...
      .. .. .. .. ..$ pvalue   : num 2.22e-09
      .. .. .. .. ..$ oddsRatio: num 2.43
      .. .. .. .. ..$ expCount : num 32.2
      .. .. .. ..$ GO:0006955:List of 4
      .. .. .. .. ..$ geneIds  : chr [1:763] "11350" "11465" "11486" "11490" ...
      .. .. .. .. ..$ pvalue   : num 2.28e-07
      .. .. .. .. ..$ oddsRatio: num 2.23
      .. .. .. .. ..$ expCount : num 30.3

...

  .. .. ..@ defaults:List of 5
  .. .. .. ..$ pvalue     : num 1
  .. .. .. ..$ geneIds    : num(0) 
  .. .. .. ..$ condGeneIds: num(0) 
  .. .. .. ..$ oddsRatio  : num 1
  .. .. .. ..$ expCount   : num(0) 
  ..@ renderInfo:Formal class 'renderInfo' [package "graph"] with 4 slots
  .. .. ..@ nodes: list()
  .. .. ..@ edges: list()
  .. .. ..@ graph: list()
  .. .. ..@ pars : list()
  ..@ graphData :List of 1
  .. ..$ edgemode: chr "directed"

So now I want to subset the graphNEL

sub <- subGraph(c("GO:0002460", "GO:0002819", "GO:0050778", "GO:0002695", "GO:0002250", "GO:0048584", "GO:0050776", "GO:0002683", "GO:0002684", "GO:0048583", "GO:0006955", "GO:0002682", "GO:0002376"), y1$`1`)

I can plot the subset, but then export into Cytoscape with 'RCy3' it fails

library(RCy3)

> cytoscapePing()
[1] "You are connected to Cytoscape!"

> createNetworkFromGraph(sub, "MyGraph")
Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE,  : 
  arguments imply differing number of rows: 13, 9161, 0

Even if I try to import the whole thing it fails also.

> createNetworkFromGraph(a1, "MyGraph")
Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE,  : 
  arguments imply differing number of rows: 60, 61330, 0
> createNetworkFromGraph(y1$`1`, "MyGraph")
Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE,  : 
  arguments imply differing number of rows: 60, 61330, 0

However, if I use the simple example from the vignette, it works.

> g <- makeSimpleGraph()
> createNetworkFromGraph(g, "Test")
Loading data...
Applying default style...
Applying preferred layout...
networkSUID 
         96 

'g' doesn't look too different than 'a1' or even 'sub'

> str(g)
Formal class 'graphNEL' [package "graph"] with 6 slots
  ..@ nodes     : chr [1:4] "node 1" "node 3" "node 2" "node 0"
  ..@ edgeL     :List of 4
  .. ..$ node 1:List of 1
  .. .. ..$ edges: num(0) 
  .. ..$ node 3:List of 1
  .. .. ..$ edges: num(0) 
  .. ..$ node 2:List of 1
  .. .. ..$ edges: num 2
  .. ..$ node 0:List of 1
  .. .. ..$ edges: num [1:3] 1 3 2
  ..@ edgeData  :Formal class 'attrData' [package "graph"] with 2 slots
  .. .. ..@ data    :List of 4
  .. .. .. ..$ node 0|node 1:List of 2
  .. .. .. .. ..$ interaction: chr "inhibits"
  .. .. .. .. ..$ weight     : num 5.1
  .. .. .. ..$ node 0|node 2:List of 2
  .. .. .. .. ..$ interaction: chr "interacts"
  .. .. .. .. ..$ weight     : num 3
  .. .. .. ..$ node 0|node 3:List of 2
  .. .. .. .. ..$ interaction: chr "activates"
  .. .. .. .. ..$ weight     : num 5.2
  .. .. .. ..$ node 2|node 3:List of 2
  .. .. .. .. ..$ interaction: chr "interacts"
  .. .. .. .. ..$ weight     : num 9.9
  .. .. ..@ defaults:List of 2
  .. .. .. ..$ interaction: chr "undefined"
  .. .. .. ..$ weight     : num 0
  ..@ nodeData  :Formal class 'attrData' [package "graph"] with 2 slots
  .. .. ..@ data    :List of 4
  .. .. .. ..$ node 0:List of 2
  .. .. .. .. ..$ group: chr "A"
  .. .. .. .. ..$ score: int 20
  .. .. .. ..$ node 1:List of 2
  .. .. .. .. ..$ group: chr "A"
  .. .. .. .. ..$ score: int 10
  .. .. .. ..$ node 2:List of 2
  .. .. .. .. ..$ group: chr "B"
  .. .. .. .. ..$ score: int 15
  .. .. .. ..$ node 3:List of 2
  .. .. .. .. ..$ group: chr "B"
  .. .. .. .. ..$ score: int 5
  .. .. ..@ defaults:List of 2
  .. .. .. ..$ group: chr "none"
  .. .. .. ..$ score: int 0
  ..@ renderInfo:Formal class 'renderInfo' [package "graph"] with 4 slots
  .. .. ..@ nodes: list()
  .. .. ..@ edges: list()
  .. .. ..@ graph: list()
  .. .. ..@ pars : list()
  ..@ graphData :List of 1
  .. ..$ edgemode: chr "directed"

If the issue is the genes, it would be nice to be able to include it, or is there even an easy way to get rid of that data that would help. I was able to get this to work previously. I'm stuck now though. Any advice or assistance is greatly appreciated!

   > sessionInfo()
    R version 3.6.0 (2019-04-26)
    Platform: x86_64-pc-linux-gnu (64-bit)
    Running under: Ubuntu 18.04.2 LTS

    Matrix products: default
    BLAS:   /usr/lib/x86_64-linux-gnu/openblas/libblas.so.3
    LAPACK: /usr/lib/x86_64-linux-gnu/libopenblasp-r0.2.20.so

    Random number generation:
     RNG:     Mersenne-Twister 
     Normal:  Inversion 
     Sample:  Rounding 

    locale:
     [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
     [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
     [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
     [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
     [9] LC_ADDRESS=C               LC_TELEPHONE=C            
    [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

    attached base packages:
    [1] grid      parallel  stats     graphics  grDevices utils     datasets 
    [8] methods   base     

    other attached packages:
    [1] Rgraphviz_2.28.0    graph_1.62.0        BiocGenerics_0.30.0
    [4] RCy3_2.4.0         

    loaded via a namespace (and not attached):
     [1] igraph_1.2.4.1       Rcpp_1.0.1           AnnotationDbi_1.46.0
     [4] magrittr_1.5         IRanges_2.18.0       bit_1.1-14          
     [7] R6_2.4.0             blob_1.1.1           httr_1.4.0          
    [10] Biobase_2.44.0       R.oo_1.22.0          DBI_1.0.0           
    [13] bit64_0.9-7          digest_0.6.18        RJSONIO_1.3-1.1     
    [16] R.utils_2.8.0        S4Vectors_0.22.0     curl_3.3            
    [19] memoise_1.1.0        RSQLite_2.1.1        compiler_3.6.0      
    [22] R.methodsS3_1.7.1    stats4_3.6.0         XML_3.98-1.19       
    [25] pkgconfig_2.0.2     ]](url)
AlexanderPico commented 5 years ago

Thanks for the thorough bug report. Yes, you've correctly identified the problem: CyREST (and therefore RCy3) does not handle node attributes of type list at this time. The current function appears to choke on this case (which I neglected to test). I should be able to update the function to at least render the list as a string (stay tuned for pending fix...).

In the meantime, you could remove the attribute prior to running the function as a workaround. I don't know how to do this with GraphNELs, but I do with igraphs... and the first step in createNetworkFromGraph is to convert it to igraph :) So...

library(igraph)
ig<-igraph.from.graphNEL(a1)
ig<-delete_vertex_attr(ig, 'geneIds')
ig<-delete_vertex_attr(ig, 'condGeneIds')
#note: there is also a problem with a mix of strings (i.e., "Infinity") in the oddsRatio column, which is otherwise handled as floats. So we have to remove that for now as well...
ig<-delete_vertex_attr(ig, 'oddsRatio') 
RCy3::createNetworkFromIgraph(ig)
AlexanderPico commented 5 years ago

Ok. I'm pushing a fix to this repo now. I tested it with an example adapted from the GOstats vignette below. Note that the removal of oddsRatio is still required due to the lack of support for "Infinity" in CyREST. Not sure how to handle this one yet...

To test with your own data, first install the dev version of RCy3:

install.packages("devtools")
library(devtools)
install_github('cytoscape/RCy3', build_vignettes=TRUE)
#If installation fails due to package 'XXX' not found,
# then run install.packages("XXX") and then try install_github('cytoscape/RCy3') again
library(RCy3)

Please try this example first and let me know:

library(GOstats) 
library(org.Hs.eg.db)
library(GSEABase)

frame = toTable(org.Hs.egGO)
goframeData = data.frame(frame$go_id, frame$Evidence, frame$gene_id)
goFrame=GOFrame(goframeData,organism="Homo sapiens")
goAllFrame=GOAllFrame(goFrame)
gsc <- GeneSetCollection(goAllFrame, setType = GOCollection())

universe = Lkeys(org.Hs.egGO)
genes = universe[1:500]

params <- GSEAGOHyperGParams(name="My Custom GSEA based annot Params",
                            geneSetCollection=gsc,                             
                            geneIds = genes,                            
                            universeGeneIds = universe,
                            ontology = "MF",
                            pvalueCutoff = 0.05,
                            conditional = FALSE,
                            testDirection = "over")

hgOver1 <- hyperGTest(params)

y1 = termGraphs(hgOver1, use.terms=FALSE, pvalue=0.05)
a1 <- y1$`1`

library(igraph)
ig<-igraph.from.graphNEL(a1)
ig<-delete_vertex_attr(ig, "oddsRatio")
createNetworkFromIgraph(ig)