Document lib/ CLI tools and refresh CLAUDE.md to match
Add doc/Python_Scripts.md covering material_flow.py, tro_flow.py, tro_annotate.py, tro_catalog.py and dxf_registration.py: purpose, CLI switches, outputs and exit codes. Update CLAUDE.md, which still described lib/ and doc/ as empty design-phase scaffolding: reflect the working tooling, the doc/ reorganization (HundM/, 500573_Mubea/, TRO_Katalog/), the moved SCL templates, and the now-accepted bin/<tool>.bat+.sh wrapper convention. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,249 @@
|
||||
# Python Scripts — CLI Tooling Overview
|
||||
|
||||
**As of:** 2026-08-03
|
||||
|
||||
`lib/` currently holds five Python modules (three of them runnable CLI tools,
|
||||
two 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, and an annotated copy of the BricsCAD drawing.
|
||||
|
||||
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
|
||||
layout concept, I/O-list analysis) see `TRO_Typen.md`, `Json_Layout-Konzept.md`,
|
||||
`EA-Listen-Analyse.md`, `BricsCAD_TRO_Symbol.md` and
|
||||
`doc/TRO_Katalog/TRO_Katalog.md`.
|
||||
|
||||
## 1. How the pieces fit together
|
||||
|
||||
```
|
||||
CSV export (in %SKEL_DATA%)
|
||||
│
|
||||
▼
|
||||
material_flow.py ──► <name>_material_flow.dot / .svg / .md
|
||||
│ (read_elements, build_graph — reused by tro_flow.py)
|
||||
▼
|
||||
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)
|
||||
```
|
||||
|
||||
- `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**
|
||||
(TROs) from the same graph and draws their flow instead.
|
||||
- `tro_annotate.py` takes the TROs from `tro_flow.py` and burns them into a
|
||||
**copy** of the BricsCAD drawing as attributed blocks (never touches the
|
||||
original).
|
||||
|
||||
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/dxf_registration.py`** — derives, verifies and persists the rigid
|
||||
(rotation + offset) transform between the CSV export's coordinate system and
|
||||
the DXF drawing's.
|
||||
|
||||
Separate, documentation-only tool (not part of the generator pipeline):
|
||||
|
||||
- **`doc/TRO_Katalog/tro_graphs/gen_tro_graphs.py`** — regenerates the
|
||||
schematic per-type SVGs, the edge-type legend and the per-controller
|
||||
(UH01–UH05) topology graphs embedded in `TRO_Katalog.md`, built from
|
||||
`doc/TRO_Katalog/connect.ini`.
|
||||
|
||||
## 2. Running the scripts
|
||||
|
||||
Each CLI tool is invoked through its `bin/<name>.bat` (Windows) / `bin/<name>.sh`
|
||||
(Linux/macOS) wrapper, which:
|
||||
|
||||
1. calls `setenv` to set `SPS_SKEL`, `SKEL_DATA`, `SKEL_RESULTS`, `SKEL_CFG`,
|
||||
`SKEL_LIB` and prepend `SKEL_LIB` to `PYTHONPATH`;
|
||||
2. activates `.venv` if it exists (`bin/install_py` creates it);
|
||||
3. runs the module with `py` (falling back to `python`).
|
||||
|
||||
```bat
|
||||
bin\material_flow.bat --file mubea.csv --tosvg
|
||||
bin\tro_flow.bat --file mubea.csv --tosvg --doc
|
||||
bin\tro_annotate.bat --file mubea.csv --dxf 500573_60_1.dxf --flow --fb --legend
|
||||
```
|
||||
|
||||
Conventions shared by all three tools:
|
||||
|
||||
- `--file` / `--dxf` accept either a bare filename — resolved against
|
||||
`%SKEL_DATA%` — or a full path.
|
||||
- All generated output is written to `%SKEL_RESULTS%`.
|
||||
- `tro_annotate.py` additionally persists the verified CSV↔DXF coordinate
|
||||
offset to `%SKEL_CFG%\dxf_registration.json`.
|
||||
- Every run prints a `====` bordered report to stdout (counts, warnings,
|
||||
output file paths); non-fatal findings are printed as `?`/`!` lines and also
|
||||
do not stop the run.
|
||||
- Requires the packages pinned in `requirements.txt` (`pydantic>=2.0.0`;
|
||||
`ezdxf>=1.4.0` for `tro_annotate.py` only) — run `bin\install_py.bat` once.
|
||||
- `--tosvg` needs Graphviz's `dot` (or `neato`, for `tro_flow.py
|
||||
--use-cords`) on `PATH`, or the `GRAPHVIZ_DOT` environment variable pointing
|
||||
at the `dot` executable.
|
||||
|
||||
## 3. `material_flow.py` — material-flow graph of the mechanical layout
|
||||
|
||||
Reads the CSV export and builds a directed graph of the mechanical objects:
|
||||
|
||||
- **Gefällestrecke** / **Strecke** (conveyor segments) → one node each.
|
||||
- **Kreisel** (rotary/turntable) → two nodes (`-L` / `-R`), linked by the
|
||||
`Drehrichtung` feature (`UZS` = clockwise = right→left, `GUZ` =
|
||||
counter-clockwise = left→right).
|
||||
- **Separator** / **Scanner** → no node of their own; shown via `Zuordnung`
|
||||
(assignment) on the label of their owning node.
|
||||
|
||||
Flow direction between conveyor segments is derived from height change
|
||||
(`Hoehe_Von_mm`/`Hoehe_Bis_mm`) or, failing that, from `Antriebfahrtrichtung`
|
||||
("Auf"/"Ab"); connections whose direction can't be determined are drawn
|
||||
bidirectional and reported as a warning. `--doc` additionally cross-checks
|
||||
stated `Anzahl_Separator`/`Anzahl_Scanner` counts against what was actually
|
||||
attached.
|
||||
|
||||
| Switch | Argument | Default | Meaning |
|
||||
|---|---|---|---|
|
||||
| `--file` | `NAME` | `export.csv` | CSV input file, resolved against `%SKEL_DATA%`, or a full path. |
|
||||
| `--tosvg` | — | off | Also render the `.dot` file to `.svg` via Graphviz `dot`. |
|
||||
| `--doc` | — | off | Also write a Markdown report (`<name>_material_flow.md`) with object list, connections and plausibility findings. |
|
||||
|
||||
**Output** (in `%SKEL_RESULTS%`): `<name>_material_flow.dot` (always),
|
||||
`<name>_material_flow.svg` (with `--tosvg`), `<name>_material_flow.md`
|
||||
(with `--doc`).
|
||||
|
||||
**Exit codes:** `0` ok · `1` input/CLI error · `2` SVG rendering failed
|
||||
(Graphviz).
|
||||
|
||||
## 4. `tro_flow.py` — derive and draw the TROs
|
||||
|
||||
Sister program to `material_flow.py` — same `--file`/`--tosvg`/`--doc`
|
||||
switches, but instead of the mechanical objects it derives the **TROs**
|
||||
(Transfer Route Objects, i.e. control-logic units) from the same graph and
|
||||
draws *their* flow. Derivation rules (see
|
||||
`doc/500573_Mubea/TRO_Identifikation_500573.md` for the source analysis):
|
||||
|
||||
| Host of the separator | TRO type |
|
||||
|---|---|
|
||||
| Gefällestrecke, ≥ 2 lines sharing an in-/outfeed | `PinStore_Auto` (one block per line group) |
|
||||
| Gefällestrecke, single line | `1Sep` |
|
||||
| Strecke (driven) | `Vario` (one per segment) |
|
||||
| Kreisel lane | `1Sep` |
|
||||
| — additionally: 2 or 3 outgoing paths | upgraded to `1Sep1Swi` / `1Sep2Swi` |
|
||||
|
||||
A scanner mounted on a separator does **not** change the type (stays `1Sep`);
|
||||
the `1Sep_SSCC` special case can't be recognized from the mechanical layout
|
||||
alone and is only raised as a finding. TRO types, FB blocks, sub-components and
|
||||
colors all come from `lib/tro_catalog.py` — nothing is hard-coded here.
|
||||
|
||||
| Switch | Argument | Default | Meaning |
|
||||
|---|---|---|---|
|
||||
| `--file` | `NAME` | `export.csv` | CSV input file, resolved against `%SKEL_DATA%`, or a full path. |
|
||||
| `--tosvg` | — | off | Also render the TRO flow diagram to `.svg`. |
|
||||
| `--use-cords` (alias `--use-coords`) | — | off | Place every TRO at the centroid of the components it was built from and render with `neato -n` (fixed positions) instead of `dot`'s computed layout, so the diagram matches the plant layout. Only has an effect together with `--tosvg`; fails if any TRO has no coordinate. |
|
||||
| `--doc` | — | off | Also write a Markdown report (`<name>_tro_doc.md`) with the TRO list, connections, findings and the full type catalog. |
|
||||
|
||||
**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).
|
||||
|
||||
**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
|
||||
|
||||
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
|
||||
with:
|
||||
|
||||
- one colored marker block per TRO, each type with its own shape (circle,
|
||||
triangle, square, diamond, …; see `TroSymbol` in `tro_catalog.py`) so types
|
||||
are distinguishable even without color;
|
||||
- visible attributes `ID`, `TYPE` (and `FB_BLOCK` with `--fb`); hidden
|
||||
attributes `ITEMS`, `CONFIDENCE`, `SEPARATORS` for downstream tooling;
|
||||
- optional directional flow arrows between TROs (`--flow`) and a legend
|
||||
(`--legend`).
|
||||
|
||||
The original drawing is never modified. Everything this tool adds lives on its
|
||||
own `TRO_`-prefixed layers and carries XDATA under the app id
|
||||
`SPS_SKEL_TRO`; a re-run removes exactly those tagged objects (not by layer
|
||||
name) and rebuilds them, so hand-drawn content on the same layers survives.
|
||||
|
||||
CSV and DXF live in different coordinate systems; the offset between them is
|
||||
handled by `dxf_registration.py` — derived once, verified on every run, and
|
||||
cached per CSV/DXF filename pair in `%SKEL_CFG%\dxf_registration.json` unless
|
||||
overridden.
|
||||
|
||||
| Switch | Argument | Default | Meaning |
|
||||
|---|---|---|---|
|
||||
| `--file` | `NAME` | `export.csv` | CSV export, resolved against `%SKEL_DATA%`, or a full path. |
|
||||
| `--dxf` | `NAME` | — | Original drawing as DXF (path, or name resolved against `%SKEL_DATA%`). Required unless `--emit-lisp` is used alone. DWG is not supported. |
|
||||
| `--out` | `NAME` | `<csv-stem>_annotated.dxf` | Output filename in `%SKEL_RESULTS%`. |
|
||||
| `--flow` | — | off | Draw directional flow arrows between the TROs. |
|
||||
| `--fb` | — | off | Show the Siemens FB block name as a visible attribute on the marker. |
|
||||
| `--legend` | — | off | Draw a legend of the color groups. |
|
||||
| `--marker-size` | `MM` (float) | `300.0` | Marker radius in mm. |
|
||||
| `--text-height` | `MM` (float) | `220.0` | Text height in mm. |
|
||||
| `--layer-prefix` | `P` | `TRO_` | Prefix for the layers this tool creates. |
|
||||
| `--offset` | `DX,DY` | — | Set the CSV↔DXF offset by hand instead of deriving/loading it. |
|
||||
| `--re-register` | — | off | Re-derive the coordinate offset even if a verified one is already cached in `%SKEL_CFG%`. |
|
||||
| `--max-residual` | `MM` (float) | `600.0` | Largest residual error of the coordinate registration that is still accepted; above it the run fails (exit 4). |
|
||||
| `--check` | — | off | Dry run: only analyze and report, write no output file. |
|
||||
| `--emit-lisp` | — | off | Regenerate `cad/tro_types.lsp` (the type list for the `TROEDIT` dialog) from `tro_catalog.py` and exit — no `--dxf` needed. Written under `%DXFM_LISP%` if set (next to the `dxfmakros` SSG_LIB modules that provide the dialog), otherwise under `<SPS_SKEL>/cad`. |
|
||||
|
||||
**Output** (in `%SKEL_RESULTS%`, unless `--check`): `<name>_annotated.dxf`,
|
||||
`<name>_registration.json` (the coordinate transform used, with its proof).
|
||||
|
||||
**Exit codes:** `0` ok · `1` input/CLI error · `4` coordinate registration
|
||||
could not be proven (or exceeds `--max-residual`) — resolve with `--offset` or
|
||||
by raising `--max-residual`.
|
||||
|
||||
## 6. `tro_catalog.py` — TRO type catalog (library, no CLI)
|
||||
|
||||
The single source of truth for everything needed to generate or draw a TRO
|
||||
type: short name (as used in `FB_Main`/`connect.ini`), Siemens FB block,
|
||||
sub-components and their counts, color group (for Graphviz/Mermaid/CAD) and
|
||||
CAD marker shape. Ten types are defined in `TRO_CATALOG`, verified against
|
||||
`data/*.scl` where the source is vendored locally and against `TRO_Typen.md`'s
|
||||
mapping table otherwise (see the module docstring, `CATALOG_AS_OF`, for
|
||||
provenance per type). 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.
|
||||
|
||||
## 7. `dxf_registration.py` — CSV↔DXF coordinate registration (library, no CLI)
|
||||
|
||||
Derives the rigid transform (rotation + offset, no scaling) between the CSV
|
||||
export's and the DXF drawing's coordinate systems, by voting on the offset
|
||||
between same-role anchor points (`Separator` and `Scanner` blocks, see
|
||||
`ANCHOR_BLOCKS`), refining the best candidates via a Procrustes fit, and
|
||||
picking the candidate with the most exact matches. Raises `RegistrationError`
|
||||
if fewer than `MIN_INLIERS` (5) exact matches are found for any candidate.
|
||||
Persists/loads the verified transform per CSV/DXF filename pair under
|
||||
`%SKEL_CFG%\dxf_registration.json`. Used exclusively by `tro_annotate.py`; not
|
||||
run directly.
|
||||
|
||||
## 8. `gen_tro_graphs.py` — documentation image generator (doc tooling, not part of the generator)
|
||||
|
||||
Lives under `doc/TRO_Katalog/tro_graphs/`, not `lib/` — it produces the
|
||||
pictures embedded in `TRO_Katalog.md`, not generator output. Two families:
|
||||
|
||||
1. one schematic SVG per TRO type showing the block with its *possible*
|
||||
connection edges (`normal`/`dir2`/`dir3`/`bypass`/`finger`/`plc`/`extern`,
|
||||
each with its own color and line style), plus a shared `edge_legend.svg`;
|
||||
2. one Graphviz topology graph per controller (`uh01`..`uh05`), built from
|
||||
`doc/TRO_Katalog/connect.ini`, rendered to SVG.
|
||||
|
||||
No command-line switches — run it directly and re-run after editing
|
||||
`connect.ini`:
|
||||
|
||||
```
|
||||
py doc/TRO_Katalog/tro_graphs/gen_tro_graphs.py
|
||||
```
|
||||
|
||||
Needs Graphviz `dot` on `PATH` (or at the default Windows install location);
|
||||
without it the `.dot` files are still written, just not rendered to `.svg`.
|
||||
Reference in New Issue
Block a user