TUI for batch IDEA StatiCa connection reporting and white-label export
Project description
statica-reporter
A terminal UI (TUI) for batch IDEA StatiCa connection reporting. Browse multiple
.ideaCon projects and their connections in a tree, glance at per-connection
details, build an ordered report selection, and export in four formats.
Run
# TUI (interactive)
uvx --from . statica-reporter # before publishing
# uvx statica-reporter # once published to PyPI
# Headless batch (preserves the original main.py workflow)
uvx --from . statica-reporter-batch --input-dir inputs --output-dir out --json
Requires a running IDEA StatiCa Connection REST service. The TUI attaches to one
at http://localhost:5000 by default; if none is reachable it offers to start a
detected local installation (or accept a custom URL).
Features
- Browse: tree of projects → connections with status glyphs; lazy two-pane
detail (status + per-category checks, design forces, geometry counts). Press
Enterto fetch,cto run CBFEM analysis. - Report builder: move connections from an Available tree into an ordered
Selected list (
Space/Enteradd,Aadd all,J/Kreorder,dremove). - Export (combined by default, optional split-per-connection):
- StatiCa PDF (native multi-connection report, grouped per project)
- Connection summary docx (one table: ID, isometric view, forces, checks)
- JSON data dump (raw results)
- Bound white-label docx — all selected reports concatenated and run through Pandoc with a blank reference document, so headings/tables map to stock Word styles and inherit a company template on paste (with TOC + bookmarks).
- Workspaces: save/open named workspaces (added projects, selection, output
dir, export prefs) under
%APPDATA%/statica-reporter/workspaces.
Architecture
statica_reporter/core/— UI-free engine (service, client, analysis, exports, rendering, summary_docx, bound_report). Fully unit-tested without a live service.statica_reporter/tui/— Textual app, screens, widgets.statica_reporter/cli.py— headless batch entry point.statica_reporter/workspace.py— named workspace persistence.
Run the tests with uv run pytest.
The legacy root-level
main.pyandreport_generator.pyare superseded by the package (migrated intocore/); they remain only for reference and can be removed.
IDEA StatiCa Connection API — Developer Reference
This document captures everything learned from working against the live API (server v26.0.1.2450, Python client v26.0.0.3314) so future development doesn't have to rediscover it.
Setup
Install the client
uv add ideastatica-connection-api
# or: pip install ideastatica-connection-api
Prerequisites
The API requires a running IDEA StatiCa REST service. In this project the server is already running at http://localhost:5000. Docs for the running instance are available at http://localhost:5000/api.
Connecting
Use ConnectionApiServiceAttacher as a context manager. It handles session lifecycle automatically (client registration and cleanup on exit).
import ideastatica_connection_api.connection_api_service_attacher as connection_api_service_attacher
BASE_URL = "http://localhost:5000"
with connection_api_service_attacher.ConnectionApiServiceAttacher(BASE_URL).create_api_client() as api_client:
# all work happens here
pass
The api_client object exposes every API group as an attribute:
| Attribute | Purpose |
|---|---|
api_client.project |
Open, close, query projects |
api_client.connection |
Query and modify connections |
api_client.calculation |
Run analysis, fetch results |
api_client.report |
Export PDF / Word / HTML |
api_client.load_effect |
Manage load cases |
api_client.material |
Steel, bolt, weld, concrete materials |
api_client.member |
Connection members |
api_client.operation |
Connection operations (welds, bolts, etc.) |
api_client.parameter |
Parametric values |
api_client.template |
Connection templates |
api_client.settings |
Project settings |
api_client.export |
IOM / IFC export |
api_client.presentation |
3D scene data |
Core workflow
1. Open a project
api_client.project.open_project_from_filepath(r"C:\path\to\file.ideaCon")
project_id = api_client.project.active_project_id # str UUID, set automatically
2. List connections
project_data = api_client.project.get_project_data(project_id)
# project_data.connections -> list of ConConnection
for conn in project_data.connections:
print(conn.id, conn.name) # id is an int
3. Check if a connection is already analyzed
There is no explicit "status" field. Check by calling get_results and inspecting check_res_summary:
results = api_client.calculation.get_results(project_id, [conn_id])
already_analyzed = (
results
and results[0]
and results[0].check_res_summary is not None
)
ConnectionCheckRes fields: check_res_summary, check_res_plate, check_res_weld, check_res_bolt, check_res_anchor, check_res_concrete_block, buckling_results, name, connection_id, id, messages.
4. Run analysis
summaries = api_client.calculation.calculate(project_id, [conn_id])
# returns List[ConResultSummary]
# ConResultSummary fields: id, passed, result_summary
calculate accepts a plain List[int] of connection IDs — pass multiple IDs to batch.
Note: The official documentation shows a
ConCalculationParameterobject, but this class does not exist in the installed Python client. Pass a plain list directly.
5. Fetch raw JSON results
raw_list = api_client.calculation.get_raw_json_results(project_id, [conn_id])
# returns List[str], one JSON string per connection ID
import json
data = json.loads(raw_list[0])
Top-level keys in the returned object: codeType, plates, platesDeformation, bolts, welds, anchors, concreteBlock, bucklingResults, and others depending on connection type.
6. Fetch structured results
results = api_client.calculation.get_results(project_id, [conn_id])
# returns List[ConnectionCheckRes]
summary = results[0].check_res_summary # ConResultSummary
plates = results[0].check_res_plate # list of CheckResPlate
welds = results[0].check_res_weld # list of CheckResWeld
bolts = results[0].check_res_bolt # list of CheckResBolt
7. Export reports
# PDF — returns bytes, write manually
pdf_bytes = api_client.report.generate_pdf(project_id, conn_id) # conn_id is int
with open("report.pdf", "wb") as f:
f.write(pdf_bytes)
# Word
docx_bytes = api_client.report.generate_word(project_id, conn_id)
# HTML zip
zip_bytes = api_client.report.generate_html_zip(project_id, conn_id)
# Batch PDF (all connections at once)
# Note: "mutliple" is a typo in the API itself — use it exactly as shown
pdf_bytes = api_client.report.generate_pdf_for_mutliple(project_id, [conn_id_1, conn_id_2])
Note: The return type annotation says
Noneforgenerate_pdf— this is wrong. It returnsbytes.
8. Close the project
api_client.project.close_project(project_id)
Always close when done. Unclosed projects remain in the server's memory.
Units
The API never returns unit labels. There are no unit-related classes, settings, or fields anywhere in the package. All raw numeric values are in SI units, regardless of the project's design code (American, Eurocode, etc.):
| Quantity | Unit |
|---|---|
| Length / dimension | m |
| Stress / pressure / strength | Pa |
| Force | N |
| Moment | N·m |
Example cross-check from a real result (codeType: "american", material A992):
thickness: 0.04→ 40 mm plate ✓materialFy: 344_740_000→ 344.7 MPa ≈ 50 ksi ✓materialModulusOfElasticity: 200_000_000_000→ 200 GPa ✓
Settings
get_settings returns a flat Dict[str, object] keyed by slash-separated paths:
settings = api_client.settings.get_settings(project_id)
# e.g. settings["calculationCommon/Checks/Shared/LimitPlasticStrain"] -> 0.05
# Search by keyword
settings = api_client.settings.get_settings(project_id, search="mesh")
Update a setting:
api_client.settings.update_settings(project_id, {
"calculationCommon/Checks/Shared/LimitPlasticStrain": 0.03
})
Other useful APIs
Load effects
load_effects = api_client.load_effect.get_load_effects(project_id, conn_id)
Materials
steels = api_client.material.get_steel_materials(project_id)
bolts = api_client.material.get_bolt_grade_materials(project_id)
sections = api_client.material.get_cross_sections(project_id)
Export to IOM/IFC
iom_xml = api_client.export.export_iom(project_id, conn_id)
ifc_data = api_client.export.export_ifc(project_id, conn_id)
3D scene data
scene_json = api_client.presentation.get_data_scene3_d_text(project_id, conn_id)
Complete working example
This is the pattern used in main.py:
import glob, json, os
import ideastatica_connection_api.connection_api_service_attacher as connection_api_service_attacher
BASE_URL = "http://localhost:5000"
with connection_api_service_attacher.ConnectionApiServiceAttacher(BASE_URL).create_api_client() as api_client:
api_client.project.open_project_from_filepath(r"inputs\myfile.ideaCon")
project_id = api_client.project.active_project_id
project_data = api_client.project.get_project_data(project_id)
for conn in project_data.connections:
conn_id = conn.id # int
# Skip calculation if already done
results = api_client.calculation.get_results(project_id, [conn_id])
if not (results and results[0] and results[0].check_res_summary is not None):
api_client.calculation.calculate(project_id, [conn_id])
# PDF report
pdf_bytes = api_client.report.generate_pdf(project_id, conn_id)
with open(f"reports/{conn.name}.pdf", "wb") as f:
f.write(pdf_bytes)
# Raw JSON data
raw = api_client.calculation.get_raw_json_results(project_id, [conn_id])
parsed = json.loads(raw[0])
with open(f"data/{conn.name}.json", "w") as f:
json.dump(parsed, f, indent=2)
api_client.project.close_project(project_id)
Gotchas
ConCalculationParameterdoes not exist in the installed client. PassList[int]directly tocalculateandget_raw_json_results.generate_pdfreturn type is annotated asNonebut actually returnsbytes. Open the file in"wb"mode.- All values are SI — convert to display units in your own layer if needed.
- Always close projects — the server holds them in memory until explicitly closed or the session ends.
active_project_idis set automatically afteropen_project_from_filepath. You do not need to parse the return value.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file statica_reporter-0.1.0.tar.gz.
File metadata
- Download URL: statica_reporter-0.1.0.tar.gz
- Upload date:
- Size: 117.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
14a16ef8975237ede9f9c10301d6183ab02d2dfaa08410ea0789f932bcd002b2
|
|
| MD5 |
527f15e79313d7e2f5b4a9492ee076e7
|
|
| BLAKE2b-256 |
7cc9bb993e20ce4fc84f33b63b4861f322209df19264b47b0185137aed48836e
|
Provenance
The following attestation bundles were made for statica_reporter-0.1.0.tar.gz:
Publisher:
release.yml on Mark-Milkis/statica-reporter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
statica_reporter-0.1.0.tar.gz -
Subject digest:
14a16ef8975237ede9f9c10301d6183ab02d2dfaa08410ea0789f932bcd002b2 - Sigstore transparency entry: 1840709425
- Sigstore integration time:
-
Permalink:
Mark-Milkis/statica-reporter@bf0d3f241165b22b7222dc485b33b43e7becde49 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Mark-Milkis
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@bf0d3f241165b22b7222dc485b33b43e7becde49 -
Trigger Event:
push
-
Statement type:
File details
Details for the file statica_reporter-0.1.0-py3-none-any.whl.
File metadata
- Download URL: statica_reporter-0.1.0-py3-none-any.whl
- Upload date:
- Size: 50.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
451d911b347e194e95183357ce0ada91ee36b138ee8eeac4153e761da530ffae
|
|
| MD5 |
05dfb81e98c2a9860d9a20bed85a8c7d
|
|
| BLAKE2b-256 |
c1a75655b166e0838d641633ad5522c37f71eefa3c8533fca019f809ef764c53
|
Provenance
The following attestation bundles were made for statica_reporter-0.1.0-py3-none-any.whl:
Publisher:
release.yml on Mark-Milkis/statica-reporter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
statica_reporter-0.1.0-py3-none-any.whl -
Subject digest:
451d911b347e194e95183357ce0ada91ee36b138ee8eeac4153e761da530ffae - Sigstore transparency entry: 1840709510
- Sigstore integration time:
-
Permalink:
Mark-Milkis/statica-reporter@bf0d3f241165b22b7222dc485b33b43e7becde49 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Mark-Milkis
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@bf0d3f241165b22b7222dc485b33b43e7becde49 -
Trigger Event:
push
-
Statement type: