<div align=center><img src="docs/grand.png" width=400 /></div>
<div align=center><a href="https://pypi.org/project/grand-graph/"><img src="https://img.shields.io/pypi/v/grand-graph?style=for-the-badge" /></a> <a href="https://app.codecov.io/gh/aplbrain/grand"><img alt="Codecov" src="https://img.shields.io/codecov/c/github/aplbrain/grand?style=for-the-badge"></a></div>
<!-- <a href="https://github.com/aplbrain/grand/actions/workflows/python-package.yml"><img alt="GitHub Workflow Status (with branch)" src="https://img.shields.io/github/actions/workflow/status/aplbrain/grand/python-package.yml?style=for-the-badge"></a> -->
<br />
<p align=center>Graph toolkit interoperability and scalability for Python</p>
## Installation
```shell
pip install grand-graph
```
## Example use-cases
- Write NetworkX commands to analyze true-serverless graph databases using DynamoDB\*
- Query a host graph in SQL for subgraph isomorphisms with DotMotif
- Write iGraph code to construct a graph, and then play with it in Networkit
- Attach node and edge attributes to Networkit or IGraph graphs
> \* [Neptune is not true-serverless.](docs/What-About-Neptune.md)
## Why it's a big deal
_Grand_ is a Rosetta Stone of graph technologies. A _Grand_ graph has a "Backend," which handles the implementation-details of talking to data on disk (or in the cloud), and an "Dialect", which is your preferred way of talking to a graph.
For example, here's how you make a graph that is persisted in DynamoDB (the "Backend") but that you can talk to as though it's a `networkx.DiGraph` (the "Dialect"):
```python
import grand
G = grand.Graph(backend=grand.DynamoDBBackend())
G.nx.add_node("Jordan", type="Person")
G.nx.add_node("DotMotif", type="Project")
G.nx.add_edge("Jordan", "DotMotif", type="Created")
assert len(G.nx.edges()) == 1
assert len(G.nx.nodes()) == 2
```
It doesn't stop there. If you like the way IGraph handles anonymous node insertion (ugh) but you want to handle the graph using regular NetworkX syntax, use a `IGraphDialect` and then switch to a `NetworkXDialect` halfway through:
```python
import grand
G = grand.Graph()
# Start in igraph:
G.igraph.add_vertices(5)
# A little bit of networkit:
G.networkit.addNode()
# And switch to networkx:
assert len(G.nx.nodes()) == 6
# And back to igraph!
assert len(G.igraph.vs) == 6
```
You should be able to use the "dialect" objects the same way you'd use a real graph from the constituent libraries. For example, here is a NetworkX algorithm running on NetworkX graphs alongside Grand graphs:
```python
import networkx as nx
nx.algorithms.isomorphism.GraphMatcher(networkxGraph, grandGraph.nx)
```
Here is an example of using Networkit, a highly performant graph library, and attaching node/edge attributes, which are not supported by the library by default:
```python
import grand
from grand.backends.networkit import NetworkitBackend
G = grand.Graph(backend=NetworkitBackend())
G.nx.add_node("Jordan", type="Person")
G.nx.add_node("Grand", type="Software")
G.nx.add_edge("Jordan", "Grand", weight=1)
print(G.nx.edges(data=True)) # contains attributes, even though graph is stored in networkit
```
## Current Support
<table><tr>
<th>✅ = Fully Implemented</th>
<th>🤔 = In Progress</th>
<th>🔴 = Unsupported</th>
</tr></table>
| Dialect | Description & Notes | Status |
| ------------------ | ------------------------ | ------ |
| `IGraphDialect` | Python-IGraph interface | ✅ |
| `NetworkXDialect` | NetworkX-like interface | ✅ |
| `NetworkitDialect` | Networkit-like interface | ✅ |
| Backend | Description & Notes | Status |
| ------------------ | ---------------------------- | ------ |
| `DataFrameBackend` | Stored in pandas-like tables | ✅ |
| `DynamoDBBackend` | Edge/node tables in DynamoDB | ✅ |
| `GremlinBackend` | For Gremlin datastores | ✅ |
| `IGraphBackend` | An IGraph graph, in memory | ✅ |
| `NetworkitBackend` | A Networkit graph, in memory | ✅ |
| `NetworkXBackend` | A NetworkX graph, in memory | ✅ |
| `SQLBackend` | Two SQL-queryable tables | ✅ |
You can read more about usage and learn about backends and dialects in [the wiki](https://github.com/aplbrain/grand/wiki).
## Citing
If this tool is helpful to your research, please consider citing it with:
```bibtex
# https://doi.org/10.1038/s41598-021-91025-5
@article{Matelsky_Motifs_2021,
title={{DotMotif: an open-source tool for connectome subgraph isomorphism search and graph queries}},
volume={11},
ISSN={2045-2322},
url={http://dx.doi.org/10.1038/s41598-021-91025-5},
DOI={10.1038/s41598-021-91025-5},
number={1},
journal={Scientific Reports},
publisher={Springer Science and Business Media LLC},
author={Matelsky, Jordan K. and Reilly, Elizabeth P. and Johnson, Erik C. and Stiso, Jennifer and Bassett, Danielle S. and Wester, Brock A. and Gray-Roncal, William},
year={2021},
month={Jun}
}
```
---
<p align=center><b>Made with 💙 at <a href="https://jhuapl.edu"><img alt="JHU APL" src="https://user-images.githubusercontent.com/693511/116814564-9b268800-ab27-11eb-98bb-dfddb2e405a1.png" height="23px" /></a></b></p>
Raw data
{
"_id": null,
"home_page": "https://github.com/aplbrain/grand",
"name": "grand-graph",
"maintainer": null,
"docs_url": null,
"requires_python": null,
"maintainer_email": null,
"keywords": null,
"author": "Jordan Matelsky",
"author_email": "opensource@matelsky.com",
"download_url": "https://files.pythonhosted.org/packages/d2/62/4ab3668ec4a0e2d8b3db6d493f7ad6dc2b734e02c340f073bc92303687c7/grand-graph-0.5.1.tar.gz",
"platform": null,
"description": "<div align=center><img src=\"docs/grand.png\" width=400 /></div>\n\n<div align=center><a href=\"https://pypi.org/project/grand-graph/\"><img src=\"https://img.shields.io/pypi/v/grand-graph?style=for-the-badge\" /></a> <a href=\"https://app.codecov.io/gh/aplbrain/grand\"><img alt=\"Codecov\" src=\"https://img.shields.io/codecov/c/github/aplbrain/grand?style=for-the-badge\"></a></div>\n\n<!-- <a href=\"https://github.com/aplbrain/grand/actions/workflows/python-package.yml\"><img alt=\"GitHub Workflow Status (with branch)\" src=\"https://img.shields.io/github/actions/workflow/status/aplbrain/grand/python-package.yml?style=for-the-badge\"></a> -->\n\n<br />\n\n<p align=center>Graph toolkit interoperability and scalability for Python</p>\n\n## Installation\n\n```shell\npip install grand-graph\n```\n\n## Example use-cases\n\n- Write NetworkX commands to analyze true-serverless graph databases using DynamoDB\\*\n- Query a host graph in SQL for subgraph isomorphisms with DotMotif\n- Write iGraph code to construct a graph, and then play with it in Networkit\n- Attach node and edge attributes to Networkit or IGraph graphs\n\n> \\* [Neptune is not true-serverless.](docs/What-About-Neptune.md)\n\n## Why it's a big deal\n\n_Grand_ is a Rosetta Stone of graph technologies. A _Grand_ graph has a \"Backend,\" which handles the implementation-details of talking to data on disk (or in the cloud), and an \"Dialect\", which is your preferred way of talking to a graph.\n\nFor example, here's how you make a graph that is persisted in DynamoDB (the \"Backend\") but that you can talk to as though it's a `networkx.DiGraph` (the \"Dialect\"):\n\n```python\nimport grand\n\nG = grand.Graph(backend=grand.DynamoDBBackend())\n\nG.nx.add_node(\"Jordan\", type=\"Person\")\nG.nx.add_node(\"DotMotif\", type=\"Project\")\n\nG.nx.add_edge(\"Jordan\", \"DotMotif\", type=\"Created\")\n\nassert len(G.nx.edges()) == 1\nassert len(G.nx.nodes()) == 2\n```\n\nIt doesn't stop there. If you like the way IGraph handles anonymous node insertion (ugh) but you want to handle the graph using regular NetworkX syntax, use a `IGraphDialect` and then switch to a `NetworkXDialect` halfway through:\n\n```python\nimport grand\n\nG = grand.Graph()\n\n# Start in igraph:\nG.igraph.add_vertices(5)\n\n# A little bit of networkit:\nG.networkit.addNode()\n\n# And switch to networkx:\nassert len(G.nx.nodes()) == 6\n\n# And back to igraph!\nassert len(G.igraph.vs) == 6\n```\n\nYou should be able to use the \"dialect\" objects the same way you'd use a real graph from the constituent libraries. For example, here is a NetworkX algorithm running on NetworkX graphs alongside Grand graphs:\n\n```python\nimport networkx as nx\n\nnx.algorithms.isomorphism.GraphMatcher(networkxGraph, grandGraph.nx)\n```\n\nHere is an example of using Networkit, a highly performant graph library, and attaching node/edge attributes, which are not supported by the library by default:\n\n```python\nimport grand\nfrom grand.backends.networkit import NetworkitBackend\n\nG = grand.Graph(backend=NetworkitBackend())\n\nG.nx.add_node(\"Jordan\", type=\"Person\")\nG.nx.add_node(\"Grand\", type=\"Software\")\nG.nx.add_edge(\"Jordan\", \"Grand\", weight=1)\n\nprint(G.nx.edges(data=True)) # contains attributes, even though graph is stored in networkit\n```\n\n## Current Support\n\n<table><tr>\n<th>\u2705 = Fully Implemented</th>\n<th>\ud83e\udd14 = In Progress</th>\n<th>\ud83d\udd34 = Unsupported</th>\n</tr></table>\n\n| Dialect | Description & Notes | Status |\n| ------------------ | ------------------------ | ------ |\n| `IGraphDialect` | Python-IGraph interface | \u2705 |\n| `NetworkXDialect` | NetworkX-like interface | \u2705 |\n| `NetworkitDialect` | Networkit-like interface | \u2705 |\n\n| Backend | Description & Notes | Status |\n| ------------------ | ---------------------------- | ------ |\n| `DataFrameBackend` | Stored in pandas-like tables | \u2705 |\n| `DynamoDBBackend` | Edge/node tables in DynamoDB | \u2705 |\n| `GremlinBackend` | For Gremlin datastores | \u2705 |\n| `IGraphBackend` | An IGraph graph, in memory | \u2705 |\n| `NetworkitBackend` | A Networkit graph, in memory | \u2705 |\n| `NetworkXBackend` | A NetworkX graph, in memory | \u2705 |\n| `SQLBackend` | Two SQL-queryable tables | \u2705 |\n\nYou can read more about usage and learn about backends and dialects in [the wiki](https://github.com/aplbrain/grand/wiki).\n\n## Citing\n\nIf this tool is helpful to your research, please consider citing it with:\n\n```bibtex\n# https://doi.org/10.1038/s41598-021-91025-5\n@article{Matelsky_Motifs_2021,\n title={{DotMotif: an open-source tool for connectome subgraph isomorphism search and graph queries}},\n volume={11},\n ISSN={2045-2322},\n url={http://dx.doi.org/10.1038/s41598-021-91025-5},\n DOI={10.1038/s41598-021-91025-5},\n number={1},\n journal={Scientific Reports},\n publisher={Springer Science and Business Media LLC},\n author={Matelsky, Jordan K. and Reilly, Elizabeth P. and Johnson, Erik C. and Stiso, Jennifer and Bassett, Danielle S. and Wester, Brock A. and Gray-Roncal, William},\n year={2021},\n month={Jun}\n}\n```\n\n---\n\n<p align=center><b>Made with \ud83d\udc99 at <a href=\"https://jhuapl.edu\"><img alt=\"JHU APL\" src=\"https://user-images.githubusercontent.com/693511/116814564-9b268800-ab27-11eb-98bb-dfddb2e405a1.png\" height=\"23px\" /></a></b></p>\n",
"bugtrack_url": null,
"license": null,
"summary": "Graph database wrapper for non-graph datastores",
"version": "0.5.1",
"project_urls": {
"Homepage": "https://github.com/aplbrain/grand"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "d2624ab3668ec4a0e2d8b3db6d493f7ad6dc2b734e02c340f073bc92303687c7",
"md5": "ae95e32bfbf24b59c05f04ccf354a00a",
"sha256": "b3dd6f6e0cea2cfd56d8461c2b0471842b7056c965f2b24ddea5e831c0d206dd"
},
"downloads": -1,
"filename": "grand-graph-0.5.1.tar.gz",
"has_sig": false,
"md5_digest": "ae95e32bfbf24b59c05f04ccf354a00a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 28484,
"upload_time": "2024-05-13T12:15:44",
"upload_time_iso_8601": "2024-05-13T12:15:44.762030Z",
"url": "https://files.pythonhosted.org/packages/d2/62/4ab3668ec4a0e2d8b3db6d493f7ad6dc2b734e02c340f073bc92303687c7/grand-graph-0.5.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-05-13 12:15:44",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "aplbrain",
"github_project": "grand",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "grand-graph"
}