cytoscape / py4cytoscape

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

How to apply the node positions back to a new graph? #109

Closed gmhhope closed 1 year ago

gmhhope commented 1 year ago

Dear developers,

I have been trying to automate the process of cytoscape figure using py4cytoscape and it is quite a pleasure.

I found that the position information can be retrieved by get_node_position. However, I cannot find a function to apply those x_coordinate and y_coordinate back to the graph. There is a function set_node_custom_position, but apparently it is for setting the relative position of the customized graph of the node.

Could you help me to find a solution? Thanks!

Thanks, Minghao Gong

bdemchak commented 1 year ago

Hi --

I think so ... thanks for working with py4cytoscape!

The function you're looking for is likely to be set_node_property_bypass(), which sets properties for selected nodes. You can try this out by using Cytoscape to manually load a network and then select one node. Then execute the following py4cytoscape code:

p4c.set_node_property_bypass(p4c.get_selected_nodes(), ['40'], 'NODE_Y_LOCATION')
p4c.set_node_property_bypass(p4c.get_selected_nodes(), ['20'], 'NODE_X_LOCATION')

You can get a list of all style properties by executing:

p4c.get_visual_property_names()

I agree that given the ease of finding node positions, it's strange to have such difficulty setting node positions. This has come up in the past, and the answer has been that setting node locations is a very rare operation. So, I'm sorry for the difficulty. If we can add a function for setting node positions, we will.

Note that when setting the NODE_X_LOCATION and NODE_Y_LOCATION properties, you may get a warning that the property is unknown. This can be ignored, as it pertains to validating the coordinate value and doesn't affect setting the coordinate value.

I'll log this warning as a bug so it gets addressed in the next release.

Does this solve your problem??

gmhhope commented 1 year ago

Thanks for the quick response!

Actually it works out perfectly! Thank you!

BTW, is there anything I can use to automate the Layout tools part?

Screenshot 2023-07-09 at 5 03 41 PM

Another interesting part is that after setting the bypass, there is no way to further modify the Layout (rotation or scaling)? Are there any ways to circumvent this issue?

Best, MG

gmhhope commented 1 year ago

I also tried layout_copycat, which, based on my understanding, can be used to copy coordinates from one network to another based on the shared node id (e.g., shared name). However, after I run the command, I don't see any changes of the network. And it reports with the following:

p4c.layout_copycat(source_network = 41841,
                       target_network= p4c.get_network_suid(),
                       source_column='shared name', 
                       target_column='shared name')
{'mappedNodeCount': 194, 'unmappedNodeCount': 0}

Did I understand layout_copycat correctly? Any restrictions?

Thanks, Minghao

bdemchak commented 1 year ago

I think your understanding is correct. I can't spend much time on this now, but I can see that it's working as expected. The following code is taken from the py4cytoscape test suite. It loads a galFiltered network, then clones it and lays the clone out in a grid. It then executes layout_copycat() to recover the layout from the original network.

    def test_layout_copycat(self):
        # Initialize
        load_test_session()
        orig_suid = get_network_suid()
        cloned_suid = clone_network()

        # Verify that the basic copycat works by laying out clone in a grid, then returning it to original
        self.assertDictEqual(layout_network('grid', cloned_suid), {})
        self.assertDictEqual(layout_copycat(orig_suid, cloned_suid),
                             {'mappedNodeCount': 330, 'unmappedNodeCount': 0})
        # To verify, operator should eyeball the network in Cytoscape

        # Verify that there are no unmapped nodes when we tell copycat to ignore them
        self.assertDictEqual(layout_network('grid', cloned_suid), {})
        self.assertDictEqual(
            layout_copycat('galFiltered.sif', 'galFiltered.sif_1', grid_unmapped=False, select_unmapped=False),
            {'mappedNodeCount': 330, 'unmappedNodeCount': 0})
        # To verify, operator should eyeball the network in Cytoscape

You might also try this manually using the Cytoscape GUI. Let me know ... good luck!

bdemchak commented 1 year ago

Sorry for missing your question about the layout tools.

I think there's nothing to be done for these. py4cytoscape/RCy3 rely on REST calls made available through Cytoscape's CyREST interface. You can see the interface yourself by using the Cytoscape GUI and clicking on Help | Automation | CyREST API or Help | Automation | CyREST Command API. (There are two different menu items because they document two different sets of features.)

If you install an app from the App Store and the app provides CyREST automation features, they will be automatically available in the CyREST interface, too.

Looking at these two feature sets, you can see that the layout controls you're asking about aren't present ... so ... they're not available in py4cytoscape/RCy3 either.

I can add them to the request list if you're interested in them ... possible implementation time could be 6 months, though.

gmhhope commented 1 year ago

Thanks very much!

I think it will be great to be included for implementation. But definitely not for me but for the general community!

But overall, it was great!

Thanks, Minghao Gong

bdemchak commented 1 year ago

Thanks! I have added feature requests to our database ... let's see what happens.