fmdtools 2.1.2__tar.gz → 2.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. {fmdtools-2.1.2 → fmdtools-2.2.0}/LICENSE +1 -1
  2. {fmdtools-2.1.2/fmdtools.egg-info → fmdtools-2.2.0}/PKG-INFO +20 -20
  3. {fmdtools-2.1.2 → fmdtools-2.2.0}/README.md +14 -14
  4. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/asg_demo/demo_model.py +10 -19
  5. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/eps/eps.py +15 -29
  6. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/eps/test_eps.py +15 -6
  7. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/multiflow_demo/multiflow_demo.py +13 -13
  8. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/multiflow_demo/test_multiflow.py +8 -8
  9. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/multirotor/drone_mdl_dynamic.py +28 -36
  10. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/multirotor/drone_mdl_hierarchical.py +4 -6
  11. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/multirotor/drone_mdl_rural.py +12 -22
  12. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/multirotor/drone_mdl_static.py +49 -59
  13. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/multirotor/drone_mdl_urban.py +18 -21
  14. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/multirotor/opt_drone_rural.py +2 -2
  15. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/multirotor/test_multirotor.py +6 -6
  16. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/pump/ex_pump.py +35 -39
  17. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/pump/parallelism_methods.py +4 -9
  18. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/pump/pump_indiv.py +4 -5
  19. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/pump/pump_stochastic.py +40 -40
  20. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/pump/test_pump.py +15 -12
  21. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/pump/test_pump_example.py +36 -34
  22. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/pump/test_pump_stochastic.py +41 -50
  23. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/rover/optimization/search_rover.py +15 -12
  24. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/rover/rover_degradation.py +26 -9
  25. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/rover/rover_mode_space.py +1 -1
  26. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/rover/rover_model.py +30 -41
  27. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/rover/rover_model_human.py +26 -38
  28. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/rover/test_rover.py +1 -2
  29. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/tank/tank_model.py +35 -34
  30. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/tank/tank_optimization_model.py +14 -15
  31. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/tank/test_tank.py +26 -23
  32. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/taxiway/ATC.py +2 -2
  33. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/taxiway/asset.py +2 -5
  34. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/taxiway/common.py +6 -6
  35. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/taxiway/model.py +12 -14
  36. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/taxiway/test_asset.py +9 -9
  37. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/taxiway/test_model.py +4 -4
  38. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/__init__.py +1 -1
  39. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/analyze/common.py +25 -28
  40. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/analyze/graph/__init__.py +3 -2
  41. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/analyze/graph/base.py +266 -9
  42. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/analyze/graph/model.py +3 -3
  43. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/analyze/graph/style.py +244 -92
  44. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/analyze/history.py +27 -21
  45. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/analyze/phases.py +16 -14
  46. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/analyze/result.py +48 -14
  47. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/analyze/tabulate.py +31 -31
  48. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/architecture/action.py +111 -64
  49. fmdtools-2.2.0/fmdtools/define/architecture/base.py +673 -0
  50. fmdtools-2.2.0/fmdtools/define/architecture/component.py +116 -0
  51. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/architecture/function.py +47 -304
  52. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/architecture/geom.py +82 -6
  53. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/base.py +88 -2
  54. fmdtools-2.2.0/fmdtools/define/block/action.py +126 -0
  55. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/block/base.py +416 -173
  56. fmdtools-2.2.0/fmdtools/define/block/component.py +97 -0
  57. fmdtools-2.2.0/fmdtools/define/block/function.py +148 -0
  58. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/container/base.py +29 -15
  59. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/container/mode.py +10 -16
  60. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/container/rand.py +60 -51
  61. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/container/state.py +32 -26
  62. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/container/time.py +65 -28
  63. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/environment.py +30 -11
  64. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/flow/base.py +5 -13
  65. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/flow/commsflow.py +39 -44
  66. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/flow/multiflow.py +39 -20
  67. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/object/base.py +335 -154
  68. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/object/coords.py +121 -94
  69. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/object/geom.py +159 -85
  70. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/object/timer.py +4 -2
  71. fmdtools-2.2.0/fmdtools/sim/propagate.py +1200 -0
  72. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/sim/sample.py +32 -28
  73. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/sim/scenario.py +13 -1
  74. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/sim/search.py +84 -102
  75. {fmdtools-2.1.2 → fmdtools-2.2.0/fmdtools.egg-info}/PKG-INFO +20 -20
  76. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools.egg-info/requires.txt +2 -2
  77. {fmdtools-2.1.2 → fmdtools-2.2.0}/pyproject.toml +5 -5
  78. {fmdtools-2.1.2 → fmdtools-2.2.0}/tests/test_graph.py +11 -10
  79. {fmdtools-2.1.2 → fmdtools-2.2.0}/tests/test_hierarchical.py +15 -6
  80. fmdtools-2.1.2/fmdtools/define/architecture/base.py +0 -403
  81. fmdtools-2.1.2/fmdtools/define/architecture/component.py +0 -52
  82. fmdtools-2.1.2/fmdtools/define/block/action.py +0 -102
  83. fmdtools-2.1.2/fmdtools/define/block/component.py +0 -29
  84. fmdtools-2.1.2/fmdtools/define/block/function.py +0 -231
  85. fmdtools-2.1.2/fmdtools/sim/propagate.py +0 -1238
  86. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/__init__.py +0 -0
  87. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/asg_demo/__init__.py +0 -0
  88. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/eps/__init__.py +0 -0
  89. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/multiflow_demo/__init__.py +0 -0
  90. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/multirotor/__init__.py +0 -0
  91. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/pump/__init__.py +0 -0
  92. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/pump/jointfaults_ex.py +0 -0
  93. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/rover/__init__.py +0 -0
  94. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/rover/optimization/ea_analysis.py +0 -0
  95. {fmdtools-2.1.2 → fmdtools-2.2.0}/examples/tank/__init__.py +0 -0
  96. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/analyze/__init__.py +0 -0
  97. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/analyze/graph/label.py +0 -0
  98. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/__init__.py +0 -0
  99. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/architecture/__init__.py +0 -0
  100. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/block/__init__.py +0 -0
  101. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/container/__init__.py +0 -0
  102. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/container/parameter.py +0 -0
  103. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/flow/__init__.py +0 -0
  104. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/define/object/__init__.py +0 -0
  105. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools/sim/__init__.py +0 -0
  106. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools.egg-info/SOURCES.txt +0 -0
  107. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools.egg-info/dependency_links.txt +0 -0
  108. {fmdtools-2.1.2 → fmdtools-2.2.0}/fmdtools.egg-info/top_level.txt +0 -0
  109. {fmdtools-2.1.2 → fmdtools-2.2.0}/setup.cfg +0 -0
  110. {fmdtools-2.1.2 → fmdtools-2.2.0}/tests/test_packages.py +0 -0
@@ -1,4 +1,4 @@
1
- fmdtools version 2.1.2
1
+ fmdtools version 2.2.0
2
2
  ---------------------------
3
3
  Apache License
4
4
  Version 2.0, January 2004
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fmdtools
3
- Version: 2.1.2
3
+ Version: 2.2.0
4
4
  Summary: System resilience modelling, simulation, and assessment in Python
5
5
  Author: fmdtools Developers
6
6
  Maintainer-email: Daniel Hulse <daniel.e.hulse@nasa.gov>
7
- License: fmdtools version 2.1.2
7
+ License: fmdtools version 2.2.0
8
8
  ---------------------------
9
9
  Apache License
10
10
  Version 2.0, January 2004
@@ -236,24 +236,24 @@ Project-URL: Documentation, https://nasa.github.io/fmdtools/
236
236
  Project-URL: source-code, https://github.com/nasa/fmdtools
237
237
  Classifier: Development Status :: 5 - Production/Stable
238
238
  Classifier: Intended Audience :: Science/Research
239
- Classifier: Programming Language :: Python :: 3.10
240
239
  Classifier: Programming Language :: Python :: 3.11
241
240
  Classifier: Programming Language :: Python :: 3.12
241
+ Classifier: Programming Language :: Python :: 3.13
242
242
  Classifier: License :: OSI Approved :: Apache Software License
243
243
  Classifier: Operating System :: OS Independent
244
244
  Classifier: Topic :: Scientific/Engineering
245
- Requires-Python: >=3.10
245
+ Requires-Python: >=3.11
246
246
  Description-Content-Type: text/markdown
247
247
  License-File: LICENSE
248
248
  Requires-Dist: scipy
249
249
  Requires-Dist: tqdm
250
250
  Requires-Dist: networkx
251
- Requires-Dist: numpy<=1.26.4,>1.10
251
+ Requires-Dist: numpy>=2.0
252
252
  Requires-Dist: matplotlib>=3.7.0
253
253
  Requires-Dist: pandas
254
254
  Requires-Dist: ordered-set
255
255
  Requires-Dist: dill
256
- Requires-Dist: recordclass==0.22.1
256
+ Requires-Dist: recordclass==0.23.1
257
257
  Requires-Dist: pytest
258
258
  Requires-Dist: graphviz
259
259
  Requires-Dist: shapely>=2.0
@@ -263,15 +263,15 @@ Dynamic: license-file
263
263
 
264
264
  # Overview
265
265
 
266
- ![Python Version](https://img.shields.io/badge/Python-3.11-blue)
266
+ ![Python Version](https://img.shields.io/badge/Python-3.13-blue)
267
267
  [![PyPI](https://img.shields.io/pypi/v/fmdtools)](https://pypi.org/project/fmdtools/)
268
268
  [![Total Downloads](https://static.pepy.tech/badge/fmdtools)](https://pepy.tech/project/fmdtools)
269
269
  [![Downloads/Month](https://static.pepy.tech/badge/fmdtools/month)](https://pepy.tech/project/fmdtools)
270
270
  [![GitHub release (latest by date)](https://img.shields.io/github/v/release/nasa/fmdtools?label=GitHub%20Release)](https://github.com/nasa/fmdtools/releases)
271
271
  [![GitHub Tag](https://img.shields.io/github/v/tag/nasa/fmdtools)](https://github.com/nasa/fmdtools/tags)
272
272
  [![CodeFactor](https://www.codefactor.io/repository/github/nasa/fmdtools/badge)](https://www.codefactor.io/repository/github/nasa/fmdtools)
273
- [![Tests Status](./reports/full-py311/tests-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/full-py311/junit/report.html)
274
- [![Tests Coverage](./reports/full-py311/coverage-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/full-py311/coverage_html/index.html)
273
+ [![Tests Status](./reports/full-py313/tests-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/full-py313/junit/report.html)
274
+ [![Tests Coverage](./reports/full-py313/coverage-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/full-py313/coverage_html/index.html)
275
275
  [![GitHub License](https://img.shields.io/badge/License-Apache%202.0-green)](https://github.com/nasa/fmdtools/blob/main/LICENSE)
276
276
  [![NASA Software Classification](https://img.shields.io/badge/Software_Class-E-blue)](https://nodis3.gsfc.nasa.gov/displayDir.cfm?Internal_ID=N_PR_7150_002D_&page_name=AppendixD)
277
277
 
@@ -306,23 +306,23 @@ The fmdtools documentation repository is also home to the Functional Reasoning D
306
306
 
307
307
  ### Python version compatibility
308
308
 
309
- The fmdtools library is developed in Python 3.11 but tested to maintain compatibility over three versions of Python. See current doctest reports below:
309
+ The fmdtools library is developed in Python 3.13 but is tested to maintain compatibility over three versions of Python. See current doctest reports below:
310
310
 
311
311
  | Python Version | Doctests |
312
312
  | -------- | ------- |
313
- | 3.10 | [![Python 3.10 Tests](./reports/doctests-py310/tests-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/doctests-py310/junit/report.html) |
314
- | 3.11 | [![Python 3.11 Tests](./reports/doctests-py311/tests-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/doctests-py311/junit/report.html) |
315
- | 3.12 | [![Python 3.12 Tests](./reports/doctests-py312/tests-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/doctests-py312/junit/report.html) |
313
+ | 3.11 | [![Python 3.11 Tests](./reports/doctests-py311/tests-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/doctests-py311/junit/report.html) |
314
+ | 3.12 | [![Python 3.12 Tests](./reports/doctests-py312/tests-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/doctests-py312/junit/report.html) |
315
+ | 3.13 | [![Python 3.13 Tests](./reports/doctests-py313/tests-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/doctests-py313/junit/report.html) |
316
316
 
317
- Further (functional and integration) tests are performed in the Python 3.11 to ensure that examples run as desired. Thus, it is generally reccommended to use Python 3.11 to keep pace with development, especially when running examples.
317
+ Further (functional and integration) tests are performed in the Python 3.13 to ensure that examples run as desired. Thus, it is generally reccommended to use Python 3.13 with this version to keep pace with development, especially when running examples.
318
318
 
319
319
  ### Set up python tooling environment
320
320
 
321
321
  The fmdtools library was developed to run in a python development environments.
322
322
 
323
- If you do not have an existing python environment, first [download and install anaconda](https://docs.anaconda.com/free/anaconda/install/index.html) or [uv]().
323
+ If you do not have an existing python environment, first [download and install anaconda](https://docs.anaconda.com/free/anaconda/install/index.html) or [uv](https://docs.astral.sh/uv/).
324
324
 
325
- After the base installation, set up a new `Python 3.11` environment for fmdtools and install these external external packages in it:
325
+ After the base installation, set up a new `Python 3.13` environment for fmdtools and install these external external packages in it:
326
326
 
327
327
  ```
328
328
  spyder-kernels
@@ -367,13 +367,13 @@ This may then be installed using:
367
367
  Note that this version reflects the latest version on the ``main`` git branch along with any local changes. To use a particular version of ``fmdtools`` you can checkout the tag corresponding to the version you want, e.g.:
368
368
 
369
369
  ```
370
- git checkout v2.1.2
370
+ git checkout v2.2.0
371
371
  ```
372
372
 
373
373
 
374
374
  #### Dependencies
375
375
 
376
- fmdtools requires `Python 3.11` and depends directly on the packages below (see requirements.txt). Note that the use of these depencencies is governed by their respective licences, which may be obtained at the provided links.
376
+ fmdtools requires `Python 3.13` and depends directly on the packages below (see requirements.txt). Note that the use of these depencencies is governed by their respective licences, which may be obtained at the provided links.
377
377
 
378
378
  ```
379
379
  scipy
@@ -505,8 +505,8 @@ To cite a particular version of the fmdtools, you may use:
505
505
  author = {{NASA}},
506
506
  title = {fmdtools},
507
507
  url = {https://github.com/nasa/fmdtools},
508
- version = {2.1.2},
509
- date = {2025-5-19},
508
+ version = {2.2.0},
509
+ date = {2025-6-6},
510
510
  }
511
511
  ```
512
512
 
@@ -2,15 +2,15 @@
2
2
 
3
3
  # Overview
4
4
 
5
- ![Python Version](https://img.shields.io/badge/Python-3.11-blue)
5
+ ![Python Version](https://img.shields.io/badge/Python-3.13-blue)
6
6
  [![PyPI](https://img.shields.io/pypi/v/fmdtools)](https://pypi.org/project/fmdtools/)
7
7
  [![Total Downloads](https://static.pepy.tech/badge/fmdtools)](https://pepy.tech/project/fmdtools)
8
8
  [![Downloads/Month](https://static.pepy.tech/badge/fmdtools/month)](https://pepy.tech/project/fmdtools)
9
9
  [![GitHub release (latest by date)](https://img.shields.io/github/v/release/nasa/fmdtools?label=GitHub%20Release)](https://github.com/nasa/fmdtools/releases)
10
10
  [![GitHub Tag](https://img.shields.io/github/v/tag/nasa/fmdtools)](https://github.com/nasa/fmdtools/tags)
11
11
  [![CodeFactor](https://www.codefactor.io/repository/github/nasa/fmdtools/badge)](https://www.codefactor.io/repository/github/nasa/fmdtools)
12
- [![Tests Status](./reports/full-py311/tests-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/full-py311/junit/report.html)
13
- [![Tests Coverage](./reports/full-py311/coverage-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/full-py311/coverage_html/index.html)
12
+ [![Tests Status](./reports/full-py313/tests-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/full-py313/junit/report.html)
13
+ [![Tests Coverage](./reports/full-py313/coverage-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/full-py313/coverage_html/index.html)
14
14
  [![GitHub License](https://img.shields.io/badge/License-Apache%202.0-green)](https://github.com/nasa/fmdtools/blob/main/LICENSE)
15
15
  [![NASA Software Classification](https://img.shields.io/badge/Software_Class-E-blue)](https://nodis3.gsfc.nasa.gov/displayDir.cfm?Internal_ID=N_PR_7150_002D_&page_name=AppendixD)
16
16
 
@@ -45,23 +45,23 @@ The fmdtools documentation repository is also home to the Functional Reasoning D
45
45
 
46
46
  ### Python version compatibility
47
47
 
48
- The fmdtools library is developed in Python 3.11 but tested to maintain compatibility over three versions of Python. See current doctest reports below:
48
+ The fmdtools library is developed in Python 3.13 but is tested to maintain compatibility over three versions of Python. See current doctest reports below:
49
49
 
50
50
  | Python Version | Doctests |
51
51
  | -------- | ------- |
52
- | 3.10 | [![Python 3.10 Tests](./reports/doctests-py310/tests-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/doctests-py310/junit/report.html) |
53
- | 3.11 | [![Python 3.11 Tests](./reports/doctests-py311/tests-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/doctests-py311/junit/report.html) |
54
- | 3.12 | [![Python 3.12 Tests](./reports/doctests-py312/tests-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/doctests-py312/junit/report.html) |
52
+ | 3.11 | [![Python 3.11 Tests](./reports/doctests-py311/tests-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/doctests-py311/junit/report.html) |
53
+ | 3.12 | [![Python 3.12 Tests](./reports/doctests-py312/tests-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/doctests-py312/junit/report.html) |
54
+ | 3.13 | [![Python 3.13 Tests](./reports/doctests-py313/tests-badge.svg)](https://htmlpreview.github.io/?https://github.com/nasa/fmdtools/blob/main/reports/doctests-py313/junit/report.html) |
55
55
 
56
- Further (functional and integration) tests are performed in the Python 3.11 to ensure that examples run as desired. Thus, it is generally reccommended to use Python 3.11 to keep pace with development, especially when running examples.
56
+ Further (functional and integration) tests are performed in the Python 3.13 to ensure that examples run as desired. Thus, it is generally reccommended to use Python 3.13 with this version to keep pace with development, especially when running examples.
57
57
 
58
58
  ### Set up python tooling environment
59
59
 
60
60
  The fmdtools library was developed to run in a python development environments.
61
61
 
62
- If you do not have an existing python environment, first [download and install anaconda](https://docs.anaconda.com/free/anaconda/install/index.html) or [uv]().
62
+ If you do not have an existing python environment, first [download and install anaconda](https://docs.anaconda.com/free/anaconda/install/index.html) or [uv](https://docs.astral.sh/uv/).
63
63
 
64
- After the base installation, set up a new `Python 3.11` environment for fmdtools and install these external external packages in it:
64
+ After the base installation, set up a new `Python 3.13` environment for fmdtools and install these external external packages in it:
65
65
 
66
66
  ```
67
67
  spyder-kernels
@@ -106,13 +106,13 @@ This may then be installed using:
106
106
  Note that this version reflects the latest version on the ``main`` git branch along with any local changes. To use a particular version of ``fmdtools`` you can checkout the tag corresponding to the version you want, e.g.:
107
107
 
108
108
  ```
109
- git checkout v2.1.2
109
+ git checkout v2.2.0
110
110
  ```
111
111
 
112
112
 
113
113
  #### Dependencies
114
114
 
115
- fmdtools requires `Python 3.11` and depends directly on the packages below (see requirements.txt). Note that the use of these depencencies is governed by their respective licences, which may be obtained at the provided links.
115
+ fmdtools requires `Python 3.13` and depends directly on the packages below (see requirements.txt). Note that the use of these depencencies is governed by their respective licences, which may be obtained at the provided links.
116
116
 
117
117
  ```
118
118
  scipy
@@ -244,8 +244,8 @@ To cite a particular version of the fmdtools, you may use:
244
244
  author = {{NASA}},
245
245
  title = {fmdtools},
246
246
  url = {https://github.com/nasa/fmdtools},
247
- version = {2.1.2},
248
- date = {2025-5-19},
247
+ version = {2.2.0},
248
+ date = {2025-6-6},
249
249
  }
250
250
  ```
251
251
 
@@ -33,7 +33,6 @@ class OutcomeStates(State):
33
33
 
34
34
  class Outcome(Flow):
35
35
 
36
- __slots__ = ()
37
36
  container_s = OutcomeStates
38
37
 
39
38
 
@@ -47,7 +46,6 @@ class HazardState(State):
47
46
 
48
47
  class Hazard(Flow):
49
48
 
50
- __slots__ = ()
51
49
  container_s = HazardState
52
50
 
53
51
 
@@ -61,12 +59,11 @@ class ActionMode(Mode):
61
59
  class Perceive(Action):
62
60
  """A user's perception abilities/behaviors for percieving the hazard."""
63
61
 
64
- __slots__ = ('hazard', 'outcome')
65
62
  container_m = ActionMode
66
63
  flow_hazard = Hazard
67
64
  flow_outcome = Outcome
68
65
 
69
- def behavior(self, time):
66
+ def dynamic_behavior(self):
70
67
  if not self.m.in_mode('failed', 'unable'):
71
68
  self.hazard.s.percieved = self.hazard.s.present
72
69
  self.outcome.s.num_perceptions += self.hazard.s.percieved
@@ -81,12 +78,11 @@ class Perceive(Action):
81
78
  class Act(Action):
82
79
  """User actions to mitigate the hazard."""
83
80
 
84
- __slots__ = ('hazard', 'outcome')
85
81
  container_m = ActionMode
86
82
  flow_hazard = Hazard
87
83
  flow_outcome = Outcome
88
84
 
89
- def behavior(self, time):
85
+ def dynamic_behavior(self):
90
86
  if not self.m.in_mode('failed', 'unable'):
91
87
  self.outcome.s.num_actions += 1
92
88
  self.hazard.s.mitigated = True
@@ -103,10 +99,9 @@ class Act(Action):
103
99
  class Done(Action):
104
100
  """User state after performing the action."""
105
101
 
106
- __slots__ = ('hazard')
107
102
  flow_hazard = Hazard
108
103
 
109
- def behavior(self, time):
104
+ def dynamic_behavior(self):
110
105
  if not self.hazard.s.present:
111
106
  self.hazard.s.mitigated = False
112
107
 
@@ -136,7 +131,6 @@ class Human(ActionArchitecture):
136
131
  class DetectHazard(Function):
137
132
  """Function containing the human."""
138
133
 
139
- __slots__ = ('hazard')
140
134
  container_m = Mode
141
135
  arch_aa = Human
142
136
  flow_hazard = Hazard
@@ -145,11 +139,10 @@ class DetectHazard(Function):
145
139
  class ProduceHazard(Function):
146
140
  """Function producing Hazards."""
147
141
 
148
- __slots__ = ('hazard',)
149
142
  flow_hazard = Hazard
150
143
 
151
- def dynamic_behavior(self, time):
152
- if not time % 4:
144
+ def dynamic_behavior(self):
145
+ if not self.t.time % 4:
153
146
  self.hazard.s.present = True
154
147
  else:
155
148
  self.hazard.s.present = False
@@ -165,11 +158,10 @@ class PassStates(State):
165
158
  class PassHazard(Function):
166
159
  """Accumulates total hazards/mitigations."""
167
160
 
168
- __slots__ = ('hazard',)
169
161
  container_s = PassStates
170
162
  flow_hazard = Hazard
171
163
 
172
- def dynamic_behavior(self, time):
164
+ def dynamic_behavior(self):
173
165
  if self.hazard.s.present and self.hazard.s.mitigated:
174
166
  self.s.hazards_mitigated += 1
175
167
  elif self.hazard.s.present and not self.hazard.s.mitigated:
@@ -179,7 +171,6 @@ class PassHazard(Function):
179
171
  class HazardModel(FunctionArchitecture):
180
172
  """Overall model of the human in context."""
181
173
 
182
- __slots__ = ()
183
174
  default_sp = dict(end_time=60, dt=1.0)
184
175
 
185
176
  def init_architecture(self, **kwargs):
@@ -194,9 +185,9 @@ if __name__ == '__main__':
194
185
  mdl = HazardModel()
195
186
  result_fault, mdlhist_fault = prop.one_fault(mdl, 'detect_hazard.aa.acts.act',
196
187
  'unable', time=4,
197
- desired_result='graph')
188
+ to_return='graph')
198
189
 
199
- result_fault.graph.draw()
190
+ result_fault.get_faulty().tend.graph.draw()
200
191
  ex_fxn = DetectHazard('detect_hazard')
201
192
  result_indiv, hist_indiv = prop.nominal(ex_fxn,
202
193
  disturbances={5:{'aa.flows.hazard.s.present':True}})
@@ -206,5 +197,5 @@ if __name__ == '__main__':
206
197
 
207
198
  result_fault, mdlhist_fault = prop.one_fault(mdl, 'detect_hazard.aa.acts.perceive',
208
199
  'failed', time=4,
209
- desired_result='graph.fxns.detect_hazard.aa')
210
- result_fault.graph.fxns.detect_hazard.aa.draw_graphviz(layout='dot')
200
+ to_return='graph.fxns.detect_hazard.aa')
201
+ result_fault.get_faulty().tend.graph.fxns.detect_hazard.aa.draw_graphviz(layout='dot')
@@ -44,7 +44,6 @@ class GenericState(State):
44
44
 
45
45
  class GenericFlow(Flow):
46
46
 
47
- __slots__ = ()
48
47
  container_s = GenericState
49
48
 
50
49
 
@@ -53,7 +52,6 @@ class SigState(State):
53
52
 
54
53
 
55
54
  class Signal(Flow):
56
- __slots__ = ()
57
55
  container_s = SigState
58
56
 
59
57
 
@@ -65,7 +63,6 @@ class ImportEEModes(Mode):
65
63
 
66
64
  class ImportEE(Function):
67
65
 
68
- __slots__ = ("ee_out",)
69
66
  container_m = ImportEEModes
70
67
  flow_ee_out = GenericFlow
71
68
  flownames = {"ee_1": "ee_out"}
@@ -84,7 +81,7 @@ class ImportEE(Function):
84
81
  Both representations can be used--this just shows this representation.
85
82
  """
86
83
 
87
- def static_behavior(self, time):
84
+ def static_behavior(self):
88
85
  if self.m.has_fault("no_v"):
89
86
  self.ee_out.s.effort = 0.0
90
87
  elif self.m.has_fault("high_v"):
@@ -102,12 +99,11 @@ class ImportSigModes(Mode):
102
99
 
103
100
  class ImportSig(Function):
104
101
 
105
- __slots__ = ("sig_out",)
106
102
  container_m = ImportSigModes
107
103
  flow_sig_out = Signal
108
104
  flownames = {"sig_in": "sig_out"}
109
105
 
110
- def static_behavior(self, time):
106
+ def static_behavior(self):
111
107
  if self.m.has_fault("partial_signal"):
112
108
  self.sig_out.s.value = 0.5
113
109
  elif self.m.has_fault("no_signal"):
@@ -123,7 +119,6 @@ class StoreEEModes(Mode):
123
119
 
124
120
  class StoreEE(Function):
125
121
 
126
- __slots__ = ("ee_in", "ee_out")
127
122
  container_m = StoreEEModes
128
123
  flow_ee_in = GenericFlow
129
124
  flow_ee_out = GenericFlow
@@ -135,7 +130,7 @@ class StoreEE(Function):
135
130
  elif self.ee_out.s.effort * self.ee_out.s.rate >= 2.0:
136
131
  self.m.add_fault("low_storage")
137
132
 
138
- def static_behavior(self, time):
133
+ def static_behavior(self):
139
134
  self.set_faults()
140
135
  if self.m.has_fault("no_storage"):
141
136
  self.ee_out.s.effort = 0.0
@@ -158,7 +153,6 @@ class SupplyEEModes(Mode):
158
153
 
159
154
  class SupplyEE(Function):
160
155
 
161
- __slots__ = ("ee_in", "ee_out", "heat_out")
162
156
  container_m = SupplyEEModes
163
157
  flow_ee_in = GenericFlow
164
158
  flow_ee_out = GenericFlow
@@ -171,7 +165,7 @@ class SupplyEE(Function):
171
165
  elif self.ee_out.s.rate > 1.0:
172
166
  self.m.add_fault("open_circuit")
173
167
 
174
- def static_behavior(self, time):
168
+ def static_behavior(self):
175
169
  self.set_faults()
176
170
  if self.m.has_fault("open_circuit"):
177
171
  self.ee_out.s.effort = 0.0
@@ -201,7 +195,6 @@ class DistEEModes(Mode):
201
195
 
202
196
  class DistEE(Function):
203
197
 
204
- __slots__ = ("sig_in", "ee_in", "ee_m", "ee_h", "ee_o")
205
198
  container_m = DistEEModes
206
199
  flow_sig_in = Signal
207
200
  flow_ee_in = GenericFlow
@@ -214,7 +207,7 @@ class DistEE(Function):
214
207
  if max(self.ee_m.s.rate, self.ee_h.s.rate, self.ee_o.s.rate) > 2.0:
215
208
  self.m.add_fault("short")
216
209
 
217
- def static_behavior(self, time):
210
+ def static_behavior(self):
218
211
  self.set_faults()
219
212
  if self.m.has_fault("short"):
220
213
  self.ee_in.s.rate = self.ee_in.s.effort * 4.0
@@ -253,12 +246,11 @@ class ExportHEModes(Mode):
253
246
 
254
247
  class ExportHE(Function):
255
248
 
256
- __slots__ = ("he",)
257
249
  container_m = ExportHEModes
258
250
  flow_he = GenericFlow
259
251
  flownames = {"waste_he_1": "he", "waste_he_o": "he", "waste_he_m": "he"}
260
252
 
261
- def static_behavior(self, time):
253
+ def static_behavior(self):
262
254
  if self.m.has_fault("ineffective_sink"):
263
255
  self.he.s.rate = 4.0
264
256
  elif self.m.has_fault("hot_sink"):
@@ -269,19 +261,17 @@ class ExportHE(Function):
269
261
 
270
262
  class ExportME(Function):
271
263
 
272
- __slots__ = ("me",)
273
264
  flow_me = GenericFlow
274
265
 
275
- def static_behavior(self, time):
266
+ def static_behavior(self):
276
267
  self.me.s.rate = self.me.s.effort
277
268
 
278
269
 
279
270
  class ExportOE(Function):
280
271
 
281
- __slots__ = ("oe",)
282
272
  flow_oe = GenericFlow
283
273
 
284
- def static_behavior(self, time):
274
+ def static_behavior(self):
285
275
  self.oe.s.rate = self.oe.s.effort
286
276
 
287
277
 
@@ -295,14 +285,13 @@ class EEtoMEModes(Mode):
295
285
 
296
286
  class EEtoME(Function):
297
287
 
298
- __slots__ = ("ee_in", "me", "he_out")
299
288
  container_m = EEtoMEModes
300
289
  flow_ee_in = GenericFlow
301
290
  flow_me = GenericFlow
302
291
  flow_he_out = GenericFlow
303
292
  flownames = {"ee_m": "ee_in", "waste_he_m": "he_out"}
304
293
 
305
- def static_behavior(self, time):
294
+ def static_behavior(self):
306
295
  if self.m.has_fault("high_torque"):
307
296
  self.he_out.s.effort = self.ee_in.s.effort + 1.0
308
297
  self.me.s.effort = self.ee_in.s.effort + 1.0
@@ -341,7 +330,6 @@ class EEtoHEModes(Mode):
341
330
 
342
331
  class EEtoHE(Function):
343
332
 
344
- __slots__ = ("ee_in", "he")
345
333
  container_m = EEtoHEModes
346
334
  flow_ee_in = GenericFlow
347
335
  flow_he = GenericFlow
@@ -353,7 +341,7 @@ class EEtoHE(Function):
353
341
  elif self.ee_in.s.effort > 1.0:
354
342
  self.m.add_fault("low_heat")
355
343
 
356
- def static_behavior(self, time):
344
+ def static_behavior(self):
357
345
  if self.m.has_fault("open_circuit"):
358
346
  self.he.s.effort = 0.0
359
347
  self.ee_in.s.rate = 0.0
@@ -378,7 +366,6 @@ class EEtoOEModes(Mode):
378
366
 
379
367
  class EEtoOE(Function):
380
368
 
381
- __slots__ = ("ee_in", "oe", "he_out")
382
369
  container_m = EEtoOEModes
383
370
  flow_ee_in = GenericFlow
384
371
  flow_oe = GenericFlow
@@ -389,7 +376,7 @@ class EEtoOE(Function):
389
376
  if self.ee_in.s.effort >= 2.0:
390
377
  self.m.add_fault("burnt_out")
391
378
 
392
- def static_behavior(self, time):
379
+ def static_behavior(self):
393
380
  if self.m.has_fault("burnt_out"):
394
381
  self.ee_in.s.rate = 0.0
395
382
  self.he_out.s.effort = 0.0
@@ -406,7 +393,6 @@ class EEtoOE(Function):
406
393
 
407
394
  class EPS(FunctionArchitecture):
408
395
 
409
- __slots__ = ()
410
396
  default_track = {"flows": ["he", "me", "oe"]}
411
397
  default_sp = {'end_time': 0}
412
398
 
@@ -444,7 +430,7 @@ class EPS(FunctionArchitecture):
444
430
  self.add_fxn("export_waste_ho", ExportHE, "waste_he_o")
445
431
  self.add_fxn("export_waste_hm", ExportHE, "waste_he_m")
446
432
 
447
- def find_classification(self, scen, mdlhists):
433
+ def classify(self, scen={}, mdlhists={}, **kwargs):
448
434
  outflows = ["he", "me", "oe"]
449
435
 
450
436
  qualfunc = [
@@ -493,12 +479,12 @@ if __name__ == "__main__":
493
479
  result, mdlhists = propagate.one_fault(mdl, "distribute_ee", "short")
494
480
 
495
481
  result, mdlhists = propagate.one_fault(mdl, "distribute_ee", "short",
496
- desired_result="graph")
482
+ to_return="graph")
497
483
 
498
- result.graph.draw()
484
+ result.get_faulty().tend.graph.draw()
499
485
  # endclasses, mdlhists = propagate.single_faults(mdl)
500
486
 
501
- # resgraph, mdlhists = propagate.one_fault(mdl, 'ee_to_me', 'toohigh_torque', desired_result="fxnflowgraph")
487
+ # resgraph, mdlhists = propagate.one_fault(mdl, 'ee_to_me', 'toohigh_torque', to_return="fxnflowgraph")
502
488
  # result.graph.draw()
503
489
  ks = [*mdl.get_roles_as_dict("fxn", "flow", flex_prefixes=True)]
504
490
 
@@ -39,16 +39,18 @@ class epsTests(unittest.TestCase, CommonTests):
39
39
  backwards through the graph as expected - distributor short leads to empty battery
40
40
  """
41
41
  res, hist = prop.one_fault(self.mdl, "distribute_ee", "short",
42
- desired_result="endfaults")
43
- self.assertEqual(res["endfaults"], ['store_ee.no_storage', 'distribute_ee.short'])
42
+ to_return="faults")
43
+ self.assertEqual(res.get_faulty().tend.faults,
44
+ ['store_ee.no_storage', 'distribute_ee.short'])
44
45
 
45
46
  def test_backward_fault_prop_2(self):
46
47
  """Tests that defined fault cases that require reverse propagation propagate
47
48
  backwards through the graph as expected - motor short leads to distributor short
48
49
  """
49
50
  res, hist = prop.one_fault(self.mdl, "ee_to_me", "short",
50
- desired_result="endfaults")
51
- self.assertEqual(res["endfaults"], ['store_ee.no_storage', 'distribute_ee.short', 'ee_to_me.short'])
51
+ to_return="faults")
52
+ self.assertEqual(res.get_faulty().tend.faults,
53
+ ['store_ee.no_storage', 'distribute_ee.short', 'ee_to_me.short'])
52
54
 
53
55
  def test_all_faults(self):
54
56
  """Some basic tests for propagating lists of faults in the model--
@@ -82,7 +84,6 @@ class epsTests(unittest.TestCase, CommonTests):
82
84
  fs.add_fault_phases(n_joint=n_joint)
83
85
  # tests the length
84
86
  self.assertEqual(len(fs.scenarios()), math.comb(actual_num_faults, n_joint))
85
- ec, hists = prop.fault_sample(self.mdl, fs, showprogress=False)
86
87
 
87
88
  def test_pickleability(self):
88
89
  unpickleable = check_pickleability(self.mdl, verbose=False)
@@ -117,9 +118,17 @@ class epsTests(unittest.TestCase, CommonTests):
117
118
 
118
119
 
119
120
  if __name__ == "__main__":
121
+ import sys
122
+ sys.path.append("../..")
123
+
124
+ # suite = unittest.TestSuite()
125
+ # suite.addTest(epsTests("test_fault_app"))
126
+ # runner = unittest.TextTestRunner()
127
+ # runner.run(suite)
128
+
120
129
  unittest.main()
121
130
 
122
- mdl = EPS()
131
+ # mdl = EPS()
123
132
 
124
133
 
125
134
  # endresults, resgraph, mdlhist = propagate.one_fault(mdl, 'Distribute_EE', 'short')