# `parag`<a href="#"><img src="https://openmoji.org/data/color/svg/1F386.svg" align="right" width="20%"></a>
<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->
**Para** (beyond pairwise) **G**raph: interactive visualization of
higher-order graphs in Python
<!-- [![Contributors][contributors-shield]][contributors-url]
[![Forks][forks-shield]][forks-url]
[![Stargazers][stars-shield]][stars-url] -->
<!-- <a href="">[![PyPI](https://img.shields.io/pypi/v/parag?style=for-the-badge)![Python](https://img.shields.io/pypi/pyversions/parag?style=for-the-badge)](https://pypi.org/project/parag)</a> -->
<a href="">[<img
src="https://img.shields.io/github/actions/workflow/status/rraadd88/beditor/build.yml?style=for-the-badge"
class="quarto-discovered-preview-image" alt="build" />](https://github.com/rraadd88/parag/actions/workflows/build.yml)</a>
<a href="">[![Issues](https://img.shields.io/github/issues/rraadd88/parag.svg?style=for-the-badge)](https://github.com/rraadd88/parag/issues)</a>
<a href="">[![Downloads](https://img.shields.io/pypi/dm/parag?style=for-the-badge.png)](https://pepy.tech/project/parag)</a>
<a href="">[![GNU
License](https://img.shields.io/github/license/rraadd88/parag.svg?style=for-the-badge)](https://github.com/rraadd88/parag/blob/master/LICENSE)</a>
<a href="">[![DOI](https://img.shields.io/badge/DOI-zenodo-blue?style=for-the-badge.png)](https://doi.org//zenodo.)</a>
## Install
``` sh
pip install parag
```
## Interpretation as a hypergraph, using proportion of degrees by communities
Proportion of degrees by communities in a pairwise graph helps reveal
how nodes are grouped together and connected within different
communities. This analysis highlights clusters of nodes with strong
internal connections, potentially representing higher-order
relationships. By comparing the degree proportions within and between
communities, we can distinguish internal cohesion from inter-community
interactions. These insights aid in interpreting the graph as a
hypergraph, where communities with high intra-community connections may
signify higher-order relationships, offering a richer understanding of
complex interactions beyond simple pairwise connections.
Inspired by
> Vehlow, Corinna, Thomas Reinhardt, and Daniel Weiskopf. “Visualizing
> fuzzy overlapping communities in networks.” IEEE Transactions on
> Visualization and Computer Graphics 19.12 (2013): 2486-2495.
> [Figure
> 9B](https://www.researchgate.net/profile/Corinna-Vehlow/publication/256837277/figure/fig4/AS:601696052985880@1520466926646/The-protein-protein-interaction-network-from-Figure-8-shown-with-our-circular-layout-a.png)
Examples:
### Gene interaction networks
``` python
from parag.hypergraph import to_net
cfg,df_=to_net(
nodes=nodes.sort_values('Essentiality (determined from multiple datasets)'),
edges=edges,
col_node_id='Gene ID',
col_source='# protein1',
col_target='protein2',
col_subset_id='Essentiality (determined from multiple datasets)',
show_node_names=True,
defaults=dict(
radius=250,
innerRadius=280,
outerRadius=295,
textSize=7,
textOffset=3,
),
)
```
<iframe
width="100%"
height="1000"
src="outputs//interactions.html"
frameborder="0"
allowfullscreen
></iframe>
<div>
[![](examples/outputs//interactions.png)](https://rraadd88.github.io/parag#interpretation-as-a-hypergraph-using-proportion-of-degrees-by-communities)
</div>
### Neighbourhood analysis in latent space e.g. single cell data
``` python
sc.pl.umap(adata, color="bulk_labels",title='Latent space')
```
![](index_files/figure-commonmark/cell-5-output-1.png)
``` python
from parag.core import get_net_data
nodes,edges=get_net_data(adata) ## generated network data by measuring distances in the latent space and thresholding
```
``` python
from parag.hypergraph import to_net
cfg,df_=to_net(
nodes,
edges,
col_node_id='cell id',
col_source='cell id1',
col_target='cell id2',
col_subset_id='bulk_labels',
show_node_names=False,
defaults=dict(
textSize=8,
textOffset=3,
),
)
```
<iframe
width="100%"
height="1000"
src="outputs//neighbourhoods.html"
frameborder="0"
allowfullscreen
></iframe>
<div>
[![](examples/outputs//neighbourhoods.png)](https://rraadd88.github.io/parag#interpretation-as-a-hypergraph-using-proportion-of-degrees-by-communities)
</div>
### Heterogeneous graph e.g. drug side-effects network
``` python
## filter
nodes=(df02
.loc[:,["Individual Side Effect","Side Effect Name"]]
.log.drop_duplicates()
.assign(
#Side Effect type
subset=lambda df: df['Side Effect Name'].str.split(' ',expand=True)[0],
)
.drop(['Side Effect Name'],axis=1)
.groupby('subset').filter(lambda df: len(df)>3 and len(df)<10)
.head(5)
.sort_values('subset')
.log('Individual Side Effect') # id
.log('Individual Side Effect') # name
)
nodes.head(1)
```
<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
| | Individual Side Effect | subset |
|-----|------------------------|------------------|
| 1 | C0162830 | Photosensitivity |
</div>
``` python
edges=(
df02
.log.query(expr=f"`Individual Side Effect` == {nodes['Individual Side Effect'].unique().tolist()}")
)
edges.head(1)
```
<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
| | \# STITCH | Individual Side Effect | Side Effect Name |
|-----|--------------|------------------------|---------------------------|
| 1 | CID003062316 | C0162830 | Photosensitivity reaction |
</div>
``` python
## append drugs to nodes
nodes=pd.concat(
[
edges.loc[:,['# STITCH']].drop_duplicates().rename(columns={'# STITCH':'node id'},errors='raise').assign(subset='drug'),
nodes.rename(columns={'Individual Side Effect':'node id'},errors='raise'),
],
axis=0,
)
nodes.head(1)
```
<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
| | node id | subset |
|-----|--------------|--------|
| 1 | CID003062316 | drug |
</div>
``` python
from parag.hypergraph import to_net
cfg,df_=to_net(
nodes,
edges,
col_node_id='node id',
col_source='# STITCH',
col_target='Individual Side Effect',
col_subset_id='subset',
show_node_names=False,
defaults=dict(
radius=200,
innerRadius=205,
outerRadius=235,
textSize=9,
textOffset=3,
cornerRadius=3.5,
),
)
```
<iframe
width="100%"
height="1000"
src="outputs//heterogeneous.html"
frameborder="0"
allowfullscreen
></iframe>
<div>
[![](examples/outputs//heterogeneous.png)](https://rraadd88.github.io/parag#interpretation-as-a-hypergraph-using-proportion-of-degrees-by-communities)
</div>
### Network communities
``` python
# Plot graph with colouring based on communities
fig, ax = plt.subplots(1,1, figsize=(5, 3))
visualize_communities(G, communities[3], 2)
```
![](index_files/figure-commonmark/cell-16-output-1.png)
``` python
nodes=pd.Series({i:list(t) for i,t in enumerate(communities[3])}).explode().to_frame('node id').reset_index().rename(columns={'index':'community id'}).sort_values('community id')
nodes.head(1)
```
<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
| | community id | node id |
|-----|--------------|---------|
| 0 | 0 | 0 |
</div>
``` python
edges=pd.DataFrame(G.edges,columns=['source','target'])
edges.head(1)
```
<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
| | source | target |
|-----|--------|--------|
| 0 | 0 | 1 |
</div>
``` python
from parag.hypergraph import to_net
cfg,df_=to_net(
nodes.applymap(str),
edges.applymap(str),
col_node_id='node id',
col_source='source',
col_target='target',
col_subset_id='community id',
show_node_names=True,
defaults=dict(
radius=180,
innerRadius=205,
outerRadius=235,
textSize=17,
textOffset=4,
cornerRadius=3.5,
),
)
```
<iframe
width="100%"
height="1000"
src="outputs//communities.html"
frameborder="0"
allowfullscreen
></iframe>
<div>
[![](examples/outputs//communities.png)](https://rraadd88.github.io/parag#interpretation-as-a-hypergraph-using-proportion-of-degrees-by-communities)
</div>
## How to cite?
1. Using BibTeX:
<!-- -->
@software{Dandage_parag,
title = {parag: interactive visualization of higher-order graphs in Python},
author = {Dandage, Rohan},
year = {2024},
url = {https://doi.org//zenodo.},
version = {v0.0.1},
note = {The URL is a DOI link to the permanent archive of the software.},
}
2. DOI link:
[![DOI](https://zenodo.org/badge/DOI//zenodo..svg)](https://doi.org//zenodo.),
or
3. Using citation information from [CITATION.CFF
file](https://github.com/rraadd88/parag/blob/main/CITATION.cff).
## Future directions, for which contributions are welcome
- [ ] Showing degree counts in addition to the percentages
- [ ] Inferring the `defaults` e.g. radii from the input data.
- [ ] Bind `rotate` signal to the hypergraph and `start/endAngle` to
graph.
- [ ] Set up `tidy` `layout`.
- [ ] Edge coloring by source and target nodes and setting
`interaction`s.
- [ ] CI for quicker testing use lighter example.
- [ ] More examples
Raw data
{
"_id": null,
"home_page": "https://github.com/rraadd88/parag",
"name": "parag",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "",
"keywords": "nbdev jupyter notebook python",
"author": "Rohan Dandage",
"author_email": "rohanadanadge@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/ad/b7/f546a72263df00e414d70086cca58515845fed945d65ea962a9cc767e70f/parag-0.0.1.tar.gz",
"platform": null,
"description": "# `parag`<a href=\"#\"><img src=\"https://openmoji.org/data/color/svg/1F386.svg\" align=\"right\" width=\"20%\"></a>\n\n<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->\n\n**Para** (beyond pairwise) **G**raph: interactive visualization of\nhigher-order graphs in Python\n\n<!-- [![Contributors][contributors-shield]][contributors-url]\n[![Forks][forks-shield]][forks-url]\n[![Stargazers][stars-shield]][stars-url] -->\n<!-- <a href=\"\">[![PyPI](https://img.shields.io/pypi/v/parag?style=for-the-badge)![Python](https://img.shields.io/pypi/pyversions/parag?style=for-the-badge)](https://pypi.org/project/parag)</a> -->\n\n<a href=\"\">[<img\nsrc=\"https://img.shields.io/github/actions/workflow/status/rraadd88/beditor/build.yml?style=for-the-badge\"\nclass=\"quarto-discovered-preview-image\" alt=\"build\" />](https://github.com/rraadd88/parag/actions/workflows/build.yml)</a>\n<a href=\"\">[![Issues](https://img.shields.io/github/issues/rraadd88/parag.svg?style=for-the-badge)](https://github.com/rraadd88/parag/issues)</a>\n<a href=\"\">[![Downloads](https://img.shields.io/pypi/dm/parag?style=for-the-badge.png)](https://pepy.tech/project/parag)</a>\n<a href=\"\">[![GNU\nLicense](https://img.shields.io/github/license/rraadd88/parag.svg?style=for-the-badge)](https://github.com/rraadd88/parag/blob/master/LICENSE)</a>\n<a href=\"\">[![DOI](https://img.shields.io/badge/DOI-zenodo-blue?style=for-the-badge.png)](https://doi.org//zenodo.)</a>\n\n## Install\n\n``` sh\npip install parag\n```\n\n## Interpretation as a hypergraph, using proportion of degrees by communities\n\nProportion of degrees by communities in a pairwise graph helps reveal\nhow nodes are grouped together and connected within different\ncommunities. This analysis highlights clusters of nodes with strong\ninternal connections, potentially representing higher-order\nrelationships. By comparing the degree proportions within and between\ncommunities, we can distinguish internal cohesion from inter-community\ninteractions. These insights aid in interpreting the graph as a\nhypergraph, where communities with high intra-community connections may\nsignify higher-order relationships, offering a richer understanding of\ncomplex interactions beyond simple pairwise connections.\n\nInspired by\n\n> Vehlow, Corinna, Thomas Reinhardt, and Daniel Weiskopf. \u201cVisualizing\n> fuzzy overlapping communities in networks.\u201d IEEE Transactions on\n> Visualization and Computer Graphics 19.12 (2013): 2486-2495. \n> [Figure\n> 9B](https://www.researchgate.net/profile/Corinna-Vehlow/publication/256837277/figure/fig4/AS:601696052985880@1520466926646/The-protein-protein-interaction-network-from-Figure-8-shown-with-our-circular-layout-a.png)\n\nExamples:\n\n### Gene interaction networks\n\n``` python\nfrom parag.hypergraph import to_net\ncfg,df_=to_net(\n nodes=nodes.sort_values('Essentiality (determined from multiple datasets)'),\n edges=edges,\n col_node_id='Gene ID',\n col_source='# protein1',\n col_target='protein2',\n col_subset_id='Essentiality (determined from multiple datasets)',\n show_node_names=True,\n defaults=dict(\n radius=250,\n innerRadius=280,\n outerRadius=295,\n textSize=7,\n textOffset=3,\n ),\n)\n```\n\n <iframe\n width=\"100%\"\n height=\"1000\"\n src=\"outputs//interactions.html\"\n frameborder=\"0\"\n allowfullscreen\n ></iframe>\n \n<div>\n\n[![](examples/outputs//interactions.png)](https://rraadd88.github.io/parag#interpretation-as-a-hypergraph-using-proportion-of-degrees-by-communities)\n\n</div>\n\n### Neighbourhood analysis in latent space e.g.\u00a0single cell data\n\n``` python\nsc.pl.umap(adata, color=\"bulk_labels\",title='Latent space')\n```\n\n![](index_files/figure-commonmark/cell-5-output-1.png)\n\n``` python\nfrom parag.core import get_net_data\nnodes,edges=get_net_data(adata) ## generated network data by measuring distances in the latent space and thresholding\n```\n\n``` python\nfrom parag.hypergraph import to_net\ncfg,df_=to_net(\n nodes,\n edges,\n col_node_id='cell id',\n col_source='cell id1',\n col_target='cell id2',\n col_subset_id='bulk_labels',\n show_node_names=False,\n defaults=dict(\n textSize=8,\n textOffset=3,\n ),\n)\n```\n\n <iframe\n width=\"100%\"\n height=\"1000\"\n src=\"outputs//neighbourhoods.html\"\n frameborder=\"0\"\n allowfullscreen\n ></iframe>\n \n<div>\n\n[![](examples/outputs//neighbourhoods.png)](https://rraadd88.github.io/parag#interpretation-as-a-hypergraph-using-proportion-of-degrees-by-communities)\n\n</div>\n\n### Heterogeneous graph e.g.\u00a0drug side-effects network\n\n``` python\n## filter\nnodes=(df02\n .loc[:,[\"Individual Side Effect\",\"Side Effect Name\"]]\n .log.drop_duplicates()\n .assign(\n #Side Effect type\n subset=lambda df: df['Side Effect Name'].str.split(' ',expand=True)[0], \n )\n .drop(['Side Effect Name'],axis=1)\n .groupby('subset').filter(lambda df: len(df)>3 and len(df)<10)\n .head(5)\n .sort_values('subset')\n .log('Individual Side Effect') # id\n .log('Individual Side Effect') # name\n )\nnodes.head(1)\n```\n\n<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n .dataframe tbody tr th {\n vertical-align: top;\n }\n .dataframe thead th {\n text-align: right;\n }\n</style>\n\n| | Individual Side Effect | subset |\n|-----|------------------------|------------------|\n| 1 | C0162830 | Photosensitivity |\n\n</div>\n\n``` python\nedges=(\n df02\n .log.query(expr=f\"`Individual Side Effect` == {nodes['Individual Side Effect'].unique().tolist()}\")\n )\nedges.head(1)\n```\n\n<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n .dataframe tbody tr th {\n vertical-align: top;\n }\n .dataframe thead th {\n text-align: right;\n }\n</style>\n\n| | \\# STITCH | Individual Side Effect | Side Effect Name |\n|-----|--------------|------------------------|---------------------------|\n| 1 | CID003062316 | C0162830 | Photosensitivity reaction |\n\n</div>\n\n``` python\n## append drugs to nodes\nnodes=pd.concat(\n [\n edges.loc[:,['# STITCH']].drop_duplicates().rename(columns={'# STITCH':'node id'},errors='raise').assign(subset='drug'),\n nodes.rename(columns={'Individual Side Effect':'node id'},errors='raise'),\n ],\n axis=0,\n )\nnodes.head(1)\n```\n\n<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n .dataframe tbody tr th {\n vertical-align: top;\n }\n .dataframe thead th {\n text-align: right;\n }\n</style>\n\n| | node id | subset |\n|-----|--------------|--------|\n| 1 | CID003062316 | drug |\n\n</div>\n\n``` python\nfrom parag.hypergraph import to_net\ncfg,df_=to_net(\n nodes,\n edges,\n col_node_id='node id',\n col_source='# STITCH',\n col_target='Individual Side Effect',\n col_subset_id='subset',\n show_node_names=False,\n defaults=dict(\n radius=200,\n innerRadius=205,\n outerRadius=235,\n textSize=9,\n textOffset=3,\n cornerRadius=3.5,\n ),\n)\n```\n\n <iframe\n width=\"100%\"\n height=\"1000\"\n src=\"outputs//heterogeneous.html\"\n frameborder=\"0\"\n allowfullscreen\n ></iframe>\n \n<div>\n\n[![](examples/outputs//heterogeneous.png)](https://rraadd88.github.io/parag#interpretation-as-a-hypergraph-using-proportion-of-degrees-by-communities)\n\n</div>\n\n### Network communities\n\n``` python\n# Plot graph with colouring based on communities\nfig, ax = plt.subplots(1,1, figsize=(5, 3))\nvisualize_communities(G, communities[3], 2)\n```\n\n![](index_files/figure-commonmark/cell-16-output-1.png)\n\n``` python\nnodes=pd.Series({i:list(t) for i,t in enumerate(communities[3])}).explode().to_frame('node id').reset_index().rename(columns={'index':'community id'}).sort_values('community id')\nnodes.head(1)\n```\n\n<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n .dataframe tbody tr th {\n vertical-align: top;\n }\n .dataframe thead th {\n text-align: right;\n }\n</style>\n\n| | community id | node id |\n|-----|--------------|---------|\n| 0 | 0 | 0 |\n\n</div>\n\n``` python\nedges=pd.DataFrame(G.edges,columns=['source','target'])\nedges.head(1)\n```\n\n<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n .dataframe tbody tr th {\n vertical-align: top;\n }\n .dataframe thead th {\n text-align: right;\n }\n</style>\n\n| | source | target |\n|-----|--------|--------|\n| 0 | 0 | 1 |\n\n</div>\n\n``` python\nfrom parag.hypergraph import to_net\ncfg,df_=to_net(\n nodes.applymap(str),\n edges.applymap(str),\n col_node_id='node id',\n col_source='source',\n col_target='target',\n col_subset_id='community id',\n show_node_names=True,\n defaults=dict(\n radius=180,\n innerRadius=205,\n outerRadius=235,\n textSize=17,\n textOffset=4,\n cornerRadius=3.5,\n ),\n)\n```\n\n <iframe\n width=\"100%\"\n height=\"1000\"\n src=\"outputs//communities.html\"\n frameborder=\"0\"\n allowfullscreen\n ></iframe>\n \n<div>\n\n[![](examples/outputs//communities.png)](https://rraadd88.github.io/parag#interpretation-as-a-hypergraph-using-proportion-of-degrees-by-communities)\n\n</div>\n\n## How to cite?\n\n1. Using BibTeX: \n\n<!-- -->\n\n @software{Dandage_parag,\n title = {parag: interactive visualization of higher-order graphs in Python},\n author = {Dandage, Rohan},\n year = {2024},\n url = {https://doi.org//zenodo.},\n version = {v0.0.1},\n note = {The URL is a DOI link to the permanent archive of the software.},\n }\n\n2. DOI link:\n [![DOI](https://zenodo.org/badge/DOI//zenodo..svg)](https://doi.org//zenodo.),\n or\n\n3. Using citation information from [CITATION.CFF\n file](https://github.com/rraadd88/parag/blob/main/CITATION.cff).\n\n## Future directions, for which contributions are welcome\n\n- [ ] Showing degree counts in addition to the percentages \n- [ ] Inferring the `defaults` e.g.\u00a0radii from the input data.\n- [ ] Bind `rotate` signal to the hypergraph and `start/endAngle` to\n graph. \n- [ ] Set up `tidy` `layout`.\n- [ ] Edge coloring by source and target nodes and setting\n `interaction`s.\n- [ ] CI for quicker testing use lighter example.\n- [ ] More examples\n",
"bugtrack_url": null,
"license": "Apache Software License 2.0",
"summary": "parag: interactive visualization of higher-order graphs in Python",
"version": "0.0.1",
"project_urls": {
"Homepage": "https://github.com/rraadd88/parag"
},
"split_keywords": [
"nbdev",
"jupyter",
"notebook",
"python"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "adb7f546a72263df00e414d70086cca58515845fed945d65ea962a9cc767e70f",
"md5": "6b0af6fc6c8a7885cd8db9f837126f9b",
"sha256": "8c005173597dcaaf3724aa62ada54158322b4082098f0b58e6f8e115a36c6e54"
},
"downloads": -1,
"filename": "parag-0.0.1.tar.gz",
"has_sig": false,
"md5_digest": "6b0af6fc6c8a7885cd8db9f837126f9b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 28389,
"upload_time": "2024-02-25T22:50:36",
"upload_time_iso_8601": "2024-02-25T22:50:36.586678Z",
"url": "https://files.pythonhosted.org/packages/ad/b7/f546a72263df00e414d70086cca58515845fed945d65ea962a9cc767e70f/parag-0.0.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-02-25 22:50:36",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "rraadd88",
"github_project": "parag",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "parag"
}