dxfmakros' TRO menu can now insert new TRO markers by hand (TRO_INSERT), not just edit ones tro_annotate.py placed; note it here since this is where the workflow and --emit-lisp switch are documented.
13 KiB
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.pymodels the material flow of the mechanical objects only (Gefällestrecke, Strecke, Kreisel).tro_flow.pyis its sister program: it derives the control objects (TROs) from the same graph and draws their flow instead.tro_annotate.pytakes the TROs fromtro_flow.pyand 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 inTRO_Katalog.md, built fromdoc/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:
- calls
setenvto setSPS_SKEL,SKEL_DATA,SKEL_RESULTS,SKEL_CFG,SKEL_LIBand prependSKEL_LIBtoPYTHONPATH; - activates
.venvif it exists (bin/install_pycreates it); - runs the module with
py(falling back topython).
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/--dxfaccept either a bare filename — resolved against%SKEL_DATA%— or a full path.- All generated output is written to
%SKEL_RESULTS%. tro_annotate.pyadditionally 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.0fortro_annotate.pyonly) — runbin\install_py.batonce. --tosvgneeds Graphviz'sdot(orneato, fortro_flow.py --use-cords) onPATH, or theGRAPHVIZ_DOTenvironment variable pointing at thedotexecutable.
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 theDrehrichtungfeature (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
TroSymbolintro_catalog.py) so types are distinguishable even without color; - visible attributes
ID,TYPE(andFB_BLOCKwith--fb); hidden attributesITEMS,CONFIDENCE,SEPARATORSfor 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.
Once at least one marker of a given type has been annotated, the dxfmakros
BricsCAD menu (SSG_LIB > TRO) can insert further markers of that type by
hand — TRO_INSERT reuses the TRO_SYM_<Typ> block definition this tool
created and only asks for a point, an id and (optionally) a different type;
TRO_EDIT changes ID/TYPE on an existing marker. Neither command draws
new shapes — a type with no prior annotated instance in the drawing must be
run through this tool at least once first.
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 TRO_INSERT/TRO_EDIT dialogs) 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 dialogs), 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:
- 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 sharededge_legend.svg; - one Graphviz topology graph per controller (
uh01..uh05), built fromdoc/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.