model.py: gemeinsames TRO-Modell; Hauptweg CSV -> tro_flow --json -> scl_skeleton
- lib/model.py (neu, pydantic): TroBase -> DerivedTro, Connection, OpenPoint, Analysis (aus tro_flow verschoben), TroDocument = TRO-JSON (Schema sps_skel-tro-v2). items/fbType werden immer ueber den Typ aus tro_catalog gelesen, nie gespeichert; abweichende Werte in einer JSON sind ein Fehler. JSON-Schluessel wie bisher (id, type, fbType ...), extra="forbid". - tro_flow: Tro/Analysis aus model.py; neuer Schalter --json schreibt <name>_tro.json (TroDocument) - scl_skeleton: liest die JSON ueber TroDocument statt per Dict-Zugriff, Bauteile ueber TroItem-Konstanten; ungueltige JSON -> Exit 1 ohne SCL, alte tro_extract-JSON (v1) mit Hinweis auf tro_flow --json - tro_annotate: nur noch Ansicht; derselbe analyse_tros-Aufruf wie tro_flow (inkl. sepliste-Gegenprobe), damit Zeichnung und JSON uebereinstimmen - tro_extract: geparkt (unveraendert) - tests/test_model.py + conftest.py, pytest in requirements.txt aktiviert - Doku: Python_Scripts.md (§6b model.py), Commandlines.md, CLAUDE.md, Aufrufkommentare in bin/ (scl_skeleton.bat zeigte tro_flow-Aufrufe) Geprueft: alle tro_flow/tro_annotate-Ausgaben (8 CSVs) bis auf Zeitstempel identisch zum vorherigen Stand; scl_skeleton alt/neu auf derselben JSON byte-identisch (export, mubea, HundM05); 10 Tests gruen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
90cafec99c
commit
97a0db6707
+92
-25
@@ -1,13 +1,14 @@
|
||||
# Python Scripts — CLI Tooling Overview
|
||||
|
||||
**As of:** 2026-09-17
|
||||
**As of:** 2026-10-09
|
||||
|
||||
`lib/` currently holds nine Python modules (five of them runnable CLI tools,
|
||||
four supporting libraries), plus one documentation-generator script that lives
|
||||
`lib/` currently holds ten Python modules (five of them runnable CLI tools,
|
||||
five supporting libraries), plus one documentation-generator script that lives
|
||||
under `doc/TRO_Katalog/tro_graphs/`. Together the CLI tools turn a CSV export
|
||||
of the mechanical layout (ILS 2.0) into a material-flow graph, a derived TRO
|
||||
list/diagram, an annotated copy of the BricsCAD drawing, a TRO-JSON read back
|
||||
out of that drawing, and an `FB_Main` SCL skeleton generated from that JSON.
|
||||
list/diagram, a TRO-JSON (shared model `lib/model.py`), an `FB_Main` SCL
|
||||
skeleton generated from that JSON, and an annotated copy of the BricsCAD
|
||||
drawing for visual checking.
|
||||
|
||||
This document is the practical "what does each script do and which switches
|
||||
does it take" reference. For the underlying domain model (TRO types, JSON
|
||||
@@ -26,18 +27,25 @@ material_flow.py ──► <name>_material_flow.dot / .svg / .md
|
||||
▼
|
||||
tro_flow.py ──► <name>_tro_flow.dot / .svg, _tro_doc.md, _tro_errors.md
|
||||
│ (derives TROs, using the type catalog in tro_catalog.py)
|
||||
▼
|
||||
tro_annotate.py ──► <name>_annotated.dxf, <name>_registration.json
|
||||
│ (also needs the BricsCAD DXF; uses dxf_registration.py for the CSV↔DXF
|
||||
│ coordinate offset and tro_catalog.py for marker shape/color per TRO type)
|
||||
▼ (drawing may be hand-edited in BricsCAD before the next step)
|
||||
tro_extract.py ──► <drawing>_tro.json
|
||||
│ (reads only the drawing; resolves plant coords via the registration)
|
||||
▼
|
||||
scl_skeleton.py ──► <source>_FB_Main.scl
|
||||
(one REGION per TRO; E-planning values left as TODO(E-Planung) gaps)
|
||||
│
|
||||
├── --json ──► <name>_tro.json (model.TroDocument — MAIN PATH)
|
||||
│ │
|
||||
│ ▼
|
||||
│ scl_skeleton.py ──► <name>_FB_Main.scl
|
||||
│ (validates the JSON against model.py; one REGION per TRO;
|
||||
│ E-planning values left as TODO(E-Planung) gaps)
|
||||
│
|
||||
└── same derivation ──► tro_annotate.py ──► <name>_annotated.dxf (VIEWER ONLY)
|
||||
(also needs the BricsCAD DXF; uses dxf_registration.py for the CSV↔DXF
|
||||
coordinate offset and tro_catalog.py for marker shape/color per TRO type)
|
||||
|
||||
parked: tro_extract.py drawing ──► JSON (not extended; see §5a)
|
||||
```
|
||||
|
||||
The drawing is a **view** for checking the result, not a data source: the
|
||||
TRO-JSON is written by `tro_flow.py --json` straight from the CSV, and
|
||||
`tro_annotate.py` derives exactly the same TROs to draw them.
|
||||
|
||||
- `material_flow.py` models the material flow of the **mechanical** objects only
|
||||
(Gefällestrecke, Strecke, Kreisel).
|
||||
- `tro_flow.py` is its sister program: it derives the **control objects**
|
||||
@@ -51,6 +59,10 @@ Supporting libraries (no CLI of their own, imported by the tools above):
|
||||
- **`lib/tro_catalog.py`** — the single source of truth for TRO types: short
|
||||
name, Siemens FB block, sub-components and counts, color group, CAD marker
|
||||
shape.
|
||||
- **`lib/model.py`** — the shared pydantic model of TRO *instances* and of the
|
||||
TRO-JSON (`TroBase`, `DerivedTro`, `Connection`, `OpenPoint`, `Analysis`,
|
||||
`TroDocument`). Written by `tro_flow.py --json`, read and validated by
|
||||
`scl_skeleton.py`. See §6b.
|
||||
- **`lib/dxf_registration.py`** — derives, verifies and persists the rigid
|
||||
(rotation + offset) transform between the CSV export's coordinate system and
|
||||
the DXF drawing's.
|
||||
@@ -77,7 +89,8 @@ Each CLI tool is invoked through its `bin/<name>.bat` (Windows) / `bin/<name>.sh
|
||||
|
||||
```bat
|
||||
bin\material_flow.bat --file mubea.csv --tosvg --use-cords --doc
|
||||
bin\tro_flow.bat --file mubea.csv --tosvg --use-cords --doc
|
||||
bin\tro_flow.bat --file mubea.csv --tosvg --use-cords --doc --json
|
||||
bin\scl_skeleton.bat --json mubea_tro.json
|
||||
bin\tro_annotate.bat --file mubea.csv --dxf 500573_60_1.dxf --flow --fb --legend
|
||||
```
|
||||
|
||||
@@ -281,6 +294,7 @@ colors all come from `lib/tro_catalog.py` — nothing is hard-coded here.
|
||||
| `--doc` | — | off | Also write a Markdown report (`<name>_tro_doc.md`) with the TRO list, connections, findings and the full type catalog. |
|
||||
| `--connect` | — | off | Also write the TRO topology as `<name>_tro_connect.ini` (nodes, connections, system boundaries, predecessors/successors per TRO). Pure output, never read back. |
|
||||
| `--true-scale` | — | off | Only with `--use-cords`: draw to scale. By default empty stretches longer than 1500 mm between nodes are shortened (order and neighbourhood are kept). |
|
||||
| `--json` | — | off | Also write the TRO-JSON `<name>_tro.json` (schema `sps_skel-tro-v2`, model `TroDocument` in `lib/model.py`): TROs, system boundaries (`SYSn`), connections with their kind, findings. Input for `scl_skeleton.py`. |
|
||||
|
||||
TROs, types and connections always come from the layout alone;
|
||||
`cfg/tro_overrides.ini` is not read. Errors in the derivation are fixed in
|
||||
@@ -288,16 +302,21 @@ TROs, types and connections always come from the layout alone;
|
||||
|
||||
**Output** (in `%SKEL_RESULTS%`): `<name>_tro_flow.dot` (always, with `pos`
|
||||
attributes when `--use-cords` was used), `<name>_tro_flow.svg` (with
|
||||
`--tosvg`), `<name>_tro_doc.md` (with `--doc`), `<name>_tro_errors.md` (only
|
||||
if TROs are unconnected or of an unknown type).
|
||||
`--tosvg`), `<name>_tro_doc.md` (with `--doc`), `<name>_tro.json` (with
|
||||
`--json`), `<name>_tro_errors.md` (only if TROs are unconnected or of an
|
||||
unknown type).
|
||||
|
||||
**Exit codes:** `0` ok · `1` input/CLI error · `2` SVG rendering failed
|
||||
(Graphviz) · `3` TRO validation errors found (error file written).
|
||||
|
||||
## 5. `tro_annotate.py` — burn the TROs into a copy of the CAD drawing
|
||||
|
||||
**Viewer only.** The drawing shows the result for a visual check in BricsCAD;
|
||||
it is no longer a data source for the SCL (that is `tro_flow.py --json`).
|
||||
|
||||
Takes the CSV export, the original BricsCAD drawing (DXF) and the TROs
|
||||
derived the same way as `tro_flow.py`, and writes a **copy** of the drawing
|
||||
derived with exactly the same call as `tro_flow.py` (including the separator
|
||||
cross-check from `<name>_raw.json`), and writes a **copy** of the drawing
|
||||
with:
|
||||
|
||||
- one colored marker block per TRO, each type with its own shape (circle,
|
||||
@@ -353,6 +372,13 @@ could not be proven (or its residual error exceeds 600 mm) — resolve with
|
||||
|
||||
## 5a. `tro_extract.py` — read the TROs back out of the drawing into JSON
|
||||
|
||||
> **Parked since 2026-10-09.** The TRO-JSON for `scl_skeleton.py` now comes
|
||||
> from `tro_flow.py --json`. `tro_extract.py` is kept but not extended; its
|
||||
> output (schema `sps_skel-tro-extract-v1`) is **not** accepted by
|
||||
> `scl_skeleton.py` any more, which says so and asks for `tro_flow --json`. If
|
||||
> hand edits in the drawing are ever needed again, it should write the same
|
||||
> `model.TroDocument` format.
|
||||
|
||||
The counter-direction to `tro_annotate.py`:
|
||||
|
||||
```
|
||||
@@ -394,12 +420,18 @@ Last step of the chain:
|
||||
|
||||
```
|
||||
material_flow.py objects -> material flow
|
||||
tro_flow.py flow -> TROs
|
||||
tro_annotate.py TROs -> markers in the drawing
|
||||
tro_extract.py drawing -> JSON
|
||||
tro_flow.py flow -> TROs -> <name>_tro.json (--json)
|
||||
scl_skeleton.py JSON -> FB_Main.scl
|
||||
```
|
||||
|
||||
The JSON is read through `model.TroDocument` and **validated**: an unknown or
|
||||
renamed key, or `items`/`fbType` that do not match the TRO type in
|
||||
`tro_catalog.py`, stops the run with exit code `1` and the validation error —
|
||||
no SCL is written. A file with a different schema (e.g. the old
|
||||
`tro_extract.py` output) gets a short message asking for `tro_flow --json`.
|
||||
Part counts (`items`) and the FB type are taken from the catalog via the TRO
|
||||
type.
|
||||
|
||||
Produces a **skeleton, not a running program**: one `REGION` per TRO with the
|
||||
instance call and every parameter line in the right order, following the real
|
||||
call sites in `doc/TRO_Katalog/scl_templates/*.scl`.
|
||||
@@ -426,14 +458,16 @@ only auto-filled for a single-switch TRO; where several switches share the
|
||||
exits, how they divide them is a planning decision, so it stays a gap rather
|
||||
than a guess.
|
||||
|
||||
Switches: `--json NAME` (default `export_tro.json`), `--out NAME` (default
|
||||
Switches: `--json NAME` (default `export_tro.json`, looked up in
|
||||
`%SKEL_RESULTS%`; written by `tro_flow.py --json`), `--out NAME` (default
|
||||
`<source>_FB_Main.scl`), `--start TRO`. The last one matters while the plant has
|
||||
no loading/unloading station: the flow is then a closed loop with no entry, so
|
||||
the order has to be broken somewhere arbitrary. The chosen start and the reason
|
||||
are recorded in the file header.
|
||||
|
||||
**Stations (`SYSn`).** Loading/unloading stations from `tro_flow.py` appear in
|
||||
the JSON as `SYSn` neighbours, not as TROs. They get no REGION and no instance.
|
||||
the JSON under `boundaries` and as `SYSn` neighbours of the TROs, not in
|
||||
`tros`. They get no REGION and no instance.
|
||||
A TRO fed by a `SYSn` is the start of the order ("Materialeingang ueber SYSn"),
|
||||
so `--start` is no longer needed once the export contains a station. In the
|
||||
jam-area comments they are marked "(Station, kein TRO)", and an exit station
|
||||
@@ -461,7 +495,40 @@ verified against `data/*.scl` where the source is vendored locally, and against
|
||||
Everything is a Pydantic v2 model
|
||||
(`TroDefinition`/`TroStyle`), so it validates on every assignment and comes
|
||||
with `model_dump()`/`model_validate()` for the planned JSON layout model for
|
||||
free. Consumed by `tro_flow.py` and `tro_annotate.py`; not run directly.
|
||||
free. Consumed by `model.py`, `tro_flow.py`, `tro_annotate.py` and
|
||||
`scl_skeleton.py`; not run directly.
|
||||
|
||||
## 6b. `model.py` — shared model of TRO instances and the TRO-JSON (library, no CLI)
|
||||
|
||||
`tro_catalog.py` says what a TRO **type** is; `model.py` says what one concrete
|
||||
TRO in a plant, and the whole TRO-JSON, look like. It imports only the catalog.
|
||||
|
||||
```
|
||||
tro_catalog.py type level TroDefinition (items, FB block, color, symbol)
|
||||
▲ get_tro()
|
||||
model.py instance level TroBase ─► DerivedTro, Connection, OpenPoint,
|
||||
Analysis, TroDocument
|
||||
▲
|
||||
tro_flow.py (writes) · scl_skeleton.py (reads) · tro_annotate.py (draws)
|
||||
```
|
||||
|
||||
| Class | What it is |
|
||||
|---|---|
|
||||
| `TroBase` | Core of every TRO: `id`, `type`, `confidence`, `separators`, `predecessors`, `successors`, `position` (`{x,y,z}` in JSON). `definition()`, `fb_block` (JSON `fbType`) and `items` are **read from the catalog** on every access, never stored — so they follow a type change and cannot go stale. |
|
||||
| `DerivedTro` | `TroBase` + what `tro_flow.py` knows from the derivation: `label`, `hosts`, `scanners`, `reason`, `colocated`, `positionFrom`, `positionPoints`. Also used for the system boundaries `SYSn`. |
|
||||
| `Connection` | Directed edge `from` → `to` with its `kind` (transfer / umlauf / weiche / unbestimmt / normal / bahn). |
|
||||
| `OpenPoint` | A reported spot that is not a TRO yet (empty in the JSON for now; meant to replace the class of the same name in `tro_overrides.py`). |
|
||||
| `Analysis` | Working result of `tro_flow.analyse_tros` (moved here from `tro_flow.py`). |
|
||||
| `TroDocument` | The TRO-JSON: `schema` (`sps_skel-tro-v2`), `source`, `created`, `note`, `tros`, `boundaries`, `connections`, `openPoints`, `findings`. `from_analysis()`, `to_json()`, `from_json()`. |
|
||||
|
||||
All models validate on creation and assignment and reject unknown keys
|
||||
(`extra="forbid"`). JSON keys keep the camelCase names of the TRO-JSON (`id`,
|
||||
`type`, `fbType`, `openPoints` …); Python code uses the field names
|
||||
(`tro_id`, `type_name`, `fb_block`, `open_points`) — both are accepted on input.
|
||||
|
||||
Tests: `tests/test_model.py` (round trip, catalog-backed fields, rejection of
|
||||
wrong keys/items, SCL rendering from a document) — run with
|
||||
`python -m pytest tests/`.
|
||||
|
||||
## 6a. `tro_overrides.py` — manual corrections to the derived TROs (library, no CLI)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user