Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# ruff format, line length 100
65ca0f267e1804971ddb71ea2f85a02cad9f8294
8 changes: 6 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ on:
jobs:
label-gate:
uses: AustralianCancerDataNetwork/cava-devops/.github/workflows/label-gate.yml@main
ruff:
uses: AustralianCancerDataNetwork/cava-devops/.github/workflows/ruff.yml@ruff-ty-workflows
ty:
uses: AustralianCancerDataNetwork/cava-devops/.github/workflows/ty.yml@ruff-ty-workflows
build-test-sqlite:
uses: AustralianCancerDataNetwork/cava-devops/.github/workflows/build-test.yml@main
uses: AustralianCancerDataNetwork/cava-devops/.github/workflows/build-test-sqlite.yml@ruff-ty-workflows
build-test-postgres:
uses: AustralianCancerDataNetwork/cava-devops/.github/workflows/build-test-postgres-v2.yml@main
uses: AustralianCancerDataNetwork/cava-devops/.github/workflows/build-test-postgres-v3.yml@ruff-ty-workflows
with:
postgres-db: omop_graph_test
setup-commands: |
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ This classification drives traversal filtering and scoring.
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
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,
Expand Down
6 changes: 4 additions & 2 deletions docs/graph/kg.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,10 @@ from omop_graph.graph.kg import KnowledgeGraph, KnowledgeGraphEmbeddingConfigura
from omop_emb.config import MetricType

resolver = Resolver.from_active_config()
resolved_vector_store = resolver.resolve_vector_store("vector_store") # a [vector_stores.*] entry name
resolved_model = resolver.resolve_model("embedding-model") # a [models.*] entry name
resolved_vector_store = resolver.resolve_vector_store(
"vector_store"
) # a [vector_stores.*] entry name
resolved_model = resolver.resolve_model("embedding-model") # a [models.*] entry name
backend = open_vector_store_writer(resolved_vector_store)

emb_config = KnowledgeGraphEmbeddingConfiguration(
Expand Down
63 changes: 35 additions & 28 deletions docs/mkdocs_macros.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
import pandas as pd
import pathlib as pl
from typing import Optional, List, Mapping
from collections.abc import Mapping

import pandas as pd


def define_env(env):
@env.macro
def to_grouped_table(
file_path: str,
group_cols: List[int] = [0],
displayed_cols: Optional[List[int]] = None,
sort_cols: Optional[List[int]] = None,
col_mappings: Optional[Mapping[str, str]] = None
file_path: str,
group_cols: list[int] | None = None,
displayed_cols: list[int] | None = None,
sort_cols: list[int] | None = None,
col_mappings: Mapping[str, str] | None = None,
):
if group_cols is None:
group_cols = [0]

absolute_path = (pl.Path(env.project_dir) / file_path).resolve()

if not absolute_path.exists():
return f"**Error:** Could not find file at `{absolute_path}`"

suffix_loader_map = {
".csv": pd.read_csv,
".xlsx": pd.read_excel
}

suffix_loader_map = {".csv": pd.read_csv, ".xlsx": pd.read_excel}
loader_fn = suffix_loader_map[absolute_path.suffix]

df = loader_fn(absolute_path, usecols=displayed_cols)
Expand All @@ -35,36 +34,41 @@ def to_grouped_table(
df = df.rename(columns=col_mappings)

df = df.dropna(subset=df.columns[group_cols])

span_counts_map = {}
for i, col_idx in enumerate(group_cols):
relevant_cols = group_cols[:i+1]
group_changes = (df.iloc[:, relevant_cols] != df.iloc[:, relevant_cols].shift()).any(axis=1)
relevant_cols = group_cols[: i + 1]
group_changes = (df.iloc[:, relevant_cols] != df.iloc[:, relevant_cols].shift()).any(
axis=1
)
span_counts_map[col_idx] = group_changes.cumsum().value_counts(sort=False).tolist()

table_style = "width: 100%; border-collapse: collapse; margin-bottom: 1rem;"
cell_style = "border: 1px solid var(--md-typeset-table-color, #e0e0e0); padding: 12px; text-align: left;"
header_style = cell_style + " background-color: var(--md-default-bg-color, #f5f5f5); font-weight: bold;"

header_style = (
cell_style
+ " background-color: var(--md-default-bg-color, #f5f5f5); font-weight: bold;"
)

html = f'<table style="{table_style}">'
html += "<thead><tr>"
for col in df.columns:

for col in df.columns:
html += f'<th style="{header_style}">{col}</th>'
html += "</tr></thead>"

html += "<tbody>"

span_idx_map = {c: 0 for c in group_cols}
rows_to_skip_map = {c: 0 for c in group_cols}

for i, row in df.iterrows():
highest_change_level = -1
for level, col_idx in enumerate(group_cols):
if rows_to_skip_map[col_idx] == 0:
highest_change_level = level
break

if highest_change_level == 0 and i > 0:
html += '<tr style="border-top: 2px solid var(--md-default-fg-color, #666);">'
elif highest_change_level > 0 and i > 0:
Expand All @@ -77,16 +81,19 @@ def to_grouped_table(
if j in group_cols:
if rows_to_skip_map[j] == 0:
span = span_counts_map[j][span_idx_map[j]]
group_style = cell_style + " vertical-align: middle; font-weight: bold; background-color: var(--md-code-bg-color, #fafafa);"
group_style = (
cell_style
+ " vertical-align: middle; font-weight: bold; background-color: var(--md-code-bg-color, #fafafa);"
)
html += f'<td rowspan="{span}" style="{group_style}">{display_val}</td>'
rows_to_skip_map[j] = span - 1
span_idx_map[j] += 1
else:
rows_to_skip_map[j] -= 1
continue
continue
else:
html += f'<td style="{cell_style}">{display_val}</td>'
html += "</tr>"

html += "</tbody></table>"
return html
return html
4 changes: 2 additions & 2 deletions docs/reasoning/grounding.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ from omop_alchemy.cdm.query import ConceptFilter
from omop_graph.extensions.omop_alchemy import PredicateKind

constraints = GroundingConstraints(
parent_ids=(441484,), # 'Clinical Finding' — only accept descendants of this ancestor
parent_ids=(441484,), # 'Clinical Finding' — only accept descendants of this ancestor
search_constraint=ConceptFilter(
domains=("Condition",),
vocabularies=("SNOMED",),
Expand All @@ -80,7 +80,7 @@ results = ground_term(
resolver_pipeline=pipeline,
kg=kg,
query="chest pain",
query_embedding=None, # pass a precomputed vector, or None to skip embedding-based scoring
query_embedding=None, # pass a precomputed vector, or None to skip embedding-based scoring
constraints=constraints,
)
```
Expand Down
4 changes: 2 additions & 2 deletions docs/reasoning/resolvers.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ constraints = GroundingConstraints(
search_constraint=ConceptFilter(
domains=parsed_domains,
vocabularies=parsed_vocabs,
require_standard=True # We prioritize Standard Concepts
require_standard=True, # We prioritize Standard Concepts
),
max_depth=6 # How deep to traverse the hierarchy
max_depth=6, # How deep to traverse the hierarchy
)

# The resolver pipeline stops once it finds a high-confidence match
Expand Down
Loading
Loading