fmu-manipulation-toolbox 1.8.4.3b0__tar.gz → 1.9__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.
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/PKG-INFO +1 -1
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/README.md +57 -23
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/__init__.py +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/__main__.py +1 -1
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/__version__.py +1 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/assembly.py +21 -12
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/checker.py +11 -8
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/cli/__init__.py +0 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/cli/fmucontainer.py +105 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/cli/fmusplit.py +48 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/cli/fmutool.py +127 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/cli/utils.py +36 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/container.py +1054 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/gui.py +47 -55
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/gui_style.py +8 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/help.py +3 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/operations.py +577 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/remoting.py +107 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/resources/darwin64/container.dylib +0 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/resources/linux32/client_sm.so +0 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/resources/linux32/server_sm +0 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/resources/linux64/client_sm.so +0 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/resources/linux64/container.so +0 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/resources/linux64/server_sm +0 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/resources/win32/client_sm.dll +0 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/resources/win32/server_sm.exe +0 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/resources/win64/client_sm.dll +0 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/resources/win64/container.dll +0 -0
- fmu_manipulation_toolbox-1.9/fmu_manipulation_toolbox/resources/win64/server_sm.exe +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/split.py +67 -34
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox.egg-info/PKG-INFO +1 -1
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox.egg-info/SOURCES.txt +7 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/setup.py +2 -1
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/tests/test_suite.py +100 -5
- fmu_manipulation_toolbox-1.8.4.3b0/fmu_manipulation_toolbox/__init__.py +0 -1
- fmu_manipulation_toolbox-1.8.4.3b0/fmu_manipulation_toolbox/__version__.py +0 -1
- fmu_manipulation_toolbox-1.8.4.3b0/fmu_manipulation_toolbox/container.py +0 -767
- fmu_manipulation_toolbox-1.8.4.3b0/fmu_manipulation_toolbox/operations.py +0 -505
- fmu_manipulation_toolbox-1.8.4.3b0/fmu_manipulation_toolbox/resources/linux32/client_sm.so +0 -0
- fmu_manipulation_toolbox-1.8.4.3b0/fmu_manipulation_toolbox/resources/linux32/server_sm +0 -0
- fmu_manipulation_toolbox-1.8.4.3b0/fmu_manipulation_toolbox/resources/linux64/client_sm.so +0 -0
- fmu_manipulation_toolbox-1.8.4.3b0/fmu_manipulation_toolbox/resources/linux64/container.so +0 -0
- fmu_manipulation_toolbox-1.8.4.3b0/fmu_manipulation_toolbox/resources/linux64/server_sm +0 -0
- fmu_manipulation_toolbox-1.8.4.3b0/fmu_manipulation_toolbox/resources/win32/client_sm.dll +0 -0
- fmu_manipulation_toolbox-1.8.4.3b0/fmu_manipulation_toolbox/resources/win32/server_sm.exe +0 -0
- fmu_manipulation_toolbox-1.8.4.3b0/fmu_manipulation_toolbox/resources/win64/client_sm.dll +0 -0
- fmu_manipulation_toolbox-1.8.4.3b0/fmu_manipulation_toolbox/resources/win64/container.dll +0 -0
- fmu_manipulation_toolbox-1.8.4.3b0/fmu_manipulation_toolbox/resources/win64/server_sm.exe +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/LICENSE.txt +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/checkbox-checked-disabled.png +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/checkbox-checked-hover.png +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/checkbox-checked.png +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/checkbox-unchecked-disabled.png +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/checkbox-unchecked-hover.png +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/checkbox-unchecked.png +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/container.png +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/drop_fmu.png +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Annotation.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2AttributeGroups.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2ModelDescription.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2ScalarVariable.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Type.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Unit.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2VariableDependency.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Annotation.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3AttributeGroups.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3BuildDescription.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3InterfaceType.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3LayeredStandardManifest.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3ModelDescription.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Terminal.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3TerminalsAndIcons.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Type.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Unit.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Variable.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3VariableDependency.xsd +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmu.png +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/fmu_manipulation_toolbox.png +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/help.png +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/icon-round.png +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/icon.png +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/icon_fmu.png +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/license.txt +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/mask.png +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/resources/model.png +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox/version.py +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox.egg-info/dependency_links.txt +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox.egg-info/entry_points.txt +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox.egg-info/requires.txt +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/fmu_manipulation_toolbox.egg-info/top_level.txt +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0 → fmu_manipulation_toolbox-1.9}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fmu_manipulation_toolbox
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.9
|
|
4
4
|
Summary: FMU Manipulation Toolbox is a python application for modifying Functional Mock-up Units (FMUs) without recompilation or bundling them into FMU Containers
|
|
5
5
|
Home-page: https://github.com/grouperenault/fmu_manipulation_toolbox/
|
|
6
6
|
Author: Nicolas.LAURENT@Renault.com
|
|
@@ -1,12 +1,23 @@
|
|
|
1
|
-

|
|
2
2
|
|
|
3
|
-
FMU Manipulation Toolbox is a python package which help to analyse
|
|
4
|
-
without recompilation. It is highly customizable
|
|
3
|
+
FMU Manipulation Toolbox is a python package which help to analyse, modify or combine
|
|
4
|
+
[Functional Mock-up Units (FMUs)](http://fmi-standard.org/) without recompilation. It is highly customizable as it comes with
|
|
5
|
+
a Python API.
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
FMU Manipulation Toolbox can be used in different ways :
|
|
8
|
+
- Using a Graphical User Interface: suitable for end user
|
|
9
|
+
- Using a Command Line Interface: useful in
|
|
10
|
+
- Using a python API: the most efficient for automation (CI/CD, transformation scripts, ...)
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
Major features:
|
|
13
|
+
- Analyse FMU content: list ports and their attributes, check compliance of `ModelDescription.xml` with XSD, ...
|
|
14
|
+
- Alter FMU by modifying its `modelDescription.xml` file. NOTE: manipulating this file can be a dangerous
|
|
15
|
+
thing! Communicating with the FMU-developer and adapting the way the FMU is generated is preferable when
|
|
16
|
+
possible.
|
|
17
|
+
- Add binary interface. Typical use case is porting a 32bits FMUs to 64bits (or vice et versa).
|
|
18
|
+
- Nest FMUs in a [FMU Container](doc/container.md)
|
|
19
|
+
|
|
20
|
+
FMI versions 2.0 and 3.0 are supported.
|
|
10
21
|
|
|
11
22
|
## Installation
|
|
12
23
|
|
|
@@ -17,29 +28,39 @@ Two options available to install FMU Manipulation Toolbox:
|
|
|
17
28
|
- Compile and install from [github repository](https://github.com/grouperenault/fmu_manipulation_toolbox). You will need
|
|
18
29
|
- Python required packages. See [`requirements.txt`](requirements.txt).
|
|
19
30
|
- C compiler (C99 or later)
|
|
20
|
-
- CMake (>= 3.
|
|
31
|
+
- CMake (>= 3.20)
|
|
32
|
+
|
|
21
33
|
|
|
22
34
|
### Supported platforms
|
|
23
|
-
|
|
24
|
-
|
|
35
|
+
|
|
36
|
+
FMU Manipulation Toolbox is packaged for:
|
|
37
|
+
- Windows 10/11 (primary platform)
|
|
25
38
|
- Linux (Ubuntu 22.04)
|
|
39
|
+
- Darwin
|
|
26
40
|
|
|
27
|
-
Compilation is reported to work on:
|
|
28
|
-
- MacOS (Apple Silicon and Intel)
|
|
29
41
|
|
|
30
42
|
## Graphical User Interface
|
|
31
43
|
|
|
32
|
-
FMU Manipulation Toolbox is released with a GUI. You can launch it with the following command `fmutool`
|
|
33
|
-
(without any option)
|
|
44
|
+
FMU Manipulation Toolbox is released with a GUI. You can launch it with the following command `fmutool-gui`
|
|
34
45
|
|
|
35
46
|

|
|
36
47
|
|
|
48
|
+
Button colors descriptions:
|
|
49
|
+
- red: remove information from the `modelDescription.xml`
|
|
50
|
+
- orange: alter `modelDescription.xml`
|
|
51
|
+
- green: add component into the FMU or check it
|
|
52
|
+
- violet: extract and save
|
|
53
|
+
- blue: filter actions scope or exit
|
|
54
|
+
|
|
55
|
+
**Original FMU is never modified**. Use `Save` button to get modified copy of the original FMU.
|
|
56
|
+
|
|
37
57
|
|
|
38
58
|
## Command Line Interface
|
|
39
59
|
|
|
40
60
|
FMU Manipulation Toolbox comes with 2 commands:
|
|
41
61
|
- `fmutool`: a versatile analysis and manipulation tool for FMU.
|
|
42
|
-
- `fmucontainer`: group
|
|
62
|
+
- `fmucontainer`: group FMUs inside FMU Containers. (see [container/README.md](container/README.md))
|
|
63
|
+
- `fmusplit: to extract FMUs from a FMU Container.
|
|
43
64
|
|
|
44
65
|
|
|
45
66
|
### Analysis and Manipulation tool:
|
|
@@ -131,24 +152,29 @@ optional arguments:
|
|
|
131
152
|
### FMU Containers
|
|
132
153
|
|
|
133
154
|
```
|
|
134
|
-
usage: fmucontainer [-h] [-fmu-directory FMU_DIRECTORY] -
|
|
135
|
-
|
|
155
|
+
usage: fmucontainer [-h] [-fmu-directory FMU_DIRECTORY] [-fmi FMI_VERSION]
|
|
156
|
+
-container filename.{csv|json|ssp},[:step_size] [-debug] [-no-auto-input] [-no-auto-output]
|
|
157
|
+
[-auto-parameter] [-auto-local] [-no-auto-link] [-mt] [-profile] [-sequential] [-dump-json]
|
|
136
158
|
|
|
137
159
|
Generate FMU from FMU's
|
|
138
160
|
|
|
139
|
-
|
|
161
|
+
options:
|
|
140
162
|
-h, -help
|
|
141
163
|
-fmu-directory FMU_DIRECTORY Directory containing initial FMU’s and used to generate containers. If not defined,
|
|
142
164
|
current directory is used. (default: .)
|
|
165
|
+
-fmi FMI_VERSION Define version of FMI to be used for container interface.Only '2' or '3' is
|
|
166
|
+
supported. (default: 2)
|
|
143
167
|
-container filename.{csv|json|ssp},[:step_size]
|
|
144
168
|
Description of the container to create. (default: [])
|
|
145
169
|
-debug Add lot of useful log during the process. (default: False)
|
|
146
170
|
-no-auto-input Create ONLY explicit input. (default: True)
|
|
147
171
|
-no-auto-output Create ONLY explicit output. (default: True)
|
|
148
172
|
-auto-parameter Expose parameters of the embedded fmu's. (default: False)
|
|
173
|
+
-auto-local Expose local variables of the embedded fmu's. (default: False)
|
|
149
174
|
-no-auto-link Create ONLY explicit links. (default: True)
|
|
150
175
|
-mt Enable Multi-Threaded mode for the generated container. (default: False)
|
|
151
176
|
-profile Enable Profiling mode for the generated container. (default: False)
|
|
177
|
+
-sequential Use sequential mode to schedule embedded fmu's. (default: False)
|
|
152
178
|
-dump-json Dump a JSON file for each container. (default: False)
|
|
153
179
|
```
|
|
154
180
|
|
|
@@ -158,14 +184,13 @@ You can write your own FMU Manipulation scripts. Once you downloaded fmutool mod
|
|
|
158
184
|
adding the `import` statement lets you access the API :
|
|
159
185
|
|
|
160
186
|
```python
|
|
161
|
-
from fmu_manipulation_toolbox.operations import
|
|
162
|
-
|
|
163
|
-
OperationRenameFromCSV
|
|
187
|
+
from fmu_manipulation_toolbox.operations import ...
|
|
164
188
|
```
|
|
165
189
|
|
|
190
|
+
|
|
166
191
|
### remove toplevel bus (if any)
|
|
167
192
|
|
|
168
|
-
|
|
193
|
+
Given a FMU with the following I/O structure
|
|
169
194
|
```
|
|
170
195
|
├── Parameters
|
|
171
196
|
│ ├── Foo
|
|
@@ -189,6 +214,8 @@ The following transformation will lead into:
|
|
|
189
214
|
|
|
190
215
|
The following code will do this transformation:
|
|
191
216
|
```python
|
|
217
|
+
from fmu_manipulation_toolbox.operations import FMU, OperationStripTopLevel
|
|
218
|
+
|
|
192
219
|
fmu = FMU(r"bouncing_ball.fmu")
|
|
193
220
|
operation = OperationStripTopLevel()
|
|
194
221
|
fmu.apply_operation(operation)
|
|
@@ -200,8 +227,10 @@ fmu.repack(r"bouncing_ball-modified.fmu")
|
|
|
200
227
|
The following code will dump all FMU's Scalars names into a CSV:
|
|
201
228
|
|
|
202
229
|
```python
|
|
230
|
+
from fmu_manipulation_toolbox.operations import FMU, OperationSaveNamesToCSV
|
|
231
|
+
|
|
203
232
|
fmu = FMU(r"bouncing_ball.fmu")
|
|
204
|
-
operation =
|
|
233
|
+
operation = OperationSaveNamesToCSV()
|
|
205
234
|
fmu.apply_operation(operation)
|
|
206
235
|
operation.write_csv(r"bouncing_ball.csv")
|
|
207
236
|
```
|
|
@@ -219,15 +248,20 @@ g;g;4;parameter;fixed
|
|
|
219
248
|
e;e;5;parameter;tunable
|
|
220
249
|
```
|
|
221
250
|
|
|
251
|
+
|
|
222
252
|
### Read CSV and rename FMU ports
|
|
223
253
|
|
|
224
|
-
CSV file should contain
|
|
254
|
+
CSV file should contain 2 columns:
|
|
225
255
|
1. the current name
|
|
226
256
|
2. the new name
|
|
227
257
|
|
|
228
258
|
```python
|
|
259
|
+
from fmu_manipulation_toolbox.operations import FMU, OperationRenameFromCSV
|
|
260
|
+
|
|
229
261
|
fmu = FMU(r"bouncing_ball.fmu")
|
|
230
262
|
operation = OperationRenameFromCSV(r"bouncing_ball-modified.csv")
|
|
231
263
|
fmu.apply_operation(operation)
|
|
232
264
|
fmu.repack(r"bouncing_ball-renamed.fmu")
|
|
233
265
|
```
|
|
266
|
+
|
|
267
|
+
More operations exist in [`Operation.py`](fmu_manipulation_toolbox/operations.py)
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'V1.9'
|
|
@@ -37,7 +37,7 @@ class Connection:
|
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
class AssemblyNode:
|
|
40
|
-
def __init__(self, name: Optional[str], step_size: float = None, mt=False, profiling=False,
|
|
40
|
+
def __init__(self, name: Optional[str], step_size: float = None, mt=False, profiling=False, sequential=False,
|
|
41
41
|
auto_link=True, auto_input=True, auto_output=True, auto_parameter=False, auto_local=False):
|
|
42
42
|
self.name = name
|
|
43
43
|
if step_size:
|
|
@@ -50,6 +50,7 @@ class AssemblyNode:
|
|
|
50
50
|
self.step_size = None
|
|
51
51
|
self.mt = mt
|
|
52
52
|
self.profiling = profiling
|
|
53
|
+
self.sequential = sequential
|
|
53
54
|
self.auto_link = auto_link
|
|
54
55
|
self.auto_input = auto_input
|
|
55
56
|
self.auto_output = auto_output
|
|
@@ -100,12 +101,13 @@ class AssemblyNode:
|
|
|
100
101
|
def add_start_value(self, fmu_filename: str, port_name: str, value: str):
|
|
101
102
|
self.start_values[Port(fmu_filename, port_name)] = value
|
|
102
103
|
|
|
103
|
-
def make_fmu(self, fmu_directory: Path, debug=False, description_pathname=None):
|
|
104
|
+
def make_fmu(self, fmu_directory: Path, debug=False, description_pathname=None, fmi_version=2):
|
|
104
105
|
for node in self.children.values():
|
|
105
|
-
node.make_fmu(fmu_directory, debug=debug)
|
|
106
|
+
node.make_fmu(fmu_directory, debug=debug, fmi_version=fmi_version)
|
|
106
107
|
|
|
107
108
|
identifier = str(Path(self.name).stem)
|
|
108
|
-
container = FMUContainer(identifier, fmu_directory, description_pathname=description_pathname
|
|
109
|
+
container = FMUContainer(identifier, fmu_directory, description_pathname=description_pathname,
|
|
110
|
+
fmi_version=fmi_version)
|
|
109
111
|
|
|
110
112
|
for fmu_name in self.fmu_names_list:
|
|
111
113
|
container.get_fmu(fmu_name)
|
|
@@ -138,7 +140,8 @@ class AssemblyNode:
|
|
|
138
140
|
for link_rule in wired.rule_link:
|
|
139
141
|
self.add_link(link_rule[0], link_rule[1], link_rule[2], link_rule[3])
|
|
140
142
|
|
|
141
|
-
container.make_fmu(self.name, self.step_size, mt=self.mt, profiling=self.profiling,
|
|
143
|
+
container.make_fmu(self.name, self.step_size, mt=self.mt, profiling=self.profiling, sequential=self.sequential,
|
|
144
|
+
debug=debug)
|
|
142
145
|
|
|
143
146
|
for node in self.children.values():
|
|
144
147
|
logger.info(f"Deleting transient FMU Container '{node.name}'")
|
|
@@ -216,7 +219,7 @@ class AssemblyError(Exception):
|
|
|
216
219
|
|
|
217
220
|
|
|
218
221
|
class Assembly:
|
|
219
|
-
def __init__(self, filename: str, step_size=None, auto_link=True, auto_input=True, debug=False,
|
|
222
|
+
def __init__(self, filename: str, step_size=None, auto_link=True, auto_input=True, debug=False, sequential=False,
|
|
220
223
|
auto_output=True, mt=False, profiling=False, fmu_directory: Path = Path("."), auto_parameter=False,
|
|
221
224
|
auto_local=False):
|
|
222
225
|
self.filename = Path(filename)
|
|
@@ -228,6 +231,7 @@ class Assembly:
|
|
|
228
231
|
self.default_auto_parameter = auto_parameter
|
|
229
232
|
self.default_auto_local = auto_local
|
|
230
233
|
self.default_mt = mt
|
|
234
|
+
self.default_sequential = sequential
|
|
231
235
|
self.default_profiling = profiling
|
|
232
236
|
self.fmu_directory = fmu_directory
|
|
233
237
|
self.transient_filenames: List[Path] = []
|
|
@@ -238,7 +242,7 @@ class Assembly:
|
|
|
238
242
|
|
|
239
243
|
self.input_pathname = fmu_directory / self.filename
|
|
240
244
|
self.description_pathname = self.input_pathname # For inclusion in FMU
|
|
241
|
-
self.root = None
|
|
245
|
+
self.root: Optional[AssemblyNode] = None
|
|
242
246
|
self.read()
|
|
243
247
|
|
|
244
248
|
def add_transient_file(self, filename: str):
|
|
@@ -283,8 +287,9 @@ class Assembly:
|
|
|
283
287
|
name = str(self.filename.with_suffix(".fmu"))
|
|
284
288
|
self.root = AssemblyNode(name, step_size=self.default_step_size, auto_link=self.default_auto_link,
|
|
285
289
|
mt=self.default_mt, profiling=self.default_profiling,
|
|
286
|
-
|
|
287
|
-
|
|
290
|
+
sequential=self.default_sequential, auto_input=self.default_auto_input,
|
|
291
|
+
auto_output=self.default_auto_output, auto_parameter=self.default_auto_parameter,
|
|
292
|
+
auto_local=self.default_auto_local)
|
|
288
293
|
|
|
289
294
|
with open(self.input_pathname) as file:
|
|
290
295
|
reader = csv.reader(file, delimiter=';')
|
|
@@ -385,6 +390,7 @@ class Assembly:
|
|
|
385
390
|
name = data.get("name", None) # 1
|
|
386
391
|
mt = data.get("mt", self.default_mt) # 2
|
|
387
392
|
profiling = data.get("profiling", self.default_profiling) # 3
|
|
393
|
+
sequential = data.get("sequential", self.default_sequential) # 3b
|
|
388
394
|
auto_link = data.get("auto_link", self.default_auto_link) # 4
|
|
389
395
|
auto_input = data.get("auto_input", self.default_auto_input) # 5
|
|
390
396
|
auto_output = data.get("auto_output", self.default_auto_output) # 6
|
|
@@ -393,11 +399,12 @@ class Assembly:
|
|
|
393
399
|
step_size = data.get("step_size", self.default_step_size) # 7
|
|
394
400
|
|
|
395
401
|
node = AssemblyNode(name, step_size=step_size, auto_link=auto_link, mt=mt, profiling=profiling,
|
|
402
|
+
sequential=sequential,
|
|
396
403
|
auto_input=auto_input, auto_output=auto_output, auto_parameter=auto_parameter,
|
|
397
404
|
auto_local=auto_local)
|
|
398
405
|
|
|
399
406
|
for key, value in data.items():
|
|
400
|
-
if key in ('name', 'step_size', 'auto_link', 'auto_input', 'auto_output', 'mt', 'profiling',
|
|
407
|
+
if key in ('name', 'step_size', 'auto_link', 'auto_input', 'auto_output', 'mt', 'profiling', 'sequential',
|
|
401
408
|
'auto_parameter', 'auto_local'):
|
|
402
409
|
continue # Already read
|
|
403
410
|
|
|
@@ -455,6 +462,7 @@ class Assembly:
|
|
|
455
462
|
json_node["name"] = node.name # 1
|
|
456
463
|
json_node["mt"] = node.mt # 2
|
|
457
464
|
json_node["profiling"] = node.profiling # 3
|
|
465
|
+
json_node["sequential"] = node.sequential # 3b
|
|
458
466
|
json_node["auto_link"] = node.auto_link # 4
|
|
459
467
|
json_node["auto_input"] = node.auto_input # 5
|
|
460
468
|
json_node["auto_output"] = node.auto_output # 6
|
|
@@ -510,8 +518,9 @@ class Assembly:
|
|
|
510
518
|
self.root = sdd.parse(self.description_pathname)
|
|
511
519
|
self.root.name = str(self.filename.with_suffix(".fmu"))
|
|
512
520
|
|
|
513
|
-
def make_fmu(self, dump_json=False):
|
|
514
|
-
self.root.make_fmu(self.fmu_directory, debug=self.debug, description_pathname=self.description_pathname
|
|
521
|
+
def make_fmu(self, dump_json=False, fmi_version=2):
|
|
522
|
+
self.root.make_fmu(self.fmu_directory, debug=self.debug, description_pathname=self.description_pathname,
|
|
523
|
+
fmi_version=fmi_version)
|
|
515
524
|
if dump_json:
|
|
516
525
|
dump_file = Path(self.input_pathname.stem + "-dump").with_suffix(".json")
|
|
517
526
|
logger.info(f"Dump Json '{dump_file}'")
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import importlib.util
|
|
2
2
|
import inspect
|
|
3
|
+
import logging
|
|
3
4
|
import os
|
|
4
5
|
import xmlschema
|
|
5
6
|
from xmlschema.validators.exceptions import XMLSchemaValidationError
|
|
6
7
|
from .operations import OperationAbstract
|
|
7
8
|
|
|
9
|
+
logger = logging.getLogger("fmu_manipulation_toolbox")
|
|
10
|
+
|
|
8
11
|
|
|
9
12
|
class OperationGenericCheck(OperationAbstract):
|
|
10
13
|
SUPPORTED_FMI_VERSIONS = ('2.0', '3.0')
|
|
@@ -17,7 +20,7 @@ class OperationGenericCheck(OperationAbstract):
|
|
|
17
20
|
|
|
18
21
|
def fmi_attrs(self, attrs):
|
|
19
22
|
if attrs['fmiVersion'] not in self.SUPPORTED_FMI_VERSIONS:
|
|
20
|
-
|
|
23
|
+
logger.error(f"Expected FMI {','.join(self.SUPPORTED_FMI_VERSIONS)} versions.")
|
|
21
24
|
return
|
|
22
25
|
|
|
23
26
|
fmi_name = f"fmi{attrs['fmiVersion'][0]}"
|
|
@@ -27,15 +30,15 @@ class OperationGenericCheck(OperationAbstract):
|
|
|
27
30
|
try:
|
|
28
31
|
xmlschema.validate(self.fmu.descriptor_filename, schema=xsd_filename)
|
|
29
32
|
except XMLSchemaValidationError as error:
|
|
30
|
-
|
|
33
|
+
logger.error(error.reason, error.msg)
|
|
31
34
|
else:
|
|
32
35
|
self.compliant_with_version = attrs['fmiVersion']
|
|
33
36
|
|
|
34
37
|
def closure(self):
|
|
35
38
|
if self.compliant_with_version:
|
|
36
|
-
|
|
39
|
+
logger.info(f"This FMU seems to be compliant with FMI-{self.compliant_with_version}.")
|
|
37
40
|
else:
|
|
38
|
-
|
|
41
|
+
logger.error(f"This FMU does not validate with FMI standard.")
|
|
39
42
|
|
|
40
43
|
|
|
41
44
|
checker_list = [OperationGenericCheck]
|
|
@@ -44,20 +47,20 @@ checker_list = [OperationGenericCheck]
|
|
|
44
47
|
def add_from_file(checker_filename: str):
|
|
45
48
|
spec = importlib.util.spec_from_file_location(checker_filename, checker_filename)
|
|
46
49
|
if not spec:
|
|
47
|
-
|
|
50
|
+
logger.error(f"Cannot load '{checker_filename}'. Is this a python file?")
|
|
48
51
|
return
|
|
49
52
|
try:
|
|
50
53
|
checker_module = importlib.util.module_from_spec(spec)
|
|
51
54
|
try:
|
|
52
55
|
spec.loader.exec_module(checker_module)
|
|
53
56
|
except (ModuleNotFoundError, SyntaxError) as error:
|
|
54
|
-
|
|
57
|
+
logger.error(f"Cannot load '{checker_filename}': {error})")
|
|
55
58
|
return
|
|
56
59
|
|
|
57
60
|
for checker_name, checker_class in inspect.getmembers(checker_module, inspect.isclass):
|
|
58
61
|
if OperationAbstract in checker_class.__bases__:
|
|
59
62
|
checker_list.append(checker_class)
|
|
60
|
-
|
|
63
|
+
logger.info(f"Adding checker: {checker_filename}|{checker_name}")
|
|
61
64
|
|
|
62
65
|
except AttributeError:
|
|
63
|
-
|
|
66
|
+
logger.error(f"'{checker_filename}' should implement class 'OperationCheck'")
|
|
File without changes
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import logging
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
from typing import *
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from .utils import setup_logger, make_wide
|
|
9
|
+
from ..assembly import Assembly, AssemblyError
|
|
10
|
+
from ..container import FMUContainerError
|
|
11
|
+
from ..version import __version__ as version
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def fmucontainer(command_options: Sequence[str]):
|
|
15
|
+
logger = setup_logger()
|
|
16
|
+
|
|
17
|
+
logger.info(f"FMUContainer version {version}")
|
|
18
|
+
parser = argparse.ArgumentParser(prog="fmucontainer", description="Generate FMU from FMU's",
|
|
19
|
+
formatter_class=make_wide(argparse.ArgumentDefaultsHelpFormatter),
|
|
20
|
+
add_help=False,
|
|
21
|
+
epilog="see: https://github.com/grouperenault/fmu_manipulation_toolbox/blob/main/"
|
|
22
|
+
"container/README.md")
|
|
23
|
+
|
|
24
|
+
parser.add_argument('-h', '-help', action="help")
|
|
25
|
+
|
|
26
|
+
parser.add_argument("-fmu-directory", action="store", dest="fmu_directory", required=False, default=".",
|
|
27
|
+
help="Directory containing initial FMU’s and used to generate containers. "
|
|
28
|
+
"If not defined, current directory is used.")
|
|
29
|
+
|
|
30
|
+
parser.add_argument("-fmi", action="store", dest="fmi_version", required=False, default="2",
|
|
31
|
+
help="Define version of FMI to be used for container interface."
|
|
32
|
+
"Only '2' or '3' is supported.")
|
|
33
|
+
|
|
34
|
+
parser.add_argument("-container", action="append", dest="container_descriptions_list", default=[],
|
|
35
|
+
metavar="filename.{csv|json|ssp},[:step_size]", required=True,
|
|
36
|
+
help="Description of the container to create.")
|
|
37
|
+
|
|
38
|
+
parser.add_argument("-debug", action="store_true", dest="debug",
|
|
39
|
+
help="Add lot of useful log during the process.")
|
|
40
|
+
|
|
41
|
+
parser.add_argument("-no-auto-input", action="store_false", dest="auto_input", default=True,
|
|
42
|
+
help="Create ONLY explicit input.")
|
|
43
|
+
|
|
44
|
+
parser.add_argument("-no-auto-output", action="store_false", dest="auto_output", default=True,
|
|
45
|
+
help="Create ONLY explicit output.")
|
|
46
|
+
|
|
47
|
+
parser.add_argument("-auto-parameter", action="store_true", dest="auto_parameter", default=False,
|
|
48
|
+
help="Expose parameters of the embedded fmu's.")
|
|
49
|
+
|
|
50
|
+
parser.add_argument("-auto-local", action="store_true", dest="auto_local", default=False,
|
|
51
|
+
help="Expose local variables of the embedded fmu's.")
|
|
52
|
+
|
|
53
|
+
parser.add_argument("-no-auto-link", action="store_false", dest="auto_link", default=True,
|
|
54
|
+
help="Create ONLY explicit links.")
|
|
55
|
+
|
|
56
|
+
parser.add_argument("-mt", action="store_true", dest="mt", default=False,
|
|
57
|
+
help="Enable Multi-Threaded mode for the generated container.")
|
|
58
|
+
|
|
59
|
+
parser.add_argument("-profile", action="store_true", dest="profiling", default=False,
|
|
60
|
+
help="Enable Profiling mode for the generated container.")
|
|
61
|
+
|
|
62
|
+
parser.add_argument("-sequential", action="store_true", dest="sequential", default=False,
|
|
63
|
+
help="Use sequential mode to schedule embedded fmu's.")
|
|
64
|
+
|
|
65
|
+
parser.add_argument("-dump-json", action="store_true", dest="dump", default=False,
|
|
66
|
+
help="Dump a JSON file for each container.")
|
|
67
|
+
|
|
68
|
+
config = parser.parse_args(command_options)
|
|
69
|
+
|
|
70
|
+
if config.debug:
|
|
71
|
+
logger.setLevel(logging.DEBUG)
|
|
72
|
+
|
|
73
|
+
fmu_directory = Path(config.fmu_directory)
|
|
74
|
+
logger.info(f"FMU directory: '{fmu_directory}'")
|
|
75
|
+
|
|
76
|
+
for description in config.container_descriptions_list:
|
|
77
|
+
try:
|
|
78
|
+
tokens = description.split(":")
|
|
79
|
+
filename = ":".join(tokens[:-1])
|
|
80
|
+
step_size = float(tokens[-1])
|
|
81
|
+
except ValueError:
|
|
82
|
+
step_size = None
|
|
83
|
+
filename = description
|
|
84
|
+
|
|
85
|
+
try:
|
|
86
|
+
assembly = Assembly(filename, step_size=step_size, auto_link=config.auto_link,
|
|
87
|
+
auto_input=config.auto_input, auto_output=config.auto_output,
|
|
88
|
+
auto_local=config.auto_local, mt=config.mt, sequential=config.sequential,
|
|
89
|
+
profiling=config.profiling, fmu_directory=fmu_directory, debug=config.debug,
|
|
90
|
+
auto_parameter=config.auto_parameter)
|
|
91
|
+
except FileNotFoundError as e:
|
|
92
|
+
logger.fatal(f"Cannot read file: {e}")
|
|
93
|
+
sys.exit(-1)
|
|
94
|
+
except (FMUContainerError, AssemblyError) as e:
|
|
95
|
+
logger.fatal(f"{filename}: {e}")
|
|
96
|
+
sys.exit(-2)
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
assembly.make_fmu(dump_json=config.dump, fmi_version=int(config.fmi_version))
|
|
100
|
+
except FMUContainerError as e:
|
|
101
|
+
logger.fatal(f"{filename}: {e}")
|
|
102
|
+
sys.exit(-3)
|
|
103
|
+
|
|
104
|
+
if __name__ == "__main__":
|
|
105
|
+
fmucontainer(sys.argv[1:])
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import logging
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
from typing import *
|
|
6
|
+
|
|
7
|
+
from .utils import setup_logger, make_wide
|
|
8
|
+
from ..split import FMUSplitter, FMUSplitterError
|
|
9
|
+
from ..version import __version__ as version
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def fmusplit(command_options: Sequence[str]):
|
|
13
|
+
logger = setup_logger()
|
|
14
|
+
|
|
15
|
+
logger.info(f"FMUSplit version {version}")
|
|
16
|
+
parser = argparse.ArgumentParser(prog="fmusplit", description="Split FMU Container into FMU's",
|
|
17
|
+
formatter_class=make_wide(argparse.ArgumentDefaultsHelpFormatter),
|
|
18
|
+
add_help=False,
|
|
19
|
+
epilog="see: https://github.com/grouperenault/fmu_manipulation_toolbox/blob/main/"
|
|
20
|
+
"container/README.md")
|
|
21
|
+
parser.add_argument('-h', '-help', action="help")
|
|
22
|
+
|
|
23
|
+
parser.add_argument("-debug", action="store_true", dest="debug",
|
|
24
|
+
help="Add lot of useful log during the process.")
|
|
25
|
+
|
|
26
|
+
parser.add_argument("-fmu", action="append", dest="fmu_filename_list", default=[],
|
|
27
|
+
metavar="filename.fmu", required=True,
|
|
28
|
+
help="Description of the FMU container to split.")
|
|
29
|
+
|
|
30
|
+
config = parser.parse_args(command_options)
|
|
31
|
+
|
|
32
|
+
if config.debug:
|
|
33
|
+
logger.setLevel(logging.DEBUG)
|
|
34
|
+
|
|
35
|
+
for fmu_filename in config.fmu_filename_list:
|
|
36
|
+
try:
|
|
37
|
+
splitter = FMUSplitter(fmu_filename)
|
|
38
|
+
splitter.split_fmu()
|
|
39
|
+
except FMUSplitterError as e:
|
|
40
|
+
logger.fatal(f"{fmu_filename}: {e}")
|
|
41
|
+
sys.exit(-1)
|
|
42
|
+
except FileNotFoundError as e:
|
|
43
|
+
logger.fatal(f"Cannot read file: {e}")
|
|
44
|
+
sys.exit(-2)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
if __name__ == "__main__":
|
|
48
|
+
fmusplit(sys.argv[1:])
|