Skip to main content

parag

Para (beyond pairwise) Graph: interactive visualization of higher-order graphs in Python

build Issues Downloads GNU License DOI

Install

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

Examples:

Gene interaction networks

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
        &#10;        ></iframe>
    &#10;

Neighbourhood analysis in latent space e.g. single cell data

sc.pl.umap(adata, color="bulk_labels",title='Latent space')

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
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
        &#10;        ></iframe>
    &#10;

Heterogeneous graph e.g. drug side-effects network

## 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)
<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
edges=(
    df02
    .log.query(expr=f"`Individual Side Effect` == {nodes['Individual Side Effect'].unique().tolist()}")
    )
edges.head(1)
<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
## 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)
<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
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
        &#10;        ></iframe>
    &#10;

Network communities

# Plot graph with colouring based on communities
fig, ax = plt.subplots(1,1, figsize=(5, 3))
visualize_communities(G, communities[3], 2)

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)
<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
edges=pd.DataFrame(G.edges,columns=['source','target'])
edges.head(1)
<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
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
        &#10;        ></iframe>
    &#10;

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.},
}
  1. DOI link: DOI, or

  2. Using citation information from CITATION.CFF file.

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 interactions.
  • CI for quicker testing use lighter example.
  • More examples

Metadata

Release files for parag 0.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for parag 0.0.1
File Size Uploaded
parag-0.0.1.tar.gz 28.4 kB Details

Release files / parag-0.0.1.tar.gz

Download URL parag-0.0.1.tar.gz
Size 28.4 kB
Tags Source
SHA-256 checksum
How to use checksums
8c005173597dcaaf3724aa62ada54158322b4082098f0b58e6f8e115a36c6e54
BLAKE2b-256 checksum
How to use checksums
adb7f546a72263df00e414d70086cca58515845fed945d65ea962a9cc767e70f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/5.0.0 CPython/3.10.13

Release history Release notifications | RSS feed

This release

0.0.1 This release

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page