Skip to content

IvanRehder/MBSEViewer

Repository files navigation

#Disclaimer: The code was originally written by me using AI as a tool. After I finnished, in order to make it more user-friendlier, I asked an AI tool to clean it and do the commentary, which I have not double checked. But is still working as it should be.

MBSE Arcadia Diagram Generator

An automated pipeline that converts a natural-language system description into structured MBSE (Model-Based Systems Engineering) diagrams following the Arcadia methodology.

The pipeline uses an LLM (Claude) to translate a free-text description into a JSON model, then renders that model as interactive Cytoscape.js diagrams displayed in a Streamlit web application.


What it does

  1. A system description in natural language is sent to an LLM as a prompt.
  2. The LLM returns a structured JSON that follows system_template.json.
  3. main.py reads the JSON, validates the model, and renders all diagrams as self-contained HTML files under rendering/.
  4. app.py (Streamlit) lets you navigate and interact with the diagrams. Clicking a node shows its metadata in a side panel.

Diagram types produced (per phase)

Diagram Description
Stakeholder & Context / Component Architecture Actors, entities, and the system boundary
Use Case / Capability Capabilities and the actors that support them
Activity / Function Functions allocated to their performing actors (compound graph)
Sequence Step-by-step scenario execution across swimlane columns

Arcadia phases

Phase ID Description
Operational Analysis OA Stakeholders, operational entities, activities, and scenarios from an end-user perspective
System Analysis SA System boundary, external actors, system functions, and scenarios
Logical Architecture LA Internal decomposition into logical components with allocated functions

Project structure

project/
├── main.py                  # Entry point: load JSON → build graphs → render HTML
├── app.py                   # Streamlit viewer
├── system_template.json     # JSON schema / template for LLM prompt
├── system_hmi.json          # Example model: HMI system (OA + SA)
├── system_ife.json          # Example model: IFE system (OA + SA + LA)
│
├── data_model/              # Domain model (Python dataclasses)
│   ├── common.py            # Base classes: Element, Actor, Function, Scenario, …
│   ├── oa.py                # Operational Analysis phase container and subtypes
│   ├── sa.py                # System Analysis phase container
│   ├── la.py                # Logical Architecture phase container
│   ├── parser.py            # JSON → dataclass parsers (OA / SA / LA)
│   └── loader.py            # load_model_json() + ID validation + catalog writer
│
├── graph/                   # Graph building and HTML rendering
│   ├── common.py            # GraphNode, GraphEdge, Graph primitives
│   ├── config.py            # CDN URLs, layout configs, stylesheets, geometry constants
│   └── builder.py           # build_*_graph() and render_*_graph() functions
│
├── gui/
│   └── graph_listener.py    # Streamlit v2 component: embeds diagram + forwards node clicks
│
├── utils/
│   └── aux.py               # create_id() (stable SHA-256 hash), get_ids_element_list()
│
└── rendering/               # Generated output (created by main.py, not tracked in git)
    ├── OA/
    │   ├── catalog.json
    │   ├── graph_oa_actors.html
    │   ├── graph_oa_cap.html
    │   ├── graph_oa_fun.html
    │   └── graph_oa_scen_*.html
    ├── SA/
    └── LA/

Requirements

  • Python 3.10+
  • Streamlitpip install streamlit

No other Python packages are needed. The Cytoscape.js library and its layout extensions (ELK) are loaded from CDN at diagram view time.


Quick start

1. Generate diagrams from a JSON model

# main.py (or a Jupyter notebook cell)
from data_model.loader import load_model_json, phase_catalog
from graph.builder import (
    build_actors_graph,       render_actors_graph,
    build_capabilities_graph, render_capabilities_graph,
    build_functions_graph,    render_functions_graph,
    build_scenario_graph,     render_scenarios_graph,
)

OUTPUT = "rendering"

model = load_model_json("system_ife.json")

for phase in model.phases:
    phase_catalog(phase)
    out = f"{OUTPUT}/{phase.id.upper()}"

    render_actors_graph(       build_actors_graph(phase),        out)
    render_capabilities_graph( build_capabilities_graph(phase),  out)
    render_functions_graph(    build_functions_graph(phase),      out)
    render_scenarios_graph(    build_scenario_graph(phase),       out)

2. Launch the Streamlit viewer

cd project
streamlit run app.py

Open the URL printed in the terminal (default: http://localhost:8501).


JSON model format

The model JSON has a meta block and a phases block. See system_template.json for the full annotated template.

{
  "meta": { "name": "My System", "description": "..." },
  "phases": {
    "OA": { "actors": [...], "entities": [...], "capabilities": [...],
            "activities": [...], "interactions": [...], "scenarios": {...} },
    "SA": { "system": [...], "actors": [...], "missions": [...],
            "functions": [...], "interactions": [...], "scenarios": {...} },
    "LA": { "components": [...], "actors": [...], "capabilities": [...],
            "functions": [...], "interactions": [...], "scenarios": {...} }
  }
}

Element IDs follow the convention <phase>_<type>_<name>, e.g. oa_actor_pilot, sa_fun_process_sensor_data. IDs are used to express cross-references (e.g. a function's performer points to an actor ID).

If an element does not carry an explicit id field the loader generates a stable hash-based ID from the class name and label via utils.aux.create_id.


LLM prompt guidance

When asking an LLM to generate a model JSON:

  1. Provide the contents of system_template.json as the schema reference.
  2. Describe the system in natural language, specifying the scope (OA / SA / LA).
  3. Ask the LLM to return a valid JSON that matches the template exactly, including all required fields and consistent cross-reference IDs.
  4. Validate the result with load_model_json() — the loader raises descriptive errors for broken cross-references or duplicate IDs.

Architecture notes

  • Rendering is decoupled from the viewer. main.py writes static HTML files; app.py just reads them. This means diagrams can be generated offline or in a headless environment and then served later.

  • Stable IDs. create_id() hashes ClassName:label with SHA-256 so IDs are reproducible across runs as long as labels stay the same. You can also provide explicit IDs in the JSON to override this.

  • Swimlane resolution for LA. LA functions are allocated to leaf components inside a hierarchy. The _resolve_lane() helper walks the parent_id chain upward to find the top-level component that appears in scenarios_order, so each function lands in the correct swimlane column even when it belongs to a deeply nested component.

  • Node click events. The Streamlit viewer uses a custom v2 component (gui/graph_listener.py) that injects the Cytoscape.js HTML into an iframe and polls for window.cy to become available before attaching a tap event listener. Tapped node IDs are forwarded to Python via setTriggerValue.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors