Metadata-Version: 2.5
Name: omop-graph
Version: 2.0.0
Summary: Explainable, OMOP-native knowledge graph traversal and pathfinding
Author-email: Georgie Kennedy <georgie.kennedy@unsw.edu.au>, Nico Loesch <n.loesch@unsw.edu.au>
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: LLM-grounding,OHDSI,OMOP,clinical-data,health-informatics,knowledge-graph,real-world-evidence,sqlalchemy
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Healthcare Industry
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
Requires-Python: >=3.12
Requires-Dist: oa-configurator<2.0.0,>=1.0.0
Requires-Dist: oaklib
Requires-Dist: omop-alchemy<2.0.0,>=1.0.0
Requires-Dist: orm-loader<2.0.0,>=1.0.0
Requires-Dist: rich>=13.0
Requires-Dist: typer>=0.12
Requires-Dist: typing-extensions>=4.15.0
Provides-Extra: dev
Requires-Dist: ipython>=9.8.0; extra == 'dev'
Requires-Dist: mkdocs-macros-plugin; extra == 'dev'
Requires-Dist: mkdocs-material; extra == 'dev'
Requires-Dist: mkdocs-mermaid2-plugin; extra == 'dev'
Requires-Dist: mkdocs-table-reader-plugin; extra == 'dev'
Requires-Dist: mkdocs<2.0; extra == 'dev'
Requires-Dist: mkdocstrings[python]; extra == 'dev'
Requires-Dist: oa-configurator[postgres]<2.0.0,>=1.0.0; extra == 'dev'
Requires-Dist: omop-alchemy[postgres]<2.0.0,>=1.0.0; extra == 'dev'
Requires-Dist: omop-emb<3.0.0,>=2.0.0; extra == 'dev'
Requires-Dist: omop-emb[faiss-cpu]<3.0.0,>=2.0.0; extra == 'dev'
Requires-Dist: omop-emb[pgvector]<3.0.0,>=2.0.0; extra == 'dev'
Requires-Dist: pytest-cov>=7.0.0; extra == 'dev'
Requires-Dist: pytest>=9.0.2; extra == 'dev'
Requires-Dist: rich>=14.2.0; extra == 'dev'
Requires-Dist: ruff>=0.14.10; extra == 'dev'
Requires-Dist: ty>=0.0.59; extra == 'dev'
Provides-Extra: emb
Requires-Dist: omop-emb<3.0.0,>=2.0.0; extra == 'emb'
Provides-Extra: faiss-cpu
Requires-Dist: omop-emb[faiss-cpu]<3.0.0,>=2.0.0; extra == 'faiss-cpu'
Provides-Extra: pgvector
Requires-Dist: omop-emb[pgvector]<3.0.0,>=2.0.0; extra == 'pgvector'
Provides-Extra: postgres
Requires-Dist: omop-alchemy[postgres]<2.0.0,>=1.0.0; extra == 'postgres'
Description-Content-Type: text/markdown

# omop-graph

**omop-graph** is a lightweight, opinionated knowledge-graph traversal and path-analysis library built on top of the OMOP vocabulary model.

It provides:
- a stable **KnowledgeGraph façade** over OMOP concepts and relationships
- flexible **graph traversal** (forward, backward, bidirectional)
- **path discovery** with transparent scoring
- **traceable explanations** of traversal decisions
- multiple **rendering backends** (text, HTML, Mermaid)

The library is designed for:
- interactive analysis (Jupyter)
- reproducible research
- downstream tooling (NLP pipelines, ontology alignment, curation tools)

---

## Installation

```bash
pip install omop-graph
```

With embedding support:

```bash
pip install "omop-graph[emb]"
```

For larger deployments use `[pgvector]` or `[faiss-cpu]` instead (or in addition). Embedding support still needs a configured vector store, model, and provider (via oa-configurator); it isn't zero-config on its own. Full setup is covered in the [omop-emb documentation](https://australiancancerdatanetwork.github.io/omop-emb/).

---

## Core Concepts

### KnowledgeGraph

`KnowledgeGraph` is the main entry point. It wraps a SQLAlchemy `Engine` connected to an OMOP vocabulary schema and provides a high-level Pythonic API over the relational tables.

```python
from sqlalchemy import create_engine
from omop_graph.graph.kg import KnowledgeGraph
from omop_graph.graph.nodes import LabelMatchKind

engine = create_engine("postgresql://user:pass@localhost/omop")
kg = KnowledgeGraph(cdm_engine=engine)

# Lookup a concept by label
matches = kg.concept_lookup("Atrial Fibrillation", match_kind=LabelMatchKind.EXACT)
concept = matches[0]
print(f"ID: {concept.matched_concept_id}, Name: {concept.matched_concept_label}")

# Traverse the hierarchy
parents = kg.parents(concept.matched_concept_id)
```

### Nodes and Edges

Nodes are OMOP Concepts; Edges are OMOP Concept_Relationships.

Relationships are pre-classified into semantic kinds (`PredicateKind`):

- `HIERARCHY` — parent/child ontological relationships
- `IDENTITY` — mapping to standard concepts
- `COMPOSITION` — part-of relationships
- `ASSOCIATION` — lateral clinical associations
- `ATTRIBUTE` — concept attribute relationships

This classification drives traversal filtering and scoring.

### Traversal and Paths

```python
from omop_graph.graph.paths import find_shortest_paths
from omop_graph.extensions.omop_alchemy import PredicateKind

ingredient = kg.concept_id_by_code("RxNorm", "6809")    # Metformin
drug = kg.concept_id_by_code("RxNorm", "860975")         # Metformin 500 MG Oral Tablet

paths, trace = find_shortest_paths(
    kg,
    source=drug,
    target=ingredient,
    predicate_kinds=frozenset({PredicateKind.HIERARCHY, PredicateKind.IDENTITY}),
    max_depth=6,
    traced=True,
)
```

### Rendering

Outputs can be rendered as plain text, HTML (Jupyter), or Mermaid diagrams. Rendering auto-detects the environment.

```python
from IPython.display import HTML, display
from omop_graph.render import render_trace

display(HTML(render_trace(kg, trace)))
```

---

## Project Structure

```
omop_graph/
├── graph/          # graph logic, traversal, paths, scoring
├── render/         # HTML / text / Mermaid renderers
├── reasoning/      # ontology traversal methods for specific reasoner tasks
│   ├── resolvers/  # resolve labels via exact / fuzzy / full-text / synonym search
│   └── phenotypes/ # set operations for hierarchical groupings
├── oaklib_interface/  # OAK-compliant adapter
├── api.py          # stable public API surface
└── db/             # session helpers
```

---

## Configuration

omop-graph reads database connection settings from
[oa-configurator](https://github.com/AustralianCancerDataNetwork/oa-configurator).
It requires the CDM database configured by omop-alchemy.

Run once after installation:

```bash
omop-config init
omop-config configure omop_alchemy
omop-config configure omop_graph
```

See [Configuration](docs/getting-started/configuration.md) for full details.
