cytoscape / py4cytoscape

Python library for calling Cytoscape Automation via CyREST
https://Py4Cytoscape.readthedocs.io
Other
68 stars 14 forks source link

Is there a way to even export the attribute (e.g., curveness)of the edge from a cytoscape console to a data frame #135

Open gmhhope opened 2 months ago

gmhhope commented 2 months ago

Dear developers,

Is there a way to even export the attribute of the edge (e.g., curveness) based on the graph generated in the console and using py4cytoscape to export the curveness of each edges? Just like get_node_position, which can help get the node positions?

Always appreciate it!

Thanks, Minghao

bdemchak commented 1 month ago

Hi, Minghao ... Good to hear from you!

I think there is a general function that could do the trick. Have you seen get_table_columns() ?

If I understand correctly, you have attributes for edges and one of the attributes is "curveness". I think you want to return just the "curveness" attribute.

To do that, you would do something like this:

get_table_columns(table='edge', columns='curveness')

You would get back a dataframe indexed by the edge SUIDs, and it would look like this:

            curveness
4608    -0.262
4609    -0.704
...

Unlike get_node_position(), the dataframe would contain all edges. If you want just a few edge's attributes, you'd need to use dataframe filters to extract just the SUIDs you want. You can filter by name (e.g., "src (p) targ") if you want ... just add the 'name' attribute to the get_table_columns() call:

get_table_columns(table='edge', columns='name, curveness')

... and then use dataframe filters on the name column in the dataframe that's returned.

Your need is quite legitimate and would make a good addition to py4cytoscape ... you could also make your own cover function that calls get_table_columns(), too. It would take you a lot less time than waiting for us to do it.

FYI, the main difference between get_node_position() and get_table_columns() is the CyREST functions they call. get_node_position() calls CyREST property functions, which are constructed to accept a list of nodes or edges. get_table_columns() calls CyREST table functions, which don't have any node/edge qualifier.

gmhhope commented 1 month ago

Thanks @bdemchak for the detailed explanation.

I just figured out that the curveness is probably the wrong item I am looking for. Curveness was defined in other Javascript library that I am using. I think the bending in cytoscape was injected by bundle edge and the edge bending (curved edge) was defined by a column called BEND_MAP_ID. I want to know how actually BEND_MAP_ID could be reused to defined the curveness in other library such as Echart for web visualization.

It looks like the cytoscapejs just exported the BEND_MAP_ID, and the BEND_MAP_ID did not actually have any properties to be reapplied to other platform. Could I ask what exactly this BEND_MAP_ID be used to decode the graphic elements?

Warm regards, Minghao

bdemchak commented 1 month ago

Hi, Minghao ...

I see ... so I think you're asking about the column generated by Cytoscape when you perform a Layout | Bundle Edges operation. I see that the edge attribute table has a BEND_MAP_ID attribute as a result.

(I found user documentation on edge bundling here.)

As for BEND_MAP_ID, it's an index into an array within the Bend property in the Edge style sheet. You can see this by using Cytoscape to apply Bundle Edges ... that will make the BEND_MAP_ID property appear in the Edge table. Example values could be 987 or 988.

Next you open the Style tab on Cytoscape's left edge, and then select the Edge tab at the bottom of the Style panel. You should see a property called Bend.

If you open the Bend property (by clicking on the < on Bend's right margin), you'll see that the Bend property is a Discrete Mapping property, where each of BEND_MAP_ID has its own bend. You can open the bend editor by clicking on the bend glyph to the right of a BEND_MAP_ID you're interested in and then clicking on the "..." button to the right. Here's the result for BEND_MAP_ID 817.

image

Fine ... so, then, how would a py4cytoscape function get this and then change the bend?

Is this what you're trying to understand? If so, what are you hoping to accomplish?

Once I know, I can give further guidance (hopefully).

Thanks!

gmhhope commented 1 month ago

Thanks again for all the information!

Yes, I think the BEND_MAP_ID actually mapped back to the cytoscape console to find the bending information. But it looks like the exported cytoscapjs JSON won't include the information. I think it may go beyond the capacity if I ask whether I can actually export the properties for each BEND_MAP_ID, which might be able to apply to other web visualization tool (e.g., D3.js or Echart). I am trying to use Cytoscape as an intermediate step to generate the graph. e.g., https://d3-graph-gallery.com/bundle

THanks, Minghao

bdemchak commented 1 month ago

Hi, Minghao ...

If I understand this right, you'd like to use the BEND_MAP_ID to understand which bends apply to which edges so that you can do something similar with another visualization tool. Of course, I don't know much about those tools, and Cytoscape's data structures for bends are its own ... there are no standards for this (that I'm aware of). So, it's unlikely that edge bends would be easy to translate.

However, as a way of understanding better, I got a dump of the Cytoscape data structures that describe bends for a trial network. To do this, I used a CyREST call from a Swagger window I opened using Cytoscape's Help | Automation | CyREST API menu. I chose the GET /v1/styles/{name}/mappings/{vp}. For {name}, I used 'galFiltered Style', and for {vp}, I used 'EDGE_BEND'. You can get the same effect in py4cytoscape by using the advice in the Missing Functions section of the py4cytoscape manual.

So, here is a same property value for EDGE_BEND (below). The "key" value is the BEND_MAP_ID, and the "value" value is an encoding of multiple Bezier-style segments. I don't know what units the encoding has, but can find out for you if you're interested.

Does this help??

{
  "mappingType": "discrete",
  "mappingColumn": "BEND_MAP_ID",
  "mappingColumnType": "Long",
  "visualProperty": "EDGE_BEND",
  "map": [
    {
      "key": "1025",
      "value": "0.999608799902507,-0.02796868172563413,0.2456209078581003|0.9998029577956341,-0.019850581429809205,0.4932484766006404|0.999932570652765,-0.011612671861082786,0.74346781230295"
    },
    {
      "key": "1027",
      "value": "1.0,0.0,0.25|1.0,0.0,0.5|1.0,0.0,0.7500000000000001"
    },
    {
      "key": "1029",
      "value": "0.9999340738449171,0.011482506865138676,0.2519763934915669|0.9999438481096897,-0.010597199044358989,0.5243875474527304|0.9999864075273612,0.00521390070122398,0.7668535786089208"
    },
    {
      "key": "1031",
      "value": "0.9525792326264602,0.30429065968048424,0.19959862916037807|0.991337401059566,0.13133985404463164,0.4176888230870654|0.9987036784569352,0.05090149935499538,0.6545019511670636"
    },
    {
      "key": "1033",
      "value": "0.9906428704150454,0.13647968089001225,0.2594316201269411|0.9999234462601102,0.012373423911937208,0.5187990343232708|0.9992763035603996,-0.03803773314307799,0.7973261019829339"
    },