Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
783a63c
Merge pull request #7 from CostaLab/dev
ruthvik07 Oct 17, 2025
7f2bc0d
Merge pull request #8 from CostaLab/dev
ruthvik07 Oct 17, 2025
6096d5c
adding anndata
jsnagai Feb 2, 2026
68b98b5
refactoring tests
jsnagai Feb 3, 2026
9893256
refactoring
jsnagai Feb 10, 2026
abec525
refactoring
jsnagai Feb 10, 2026
c55e89c
adding scriv
jsnagai Feb 10, 2026
7a90919
adding scriv
jsnagai Feb 10, 2026
789d73b
adding scriv
jsnagai Feb 10, 2026
93ad07d
prep actions
jsnagai Feb 10, 2026
ccc38ef
prep actions
jsnagai Feb 10, 2026
7e52585
updating readthedocs and fixing small details
jsnagai Feb 25, 2026
db4d105
adding mpl test and liana parser function
jsnagai Feb 25, 2026
d0f1066
adding gmean
jsnagai Feb 25, 2026
e9e42d8
adding more tests
jsnagai Feb 26, 2026
ef37121
adding more tests
jsnagai Feb 26, 2026
e0d8d59
adding more tests
jsnagai Feb 26, 2026
8849e91
adding more tests
jsnagai Feb 26, 2026
f865604
adding badges
jsnagai Feb 27, 2026
a1e16fd
adding badges
jsnagai Feb 27, 2026
c5c2bcc
adding badges
jsnagai Feb 27, 2026
7f542c6
adding badges
jsnagai Feb 27, 2026
8db9c7a
adding badges
jsnagai Feb 27, 2026
2a826cf
fix badges
jsnagai Mar 17, 2026
9d63200
fix version
jsnagai Mar 17, 2026
380ea4d
scverse-ecosystem
jsnagai Mar 17, 2026
694ec9e
Update features section to version 2.1.3
jsnagai Mar 17, 2026
2060695
Add cache parameters to badge links in README
jsnagai Mar 17, 2026
e7fd88d
fixing comparison order in the wilcoxon
jsnagai Mar 25, 2026
ad0bc0f
fixing comparison order in the wilcoxon
jsnagai Mar 25, 2026
b519471
fixing orders
jsnagai Mar 26, 2026
5225828
WIP: planning speedup for Monte Carlo simulation
Copilot Apr 1, 2026
bb87cee
speedup: vectorise Monte Carlo permutation in fisher_test_cci
Copilot Apr 1, 2026
119290e
speedup: address code review comments in _pairwise_stats
Copilot Apr 1, 2026
44f99fb
Merge pull request #12 from CostaLab/copilot/speedup-montecarlo-simul…
jsnagai Apr 2, 2026
7780d41
adapting from_liana
jsnagai Jun 18, 2026
8b39adb
adapting from_liana
jsnagai Jun 18, 2026
be2f0df
liana
jsnagai Jun 18, 2026
640f498
liana
jsnagai Jun 18, 2026
28798b9
liana
jsnagai Jun 18, 2026
62c474d
liana
jsnagai Jun 18, 2026
46874aa
liana
jsnagai Jun 18, 2026
f38d419
liana
jsnagai Jun 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/pipypublish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Publish to PyPI

on:
release:
types: [ published ]
branches: [ main ]
workflow_dispatch:

jobs:
build-and-publish:
runs-on: ubuntu-latest

steps:
- name: Checkout sources
uses: actions/checkout@v2

- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: "3.11"

- name: Install poetry and dependencies
run: |
python -m pip install --upgrade pip
python -m pip install poetry

- name: Configure poetry
env:
pypi_token: ${{ secrets.PYPI }}
run: poetry config pypi-token.pypi $pypi_token

- name: Build and publish
run: yes | poetry publish --build
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.11
17 changes: 17 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

2026-02-10
==========

Removed
-------

- Refactor in generate_report

Added
-----

- Add save option in generate_report
- fix fisher_test

2026-02-10
==========
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

<img src="https://github.com/CostaLab/pyCrossTalkeR/blob/main/logo1.png" align="right" width="200" />


<!-- Python versions supported -->
[![Python Versions](https://img.shields.io/pypi/pyversions/pycrosstalker?cacheSeconds=300)](https://pypi.org/project/pycrosstalker/)
[![Downloads](https://img.shields.io/pypi/dm/pycrosstalker?cacheSeconds=300)](https://pypi.org/project/pycrosstalker/)
[![License](https://img.shields.io/pypi/l/pycrosstalker?cacheSeconds=300)](https://pypi.org/project/pycrosstalker/)
[![PyPI version](https://img.shields.io/pypi/v/pycrosstalker?cacheSeconds=300)](https://pypi.org/project/pycrosstalker/)

James S. Nagai<sup>1</sup>,
Vanessa Kloeker<sup>1</sup>,
Ruthvik Koppala<sup>1</sup>,
Expand All @@ -24,6 +31,7 @@ Ivan G. Costa<sup>1*</sup>

![Alt text](image.png)


**Motivation:** Ligand-receptor (LR) analysis allows the characterization of cellular crosstalk from single cell RNA-seq data. However, current LR methods provide limited approaches for prioritization of cell types, ligands or receptors or characterizing changes in crosstalk between two biological conditions.

**Results:** pyCrossTalkeR is a framework for network analysis and visualisation of LR networks. pyCrossTalkeR identifies relevant ligands, receptors and cell types contributing to changes in cell communication when contrasting two biological states: disease vs. homeostasis. A case study on scRNA-seq of human myeloproliferative neoplasms reinforces the strengths of pyCrossTalkeR for characterisation of changes in cellular crosstalk in disease state.
Expand Down Expand Up @@ -51,7 +59,7 @@ libgeos-dev
```


## Features v2.0.0
## Features v2.1.3


- Single and Comparative Reports
Expand All @@ -61,6 +69,7 @@ libgeos-dev
- All measures and PC table
- PC1 and PC2 based barplot
- LR pair visualization plot can be done
- Statistical tests for both interaction amount and also interaction strenght


# References
Expand Down
Binary file removed dist/pycrosstalker-2.1.0-py3-none-any.whl
Binary file not shown.
Binary file removed dist/pycrosstalker-2.1.0.tar.gz
Binary file not shown.
Binary file added dist/pycrosstalker-2.1.3-py3-none-any.whl
Binary file not shown.
Binary file added dist/pycrosstalker-2.1.3.tar.gz
Binary file not shown.
Binary file added dist/pycrosstalker-2.1.4-py3-none-any.whl
Binary file not shown.
Binary file added dist/pycrosstalker-2.1.4.tar.gz
Binary file not shown.
Binary file added dist/pycrosstalker-2.1.5rc0-py3-none-any.whl
Binary file not shown.
Binary file added dist/pycrosstalker-2.1.5rc0.tar.gz
Binary file not shown.
Binary file added dist/pycrosstalker-2.1.6-py3-none-any.whl
Binary file not shown.
Binary file added dist/pycrosstalker-2.1.6.tar.gz
Binary file not shown.
2 changes: 1 addition & 1 deletion docs/source/Human_Myelofibrosis.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

```{toctree}
---
maxdepth: 3
maxdepth: 2
---
notebooks/Human_Myelofibrosis.ipynb
```
2 changes: 1 addition & 1 deletion docs/source/Human_Myocardial_Infarction.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

```{toctree}
---
maxdepth: 3
maxdepth: 2
---
notebooks/Human_Myocardial_Infarction.ipynb
```
8 changes: 3 additions & 5 deletions docs/source/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@ Import pycrosstalker as:
import pycrosstalker
```


```{toctree}
:maxdepth: 2

tools
plots
:maxdepth: 1
tools
plots
```
7 changes: 5 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information


project = 'pyCrossTalkeR'
copyright = '2025, Ruthvik Koppala'
author = 'Ruthvik Koppala'
copyright = '2025, James Nagai'
author = 'James Nagai'

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration


version = '0.1.8.8'

extensions = [
Expand Down
1 change: 0 additions & 1 deletion docs/source/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ You can install pyCrossTalkeR with the simple commands below:

```
pip install pycrosstallker

```


Expand Down

Large diffs are not rendered by default.

This file was deleted.

1,697 changes: 850 additions & 847 deletions docs/source/notebooks/Human_Myelofibrosis.ipynb

Large diffs are not rendered by default.

1,846 changes: 956 additions & 890 deletions docs/source/notebooks/Human_Myocardial_Infarction.ipynb

Large diffs are not rendered by default.

2,463 changes: 1,453 additions & 1,010 deletions poetry.lock

Large diffs are not rendered by default.

6 changes: 2 additions & 4 deletions pycrosstalker/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
__version__ = "1.0.1"
__author__ = 'Ruthvik Koppala'
__version__ = "2.1.6"
__author__ = 'James Nagai'
__credits__ = 'Institute for Computational Genomics'

import pycrosstalker.tools as tl
import pycrosstalker.plots as pl


#Atfan helped to translate some of the code
Binary file added pycrosstalker/__pycache__/__init__.cpython-311.pyc
Binary file not shown.
Binary file added pycrosstalker/__pycache__/__init__.cpython-312.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
41 changes: 21 additions & 20 deletions pycrosstalker/plots/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,13 @@
import matplotlib.cm as cm
import matplotlib.colors as mcolors
import seaborn as sns
import plotly.colors as pc
import plotly.graph_objects as go
from plotnine import *
from adjustText import adjust_text
from gprofiler import GProfiler
from sankeyflow import Sankey
import json


def plot_cci(graph, colors, plt_name, coords, pg, emax=None, leg=False, low=25, high=75, ignore_alpha=False, log=False, efactor=8, vfactor=12, vnames=True, figsize=None, scale_factor=2, node_size=2, font_size=10):
def plot_cci(graph, colors, plt_name, coords, pg, emax=None, leg=False, low=25, high=75, ignore_alpha=False, log=False, efactor=8, vfactor=12, vnames=True, figsize=None, scale_factor=2, node_size=2, font_size=10,return_figure=False):
"""
This function does a CCI plot

Expand All @@ -37,17 +34,21 @@ def plot_cci(graph, colors, plt_name, coords, pg, emax=None, leg=False, low=25,
high :
Higher threshould which will be filtered. Edges within the interval [low\,high] are filtered.
ignore_alpha :
not include transparency on the plot
Not include transparency on the plot edges
log :
logscale the interactions
Logscale the interactions
efactor :
edge scale factor
Edge scale factor
vfactor :
edge scale factor
Certex scale factor
vnames :
remove vertex labels
Remove vertex labels
pg :
pagerank values
Pagerank values
figsize:
Set matplotlib figsize
return_figure:
Option for return matplotlib figure axes

Returns
-------
Expand Down Expand Up @@ -127,21 +128,21 @@ def plot_cci(graph, colors, plt_name, coords, pg, emax=None, leg=False, low=25,
min_pg, max_pg = min(pg), max(pg)
legend1 = ax.legend(loc='lower left', title="Pagerank",
handles=[plt.Line2D([], [], linestyle='', marker='o', markersize=v / vfactor, markerfacecolor='black', markeredgecolor='none') for v in [min_pg, (min_pg + max_pg) / 2, max_pg]],
labels=[round(min_pg, 2), round((min_pg + max_pg) / 2, 2), round(max_pg, 2)], bbox_to_anchor=(0.8, 0))
labels=[round(min_pg, 2), round((min_pg + max_pg) / 2, 2), round(max_pg, 2)], bbox_to_anchor=(0.95, 0.3))

# Thickness legend
non_zero_inter_edges = [d['inter'] for _, _, d in graph.edges(data=True) if d.get('inter', 0) != 0]
if non_zero_inter_edges:
e_wid_sp = [round(min(non_zero_inter_edges), 2), round(min(non_zero_inter_edges) + (emax / 2), 2), round(emax, 2)]
legend2 = ax.legend(e_wid_sp, title='Percentage of \nthe interactions', title_fontsize='small', loc='upper left', bbox_to_anchor=(0.8, 0.4))
legend2 = ax.legend(e_wid_sp, title='Percentage of \nthe interactions', title_fontsize='small', loc='upper left', bbox_to_anchor=(0.95, 0.7))

ax.add_artist(legend1)
ax.add_artist(legend2)

ax.set_title(plt_name)
# Show the plot
plt.tight_layout()
plt.show()
if return_figure:
return (fig,ax)


def plot_pca_LR_comparative(lrobj_tblPCA, pca_table, dims=(1, 2), ret=False, ggi=True, include_tf=False, gene_types="all"):
Expand Down Expand Up @@ -768,7 +769,7 @@ def plot_volcane(df, method, p_threshold=0.05, fc_threshold=1, figsize=(8, 6), a
plt.show()


def plot_clustermap(data, title, annot=True):
def plot_clustermap(data, title, annot=True, return_figure=False):
"""
This function generates a Clustermap plot

Expand All @@ -780,15 +781,16 @@ def plot_clustermap(data, title, annot=True):
Title of the plot
annot : bool
Whether to annotate the heatmap with values

return_figure:
Option for return matplotlib figure axes
Returns
-------

Python Cluster map

"""
pivot_table = data.groupby(["source", "target"])["LRScore"].sum().unstack().fillna(0)
xlabel, ylabel = "Target Tissue", "Source Tissue"

xlabel, ylabel = "Target", "Source"
g = sns.clustermap(
pivot_table,
figsize=(9, 7),
Expand All @@ -799,13 +801,12 @@ def plot_clustermap(data, title, annot=True):
dendrogram_ratio=(0.2, 0.2),
cbar_pos=(0.02, 0.8, 0.03, 0.15)
)

g.ax_heatmap.set_xlabel(xlabel)
g.ax_heatmap.set_ylabel(ylabel)
plt.title(title, fontsize=14)

plt.show()


def plot_graph_clustermap(graph, weight="LRScore", title="Ligand-Receptor Heatmap", annot=True):
"""
This function generates the graph adjacency matrix Heatmap
Expand Down
5 changes: 3 additions & 2 deletions pycrosstalker/tools/Single_Condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@

def read_lr_single_condition(input, sel_columns, out_path="/tmp/", sep=",", colors=None):
"""
This function loads the single conditions LR outputs and use it to generate the report data and it`s object It assumes that the table presents the following columns Ligand, Ligand.Cluster, Receptor,Receptor.Cluster and MeanLR/another measure
This function loads the single conditions LR outputs and use it to generate the report data and it`s object.
It assumes that the table presents the following columns Ligand, Ligand.Cluster, Receptor,Receptor.Cluster and MeanLR/another measure

Parameters
----------
Expand Down Expand Up @@ -114,7 +115,7 @@ def read_lr_single_condition(input, sel_columns, out_path="/tmp/", sep=",", colo
coords = {node: c[i] for i, node in enumerate(sorted(set(unif_celltypes), key=lambda x: x.lower()), start=0)}

if colors is None:
matplot_colors = plt.cm.get_cmap('Paired', len(set(unif_celltypes)))
matplot_colors = plt.get_cmap('Paired', len(set(unif_celltypes)))
colors = {node: mcolors.to_hex(matplot_colors(i)) for i, node in enumerate(sorted(set(unif_celltypes), key=lambda x: x.lower()), start=0)}

lr = {"graphs": graphs,
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
9 changes: 5 additions & 4 deletions pycrosstalker/tools/generate_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def analise_LR(input,
out_file=None,
output_fmt="html_document",
sel_columns=['source','target','gene_A','gene_B','type_gene_A','type_gene_B','MeanLR'],
org='hsa', comparison=None, filtered_net=False, filename=None):
comparison=None, filtered_net=False, filename=None,save=True):

"""
Core engine to generate report. Here we perform all the computation related to pyCrossTalkeR
Expand All @@ -44,7 +44,8 @@ def analise_LR(input,
columns from data
filename :
filename prefix for output files (to be provided if not already present in AnnData object)

save:
Indicates if analysis file is saved or not
Returns
-------
Rmarkdown report all objects from each step
Expand Down Expand Up @@ -75,7 +76,7 @@ def analise_LR(input,
print("Network Analysis Done")

print("Generating h5ad file with Analysed Results")
annData.write(os.path.join(out_path, annData.uns['pycrosstalker']['details']['filename'] + "_analysed.h5ad"))

if save:
annData.write(os.path.join(out_path, annData.uns['pycrosstalker']['details']['filename'] + "_analysed.h5ad"))
return(annData)

Loading
Loading