Skip to content
Merged
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,6 @@
- added an executable output-definition layer so a grounded concept can deterministically project into one or more CDM rows, with richer profile shapes to describe them
- added deterministic handling for row values that depend on a separate source field, or that should suppress the row entirely, always recorded explicitly rather than silently dropped
- fully additive; existing grounding and profile behavior is unchanged

# 0.4.0
- added Mermaid-based visualization for output-definition catalogues and projected bundles, and an optional interactive terminal explorer built on them
58 changes: 58 additions & 0 deletions docs/usage/tui.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# TUI Explorer

Use the Textual-based TUI when you want to browse a compiled output-definition
catalogue, edit JSON input, run a projection, and inspect the result in one
terminal session.

## Install

The TUI dependencies are optional:

```bash
uv sync --extra tui
```

For contributor workflows, `uv sync --extra dev` also includes the TUI
dependencies alongside the test and lint tooling.

## Launch

```bash
omop-semantics tui
```

This launches the explorer against an empty runtime. The reusable app lives in
`omop_semantics.runtime.tui` and is mainly intended to be embedded by a caller
that already has concrete `OutputDefinition` instances to browse.

Programmatic use looks like:

```python
from omop_semantics.runtime import OmopSemanticEngine
from omop_semantics.runtime.tui import run_tui

engine = OmopSemanticEngine.from_yaml_paths(registry_paths=[], profile_paths=[])
runtime = engine.build_output_definition_runtime(my_definitions)
run_tui(runtime)
```

## What it shows

- A catalogue tree built from `describe_definition()`
- An editable JSON context pane
- A result tree using the same three-state language as the visualization HTML:
green for projected rows, red for suppressed rows, amber for unresolved rows
or links

For the meaning of those states, see [Visualization](../visualization.md).

## Controls

- `Ctrl+R` runs the selected definition against the JSON payload in the context pane
- `Q` quits the app

Selecting a definition in the tree loads a starter JSON payload into the
context pane. Child rows and annotations are browsable without changing the
current context. When the app is embedded by an external caller, that payload
can use the flat `SemanticProjectionRequest` shape so it can be pasted
directly into a worker-backed flow.
5 changes: 5 additions & 0 deletions docs/visualization.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,8 @@ inputs, and suppression annotations without requiring a concrete input context.
Inline notebook display via `IPython.display.HTML(html.raw)` is convenient, but
it is best-effort only. Browser viewing of the saved `.html` file is the
guaranteed path across notebook front ends and local environments.

## Interactive exploration

For a terminal-based browse/edit/run loop, use the Textual explorer documented
in [TUI Explorer](usage/tui.md).
1 change: 1 addition & 0 deletions mkdocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ plugins:
nav:
- Home: index.md
- Usage: usage.md
- TUI Explorer: usage/tui.md
- Visualization: visualization.md
- Data Model: data-model.md
- Schema & Instances: schema-and-instances.md
Expand Down
6 changes: 5 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "omop-semantics"
version = "0.3.0"
version = "0.4.0"
description = "Define, validate, and use schema-backed semantic conventions for OMOP CDM"
readme = "README.md"
authors = [
Expand Down Expand Up @@ -28,9 +28,13 @@ dev = [
"mypy>=1.8",
"ruff>=0.4",
"rich>=13.0",
"textual>=0.60",
"tornado>=6.5.7",
"pygments>=2.20.0"
]
tui = [
"textual>=0.60",
]
docs = [
"mkdocs-material>=9.7.6",
"mkdocstrings-python>=2.0.1",
Expand Down
7 changes: 6 additions & 1 deletion src/omop_semantics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def main(argv: "list[str] | None" = None) -> int:

Subcommands:
gen-models (re)generate the committed pydantic models from the LinkML schema.
tui launch the interactive output-definition explorer.
"""
import sys

Expand All @@ -41,6 +42,10 @@ def main(argv: "list[str] | None" = None) -> int:
from omop_semantics.schema.codegen import cli as gen_models_cli

return gen_models_cli(argv[1:])
if argv and argv[0] == "tui":
from omop_semantics.runtime.tui.app import cli as tui_cli

print("usage: omop-semantics gen-models [--check] [--out DIR]", file=sys.stderr)
return tui_cli(argv[1:])

print("usage: omop-semantics {gen-models|tui} ...", file=sys.stderr)
return 2
5 changes: 5 additions & 0 deletions src/omop_semantics/runtime/tui/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from __future__ import annotations

from omop_semantics.runtime.tui.app import OutputDefinitionExplorer, run_tui

__all__ = ["OutputDefinitionExplorer", "run_tui"]
Loading
Loading