Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Embed image in nodes automation by py4cytoscape #120

Open
gmhhope opened this issue Sep 21, 2023 · 14 comments
Open

Embed image in nodes automation by py4cytoscape #120

gmhhope opened this issue Sep 21, 2023 · 14 comments

Comments

@gmhhope
Copy link

gmhhope commented Sep 21, 2023

Hey @bdemchak

Any easy and quick way to embed image automatically by providing path in local directory?

Thanks,
Minghao Gong

@gmhhope gmhhope changed the title Quick question: embed image Embed image in nodes automation by py4cytoscape Sep 21, 2023
@bdemchak
Copy link
Collaborator

Have you considered add_annotation_image()?

This corresponds to the Annotation tab on the far left of the Cytoscape window, and is activated when you hit the image button.

I'm not sure exactly what you're trying to accomplish, but that's what jumps to mind.

Or are you trying to use an image to represent a node? If so, you might consider a visual style? Doing that in py4cytoscape isn't supported by explicit calls but should be possible via generic style functions.

Does this help?

@gmhhope
Copy link
Author

gmhhope commented Sep 21, 2023

Thanks very much for helping me!

Or are you trying to use an image to represent a node? If so, you might consider a visual style? Doing that in py4cytoscape isn't supported by explicit calls but should be possible via generic style functions.

  • I am trying the latter option, which I need to have another graph to be shown in the node. Something like this:
Screenshot 2023-09-21 at 2 10 33 PM

I am currently trying to do it manually using the following way: Style>Image/Chart1>Open Image manager>add the image>then imbed per node using bypass. But it is not fun at all considering this won't be my last version.

  • Furthermore, the image size is somehow proportional to the node size and I try to use sync_node_custom_graphics_size(False), which it doesn't change anything.

I looked through the customize options. But there seems no such an option?
Screenshot 2023-09-21 at 2 15 44 PM

  • (optional question)The more advanced thing I think of is that: even if I want to include customized graph based on the node column, there is no bypass option, which sounds like I won't be able to customize what I want to show in individual node. For example, For node1, I want to show a bar plot for node column (columnA,columnB,columnC) with pie chart format in node1. Then for another node (e.g., node2), I want to show a bar plot for node column (columnD,column E)...That sounds like not achievable with the current utils?

Thanks,
Minghao Gong

@bdemchak
Copy link
Collaborator

I see ... thanks.

The visual property that you'd need to set would be NODE_CUSTOMGRAPHICS_1, and the value would be something like:

file:/C:/Users/CyDeveloper/Desktop/New%20Bitmap%20Image.jpg,bitmap image

Not so obvious. So, to nail this down, I'll pose the question to the developers to see exactly what value should be set.

(optional question) I think I can set chart type as a bypass in the Cytoscape GUI. I first select the node, then I use the Style tab to click Bypass for the Image/Chart 1 property, and then choose the Charts tab and then configure the chart. It seems like the followon question would be how to set the bypass via py4cytoscape by using a call something like set_node_custom_bar_chart() ... is that what you're thinking?

@gmhhope
Copy link
Author

gmhhope commented Sep 21, 2023

/### NODE_CUSTOMGRAPHICS_1

I see ... thanks.

The visual property that you'd need to set would be NODE_CUSTOMGRAPHICS_1, and the value would be something like:

file:/C:/Users/CyDeveloper/Desktop/New%20Bitmap%20Image.jpg,bitmap image

Not so obvious. So, to nail this down, I'll pose the question to the developers to see exactly what value should be set.

Thanks, that is exactly I am trying to find. I am also reading the automation>command API:

Based on the node list properties:
http://localhost:1234/v1/commands/node/list properties

{
  "data": [
    "Image/Chart 9",
    "Label Font Size",
    "Custom Paint 8",
    "Image/Chart Size 3",
    "Size",
    "Visible",
    "(Compound Node)",
    "Custom Paint 4",
    "(Compound Node)",
    "Image/Chart Size 8",
    "Transparency",
    "Image/Chart 1",
    "Image/Chart Position 5",
    "Image/Chart 4",
    "Border Line Type",
    "Z Location",
    "Visual Property",
    "Image/Chart Position 1",
    "Image/Chart Size 7",
    "Label Position",
    "Custom Paint 9",
    "Custom Paint 7",
    "Image/Chart 7",
    "Custom Paint 1",
    "Label Width",
    "Image/Chart Size 1",
    "Image/Chart Size 6",
    "Width",
    "Image/Chart 5",
    "Network Image Visible",
    "Label Rotation",
    "Label Color",
    "Border Transparency",
    "Custom Paint 5",
    "Paint",
    "Image/Chart Size 9",
    "Label",
    "Image/Chart Size 5",
    "Image/Chart 6",
    "Shape",
    "Image/Chart Position 2",
    "X Location",
    "Label Transparency",
    "Image/Chart Position 9",
    "Image/Chart 8",
    "Image/Chart Size 2",
    "Tooltip",
    "Border Paint",
    "Selected",
    "Image/Chart 3",
    "Image/Chart 2",
    "Border Width",
    "Image/Chart Position 8",
    "Custom Paint 3",
    "Image/Chart Position 3",
    "Selected Paint",
    "Height",
    "Label Font Face",
    "Image/Chart Size 4",
    "Image/Chart Position 7",
    "Custom Paint 2",
    "Image/Chart Position 4",
    "Custom Paint 6",
    "Image/Chart Position 6",
    "Y Location",
    "Depth",
    "Fill Color"
  ],
  "errors": []
}

I actually don't see NODE_CUSTOMGRAPHICS_1, am I looking into a wrong place?

Okay I found it by get_visual_property_names

p4c.get_visual_property_names()

[...
 'NODE_CUSTOMGRAPHICS_1',
 'NODE_CUSTOMGRAPHICS_2',
 'NODE_CUSTOMGRAPHICS_3',
 'NODE_CUSTOMGRAPHICS_4',
 'NODE_CUSTOMGRAPHICS_5',
 'NODE_CUSTOMGRAPHICS_6',
 'NODE_CUSTOMGRAPHICS_7',
 'NODE_CUSTOMGRAPHICS_8',
 'NODE_CUSTOMGRAPHICS_9',
 'NODE_CUSTOMGRAPHICS_POSITION_1',
 'NODE_CUSTOMGRAPHICS_POSITION_2',
 'NODE_CUSTOMGRAPHICS_POSITION_3',
 'NODE_CUSTOMGRAPHICS_POSITION_4',
 'NODE_CUSTOMGRAPHICS_POSITION_5',
 'NODE_CUSTOMGRAPHICS_POSITION_6',
 'NODE_CUSTOMGRAPHICS_POSITION_7',
 'NODE_CUSTOMGRAPHICS_POSITION_8',
 'NODE_CUSTOMGRAPHICS_POSITION_9',
 'NODE_CUSTOMGRAPHICS_SIZE_1',
 'NODE_CUSTOMGRAPHICS_SIZE_2',
 'NODE_CUSTOMGRAPHICS_SIZE_3',
 'NODE_CUSTOMGRAPHICS_SIZE_4',
 'NODE_CUSTOMGRAPHICS_SIZE_5',
 'NODE_CUSTOMGRAPHICS_SIZE_6',
 'NODE_CUSTOMGRAPHICS_SIZE_7',
 'NODE_CUSTOMGRAPHICS_SIZE_8',
 'NODE_CUSTOMGRAPHICS_SIZE_9',
 'NODE_CUSTOMPAINT_1',
 'NODE_CUSTOMPAINT_2',
 'NODE_CUSTOMPAINT_3',
 'NODE_CUSTOMPAINT_4',
 'NODE_CUSTOMPAINT_5',
 'NODE_CUSTOMPAINT_6',
 'NODE_CUSTOMPAINT_7',
 'NODE_CUSTOMPAINT_8',
 'NODE_CUSTOMPAINT_9',
...]


Not so obvious. So, to nail this down, I'll pose the question to the developers to see exactly what value should be set.

Thanks very much for it! This will save my life!

NODE_CUSTOMGRAPHICS_# help me set the size

p4c.set_node_property_bypass(node_names = ['m_31'],
                             new_values = [300],
                             visual_property = 'NODE_CUSTOMGRAPHICS_SIZE_1')

But if there is a way I can just set size based on the original size then it will be great! But it helps already.

set_node_custom_bar_chart_by_pass ?

It seems like the followon question would be how to set the bypass via py4cytoscape by using a call something like set_node_custom_bar_chart() ... is that what you're thinking?

Exactly this is what I am wondering. lol

Thanks again!

Best,
Minghao

@bdemchak
Copy link
Collaborator

OK ... custom graphics (as either graphs or static images) are an odd thing in Cytoscape. Clearly, this all works in the GUI. But getting defaults and bypasses working in CyREST/py4cytoscape/RCy3 is another matter. I have submitted questions, but there aren't any immediate answers. I'm also having trouble getting them to work myself from either Swagger or py4cytoscape.

I think we have to wait until the developers can engage this, and even then, with no certain result.

Sorry not to have more definite information.

@bdemchak
Copy link
Collaborator

Hi --

I have answers regarding static images ...

In Cytoscape, a static image must be registered in the ImageManager before it can be used in a NODE_CUSTOMGRAPHICS_1 style. Unfortunately, there aren't any REST calls that allow access to the ImageManager, so calls would need to be added.

I'm happy to request new calls, and they may be feasible. Supposing I were to do that, can you give me any idea of how many unique images would suit your application? I suspect that there are some ImageManager assumptions about the count of images in existing Cytoscape, supposing that they'll be entered via the GUI and would naturally be limited to only a few. Good to know these requirements and limits ahead of time.

The functions I would ask for would be Add, Delete, List, and Clear.

As for your question about a Pythonic way of loading tables, I think you must be asking about load_table_data_from_file(). You raise a decent point. I think you might get that functionality by using load_table_data() after loading a dataframe from a JSON file. No?? See here.

@gmhhope
Copy link
Author

gmhhope commented Sep 26, 2023

Hi Barry,

Thanks very much for replying back to me. Yes, if I can do python call to image for nodes that will be great. Then at least I don't need to do bypass to put new graph in each node.

I think there might be at least 20 images I need to imbed. So far, they work manually. Thus, I am not aware of the limits of images allowed in GUI. But, I think this will be something very interesting to use in long run (e.g., some metabolic flux figures, which will be much better if I can imbed bar charts in the flux (e.g., TCA) that I generated externally.

And thanks for the answer regarding load_table_data_from_file(). The problem I had before is that JSON allows some field that will be missing and when converting to table, they will turn to np.nan, which is not handled right in the cytoscape table. I found that if there is np.nan, then cytoscape seems considering the column to be character type rather than float type. I can assign some float values to replace np.nan, but this can be painful.

Thanks,
Minghao Gong

@gmhhope
Copy link
Author

gmhhope commented Sep 26, 2023

I may misunderstand what you just told me:

I understands that there might be a missing call to import external figures to ImageManager. But do you mean that if I already have the figures in the ImageManager, there is already REST call to load figure to a specific node?

If so, please let me know as assigning figures to nodes is basically the rate-limiting step for my process.

Thanks,
Minghao Gong

@gmhhope
Copy link
Author

gmhhope commented Dec 17, 2023

Hi Barry,

How is this feature going now? Just want to check in if there are updates.

Best,
MInghao Gong

@bdemchak
Copy link
Collaborator

Hi, Minghao Gong --

This is a difficult issue, and I haven't gotten a good answer from the developers yet.

For the sake of keeping track of information, suppose that there is an image loaded into the ImageManager (regardless of how it was loaded, which is another story). Setting the image for a node (e.g., 2301863) would be done by a call that looks like this:

p4c.set_node_property_bypass(2301863, "org.cytoscape.ding.customgraphics.bitmap.URLImageCustomGraphics,32,file:/C:/Users/CyDeveloper/CytoscapeConfiguration/3/karaf_data/tmp/32.png,bitmap image", 'NODE_CUSTOMGRAPHICS_1')

It's unclear how the "32" and the "32.png" figure into this. And it's unclear how the image gets loaded into ImageManager.

That's what I'm tracking down.

Stay tuned ...

@carissableker
Copy link

Hi,

In case the following is helpful for anyone. Here's a function I use to add png's per node.:

https://github.com/NIB-SI/skm-tools/blob/d29f104e03f88fb38737e924e3a430c68e848963/skm_tools/cytoscape_utils.py#L366C1-L396C1

import pandas as pd
import py4cytoscape as p4c

def add_custom_png(network, create_png, style=None):
    '''
    network : int
        Cytoscape suid, where to apply the layout
    create_png: function
        function that creates a png per node and returns png file path

    '''

    nodes = p4c.get_all_nodes(network=network)

    node_pngs = {}
    for node in nodes:
        node_png_fname = create_png(node)
        if node_png_fname:
            node_pngs[node] = {'fig_location':f"file:{str(node_png_fname.absolute())}"}

    table = pd.DataFrame.from_dict(node_pngs, orient='index')

    if style is None:
        style = p4c.styles.get_current_style(network=network)

    p4c.load_table_data(table, network=network)
    p4c.style_dependencies.sync_node_custom_graphics_size(False, style_name=style)

    style_mapping = p4c.style_mappings.map_visual_property(
        visual_prop="NODE_CUSTOMGRAPHICS_1",
        table_column="fig_location",
        mapping_type="p",
    )
    p4c.style_mappings.update_style_mapping(style, style_mapping)

For example here: skm-tools/case-study-2-CKN-network-analysis.ipynb (very last section), I create heatmaps for each node and load it next the node.

image

The style (e.g. png size and location relative to the node) is specific to my use-case, but it's easily adjusted.

@gmhhope
Copy link
Author

gmhhope commented Apr 7, 2024 via email

@carissableker
Copy link

I haven't tried it, but that should be possible, since Cytoscape does support SVG images as annotations.

@bdemchak
Copy link
Collaborator

Very nice work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants