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

Frequency Chord diagram and Heatmap in Python #85

Open
maximelepetit opened this issue Jan 31, 2024 · 7 comments
Open

Frequency Chord diagram and Heatmap in Python #85

maximelepetit opened this issue Jan 31, 2024 · 7 comments
Assignees
Labels
enhancement New feature or request

Comments

@maximelepetit
Copy link

Hi ,

Thanks a lot for this useful tool !

I'm running Liana and i'm curious that you cannot provide methods to generate Chord diagram or heatmap as in the liana R wrapper.

Have you planned to add these methods ?

Best regards,

Maxime

@maximelepetit maximelepetit added the enhancement New feature or request label Jan 31, 2024
@dbdimitrov
Copy link
Collaborator

Hi @maximelepetit,

Thanks for opening an issue!
I've been considering implementing one of the two to liana-py.

I will do my best to have at least one implemented soon.

In the meantime, ChatGPT does an excellent job when generating network plots with networkx. And a plot with https://github.com/DingWB/PyComplexHeatmap should be relatively quick to make :)

Best wishes,
Daniel

@maximelepetit
Copy link
Author

maximelepetit commented Feb 2, 2024

Hi Daniel,

For Chords diagrams i found an easy and quickly way with pyCirclize :
One example :

import pycirclize
from pycirclize import Circos
import pandas as pd
from pycirclize.parser import Matrix


## Extract liana_res
df1 = adata.uns['liana_res'][['source','target']].groupby(['source','target']).size().reset_index(name='counts')
df = df1.pivot(index='source',columns='target',values='counts')

matrix_data=df.values
row_names = list(df.index)
col_names = row_names

matrix_df = pd.DataFrame(matrix_data, index=row_names, columns=col_names)

# Initialize from matrix (Can also directly load tsv matrix file)
circos = Circos.initialize_from_matrix(
    matrix_df,
    space=3,
    cmap="tab10",
    r_lim=(93, 100),
    ticks_interval=500,
    label_kws=dict(r=94, size=12, color="white"),
    link_kws=dict(direction=1, ec="black", lw=0.5),
)

#print(matrix_df)
fig = circos.plotfig()

#print(matrix_df)
fig = circos.plotfig()

Give :
chords1
Best !
Maxime

@maximelepetit
Copy link
Author

maximelepetit commented Feb 2, 2024

You can highlight specific groups :

import pycirclize
from pycirclize import Circos
import pandas as pd
from pycirclize.parser import Matrix

# Extract liana_res
df1 = adata.uns['liana_res'][['source','target']].groupby(['source','target']).size().reset_index(name='counts')
df = df1.pivot(index='source',columns='target',values='counts')

matrix_data=df.values
row_names = list(df.index)
col_names = row_names
matrix_df = pd.DataFrame(matrix_data, index=row_names, columns=col_names)

# Define link_kws handler function to customize each link property
def link_kws_handler(from_label: str, to_label: str):
    ## Highlith Astro, CR, Microglia source
    if from_label in ('Astrocytes', 'CR', 'Microglia'):
        # Set alpha, zorder values higher than other links for highlighting
        return dict(alpha=0.5, zorder=1.0)
    else:
     return dict(alpha=0.1, zorder=1.0)

# Initialize from matrix (Can also directly load tsv matrix file)
circos = Circos.initialize_from_matrix(
    matrix_df,
    space=3,
    cmap="tab10",
    r_lim=(93, 100),
    ticks_interval=500,
    label_kws=dict(r=94, size=12, color="white"),
    link_kws=dict(direction=1, ec="black", lw=0.5),
    link_kws_handler=link_kws_handler,
)

#print(matrix_df)
fig = circos.plotfig()

Give :
chord2

;)

@maximelepetit
Copy link
Author

Alternatively you can generate Sankey plot through pySankey :

from pySankey.sankey import sankey
import pandas as pd
df1 = adata.uns['liana_res'][['source','target']].groupby(['source','target']).size().reset_index(name='counts')
sankey(
    left=df1["source"], right=df1["target"], 
    leftWeight= df1["counts"], rightWeight=df1["counts"], fontsize=10
)

GIves :
sankey

@dbdimitrov
Copy link
Collaborator

Hi @maximelepetit,

Thanks a lot for all your suggestions!
I will pin the issue and will keep it open until I have some of those in place.

I plan to do a rehaul of liana's plotting functions, and I will make sure these are included also.

Daniel

@dbdimitrov dbdimitrov pinned this issue Feb 3, 2024
@brainfo
Copy link

brainfo commented Apr 2, 2024

Hi, I feel like it's also good to have a hypothesis driven layout, showing the specific sender-ligand -- receptor-recepient pairs, with for example senders on one sphere and recepients on another and the color by any score, like the magnitude, or the significance, rank, lrmean, or change between conditions.
I used to use ChordDiagram package in r.
Maybe it's good to have this in the utils in liana+ py?

while so far for convenience with same information we can simply show bar/dot plots

and to compare the same pair in different conditions, which metric is recommended to be tested? combined rank or individual continous magnitude metric?

@dbdimitrov
Copy link
Collaborator

Hi @brainfo, thanks for the suggestion. I'm still working on refactoring the algorithmic side of liana, but once I'm done with that. I will refactor the functions and extend them with the suggestions here.

re comparing across conditions: there are a few tutorials, e.g. using differential expression analysis with liana and PyDeSeq2, or the tutorials with MOFA or Tensor-cell2cell.

I would suggest checking those 🙂 though you could compare most scores as long as you normalize such that your conditions are comparable prior to running liana.

Hope this helps.

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

No branches or pull requests

3 participants