fameio 1.8.2__py3-none-any.whl → 2.0.0__py3-none-any.whl

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.
Files changed (46) hide show
  1. CHANGELOG.md +204 -0
  2. fameio/scripts/__init__.py +8 -6
  3. fameio/scripts/__init__.py.license +3 -0
  4. fameio/scripts/convert_results.py +30 -34
  5. fameio/scripts/convert_results.py.license +3 -0
  6. fameio/scripts/make_config.py +13 -16
  7. fameio/scripts/make_config.py.license +3 -0
  8. fameio/source/cli/__init__.py +3 -0
  9. fameio/source/cli/convert_results.py +75 -0
  10. fameio/source/cli/make_config.py +62 -0
  11. fameio/source/cli/options.py +59 -0
  12. fameio/source/cli/parser.py +238 -0
  13. fameio/source/loader.py +10 -11
  14. fameio/source/logs.py +49 -25
  15. fameio/source/results/conversion.py +11 -13
  16. fameio/source/results/csv_writer.py +16 -5
  17. fameio/source/results/data_transformer.py +3 -2
  18. fameio/source/results/input_dao.py +163 -0
  19. fameio/source/results/reader.py +25 -14
  20. fameio/source/results/yaml_writer.py +28 -0
  21. fameio/source/scenario/agent.py +56 -39
  22. fameio/source/scenario/attribute.py +9 -12
  23. fameio/source/scenario/contract.py +55 -40
  24. fameio/source/scenario/exception.py +11 -9
  25. fameio/source/scenario/generalproperties.py +11 -17
  26. fameio/source/scenario/scenario.py +19 -14
  27. fameio/source/schema/agenttype.py +75 -27
  28. fameio/source/schema/attribute.py +8 -7
  29. fameio/source/schema/schema.py +24 -11
  30. fameio/source/series.py +146 -25
  31. fameio/source/time.py +8 -8
  32. fameio/source/tools.py +13 -2
  33. fameio/source/validator.py +138 -58
  34. fameio/source/writer.py +108 -112
  35. fameio-2.0.0.dist-info/LICENSES/Apache-2.0.txt +178 -0
  36. fameio-2.0.0.dist-info/LICENSES/CC-BY-4.0.txt +395 -0
  37. fameio-2.0.0.dist-info/LICENSES/CC0-1.0.txt +121 -0
  38. {fameio-1.8.2.dist-info → fameio-2.0.0.dist-info}/METADATA +694 -660
  39. fameio-2.0.0.dist-info/RECORD +52 -0
  40. {fameio-1.8.2.dist-info → fameio-2.0.0.dist-info}/WHEEL +1 -2
  41. fameio-2.0.0.dist-info/entry_points.txt +4 -0
  42. fameio/source/cli.py +0 -253
  43. fameio-1.8.2.dist-info/RECORD +0 -40
  44. fameio-1.8.2.dist-info/entry_points.txt +0 -3
  45. fameio-1.8.2.dist-info/top_level.txt +0 -1
  46. {fameio-1.8.2.dist-info → fameio-2.0.0.dist-info}/LICENSE.txt +0 -0
@@ -1,660 +1,694 @@
1
- Metadata-Version: 2.1
2
- Name: fameio
3
- Version: 1.8.2
4
- Summary: Python scripts for operation of FAME models
5
- Home-page: https://gitlab.com/fame-framework/fame-io/
6
- Author: Felix Nitsch, Christoph Schimeczek, Ulrich Frey, Marc Deissenroth-Uhrig, Benjamin Fuchs, A. Achraf El Ghazi
7
- Author-email: fame@dlr.de
8
- License: Apache License 2.0
9
- Keywords: FAME,agent-based modelling
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: License :: OSI Approved :: Apache Software License
12
- Classifier: Operating System :: OS Independent
13
- Requires-Python: >=3.8
14
- Description-Content-Type: text/markdown
15
- License-File: LICENSE.txt
16
- Requires-Dist: pandas
17
- Requires-Dist: fameprotobuf <1.3,>=1.2
18
- Requires-Dist: pyyaml
19
- Provides-Extra: dev
20
- Requires-Dist: pytest ; extra == 'dev'
21
- Requires-Dist: mockito ; extra == 'dev'
22
- Requires-Dist: pre-commit ; extra == 'dev'
23
-
24
- <!-- SPDX-FileCopyrightText: 2023 German Aerospace Center <fame@dlr.de>
25
-
26
- SPDX-License-Identifier: Apache-2.0 -->
27
- [![PyPI version](https://badge.fury.io/py/fameio.svg)](https://badge.fury.io/py/fameio)
28
- [![JOSS](https://joss.theoj.org/papers/10.21105/joss.04958/status.svg)](https://doi.org/10.21105/joss.04958)
29
- [![Zenodo](https://zenodo.org/badge/DOI/10.5281/zenodo.4314337.svg)](https://doi.org/10.5281/zenodo.4314337)
30
- [![PyPI license](https://img.shields.io/pypi/l/fameio.svg)](https://badge.fury.io/py/fameio)
31
- [![pipeline status](https://gitlab.com/fame-framework/fame-io/badges/main/pipeline.svg)](https://gitlab.com/fame-framework/fame-io/commits/main)
32
- [![coverage report](https://gitlab.com/fame-framework/fame-io/badges/main/coverage.svg)](https://gitlab.com/fame-framework/fame-io/-/commits/main)
33
- [![REUSE status](https://api.reuse.software/badge/gitlab.com/fame-framework/fame-io)](https://api.reuse.software/info/gitlab.com/fame-framework/fame-io)
34
-
35
- # FAME-Io
36
- Python scripts for FAME models, generation of protobuf input files and conversion of protobuf output files.
37
- Please visit the [FAME-Wiki](https://gitlab.com/fame-framework/wiki/-/wikis/home) to get an explanation of FAME and its components.
38
- The package is also formerly known as [FAME-Py](https://doi.org/10.5281/zenodo.4314338).
39
-
40
- # Installation
41
-
42
- We recommend installing `fameio` using PyPI:
43
-
44
- pip install fameio
45
-
46
- You may also use `pipx`. For detailed information please refer to the official `pipx` [documentation](https://github.com/pypa/pipx).
47
-
48
- pipx install fameio
49
-
50
- `fameio` is currently developed and tested for Python 3.8 or higher.
51
- See the `setup.py` for a complete listing of dependencies.
52
-
53
- # Usage
54
-
55
- FAME-Io currently offers two main scripts `makeFameRunConfig` and `convertFameResults`.
56
- Both are automatically installed with the package.
57
- The first one creates a protobuf file for FAME applications using YAML definition files and CSV files.
58
- The latter one reads output files from FAME applications in protobuf format and converts them to CSV files.
59
-
60
- You may use the [example data](https://gitlab.com/dlr-ve/esy/amiris/examples) provided for the [AMIRIS](https://gitlab.com/dlr-ve/esy/amiris/amiris) model which can be used to simulate electricity markets in [Germany](https://gitlab.com/dlr-ve/esy/amiris/examples/-/tree/main/Germany2019), [Austria](https://gitlab.com/dlr-ve/esy/amiris/examples/-/tree/main/Austria2019), and a simple [proof-of-concept model](https://gitlab.com/dlr-ve/esy/amiris/examples/-/tree/main/Simple).
61
-
62
- ## Make a FAME run configuration
63
- Digests configuration files in YAML format, combines them with CSV data files and creates a single input file for FAME applications in protobuf format.
64
- Call structure:
65
-
66
- makeFameRunConfig -f <path/to/scenario.yaml>
67
-
68
- You may also specify any of the following arguments:
69
-
70
- | Command | Action |
71
- |----------------------|-----------------------------------------------------------------------------------------------------------------|
72
- | `-l` or `--log` | Sets the logging level. Default is `info`. Options are `debug`, `info`, `warning`, `warn`, `error`, `critical`. |
73
- | `-lf` or `--logfile` | Sets the logging file. Default is `None`. If `None` is provided, all logs get only printed to the console. |
74
- | `-o` or `--output` | Sets the path of the compiled protobuf output file. Default is `config.pb`. |
75
-
76
- This could look as follows:
77
-
78
- makeFameRunConfig -f <path/to/scenario.yaml> -l debug -lf <path/to/scenario.log> -o <path/to/config.pb>
79
-
80
-
81
- You may also call the configuration builder from any Python script with
82
-
83
- ```python
84
- from fameio.scripts.make_config import run as make_config
85
-
86
- make_config("path/to/scenario.yaml")
87
- ```
88
-
89
- Similar to the console call you may also specify custom run config arguments and add it in a dictionary to the function call.
90
-
91
- ```python
92
- from fameio.scripts.make_config import run as make_config
93
- from fameio.source.cli import Options
94
-
95
- run_config = {Options.LOG_LEVEL: "info",
96
- Options.OUTPUT: "output.pb",
97
- Options.LOG_FILE: "scenario.log",
98
- }
99
-
100
- make_config("path/to/scenario.yaml", run_config)
101
- ```
102
-
103
- ### Scenario YAML
104
- The "scenario.yaml" file contains all configuration options for a FAME-based simulation.
105
- It consists of the sections `Schema`, `GeneralProperties`, `Agents` and `Contracts`, all of them described below.
106
-
107
- #### Schema
108
- The Schema is used to validate the inputs of the "scenario.yaml".
109
- Since the Schema should be valid across multiple scenarios, it is recommended to defined it in a separate file and include the file here.
110
-
111
- Currently, the schema specifies:
112
- * which type of Agents can be created
113
- * what type of input attributes an Agent uses
114
- * what type of Products an Agent can send in Contracts.
115
-
116
- The Schema consists of the sections `Header` and `AgentTypes`.
117
-
118
- ##### Header
119
- Scientific applications often evolve, and so do their required input parameters.
120
- Therefore, the header specifies information what FAME-based application the schema is corresponding to.
121
- In this way a schema.yaml is tied to a specific version an application, ensuring a match between the inputs required by the application, and those provided by the files created with FAME-Io.
122
-
123
- ```yaml
124
- Header:
125
- Project: MyProjectName
126
- RepoUrl: https://mygithosting.com/myProject
127
- CommitHash: abc123
128
- ```
129
-
130
- * `Project` name of your project / FAME-based application
131
- * `RepoUrl` URL of your project
132
- * `CommitHash` hash of the commit / version of your project
133
-
134
- ##### AgentTypes
135
- Here, each type of agent that can be created in your FAME-based application is listed, its attributes and its available Products for Contracts.
136
- The structure of this section
137
-
138
- ```yaml
139
- AgentTypes:
140
- MyAgentType:
141
- Attributes:
142
- MyAttribute:
143
- ...
144
- MyOtherAttribute:
145
- ...
146
- Products: [ 'Product1', 'Product2', 'Product3' ]
147
- MyOtherAgentWithoutProductsOrAttributes:
148
- ```
149
-
150
- * `MyAgentType` Java's simple class name of the Agent type
151
- * `Attributes` indicates that beginning of the attribute definition section for this Agent type
152
- * `MyAttribute` Name of an attribute as specified in the corresponding Java source code of this Agent type (annotated with "@Input")
153
- * `MyOtherAttribute` Name of another attribute derived from Java source code
154
- * `Products` list of Products that this Agent can send in Contracts; derived from Java source code of this Agent type (annotated with "@Product")
155
- * `MyOtherAgentWithoutProductsOrAttributes` an Agent type that requires neither Attributes nor Products
156
-
157
- Both Attributes and Products are optional - there could be useful Agents that require neither of them.
158
- In the above example attribute definition was not shown (indicated by `...`).
159
- The next example provides details on how to define an attribute:
160
-
161
- ```yaml
162
- MySimpleAttribute:
163
- AttributeType: enum
164
- Mandatory: true
165
- List: false
166
- Values: [ 'AllowedValue1', 'AllowedValue2' ]
167
- Default: 'AllowedValue1'
168
- Help: 'My help text'
169
-
170
- MyComplexAttribute:
171
- AttributeType: block
172
- NestedAttributes:
173
- InnerAttributeA:
174
- AttributeType: integer
175
- InnerAttributeB:
176
- AttributeType: double
177
- ```
178
-
179
- * `MySimpleAttribute`, `MyDoubleList`, `MyComplexAttribute` Names of the attributes as specified in the Java enum annotated with "@Input"
180
- * `AttributeType` (required) data type of the attribute; see options in table below
181
- * `Mandatory` (optional - true by default) if true: the attribute is required for this agent and validation will fail if the attribute is missing in the scenario **and** no default is provided
182
- * `List` (optional - false by default)
183
- * `AttributeType: time_series` cannot be true
184
- * `AttributeType: block`
185
- * if true: any nested element in the scenario must be part of a list element and thus can appear multiple times
186
- * if false: any nested element in the scenario can only appear once
187
- * any other AttributeType: the attribute is interpreted as list, i.e. multiple values can be assigned to this attribute in the scenario
188
- * `NestedAttributes` (required only if `AttributeType: block`, otherwise disallowed) starts an inner Attribute definition block - defined Attributes are sub-elements of `MyComplexAttribute`
189
- * `Values` (optional - None by default): if present defines a list of allowed values for this attribute
190
- * `Default` (optional - None by default): if present defines a default value to be used in case the scenario does not specify it
191
- * `Help` (optional - None by default): if present defines a help text to you attribute
192
-
193
- | AttributeType | value |
194
- |-----------------|-------------------------------------------------------------------------------------------------------------------------|
195
- | `integer` | a 32-bit integer value |
196
- | `double` | a 64-bit floating-point value (integers also allowed) |
197
- | `long` | a 64-bit integer value |
198
- | `time_stamp` | either a FAME time stamp string or 64-bit integer value |
199
- | `string` | any string |
200
- | `enum` | any string, however, usually tied to a set of allowed `Values` |
201
- | `time_series` | either a path to a .csv-file or a single 64-bit floating-point value; does not support `List: true` |
202
- | `block` | this attribute has no value of its own but hosts a group of nested Attributes; implies `NestedAttributes` to be defined |
203
-
204
- #### GeneralProperties
205
- Specifies FAME-specific properties of the simulation. Structure:
206
-
207
- ```yaml
208
- GeneralProperties:
209
- RunId: 1
210
- Simulation:
211
- StartTime: 2011-12-31_23:58:00
212
- StopTime: 2012-12-30_23:58:00
213
- RandomSeed: 1
214
- Output:
215
- Interval: 100
216
- Process: 0
217
- ```
218
-
219
- Parameters:
220
- * `RunId` an ID that can be given to the simulation; use at your discretion
221
- * `StartTime` time stamp in the format YYYY-MM-DD_hh:mm:ss; first moment of the simulation.
222
- * `StopTime` time stamp in the format YYYY-MM-DD_hh:mm:ss; last moment of the simulation - i.e. simulation terminates after passing that time stamp
223
- * `RandomSeed` seed to initialise random number generation; each value leads to a unique series of random numbers.
224
- * `Interval` number of simulation ticks in between write-to-disk events; may be used for performance optimisations;
225
- * `Process` id of process that performs write-to-disk operations; leave at 0 to be compatible with single-processes;
226
-
227
- #### Agents
228
- Specifies all Agents to be created in the simulation in a list. Each Agent has its own entry.
229
- Structure:
230
- ```yaml
231
- Agents:
232
- - Type: MyAgentWithInputs
233
- Id: 1
234
- Attributes:
235
- MyEnum: SAME_SHARES
236
- MyInteger: 2
237
- MyDouble: 4.2
238
- MyTimeSeries: "./path/to/time_series.csv"
239
-
240
- - Type: MyAgentWithoutInputs
241
- Id: 2
242
- ```
243
-
244
- Agent Parameters:
245
- * `Type` Mandatory; Java's simple class name of the agent to be created
246
- * `Id` Mandatory; simulation-unique id of this agent; if two agents have the same ID, the configuration process will stop.
247
- * `Attributes` Optional; if the agent has any attributes, specify them here in the format "AttributeName: value"; please see attribute table above
248
-
249
- The specified `Attributes` for each agent must match the specified `Attributes` options in the linked Schema (see above).
250
- For better structure and readability of the `scenario.yaml`, `Attributes` may also be specified in a nested way as demonstrated below.
251
-
252
- ```yaml
253
- Agents:
254
- - Type: MyAgentWithInputs
255
- Id: 1
256
- Attributes:
257
- Parent:
258
- MyEnum: SAME_SHARES
259
- MyInteger: 2
260
- Parent2:
261
- MyDouble: 4.2
262
- Child:
263
- MyTimeSeries: "./path/to/time_series.csv"
264
- ```
265
-
266
- In case Attributes are defined with `List: true` option, lists are assigned to an Attribute or Group:
267
-
268
- ```yaml
269
- Attributes:
270
- MyDoubleList: [5.2, 4.5, 7, 9.9]
271
- MyListGroup:
272
- - IntValueA: 5
273
- IntValueB: 42
274
- - IntValueA: 7
275
- IntValueB: 100
276
- ```
277
-
278
- Here, `MyDoubleList` and `MyListGroup` need to specify `List: true` in the corresponding Schema.
279
- The shorter `[]`-notation was used to assign a list of floating-point values to `MyDoubleList`.
280
- Nested items `IntValueA` and `IntValueB` of `MyListGroup` are assigned within a list, allowing the specification of these nested items several times.
281
-
282
- #### Contracts
283
- Specifies all Contracts, i.e. repetitive bilateral transactions in between agents.
284
- Contracts are given as a list.
285
- We recommend moving Contracts to separate files and to use the `!include` command to integrate them in the scenario.
286
-
287
- ```yaml
288
- Contracts:
289
- - SenderId: 1
290
- ReceiverId: 2
291
- ProductName: ProductOfAgent_1
292
- FirstDeliveryTime: -25
293
- DeliveryIntervalInSteps: 3600
294
-
295
- - SenderId: 2
296
- ReceiverId: 1
297
- ProductName: ProductOfAgent_2
298
- FirstDeliveryTime: -22
299
- DeliveryIntervalInSteps: 3600
300
- Attributes:
301
- ProductAppendix: value
302
- TimeOffset: 42
303
- ```
304
-
305
- Contract Parameters:
306
- * `SenderId` unique ID of agent sending the product
307
- * `ReceiverId` unique ID of agent receiving the product
308
- * `ProductName` name of the product to be sent
309
- * `FirstDeliveryTime` first time of delivery in the format "seconds after the January 1st 2000, 00:00:00"
310
- * `DeliveryIntervalInSteps` delay time in between deliveries in seconds
311
- * `Attributes` can be set to include additional information as `int`, `float`, `enum` or `dict` data types
312
-
313
- ##### Definition of Multiple Similar Contracts
314
- Often, scenarios contain multiple agents of similar type that also have similar chains of contracts.
315
- Therefore, FAME-Io supports a compact definition of multiple similar contracts.
316
- `SenderId` and `ReceiverId` can both be lists and support One-to-N, N-to-One and N-to-N relations like in the following example:
317
-
318
- ```yaml
319
- Contracts:
320
- # effectively 3 similar contracts (0 -> 11), (0 -> 12), (0 -> 13)
321
- # with otherwise identical ProductName, FirstDeliveryTime & DeliveryIntervalInSteps
322
- - SenderId: 0
323
- ReceiverId: [11, 12, 13]
324
- ProductName: MyOtherProduct
325
- FirstDeliveryTime: 100
326
- DeliveryIntervalInSteps: 3600
327
-
328
- # effectively 3 similar contracts (1 -> 10), (2 -> 10), (3 -> 10)
329
- # with otherwise identical ProductName, FirstDeliveryTime & DeliveryIntervalInSteps
330
- - SenderId: [1, 2, 3]
331
- ReceiverId: 10
332
- ProductName: MyProduct
333
- FirstDeliveryTime: 100
334
- DeliveryIntervalInSteps: 3600
335
-
336
- # effectively 3 similar contracts (1 -> 11), (2 -> 12), (3 -> 13)
337
- # with otherwise identical ProductName, FirstDeliveryTime & DeliveryIntervalInSteps
338
- - SenderId: [1, 2, 3]
339
- ReceiverId: [11, 12, 13]
340
- ProductName: MyThirdProduct
341
- FirstDeliveryTime: 100
342
- DeliveryIntervalInSteps: 3600
343
- ```
344
-
345
- Combined with YAML anchors complex contract chains can be easily reduced to a minimum of required configuration.
346
- The following example is equivalent to the previous one and allows a quick extension of contracts to a new couple of agents e.g. (4;14):
347
-
348
- ```yaml
349
- Groups:
350
- - &agentList1: [1,2,3]
351
- - &agentList2: [11,12,13]
352
-
353
- Contracts:
354
- - SenderId: 0
355
- ReceiverId: *agentList2
356
- ProductName: MyOtherProduct
357
- FirstDeliveryTime: 100
358
- DeliveryIntervalInSteps: 3600
359
-
360
- - SenderId: *agentList1
361
- ReceiverId: 10
362
- ProductName: MyProduct
363
- FirstDeliveryTime: 100
364
- DeliveryIntervalInSteps: 3600
365
-
366
- - SenderId: *agentList1
367
- ReceiverId: *agentList2
368
- ProductName: MyThirdProduct
369
- FirstDeliveryTime: 100
370
- DeliveryIntervalInSteps: 3600
371
- ```
372
-
373
- ### CSV files
374
- TIME_SERIES inputs are not directly fed into the Scenario YAML file.
375
- Instead, TIME_SERIES reference a CSV file that can be stored some place else.
376
- These CSV files follow a specific structure:
377
- * They must contain exactly two columns.
378
- * The first column must be a time stamp in form `YYYY-MM-DD_hh:mm:ss`
379
- * The second column must be a numerical value (either integer or floating-point)
380
- * The separator of the two columns is a semicolon
381
-
382
- Exemplary content of a valid CSV file:
383
-
384
- 2012-01-01_00:00:00;400
385
- 2013-01-01_00:00:00;720.5
386
- 2014-01-01_00:00:00;650
387
- 2015-01-01_00:00:00;99.27772
388
- 2016-01-01_00:00:00;42
389
- 2017-01-01_00:00:00;0.1
390
-
391
- Please refer also to the detailed article about `TimeStamps` in the [FAME-Wiki](https://gitlab.com/fame-framework/wiki/-/wikis/TimeStamp).
392
-
393
- ### Split and join multiple YAML files
394
- The user may include other YAML files into a YAML file to divide the content across files as convenient.
395
- We explicitly recommend using this feature for the `Schema` and `Contracts` sections.
396
- Otherwise, the scenario.yaml may become crowded.
397
-
398
- #### Command: !Include
399
- To hint YAML to load the content of another file use `!include "path/relative/to/including/yaml/file.yml"`.
400
- You can concatenate !include commands and can use !include in the included file as well.
401
- The path to the included file is always relative to the file using the !include command.
402
- So with the following file structure
403
-
404
- ###### file-structure
405
- ```
406
- a.yaml
407
- folder/b.yaml
408
- folder/c.yaml
409
- folder/deeper_folder/d.yaml
410
- ```
411
- the following !include commands work
412
-
413
- ###### in a.yaml
414
- ```
415
- ToBe: !include "folder/b.yaml"
416
- OrNot: !include "folder/deeper_folder/d.yaml"
417
- ```
418
-
419
- ###### in b.yaml
420
- ```
421
- ThatIs: !include "c.yaml"
422
- TheQuestion: !include "deeper_folder/d.yaml"
423
- ```
424
-
425
- Provided that
426
- ###### in c.yaml
427
- ```
428
- Or: maybe
429
- ```
430
- ###### d.yaml
431
- ```
432
- not: "?"
433
- ```
434
- the resulting file would look like this:
435
-
436
- ###### THe Joined file a.yaml
437
- ```
438
- ToBe:
439
- ThatIs:
440
- Or: maybe
441
- TheQuestion:
442
- not: "?"
443
- OrNot:
444
- not: "?"
445
- ```
446
-
447
- You may also specify absolute file paths if preferred by starting with a "/".
448
-
449
- When specifying only a file path, the complete content of the file is assigned to the given key.
450
- You always need a key to assign the !include command to.
451
- However, you cannot combine the value returned from !include with other values in the same key.
452
- Thus, the following combinations do not work:
453
- ###### caveats.yml
454
- ```
455
- !include "file.yaml" # no key assigned
456
-
457
- Key:
458
- Some: OtherItem
459
- !include "file.yaml" # cannot join with other named items
460
-
461
- List:
462
- - an: entry
463
- !include "file.yaml" # cannot directly join with list items, even if !include returns a list
464
- ```
465
-
466
- #### Integrate specific nodes of YAML files
467
- Instead of including *all* content in the included file, you may also pick a specific node within that file.
468
- For this use `!include [<relative/path/to/file.yaml>, Path:To:Field:In:Yaml]`.
469
- Here, `:` is used in the node-specifying string to select a sequence of nodes to follow - with custom depth.
470
- Consider the following two files:
471
-
472
- ###### file_to_be_included.yaml
473
- ```yaml
474
- Set1:
475
- Subset1:
476
- Key: Value
477
- Set2:
478
- OtherKey: OtherValue
479
- ```
480
-
481
- ###### including_file.yaml
482
- ```yaml
483
- - Type: MyAgentWithInputs
484
- Id: 1
485
- Attributes: !include_node [file_to_be_included.yaml, Set1:Subset1]
486
- ```
487
-
488
- Compiling "including_file.yaml" results in
489
-
490
- ###### resulting_file.yaml
491
- ```yaml
492
- - Type: MyAgentWithInputs
493
- Id: 1
494
- Attributes:
495
- Key: Value
496
- ```
497
-
498
- #### Load multiple files
499
- Using wildcards in the given path (e.g. "path/to/many/*.yaml") will lead to loading multiple files and assigning their content to the same key.
500
- You can make use of this feature with or without specifying a node selector.
501
- However, the elements to be joined across multiple files must be lists.
502
- These lists are then concatenated into a single list and then assigned to the key in the file calling !include.
503
- This feature is especially useful for Contracts: You can split the Contracts list into several files and place them in a separate folder.
504
- Then use !include to re-integrate them into your configuration. An example:
505
- ###### my_contract1.yaml
506
- ```
507
- Contracts:
508
- - ContractA
509
- - ContractB
510
- ```
511
- ###### my_contract2.yaml
512
- ```
513
- Contracts:
514
- - ContractC
515
- - ContractD
516
- - ContractE
517
- ```
518
- ###### including_file.yaml
519
- ```
520
- Contracts: [!include "my_contract*.yaml", "Contracts"]
521
- ```
522
-
523
- results in
524
- ###### result.yaml
525
- ```
526
- Contracts:
527
- - ContractA
528
- - ContractB
529
- - ContractC
530
- - ContractD
531
- - ContractE
532
- ```
533
-
534
- #### Ignoring files
535
- Files that have their name start with "IGNORE_" are not included with the !include command.
536
- You will see a debug output to notify you that the file was ignored.
537
- Use this to temporarily take files out ouf your configuration without deleting or moving them.
538
-
539
- ## Read FAME results
540
- Takes an output file in protobuf format of FAME-based applications and converts it into files in CSV format.
541
- An individual file for each type of Agent is created in a folder named after the protobuf input file.
542
- Call structure:
543
-
544
- convertFameResults -f <./path/to/protobuf_file.pb>
545
-
546
- You may also specify any of the following arguments:
547
-
548
- | Command | Action |
549
- |--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
550
- | `-l` or `--log` <option> | Sets the logging level. Default is `info`. Options are `debug`, `info`, `warning`, `warn`, `error`, `critical`. |
551
- | `-lf` or `--logfile` <file> | Sets the logging file. Default is `None`. If `None` is provided, all logs get only printed to the console. |
552
- | `-a` or `--agents` <list-of-agents> | If specified, only a subset of agents is extracted from the protobuf file. Default is to extract all agents. |
553
- | `-o` or `--output` | Sets the path to where the generated output files are written to. If not specified, the folder's name is derived from the input file's name. Folder will be created if it does not exist. |
554
- | `-se` or `--single-export` | Enables export of individual agents to individual files, when present. If not present (the default) one file per `AgentType` is created. |
555
- | `-m` or `--memory-saving` | When specified, reduces memory usage profile at the cost of runtime. Use only when necessary. |
556
- | `-cc` or `--complex-column` <option> | Defines how to deal with complex indexed output columns (if any). `IGNORE` ignores complex columns. `MERGE` squashes all data from complex columns in one big string entry. `SPLIT` creates a separate file for each complex indexed output column. |
557
- | `-t` or `--time` <option> | Option to define conversion of time steps to given format (default=`UTC`) by `-t/--time {UTC, INT, FAME}` |
558
-
559
- Additionally, you may merge TimeSteps of a certain range of steps in the output files to
560
- i) associate multiple time steps with a common logical time in your simulation
561
- ii) reduce number of lines in output files
562
-
563
- For this, add the option `merge-times` and specify the arguments as follows:
564
-
565
- | Command | Action |
566
- |---------------------------|------------------------------------------------------------------------------------------|
567
- | `-fp` or `--focal-point` | TimeStep on which `steps-before` earlier and `steps-after` later TimeSteps are merged on |
568
- | `-sb` or `--steps-before` | Range of TimeSteps before the `focal-point` they get merged to |
569
- | `-sa` or `--steps-after` | Range of TimeSteps after the `focal-point` they get merged to |
570
-
571
- This could look as follows:
572
-
573
- convertFameResults -f <./path/to/protobuf_file.pb> -l debug -lf <path/to/output.log> -a AgentType1 AgentType2 -o myCsvFolder -m -cc SPLIT merge-times -fp 0 -sb 1799 -sa 1800
574
-
575
- Make sure that in the range of time steps you specify for merging there is only one value per column in the merged time range.
576
- If multiple values per column are merged values will get concatenated and might yield unexpected results.
577
-
578
- You may also call the conversion script from any Python script with:
579
-
580
- ```python
581
- from fameio.scripts.convert_results import run as convert_results
582
-
583
- convert_results("./path/to/protobuf_file.pb")
584
- ```
585
-
586
- Similar to the console call you may also specify custom run config arguments and add it in a dictionary to the function call.
587
-
588
- ```python
589
- from fameio.scripts.convert_results import run as convert_results
590
- from fameio.source.cli import Options
591
-
592
- run_config = {Options.LOG_LEVEL: "info",
593
- Options.LOG_FILE: "scenario.log",
594
- Options.OUTPUT: "Output",
595
- Options.AGENT_LIST: ['AgentType1', 'AgentType2'],
596
- Options.MEMORY_SAVING: False,
597
- Options.SINGLE_AGENT_EXPORT: False,
598
- Options.RESOLVE_COMPLEX_FIELD: "SPLIT",
599
- Options.TIME: "INT",
600
- Options.TIME_MERGING: {},
601
- }
602
-
603
- convert_results("./path/to/protobuf_file.pb", run_config)
604
- ```
605
-
606
- ## Cite FAME-Io
607
- If you use FAME-Io for academic work, please cite as follows.
608
-
609
- Bibtex entry:
610
- ```
611
- @article{fameio2023joss,
612
- author = {Felix Nitsch and Christoph Schimeczek and Ulrich Frey and Benjamin Fuchs},
613
- title = {FAME-Io: Configuration tools for complex agent-based simulations},
614
- journal = {Journal of Open Source Software},
615
- year = {2023},
616
- doi = {doi: https://doi.org/10.21105/joss.04958}
617
- }
618
- ```
619
-
620
- ## Available Support
621
- This is a purely scientific project by (at the moment) one research group.
622
- Thus, there is no paid technical support available.
623
- However, we will give our best to answer your questions and provide support.
624
-
625
- If you experience any trouble with FAME-Io, you may contact the developers via [fame@dlr.de](mailto:fame@dlr.de).
626
- Please report bugs and make feature requests by filing issues following the provided templates (see also [Contribute](#Contribute)).
627
- For substantial enhancements, we recommend that you contact us via [fame@dlr.de](mailto:fame@dlr.de) for working together on the code in common projects or towards common publications and thus further develop FAME-Io.
628
-
629
- # Contribute
630
- Please read the Contributors License Agreement `cla.md`, sign it and send it to [`fame@dlr.de`](mailto:fame@dlr.de) before contributing.
631
-
632
- You will also find templates for [bug reports](https://gitlab.com/fame-framework/fame-io/-/blob/main/.gitlab/issue_templates/bug_report.md),
633
- [feature requests](https://gitlab.com/fame-framework/fame-io/-/blob/main/.gitlab/issue_templates/feature_request.md), and
634
- [pull requests](https://gitlab.com/fame-framework/fame-io/-/blob/main/.gitlab/issue_templates/pull_request.md).
635
-
636
- We kindly ask you to read the Contributors License Agreement `cla.md`, sign it, and send it to [`fame@dlr.de`](mailto:fame@dlr.de) before contributing. Please see our [conventions of contribution](https://gitlab.com/fame-framework/wiki/-/wikis/developers/contribute/Conventions) which are described in the Wiki.
637
-
638
- ## Testing changes locally
639
-
640
- Once some changes have been performed on the local git clone, use the following command to override your local installation with your modified copy in order to test the result:
641
-
642
- ```bash
643
- python3 setup.py bdist_wheel && pip3 install --force-reinstall --no-dependencies ./dist/*.whl
644
- ```
645
-
646
- ## Code style
647
-
648
- We use the code formatting library [`black`](https://pypi.org/project/black/).
649
- The maximum line length is defined as 120 characters.
650
- Therefore, before committing, run `black --line-length 120 .`
651
-
652
- ## Pre-Commit hooks
653
-
654
- FAME-Io uses several pre-commit hooks to ensure high code quality.
655
- To use them, install `dev` packages and then initialise pre-commit in FAME-Io's base folder:
656
-
657
- ```
658
- pip install fameio[dev]
659
- pre-commit install -t pre-commit -t pre-push
660
- ```
1
+ Metadata-Version: 2.1
2
+ Name: fameio
3
+ Version: 2.0.0
4
+ Summary: Python scripts for operation of FAME models
5
+ Home-page: https://gitlab.com/fame-framework/wiki/-/wikis/home
6
+ License: Apache-2.0
7
+ Keywords: FAME,fameio,agent-based modelling,energy systems
8
+ Author: Felix Nitsch
9
+ Author-email: fame@dlr.de
10
+ Maintainer: Felix Nitsch
11
+ Maintainer-email: fame@dlr.de
12
+ Requires-Python: >=3.9,<4.0
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: License :: OSI Approved :: Apache Software License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Topic :: Scientific/Engineering
24
+ Requires-Dist: fameprotobuf (>=1.4.0,<2.0.0)
25
+ Requires-Dist: pandas (>=1.0,<3.0)
26
+ Requires-Dist: pyyaml (>=6.0,<7.0)
27
+ Project-URL: Repository, https://gitlab.com/fame-framework/fame-io/
28
+ Description-Content-Type: text/markdown
29
+
30
+ <!-- SPDX-FileCopyrightText: 2023 German Aerospace Center <fame@dlr.de>
31
+
32
+ SPDX-License-Identifier: Apache-2.0 -->
33
+ [![PyPI version](https://badge.fury.io/py/fameio.svg)](https://badge.fury.io/py/fameio)
34
+ [![JOSS](https://joss.theoj.org/papers/10.21105/joss.04958/status.svg)](https://doi.org/10.21105/joss.04958)
35
+ [![Zenodo](https://zenodo.org/badge/DOI/10.5281/zenodo.4314337.svg)](https://doi.org/10.5281/zenodo.4314337)
36
+ [![PyPI license](https://img.shields.io/pypi/l/fameio.svg)](https://badge.fury.io/py/fameio)
37
+ [![pipeline status](https://gitlab.com/fame-framework/fame-io/badges/main/pipeline.svg)](https://gitlab.com/fame-framework/fame-io/commits/main)
38
+ [![coverage report](https://gitlab.com/fame-framework/fame-io/badges/main/coverage.svg)](https://gitlab.com/fame-framework/fame-io/-/commits/main)
39
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
40
+ [![REUSE status](https://api.reuse.software/badge/gitlab.com/fame-framework/fame-io)](https://api.reuse.software/info/gitlab.com/fame-framework/fame-io)
41
+ [![Common Changelog](https://common-changelog.org/badge.svg)](https://common-changelog.org)
42
+ ![GitLab last commit](https://img.shields.io/gitlab/last-commit/fame-framework%2Ffame-io)
43
+ ![GitLab closed issues by-label](https://img.shields.io/gitlab/issues/closed/fame-framework%2Ffame-io)
44
+
45
+
46
+ # FAME-Io
47
+ Python scripts for FAME models, generation of protobuf input files and conversion of protobuf output files.
48
+ Please visit the [FAME-Wiki](https://gitlab.com/fame-framework/wiki/-/wikis/home) to get an explanation of FAME and its components.
49
+
50
+ # Installation
51
+ We recommend installing `fameio` using PyPI:
52
+
53
+ pip install fameio
54
+
55
+ You may also use `pipx`. For detailed information please refer to the official `pipx` [documentation](https://github.com/pypa/pipx).
56
+
57
+ pipx install fameio
58
+
59
+ `fameio` is currently developed and tested for Python 3.8 or higher.
60
+ See the `pyproject.toml` for a complete listing of dependencies.
61
+
62
+ # Usage
63
+ FAME-Io currently offers two main scripts `makeFameRunConfig` and `convertFameResults`.
64
+ Both are automatically installed with the package.
65
+ The first one creates a protobuf file for FAME applications using YAML definition files and CSV files.
66
+ The latter one reads output files from FAME applications in protobuf format and converts them to CSV files.
67
+
68
+ You may use the [example data](https://gitlab.com/dlr-ve/esy/amiris/examples) provided for the [AMIRIS](https://gitlab.com/dlr-ve/esy/amiris/amiris) model which can be used to simulate electricity markets in [Germany](https://gitlab.com/dlr-ve/esy/amiris/examples/-/tree/main/Germany2019), [Austria](https://gitlab.com/dlr-ve/esy/amiris/examples/-/tree/main/Austria2019), and a simple [proof-of-concept model](https://gitlab.com/dlr-ve/esy/amiris/examples/-/tree/main/Simple).
69
+
70
+ ## Make a FAME run configuration
71
+ Digests configuration files in YAML format, combines them with CSV data files and creates a single input file for FAME applications in protobuf format.
72
+ Call structure:
73
+
74
+ makeFameRunConfig -f <path/to/scenario.yaml>
75
+
76
+ You may also specify any of the following arguments:
77
+
78
+ | Command | Action |
79
+ |----------------------|-----------------------------------------------------------------------------------------------------------------|
80
+ | `-l` or `--log` | Sets the logging level. Default is `info`. Options are `debug`, `info`, `warning`, `warn`, `error`, `critical`. |
81
+ | `-lf` or `--logfile` | Sets the logging file. Default is `None`. If `None` is provided, all logs get only printed to the console. |
82
+ | `-o` or `--output` | Sets the path of the compiled protobuf output file. Default is `config.pb`. |
83
+
84
+ This could look as follows:
85
+
86
+ makeFameRunConfig -f <path/to/scenario.yaml> -l debug -lf <path/to/scenario.log> -o <path/to/config.pb>
87
+
88
+ You may also call the configuration builder from any Python script with
89
+
90
+ ```python
91
+ from fameio.scripts.make_config import Options, run as make_config
92
+
93
+ make_config({Options.FILE: "path/to/scenario.yaml", })
94
+ ```
95
+
96
+ Similar to the console call you may also specify custom run config arguments and add it in a dictionary to the function call.
97
+
98
+ ```python
99
+ from fameio.scripts.make_config import Options, run as make_config
100
+
101
+ run_config = {Options.FILE: "path/to/scenario.yaml",
102
+ Options.LOG_LEVEL: "info",
103
+ Options.OUTPUT: "output.pb",
104
+ Options.LOG_FILE: "scenario.log",
105
+ }
106
+
107
+ make_config(run_config)
108
+ ```
109
+
110
+ You can also use the associated argument parser, to extract the run_config dynamically from a string:
111
+
112
+ ```python
113
+ from fameio.scripts.make_config import Options, run as make_config
114
+ from fameio.source.cli.make_config import handle_args
115
+
116
+ my_defaults = {Options.FILE: "path/to/scenario.yaml",
117
+ Options.LOG_LEVEL: "info",
118
+ Options.OUTPUT: "output.pb",
119
+ Options.LOG_FILE: "scenario.log",
120
+ }
121
+ my_arg_string = ['-f', 'my/other/scenario.yaml', '-l', 'error']
122
+
123
+ run_config = handle_args(my_arg_string, my_defaults)
124
+ make_config(run_config)
125
+ ```
126
+
127
+ ### Scenario YAML
128
+ The "scenario.yaml" file contains all configuration options for a FAME-based simulation.
129
+ It consists of the sections `Schema`, `GeneralProperties`, `Agents` and `Contracts`, all of them described below.
130
+
131
+ #### Schema
132
+ The Schema is used to validate the inputs of the "scenario.yaml".
133
+ Since the Schema should be valid across multiple scenarios, it is recommended to defined it in a separate file and include the file here.
134
+
135
+ Currently, the schema specifies:
136
+ * which type of Agents can be created
137
+ * what type of input attributes an Agent uses
138
+ * what type of Products an Agent can send in Contracts.
139
+
140
+ The Schema consists of the sections `Header` and `AgentTypes`.
141
+
142
+ ##### Header
143
+ Scientific applications often evolve, and so do their required input parameters.
144
+ Therefore, the header specifies information what FAME-based application the schema is corresponding to.
145
+ In this way a schema.yaml is tied to a specific version an application, ensuring a match between the inputs required by
146
+ the application, and those provided by the files created with FAME-Io.
147
+
148
+ ```yaml
149
+ Header:
150
+ Project: MyProjectName
151
+ RepoUrl: https://mygithosting.com/myProject
152
+ CommitHash: abc123
153
+ ```
154
+
155
+ * `Project` name of your project / FAME-based application
156
+ * `RepoUrl` URL of your project
157
+ * `CommitHash` hash of the commit / version of your project
158
+
159
+ ##### AgentTypes
160
+ Here, each type of agent that can be created in your FAME-based application is listed, its attributes and its available Products for Contracts.
161
+ The structure of this section
162
+
163
+ ```yaml
164
+ AgentTypes:
165
+ MyAgentType:
166
+ Attributes:
167
+ MyAttribute:
168
+ ...
169
+ MyOtherAttribute:
170
+ ...
171
+ Products: [ 'Product1', 'Product2', 'Product3' ]
172
+ MyOtherAgentWithoutProductsOrAttributes:
173
+ ```
174
+
175
+ * `MyAgentType` Java's simple class name of the Agent type
176
+ * `Attributes` indicates that beginning of the attribute definition section for this Agent type
177
+ * `MyAttribute` Name of an attribute as specified in the corresponding Java source code of this Agent type (annotated with "@Input")
178
+ * `MyOtherAttribute` Name of another attribute derived from Java source code
179
+ * `Products` list of Products that this Agent can send in Contracts; derived from Java source code of this Agent type (annotated with "@Product")
180
+ * `MyOtherAgentWithoutProductsOrAttributes` an Agent type that requires neither Attributes nor Products
181
+
182
+ Both Attributes and Products are optional - there could be useful Agents that require neither of them.
183
+ In the above example attribute definition was not shown (indicated by `...`).
184
+ The next example provides details on how to define an attribute:
185
+
186
+ ```yaml
187
+ MySimpleAttribute:
188
+ AttributeType: enum
189
+ Mandatory: true
190
+ List: false
191
+ Values: [ 'AllowedValue1', 'AllowedValue2' ]
192
+ Default: 'AllowedValue1'
193
+ Help: 'My help text'
194
+
195
+ MyComplexAttribute:
196
+ AttributeType: block
197
+ NestedAttributes:
198
+ InnerAttributeA:
199
+ AttributeType: integer
200
+ InnerAttributeB:
201
+ AttributeType: double
202
+ ```
203
+
204
+ * `MySimpleAttribute`, `MyDoubleList`, `MyComplexAttribute` Names of the attributes as specified in the Java enum annotated with "@Input"
205
+ * `AttributeType` (required) data type of the attribute; see options in table below
206
+ * `Mandatory` (optional - true by default) if true: the attribute is required for this agent and validation will fail if the attribute is missing in the scenario **and** no default is provided
207
+ * `List` (optional - false by default)
208
+ * `AttributeType: time_series` cannot be true
209
+ * `AttributeType: block`
210
+ * if true: any nested element in the scenario must be part of a list element and thus can appear multiple times
211
+ * if false: any nested element in the scenario can only appear once
212
+ * any other AttributeType: the attribute is interpreted as list, i.e. multiple values can be assigned to this attribute in the scenario
213
+ * `NestedAttributes` (required only if `AttributeType: block`, otherwise disallowed) starts an inner Attribute definition block - defined Attributes are sub-elements of `MyComplexAttribute`
214
+ * `Values` (optional - None by default): if present defines a list of allowed values for this attribute
215
+ * `Default` (optional - None by default): if present defines a default value to be used in case the scenario does not specify it
216
+ * `Help` (optional - None by default): if present defines a help text to you attribute
217
+
218
+ | AttributeType | value |
219
+ |---------------|-------------------------------------------------------------------------------------------------------------------------|
220
+ | `integer` | a 32-bit integer value |
221
+ | `double` | a 64-bit floating-point value (integers also allowed) |
222
+ | `long` | a 64-bit integer value |
223
+ | `time_stamp` | either a FAME time stamp string or 64-bit integer value |
224
+ | `string` | any string |
225
+ | `enum` | any string, however, usually tied to a set of allowed `Values` |
226
+ | `time_series` | either a path to a .csv-file or a single 64-bit floating-point value; does not support `List: true` |
227
+ | `block` | this attribute has no value of its own but hosts a group of nested Attributes; implies `NestedAttributes` to be defined |
228
+
229
+ #### GeneralProperties
230
+ Specifies FAME-specific properties of the simulation. Structure:
231
+
232
+ ```yaml
233
+ GeneralProperties:
234
+ RunId: 1
235
+ Simulation:
236
+ StartTime: 2011-12-31_23:58:00
237
+ StopTime: 2012-12-30_23:58:00
238
+ RandomSeed: 1
239
+ Output:
240
+ Interval: 100
241
+ Process: 0
242
+ ```
243
+
244
+ Parameters:
245
+ * `RunId` an ID that can be given to the simulation; use at your discretion
246
+ * `StartTime` time stamp in the format YYYY-MM-DD_hh:mm:ss; first moment of the simulation.
247
+ * `StopTime` time stamp in the format YYYY-MM-DD_hh:mm:ss; last moment of the simulation - i.e. simulation terminates
248
+ after passing that time stamp
249
+ * `RandomSeed` seed to initialise random number generation; each value leads to a unique series of random numbers.
250
+ * `Interval` number of simulation ticks in between write-to-disk events; may be used for performance optimisations;
251
+ * `Process` id of process that performs write-to-disk operations; leave at 0 to be compatible with single-processes;
252
+
253
+ #### Agents
254
+ Specifies all Agents to be created in the simulation in a list. Each Agent has its own entry.
255
+ Structure:
256
+
257
+ ```yaml
258
+ Agents:
259
+ - Type: MyAgentWithInputs
260
+ Id: 1
261
+ Attributes:
262
+ MyEnum: SAME_SHARES
263
+ MyInteger: 2
264
+ MyDouble: 4.2
265
+ MyTimeSeries: "./path/to/time_series.csv"
266
+
267
+ - Type: MyAgentWithoutInputs
268
+ Id: 2
269
+ ```
270
+
271
+ Agent Parameters:
272
+ * `Type` Mandatory; Java's simple class name of the agent to be created
273
+ * `Id` Mandatory; simulation-unique id of this agent; if two agents have the same ID, the configuration process will
274
+ stop.
275
+ * `Attributes` Optional; if the agent has any attributes, specify them here in the format "AttributeName: value"; please
276
+ see attribute table above
277
+
278
+ The specified `Attributes` for each agent must match the specified `Attributes` options in the linked Schema (see above).
279
+ For better structure and readability of the `scenario.yaml`, `Attributes` may also be specified in a nested way as demonstrated below.
280
+
281
+ ```yaml
282
+ Agents:
283
+ - Type: MyAgentWithInputs
284
+ Id: 1
285
+ Attributes:
286
+ Parent:
287
+ MyEnum: SAME_SHARES
288
+ MyInteger: 2
289
+ Parent2:
290
+ MyDouble: 4.2
291
+ Child:
292
+ MyTimeSeries: "./path/to/time_series.csv"
293
+ ```
294
+
295
+ In case Attributes are defined with `List: true` option, lists are assigned to an Attribute or Group:
296
+
297
+ ```yaml
298
+ Attributes:
299
+ MyDoubleList: [ 5.2, 4.5, 7, 9.9 ]
300
+ MyListGroup:
301
+ - IntValueA: 5
302
+ IntValueB: 42
303
+ - IntValueA: 7
304
+ IntValueB: 100
305
+ ```
306
+
307
+ Here, `MyDoubleList` and `MyListGroup` need to specify `List: true` in the corresponding Schema.
308
+ The shorter `[]`-notation was used to assign a list of floating-point values to `MyDoubleList`.
309
+ Nested items `IntValueA` and `IntValueB` of `MyListGroup` are assigned within a list, allowing the specification of these nested items several times.
310
+
311
+ #### Contracts
312
+ Specifies all Contracts, i.e. repetitive bilateral transactions in between agents.
313
+ Contracts are given as a list.
314
+ We recommend moving Contracts to separate files and to use the `!include` command to integrate them in the scenario.
315
+
316
+ ```yaml
317
+ Contracts:
318
+ - SenderId: 1
319
+ ReceiverId: 2
320
+ ProductName: ProductOfAgent_1
321
+ FirstDeliveryTime: -25
322
+ DeliveryIntervalInSteps: 3600
323
+
324
+ - SenderId: 2
325
+ ReceiverId: 1
326
+ ProductName: ProductOfAgent_2
327
+ FirstDeliveryTime: -22
328
+ DeliveryIntervalInSteps: 3600
329
+ Attributes:
330
+ ProductAppendix: value
331
+ TimeOffset: 42
332
+ ```
333
+
334
+ Contract Parameters:
335
+ * `SenderId` unique ID of agent sending the product
336
+ * `ReceiverId` unique ID of agent receiving the product
337
+ * `ProductName` name of the product to be sent
338
+ * `FirstDeliveryTime` first time of delivery in the format "seconds after the January 1st 2000, 00:00:00"
339
+ * `DeliveryIntervalInSteps` delay time in between deliveries in seconds
340
+ * `Attributes` can be set to include additional information as `int`, `float`, `enum` or `dict` data types
341
+
342
+ ##### Definition of Multiple Similar Contracts
343
+ Often, scenarios contain multiple agents of similar type that also have similar chains of contracts.
344
+ Therefore, FAME-Io supports a compact definition of multiple similar contracts.
345
+ `SenderId` and `ReceiverId` can both be lists and support One-to-N, N-to-One and N-to-N relations like in the following example:
346
+
347
+ ```yaml
348
+ Contracts:
349
+ # effectively 3 similar contracts (0 -> 11), (0 -> 12), (0 -> 13)
350
+ # with otherwise identical ProductName, FirstDeliveryTime & DeliveryIntervalInSteps
351
+ - SenderId: 0
352
+ ReceiverId: [ 11, 12, 13 ]
353
+ ProductName: MyOtherProduct
354
+ FirstDeliveryTime: 100
355
+ DeliveryIntervalInSteps: 3600
356
+
357
+ # effectively 3 similar contracts (1 -> 10), (2 -> 10), (3 -> 10)
358
+ # with otherwise identical ProductName, FirstDeliveryTime & DeliveryIntervalInSteps
359
+ - SenderId: [ 1, 2, 3 ]
360
+ ReceiverId: 10
361
+ ProductName: MyProduct
362
+ FirstDeliveryTime: 100
363
+ DeliveryIntervalInSteps: 3600
364
+
365
+ # effectively 3 similar contracts (1 -> 11), (2 -> 12), (3 -> 13)
366
+ # with otherwise identical ProductName, FirstDeliveryTime & DeliveryIntervalInSteps
367
+ - SenderId: [ 1, 2, 3 ]
368
+ ReceiverId: [ 11, 12, 13 ]
369
+ ProductName: MyThirdProduct
370
+ FirstDeliveryTime: 100
371
+ DeliveryIntervalInSteps: 3600
372
+ ```
373
+
374
+ Combined with YAML anchors complex contract chains can be easily reduced to a minimum of required configuration.
375
+ The following example is equivalent to the previous one and allows a quick extension of contracts to a new couple of agents e.g. (4;14):
376
+
377
+ ```yaml
378
+ Groups:
379
+ - &agentList1: [ 1,2,3 ]
380
+ - &agentList2: [ 11,12,13 ]
381
+
382
+ Contracts:
383
+ - SenderId: 0
384
+ ReceiverId: *agentList2
385
+ ProductName: MyOtherProduct
386
+ FirstDeliveryTime: 100
387
+ DeliveryIntervalInSteps: 3600
388
+
389
+ - SenderId: *agentList1
390
+ ReceiverId: 10
391
+ ProductName: MyProduct
392
+ FirstDeliveryTime: 100
393
+ DeliveryIntervalInSteps: 3600
394
+
395
+ - SenderId: *agentList1
396
+ ReceiverId: *agentList2
397
+ ProductName: MyThirdProduct
398
+ FirstDeliveryTime: 100
399
+ DeliveryIntervalInSteps: 3600
400
+ ```
401
+
402
+ ### CSV files
403
+ TIME_SERIES inputs are not directly fed into the Scenario YAML file.
404
+ Instead, TIME_SERIES reference a CSV file that can be stored some place else.
405
+ These CSV files follow a specific structure:
406
+ * They must contain exactly two columns.
407
+ * The first column must be a time stamp in form `YYYY-MM-DD_hh:mm:ss`
408
+ * The second column must be a numerical value (either integer or floating-point)
409
+ * The separator of the two columns is a semicolon
410
+ * The data must **not** have headers, except for comments marked with `#`
411
+
412
+ You may add comments using `#`.
413
+ Exemplary content of a valid CSV file:
414
+
415
+ # If you want an optional header, you must use a comment
416
+ 2012-01-01_00:00:00;400
417
+ 2013-01-01_00:00:00;720.5
418
+ 2014-01-01_00:00:00;650
419
+ 2015-01-01_00:00:00;99.27772
420
+ 2016-01-01_00:00:00;42 # optional comment on this particular data point
421
+ 2017-01-01_00:00:00;0.1
422
+
423
+ Please refer also to the detailed article about `TimeStamps` in the [FAME-Wiki](https://gitlab.com/fame-framework/wiki/-/wikis/TimeStamp).
424
+
425
+ ### Split and join multiple YAML files
426
+ The user may include other YAML files into a YAML file to divide the content across files as convenient.
427
+ We explicitly recommend using this feature for the `Schema` and `Contracts` sections.
428
+ Otherwise, the scenario.yaml may become crowded.
429
+
430
+ #### Command: !Include
431
+ To hint YAML to load the content of another file use `!include "path/relative/to/including/yaml/file.yml"`.
432
+ You can concatenate !include commands and can use !include in the included file as well.
433
+ The path to the included file is always relative to the file using the !include command.
434
+ So with the following file structure
435
+
436
+ ###### file-structure
437
+ ```
438
+ a.yaml
439
+ folder/b.yaml
440
+ folder/c.yaml
441
+ folder/deeper_folder/d.yaml
442
+ ```
443
+
444
+ the following !include commands work
445
+
446
+ ###### in a.yaml
447
+ ```
448
+ ToBe: !include "folder/b.yaml"
449
+ OrNot: !include "folder/deeper_folder/d.yaml"
450
+ ```
451
+
452
+ ###### in b.yaml
453
+ ```
454
+ ThatIs: !include "c.yaml"
455
+ TheQuestion: !include "deeper_folder/d.yaml"
456
+ ```
457
+
458
+ Provided that
459
+ ###### in c.yaml
460
+ ```
461
+ Or: maybe
462
+ ```
463
+
464
+ ###### d.yaml
465
+ ```
466
+ not: "?"
467
+ ```
468
+
469
+ the resulting file would look like this:
470
+
471
+ ###### THe Joined file a.yaml
472
+ ```
473
+ ToBe:
474
+ ThatIs:
475
+ Or: maybe
476
+ TheQuestion:
477
+ not: "?"
478
+ OrNot:
479
+ not: "?"
480
+ ```
481
+
482
+ You may also specify absolute file paths if preferred by starting with a "/".
483
+
484
+ When specifying only a file path, the complete content of the file is assigned to the given key.
485
+ You always need a key to assign the !include command to.
486
+ However, you cannot combine the value returned from !include with other values in the same key.
487
+ Thus, the following combinations do not work:
488
+
489
+ ###### caveats.yml
490
+ ```
491
+ !include "file.yaml" # no key assigned
492
+
493
+ Key:
494
+ Some: OtherItem
495
+ !include "file.yaml" # cannot join with other named items
496
+
497
+ List:
498
+ - an: entry
499
+ !include "file.yaml" # cannot directly join with list items, even if !include returns a list
500
+ ```
501
+
502
+ #### Integrate specific nodes of YAML files
503
+ Instead of including *all* content in the included file, you may also pick a specific node within that file.
504
+ For this use `!include [<relative/path/to/file.yaml>, Path:To:Field:In:Yaml]`.
505
+ Here, `:` is used in the node-specifying string to select a sequence of nodes to follow - with custom depth.
506
+ Consider the following two files:
507
+
508
+ ###### file_to_be_included.yaml
509
+ ```yaml
510
+ Set1:
511
+ Subset1:
512
+ Key: Value
513
+ Set2:
514
+ OtherKey: OtherValue
515
+ ```
516
+
517
+ ###### including_file.yaml
518
+ ```yaml
519
+ - Type: MyAgentWithInputs
520
+ Id: 1
521
+ Attributes: !include_node [ file_to_be_included.yaml, Set1:Subset1 ]
522
+ ```
523
+
524
+ Compiling "including_file.yaml" results in
525
+
526
+ ###### resulting_file.yaml
527
+ ```yaml
528
+ - Type: MyAgentWithInputs
529
+ Id: 1
530
+ Attributes:
531
+ Key: Value
532
+ ```
533
+
534
+ #### Load multiple files
535
+ Using wildcards in the given path (e.g. "path/to/many/*.yaml") will lead to loading multiple files and assigning their content to the same key.
536
+ You can make use of this feature with or without specifying a node selector.
537
+ However, the elements to be joined across multiple files must be lists.
538
+ These lists are then concatenated into a single list and then assigned to the key in the file calling !include.
539
+ This feature is especially useful for Contracts: You can split the Contracts list into several files and place them in a separate folder.
540
+ Then use !include to re-integrate them into your configuration. An example:
541
+
542
+ ###### my_contract1.yaml
543
+ ```
544
+ Contracts:
545
+ - ContractA
546
+ - ContractB
547
+ ```
548
+
549
+ ###### my_contract2.yaml
550
+ ```
551
+ Contracts:
552
+ - ContractC
553
+ - ContractD
554
+ - ContractE
555
+ ```
556
+
557
+ ###### including_file.yaml
558
+ ```
559
+ Contracts: [!include "my_contract*.yaml", "Contracts"]
560
+ ```
561
+
562
+ results in
563
+
564
+ ###### result.yaml
565
+ ```
566
+ Contracts:
567
+ - ContractA
568
+ - ContractB
569
+ - ContractC
570
+ - ContractD
571
+ - ContractE
572
+ ```
573
+
574
+ #### Ignoring files
575
+ Files that have their name start with "IGNORE_" are not included with the !include command.
576
+ You will see a debug output to notify you that the file was ignored.
577
+ Use this to temporarily take files out ouf your configuration without deleting or moving them.
578
+
579
+ ## Read FAME results
580
+ Takes an output file in protobuf format of FAME-based applications and converts it into files in CSV format.
581
+ An individual file for each type of Agent is created in a folder named after the protobuf input file.
582
+ Call structure:
583
+
584
+ convertFameResults -f <./path/to/protobuf_file.pb>
585
+
586
+ You may also specify any of the following arguments:
587
+
588
+ | Command | Action |
589
+ |---------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
590
+ | `-l` or `--log` <option> | Sets the logging level. Default is `info`. Options are `debug`, `info`, `warning`, `warn`, `error`, `critical`. |
591
+ | `-lf` or `--logfile` <file> | Sets the logging file. Default is `None`. If `None` is provided, all logs get only printed to the console. |
592
+ | `-a` or `--agents` <list-of-agents> | If specified, only a subset of agents is extracted from the protobuf file. Default is to extract all agents. |
593
+ | `-o` or `--output` | Sets the path to where the generated output files are written to. If not specified, the folder's name is derived from the input file's name. Folder will be created if it does not exist. |
594
+ | `-se` or `--single-export` | Enables export of individual agents to individual files, when present. If not present (the default) one file per `AgentType` is created. |
595
+ | `-m` or `--memory-saving` | When specified, reduces memory usage profile at the cost of runtime. Use only when necessary. |
596
+ | `-cc` or `--complex-column` <option> | Defines how to deal with complex indexed output columns (if any). `IGNORE` ignores complex columns. `MERGE` squashes all data from complex columns in one big string entry. `SPLIT` creates a separate file for each complex indexed output column. |
597
+ | `-t` or `--time` <option> | Option to define conversion of time steps to given format (default=`UTC`) by `-t/--time {UTC, INT, FAME}` |
598
+ | `--input-recovery` or `--no-input-recovery` | If True, all input data are recovered as well as the outputs (default=False). |
599
+
600
+ Additionally, you may merge TimeSteps of a certain range of steps in the output files to
601
+ i) associate multiple time steps with a common logical time in your simulation
602
+ ii) reduce number of lines in output files
603
+
604
+ For this, add the option `merge-times` and specify the arguments as follows:
605
+
606
+ | Command | Action |
607
+ |---------------------------|------------------------------------------------------------------------------------------|
608
+ | `-fp` or `--focal-point` | TimeStep on which `steps-before` earlier and `steps-after` later TimeSteps are merged on |
609
+ | `-sb` or `--steps-before` | Range of TimeSteps before the `focal-point` they get merged to |
610
+ | `-sa` or `--steps-after` | Range of TimeSteps after the `focal-point` they get merged to |
611
+
612
+ This could look as follows:
613
+
614
+ convertFameResults -f <./path/to/protobuf_file.pb> -l debug -lf <path/to/output.log> -a AgentType1 AgentType2 -o myCsvFolder -m -cc SPLIT merge-times -fp 0 -sb 1799 -sa 1800
615
+
616
+ Make sure that in the range of time steps you specify for merging there is only one value per column in the merged time range.
617
+ If multiple values per column are merged values will get concatenated and might yield unexpected results.
618
+
619
+ You may also call the conversion script from any Python script with:
620
+
621
+ ```python
622
+ from fameio.scripts.convert_results import Options, run as convert_results
623
+
624
+ convert_results({Options.FILE: "./path/to/protobuf_file.pb"})
625
+ ```
626
+
627
+ Similar to the console call you may also specify custom run config arguments and add it in a dictionary to the function call.
628
+
629
+ ```python
630
+ from fameio.scripts.convert_results import Options, run as convert_results
631
+
632
+ run_config = {Options.FILE: "./path/to/protobuf_file.pb",
633
+ Options.LOG_LEVEL: "info",
634
+ Options.LOG_FILE: "scenario.log",
635
+ Options.OUTPUT: "Output",
636
+ Options.AGENT_LIST: ['AgentType1', 'AgentType2'],
637
+ Options.MEMORY_SAVING: False,
638
+ Options.SINGLE_AGENT_EXPORT: False,
639
+ Options.RESOLVE_COMPLEX_FIELD: "SPLIT",
640
+ Options.TIME: "INT",
641
+ Options.TIME_MERGING: {},
642
+ }
643
+
644
+ convert_results(run_config)
645
+ ```
646
+
647
+ You can also use the associated argument parser, to extract the run_config dynamically from a string:
648
+
649
+ ```python
650
+ from fameio.scripts.convert_results import Options, run as convert_results
651
+ from fameio.source.cli.convert_results import handle_args
652
+
653
+ my_defaults = {Options.FILE: "./path/to/protobuf_file.pb",
654
+ Options.LOG_LEVEL: "info",
655
+ Options.LOG_FILE: "scenario.log",
656
+ Options.OUTPUT: "Output",
657
+ Options.AGENT_LIST: ['AgentType1', 'AgentType2'],
658
+ Options.MEMORY_SAVING: False,
659
+ Options.SINGLE_AGENT_EXPORT: False,
660
+ Options.RESOLVE_COMPLEX_FIELD: "SPLIT",
661
+ Options.TIME: "INT",
662
+ Options.TIME_MERGING: {},
663
+ }
664
+ my_arg_string = ['-f', 'my/other/scenario.yaml', '-l', 'error']
665
+
666
+ run_config = handle_args(my_arg_string, my_defaults)
667
+ convert_results(run_config)
668
+ ```
669
+
670
+ ## Cite FAME-Io
671
+ If you use FAME-Io for academic work, please cite as follows.
672
+
673
+ Bibtex entry:
674
+
675
+ ```
676
+ @article{fameio2023joss,
677
+ author = {Felix Nitsch and Christoph Schimeczek and Ulrich Frey and Benjamin Fuchs},
678
+ title = {FAME-Io: Configuration tools for complex agent-based simulations},
679
+ journal = {Journal of Open Source Software},
680
+ year = {2023},
681
+ doi = {doi: https://doi.org/10.21105/joss.04958}
682
+ }
683
+ ```
684
+
685
+ ## Available Support
686
+ This is a purely scientific project by (at the moment) one research group.
687
+ Thus, there is no paid technical support available.
688
+ However, we will give our best to answer your questions and provide support.
689
+
690
+ If you experience any trouble with FAME-Io, you may contact the developers via [fame@dlr.de](mailto:fame@dlr.de).
691
+ Please report bugs and make feature requests by filing issues following the provided templates (see also [Contribute](CONTRIBUTING.md)).
692
+ For substantial enhancements, we recommend that you contact us via [fame@dlr.de](mailto:fame@dlr.de) for working
693
+ together on the code in common projects or towards common publications and thus further develop FAME-Io.
694
+