rfem-table-export 0.2.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rfem-table-export
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Terminal UI for exporting RFEM 6 input and result tables to Excel
5
5
  Project-URL: Homepage, https://github.com/Mark-Milkis/rfem-table-export
6
6
  Project-URL: Repository, https://github.com/Mark-Milkis/rfem-table-export
@@ -22,6 +22,7 @@ Requires-Python: >=3.11
22
22
  Requires-Dist: dlubal-api==2.14.3
23
23
  Requires-Dist: openpyxl>=3.1
24
24
  Requires-Dist: pandas>=2.0
25
+ Requires-Dist: pint>=0.20
25
26
  Requires-Dist: textual>=0.80
26
27
  Description-Content-Type: text/markdown
27
28
 
@@ -48,8 +49,30 @@ The table-picker UX is modeled on SAP2000's "Export Tables to Excel" dialog.
48
49
  cross-sections, supports, hinges, load cases/combinations, loads) and static
49
50
  result tables (support forces, internal forces, deformations) iterated across
50
51
  every load case and combination.
51
- - **Model units, no surprises** values are written exactly as the RFEM API
52
- returns them (the model's own units); the info sheet records this.
52
+ - **Object filtering** (`o`)toggle between *all objects* and *only the
53
+ objects currently selected in the RFEM model* (read live via the API's
54
+ `only_selected` query); the status bar shows a live count of what's selected
55
+ (e.g. "1 member"). To export a saved RFEM object selection or Group of Object
56
+ Selections, activate it in RFEM (which sets the live selection), then toggle to
57
+ *Currently selected objects*. Tables whose rows aren't tied to selectable
58
+ objects (materials, cross-sections, load cases/combinations) ignore the filter
59
+ and always export in full; loads, supports and result rows are filtered by the
60
+ object they act on/report.
61
+ - **Case / combination filtering** (`c`) — for result tables, pick exactly which
62
+ load cases and combinations to export from a check-list instead of iterating
63
+ every one.
64
+ - **Result-row detail** (`t`) — cycle a result table's rows between *all*,
65
+ *envelope only* (extreme rows whose `tag` ends in `min`/`max`), and *itemized
66
+ only* (the per-location rows, with no `min`/`max` tag).
67
+ - **Analysis-aware** — result tables are greyed out and unselectable until the
68
+ model has been solved, so you never queue a result export that can't run.
69
+ - **Metric or imperial units** — pick a unit system and every value is
70
+ converted to it (metric: kN, kN·m, m/mm, MPa; imperial: kip, kip·ft, ft/in,
71
+ ksi). Conversion is dimensionality-driven via [Pint](https://pint.readthedocs.io/):
72
+ no multipliers are hard-coded, so compound units (kN·m, kN/m, kN/m²) convert
73
+ correctly and can't be cross-applied. The info sheet records the system and
74
+ the target unit for each magnitude; converted columns carry their unit in the
75
+ header (e.g. `n [kip]`, `area_axial [in²]`).
53
76
  - **One workbook per export** — a new file is always written to `results/`;
54
77
  nothing is overwritten.
55
78
  - **Resilient** — a single problematic table produces a warning on the info
@@ -113,16 +136,41 @@ pip install -e .
113
136
  3. Confirm the banner shows the correct active model.
114
137
  4. Navigate the tree and toggle the tables you want:
115
138
 
116
- | Key | Action |
117
- |---------|-------------------|
118
- | `space` | Toggle table |
119
- | `a` | Select all |
120
- | `n` | Clear selection |
121
- | `e` | Export |
122
- | `r` | Reconnect to RFEM |
123
- | `q` | Quit |
139
+ | Key | Action |
140
+ |---------|-------------------------------------------|
141
+ | `space` | Toggle table |
142
+ | `a` | Select all |
143
+ | `n` | Clear selection |
144
+ | `o` | Object scope (all / currently selected) |
145
+ | `c` | Case & combination filter (results) |
146
+ | `t` | Result rows (all / envelope / itemized) |
147
+ | `u` | Cycle units (metric/imperial) |
148
+ | `e` | Export |
149
+ | `r` | Reconnect to RFEM |
150
+ | `q` | Quit |
124
151
 
125
152
  5. Press `e`. The workbook is written to `results/rfem_export_<model>_<timestamp>.xlsx`.
153
+ The info sheet records the active object and case filters, and each table's
154
+ row lists how many rows the filter kept.
155
+
156
+ ## Units
157
+
158
+ Choose the unit system with `u` in the TUI, or `--units {metric,imperial}` on
159
+ the command line (default: `imperial`). Values are converted by *dimensionality*,
160
+ never by a hard-coded factor:
161
+
162
+ - **Input tables** carry a unit per column straight from the RFEM API
163
+ (`m`, `kN`, `kNm`, `mm⁴`, …). Pint parses that unit, derives its dimensionality
164
+ and computes the conversion.
165
+ - **Result tables** expose no units over the API, so each result table declares
166
+ the *SI* unit of its value columns (in [`catalog.py`](rfem_export/catalog.py)).
167
+ Only the dimension is asserted — Pint still computes every factor.
168
+
169
+ A length lands in feet/metres for geometry but inches/millimetres for section
170
+ dimensions and deflections (RFEM's own unit categories drive this). Quantities
171
+ with no conversion rule (e.g. dimensionless ratios) are passed through unchanged
172
+ and noted in the export log. If Pint isn't installed, values are written in
173
+ their source units and the info sheet says so.
126
174
 
127
175
  ## Configuration
128
176
 
@@ -144,7 +192,8 @@ rfem_export/
144
192
  __init__.py
145
193
  connection.py # API-key resolution, attach to RFEM, model info, unit summary
146
194
  catalog.py # curated navigator tree of exportable tables (TableDef / Group)
147
- extract.py # protobuf objects + result tables -> pandas DataFrames
195
+ units.py # Pint-based, dimensionality-driven metric/imperial conversion
196
+ extract.py # object tables + result tables -> pandas DataFrames (+ units)
148
197
  excel.py # workbook writer: one sheet per table + info sheet
149
198
  app.py # Textual TUI + console entry point
150
199
  examples/
@@ -154,9 +203,11 @@ examples/
154
203
  ### Extending table coverage
155
204
 
156
205
  Add a `TableDef` to the `TREE` in [`rfem_export/catalog.py`](rfem_export/catalog.py).
157
- Both extraction and the TUI pick up new entries automatically — inputs are
158
- extracted by enumerating object IDs of an `ObjectType`; results via
159
- `get_result_table` across every loading.
206
+ Both extraction and the TUI pick up new entries automatically — inputs via
207
+ `get_object_table` for an `ObjectType` (which also supplies per-column units);
208
+ results via `get_result_table` across every loading. For a **result** table,
209
+ also fill in `result_units` (the SI unit of each value column) so the values can
210
+ be converted — result tables carry no units over the API.
160
211
 
161
212
  ## Development
162
213
 
@@ -21,8 +21,30 @@ The table-picker UX is modeled on SAP2000's "Export Tables to Excel" dialog.
21
21
  cross-sections, supports, hinges, load cases/combinations, loads) and static
22
22
  result tables (support forces, internal forces, deformations) iterated across
23
23
  every load case and combination.
24
- - **Model units, no surprises** values are written exactly as the RFEM API
25
- returns them (the model's own units); the info sheet records this.
24
+ - **Object filtering** (`o`)toggle between *all objects* and *only the
25
+ objects currently selected in the RFEM model* (read live via the API's
26
+ `only_selected` query); the status bar shows a live count of what's selected
27
+ (e.g. "1 member"). To export a saved RFEM object selection or Group of Object
28
+ Selections, activate it in RFEM (which sets the live selection), then toggle to
29
+ *Currently selected objects*. Tables whose rows aren't tied to selectable
30
+ objects (materials, cross-sections, load cases/combinations) ignore the filter
31
+ and always export in full; loads, supports and result rows are filtered by the
32
+ object they act on/report.
33
+ - **Case / combination filtering** (`c`) — for result tables, pick exactly which
34
+ load cases and combinations to export from a check-list instead of iterating
35
+ every one.
36
+ - **Result-row detail** (`t`) — cycle a result table's rows between *all*,
37
+ *envelope only* (extreme rows whose `tag` ends in `min`/`max`), and *itemized
38
+ only* (the per-location rows, with no `min`/`max` tag).
39
+ - **Analysis-aware** — result tables are greyed out and unselectable until the
40
+ model has been solved, so you never queue a result export that can't run.
41
+ - **Metric or imperial units** — pick a unit system and every value is
42
+ converted to it (metric: kN, kN·m, m/mm, MPa; imperial: kip, kip·ft, ft/in,
43
+ ksi). Conversion is dimensionality-driven via [Pint](https://pint.readthedocs.io/):
44
+ no multipliers are hard-coded, so compound units (kN·m, kN/m, kN/m²) convert
45
+ correctly and can't be cross-applied. The info sheet records the system and
46
+ the target unit for each magnitude; converted columns carry their unit in the
47
+ header (e.g. `n [kip]`, `area_axial [in²]`).
26
48
  - **One workbook per export** — a new file is always written to `results/`;
27
49
  nothing is overwritten.
28
50
  - **Resilient** — a single problematic table produces a warning on the info
@@ -86,16 +108,41 @@ pip install -e .
86
108
  3. Confirm the banner shows the correct active model.
87
109
  4. Navigate the tree and toggle the tables you want:
88
110
 
89
- | Key | Action |
90
- |---------|-------------------|
91
- | `space` | Toggle table |
92
- | `a` | Select all |
93
- | `n` | Clear selection |
94
- | `e` | Export |
95
- | `r` | Reconnect to RFEM |
96
- | `q` | Quit |
111
+ | Key | Action |
112
+ |---------|-------------------------------------------|
113
+ | `space` | Toggle table |
114
+ | `a` | Select all |
115
+ | `n` | Clear selection |
116
+ | `o` | Object scope (all / currently selected) |
117
+ | `c` | Case & combination filter (results) |
118
+ | `t` | Result rows (all / envelope / itemized) |
119
+ | `u` | Cycle units (metric/imperial) |
120
+ | `e` | Export |
121
+ | `r` | Reconnect to RFEM |
122
+ | `q` | Quit |
97
123
 
98
124
  5. Press `e`. The workbook is written to `results/rfem_export_<model>_<timestamp>.xlsx`.
125
+ The info sheet records the active object and case filters, and each table's
126
+ row lists how many rows the filter kept.
127
+
128
+ ## Units
129
+
130
+ Choose the unit system with `u` in the TUI, or `--units {metric,imperial}` on
131
+ the command line (default: `imperial`). Values are converted by *dimensionality*,
132
+ never by a hard-coded factor:
133
+
134
+ - **Input tables** carry a unit per column straight from the RFEM API
135
+ (`m`, `kN`, `kNm`, `mm⁴`, …). Pint parses that unit, derives its dimensionality
136
+ and computes the conversion.
137
+ - **Result tables** expose no units over the API, so each result table declares
138
+ the *SI* unit of its value columns (in [`catalog.py`](rfem_export/catalog.py)).
139
+ Only the dimension is asserted — Pint still computes every factor.
140
+
141
+ A length lands in feet/metres for geometry but inches/millimetres for section
142
+ dimensions and deflections (RFEM's own unit categories drive this). Quantities
143
+ with no conversion rule (e.g. dimensionless ratios) are passed through unchanged
144
+ and noted in the export log. If Pint isn't installed, values are written in
145
+ their source units and the info sheet says so.
99
146
 
100
147
  ## Configuration
101
148
 
@@ -117,7 +164,8 @@ rfem_export/
117
164
  __init__.py
118
165
  connection.py # API-key resolution, attach to RFEM, model info, unit summary
119
166
  catalog.py # curated navigator tree of exportable tables (TableDef / Group)
120
- extract.py # protobuf objects + result tables -> pandas DataFrames
167
+ units.py # Pint-based, dimensionality-driven metric/imperial conversion
168
+ extract.py # object tables + result tables -> pandas DataFrames (+ units)
121
169
  excel.py # workbook writer: one sheet per table + info sheet
122
170
  app.py # Textual TUI + console entry point
123
171
  examples/
@@ -127,9 +175,11 @@ examples/
127
175
  ### Extending table coverage
128
176
 
129
177
  Add a `TableDef` to the `TREE` in [`rfem_export/catalog.py`](rfem_export/catalog.py).
130
- Both extraction and the TUI pick up new entries automatically — inputs are
131
- extracted by enumerating object IDs of an `ObjectType`; results via
132
- `get_result_table` across every loading.
178
+ Both extraction and the TUI pick up new entries automatically — inputs via
179
+ `get_object_table` for an `ObjectType` (which also supplies per-column units);
180
+ results via `get_result_table` across every loading. For a **result** table,
181
+ also fill in `result_units` (the SI unit of each value column) so the values can
182
+ be converted — result tables carry no units over the API.
133
183
 
134
184
  ## Development
135
185
 
@@ -23,6 +23,7 @@ dependencies = [
23
23
  "textual>=0.80",
24
24
  "pandas>=2.0",
25
25
  "openpyxl>=3.1",
26
+ "pint>=0.20",
26
27
  ]
27
28
 
28
29
  [project.urls]
@@ -79,5 +80,6 @@ select = ["E", "F", "I", "W", "UP", "B"]
79
80
  "rfem_export/catalog.py" = ["E501"]
80
81
  # Side-effect import ordering must be preserved (see comment in the module).
81
82
  "rfem_export/extract.py" = ["I001", "E402", "E501"]
83
+ "rfem_export/filters.py" = ["I001", "E402"]
82
84
  # Dlubal path injection happens before the dlubal import by design.
83
85
  "rfem_export/connection.py" = ["E402"]
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.2.0'
22
- __version_tuple__ = version_tuple = (0, 2, 0)
21
+ __version__ = version = '0.3.0'
22
+ __version_tuple__ = version_tuple = (0, 3, 0)
23
23
 
24
24
  __commit_id__ = commit_id = None