fmdtools 2.5.0__tar.gz → 2.5.2__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.
- {fmdtools-2.5.0 → fmdtools-2.5.2}/LICENSE +1 -1
- {fmdtools-2.5.0 → fmdtools-2.5.2}/PKG-INFO +26 -9
- {fmdtools-2.5.0 → fmdtools-2.5.2}/README.md +24 -7
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/water_rescue/model_responder.py +7 -8
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/multirotor_drone/test_multirotor.py +1 -1
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/navigating_rover/test_rover.py +4 -3
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/water_pump/model_main.py +8 -6
- {fmdtools-2.5.0 → fmdtools-2.5.2}/fmdtools.egg-info/PKG-INFO +26 -9
- {fmdtools-2.5.0 → fmdtools-2.5.2}/fmdtools.egg-info/SOURCES.txt +25 -1
- {fmdtools-2.5.0 → fmdtools-2.5.2}/pyproject.toml +1 -1
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/__init__.py +1 -1
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/analyze/common.py +27 -18
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/analyze/history.py +12 -3
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/analyze/phases.py +7 -3
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/analyze/result.py +32 -18
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/analyze/tabulate.py +3 -1
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/architecture/component.py +0 -2
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/architecture/geom.py +4 -4
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/base.py +10 -7
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/container/base.py +2 -2
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/container/rand.py +25 -2
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/container/time.py +1 -1
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/environment.py +6 -7
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/object/base.py +67 -43
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/object/coords.py +35 -12
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/object/geom.py +109 -26
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/sim/propagate.py +7 -3
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/sim/sample.py +16 -12
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/sim/scenario.py +3 -3
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/sim/search.py +2 -2
- fmdtools-2.5.2/tests/test_array_random_states.py +182 -0
- fmdtools-2.5.2/tests/test_calc_metric_ci_constant_outputs.py +218 -0
- fmdtools-2.5.2/tests/test_comparison_groups.py +162 -0
- fmdtools-2.5.2/tests/test_confidence_history_clipping.py +181 -0
- fmdtools-2.5.2/tests/test_error_history_plots.py +197 -0
- fmdtools-2.5.2/tests/test_fault_sample_without_nominal.py +231 -0
- fmdtools-2.5.2/tests/test_fault_time_without_traces.py +141 -0
- fmdtools-2.5.2/tests/test_geom.py +139 -0
- fmdtools-2.5.2/tests/test_history_standard_deviation.py +95 -0
- fmdtools-2.5.2/tests/test_join_phasemaps.py +94 -0
- fmdtools-2.5.2/tests/test_joint_fault_weights.py +116 -0
- fmdtools-2.5.2/tests/test_nested_nominal_groups.py +200 -0
- fmdtools-2.5.2/tests/test_nesting_custom_separators.py +151 -0
- fmdtools-2.5.2/tests/test_parameter_sample_seeds.py +104 -0
- fmdtools-2.5.2/tests/test_parameter_subsampling_types.py +147 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/tests/test_pathplan.py +0 -2
- fmdtools-2.5.2/tests/test_phase_timestep.py +73 -0
- fmdtools-2.5.2/tests/test_pruned_fault_times.py +163 -0
- fmdtools-2.5.2/tests/test_result.py +173 -0
- fmdtools-2.5.2/tests/test_sample.py +165 -0
- fmdtools-2.5.2/tests/test_scenario.py +111 -0
- fmdtools-2.5.2/tests/test_scenario_defaults.py +168 -0
- fmdtools-2.5.2/tests/test_table_factor_indices.py +154 -0
- fmdtools-2.5.2/tests/test_time.py +101 -0
- fmdtools-2.5.2/tests/test_uniform_density.py +83 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airport_taxiway/model_asset.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airport_taxiway/model_atc.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airport_taxiway/model_common.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airport_taxiway/model_main.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airport_taxiway/test_asset.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airport_taxiway/test_model.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/base/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/base/aircraft.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/base/aircraftarchitecture.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/base/arch/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/base/arch/aviate.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/base/arch/controlflight.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/base/arch/flows.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/base/arch/holdpayload.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/base/arch/perceiveenvironment.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/base/arch/storeee.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/base/parameter.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/base/state.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/contingency_management/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/contingency_management/model_aircraft.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/contingency_management/model_environment.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/contingency_management/model_flightplanner.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/water_rescue/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/water_rescue/model_drone.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/water_rescue/model_environment.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/water_rescue/model_main.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/wildfire_response/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/wildfire_response/model_aircraft.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/wildfire_response/model_environment.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/airspacelib/wildfire_response/model_main.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/cooling_tank/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/cooling_tank/model_main.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/cooling_tank/model_optimization.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/cooling_tank/test_tank.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/electric_power_system/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/electric_power_system/model_main.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/electric_power_system/test_model.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/human_hazard_mitigation/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/human_hazard_mitigation/model_main.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/multirotor_drone/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/multirotor_drone/model_dynamic.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/multirotor_drone/model_hierarchical.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/multirotor_drone/model_rural.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/multirotor_drone/model_static.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/multirotor_drone/model_urban.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/multirotor_drone/script_opt_model_rural.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/navigating_rover/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/navigating_rover/model_degradation.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/navigating_rover/model_human.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/navigating_rover/model_main.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/navigating_rover/model_troupe.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/navigating_rover/script_ea_analysis.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/navigating_rover/script_mode_space.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/navigating_rover/script_search_rover.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/state_communication/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/state_communication/model_main.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/state_communication/test_multiflow.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/water_pump/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/water_pump/model_indiv.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/water_pump/model_stochastic.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/water_pump/script_jointfaults.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/water_pump/script_parallelism.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/water_pump/test_pump.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/water_pump/test_pump_example.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/examples/water_pump/test_pump_stochastic.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/fmdtools.egg-info/dependency_links.txt +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/fmdtools.egg-info/requires.txt +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/fmdtools.egg-info/top_level.txt +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/setup.cfg +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/analyze/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/analyze/graph/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/analyze/graph/base.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/analyze/graph/label.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/analyze/graph/model.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/analyze/graph/style.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/architecture/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/architecture/action.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/architecture/base.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/architecture/function.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/block/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/block/action.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/block/base.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/block/component.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/block/function.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/container/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/container/mode.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/container/parameter.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/container/state.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/flow/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/flow/base.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/flow/commsflow.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/flow/multiflow.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/object/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/object/timer.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/define/pathplan.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/src/fmdtools/sim/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/tests/__init__.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/tests/common.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/tests/test_graph.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/tests/test_hierarchical.py +0 -0
- {fmdtools-2.5.0 → fmdtools-2.5.2}/tests/test_packages.py +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fmdtools
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.2
|
|
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.5.
|
|
7
|
+
License: fmdtools version 2.5.2
|
|
8
8
|
---------------------------
|
|
9
9
|
Apache License
|
|
10
10
|
Version 2.0, January 2004
|
|
@@ -306,8 +306,8 @@ The fmdtools library provides the computational support needed to perform a simu
|
|
|
306
306
|
|
|
307
307
|
<img align="left" width="100" height="100" src="/docs-source/figures/powerpoint/flexible.svg">
|
|
308
308
|
|
|
309
|
-
### Flexible Modelling Paradigm
|
|
310
|
-
Models in fmdtools use a
|
|
309
|
+
### Flexible, AI-Ready Modelling Paradigm
|
|
310
|
+
Models in fmdtools use a straightforward and composable code-based representation of system structure and behavior. Since fmdtools models are based on open-source Python, models can be readily generated from your AI of choice with the right prompting. Whether you want to model a simple component, a complex system-of-systems, or both, fmdtools can help.
|
|
311
311
|
|
|
312
312
|
<img align="left" width="100" height="100" src="/docs-source/figures/powerpoint/powerful.svg">
|
|
313
313
|
|
|
@@ -394,7 +394,7 @@ More guidance on development installations is provided in [How to Contribute](ht
|
|
|
394
394
|
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`` in the context of a development install you can checkout the tag corresponding to the version you want, e.g.:
|
|
395
395
|
|
|
396
396
|
```
|
|
397
|
-
git checkout v2.5.
|
|
397
|
+
git checkout v2.5.2
|
|
398
398
|
```
|
|
399
399
|
|
|
400
400
|
|
|
@@ -490,10 +490,27 @@ Once fmdtools is installed, use the following to get acquainted with how to use
|
|
|
490
490
|
|
|
491
491
|
- Explore more [examples](https://nasa.github.io/fmdtools/examples/Examples.html) of particular use-cases by going through the [examples folder](https://github.com/nasa/fmdtools/tree/main/examples)
|
|
492
492
|
|
|
493
|
-
- Read about contributions and model development best practices by perusing the [Development Guide](https://nasa.github.io/fmdtools/docs-source/
|
|
493
|
+
- Read about contributions and model development best practices by perusing the [Development Guide](https://nasa.github.io/fmdtools/docs-source/development-guide.html).
|
|
494
494
|
|
|
495
495
|
- Explore the searchable [module reference](https://nasa.github.io/fmdtools/docs-source/fmdtools.html) for syntax and usage documentation.
|
|
496
496
|
|
|
497
|
+
### AI/LLM Tips
|
|
498
|
+
|
|
499
|
+
Decent (but **very imperfect**) results can be achieved using LLMs for model development using the prompt:
|
|
500
|
+
|
|
501
|
+
```prompt
|
|
502
|
+
You are an experienced software engineer learning a new Python library for the first time.
|
|
503
|
+
Make an fmdtools simulation of a <enter your system here> using the latest syntax from `https://github.com/nasa/fmdtools/tree/v2.5.1` for all modeling (`fmdtools.define`), simulation (`fmdtools.sim`), and analysis (`fmdtools.analyze`) classes.
|
|
504
|
+
The output should be a bare bones but well-commented .py file with simple behaviors for each class and a small script at the bottom leveraging the built-in capabilities in the `fmdtools.analyze` package instead of directly using external libraries like matplotlib.
|
|
505
|
+
As you are going, explain the structure of each class, the usage of each function call and how they each leverage the correct fmdtools v2.5.1 syntax.
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
The important aspects of this prompt are specifying the URL and version--otherwise the LLM is likely to hallucinate usage or recall an earlier version of fmdtools. Do not expect perfect output from this--you may have to spend some time identifying the problems so they can be fixed!
|
|
509
|
+
|
|
510
|
+
For somewhat better results, we recommend using an on-machine coding "agent" such as OpenCode/Claude Code/Codex.
|
|
511
|
+
|
|
512
|
+
More elaborate prompts can be found in our [AGENTS.md](AGENTS.md) and repository skills at `.agents/skills`.
|
|
513
|
+
|
|
497
514
|
## Contributions
|
|
498
515
|
fmdtools is developed primarily by researchers at NASA Ames Research Center. External contributions are welcome under a Contributor License Agreement:
|
|
499
516
|
|
|
@@ -527,12 +544,12 @@ To cite fmdtools in general, you may cite our explanatory publication:
|
|
|
527
544
|
To cite a particular version of the fmdtools, you may use:
|
|
528
545
|
|
|
529
546
|
```
|
|
530
|
-
@software{
|
|
547
|
+
@software{nasa2026fmdtools,
|
|
531
548
|
author = {{NASA}},
|
|
532
549
|
title = {fmdtools},
|
|
533
550
|
url = {https://github.com/nasa/fmdtools},
|
|
534
|
-
version = {2.5.
|
|
535
|
-
date = {2026-
|
|
551
|
+
version = {2.5.2},
|
|
552
|
+
date = {2026-9-28},
|
|
536
553
|
}
|
|
537
554
|
```
|
|
538
555
|
|
|
@@ -35,8 +35,8 @@ The fmdtools library provides the computational support needed to perform a simu
|
|
|
35
35
|
|
|
36
36
|
<img align="left" width="100" height="100" src="/docs-source/figures/powerpoint/flexible.svg">
|
|
37
37
|
|
|
38
|
-
### Flexible Modelling Paradigm
|
|
39
|
-
Models in fmdtools use a
|
|
38
|
+
### Flexible, AI-Ready Modelling Paradigm
|
|
39
|
+
Models in fmdtools use a straightforward and composable code-based representation of system structure and behavior. Since fmdtools models are based on open-source Python, models can be readily generated from your AI of choice with the right prompting. Whether you want to model a simple component, a complex system-of-systems, or both, fmdtools can help.
|
|
40
40
|
|
|
41
41
|
<img align="left" width="100" height="100" src="/docs-source/figures/powerpoint/powerful.svg">
|
|
42
42
|
|
|
@@ -123,7 +123,7 @@ More guidance on development installations is provided in [How to Contribute](ht
|
|
|
123
123
|
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`` in the context of a development install you can checkout the tag corresponding to the version you want, e.g.:
|
|
124
124
|
|
|
125
125
|
```
|
|
126
|
-
git checkout v2.5.
|
|
126
|
+
git checkout v2.5.2
|
|
127
127
|
```
|
|
128
128
|
|
|
129
129
|
|
|
@@ -219,10 +219,27 @@ Once fmdtools is installed, use the following to get acquainted with how to use
|
|
|
219
219
|
|
|
220
220
|
- Explore more [examples](https://nasa.github.io/fmdtools/examples/Examples.html) of particular use-cases by going through the [examples folder](https://github.com/nasa/fmdtools/tree/main/examples)
|
|
221
221
|
|
|
222
|
-
- Read about contributions and model development best practices by perusing the [Development Guide](https://nasa.github.io/fmdtools/docs-source/
|
|
222
|
+
- Read about contributions and model development best practices by perusing the [Development Guide](https://nasa.github.io/fmdtools/docs-source/development-guide.html).
|
|
223
223
|
|
|
224
224
|
- Explore the searchable [module reference](https://nasa.github.io/fmdtools/docs-source/fmdtools.html) for syntax and usage documentation.
|
|
225
225
|
|
|
226
|
+
### AI/LLM Tips
|
|
227
|
+
|
|
228
|
+
Decent (but **very imperfect**) results can be achieved using LLMs for model development using the prompt:
|
|
229
|
+
|
|
230
|
+
```prompt
|
|
231
|
+
You are an experienced software engineer learning a new Python library for the first time.
|
|
232
|
+
Make an fmdtools simulation of a <enter your system here> using the latest syntax from `https://github.com/nasa/fmdtools/tree/v2.5.1` for all modeling (`fmdtools.define`), simulation (`fmdtools.sim`), and analysis (`fmdtools.analyze`) classes.
|
|
233
|
+
The output should be a bare bones but well-commented .py file with simple behaviors for each class and a small script at the bottom leveraging the built-in capabilities in the `fmdtools.analyze` package instead of directly using external libraries like matplotlib.
|
|
234
|
+
As you are going, explain the structure of each class, the usage of each function call and how they each leverage the correct fmdtools v2.5.1 syntax.
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
The important aspects of this prompt are specifying the URL and version--otherwise the LLM is likely to hallucinate usage or recall an earlier version of fmdtools. Do not expect perfect output from this--you may have to spend some time identifying the problems so they can be fixed!
|
|
238
|
+
|
|
239
|
+
For somewhat better results, we recommend using an on-machine coding "agent" such as OpenCode/Claude Code/Codex.
|
|
240
|
+
|
|
241
|
+
More elaborate prompts can be found in our [AGENTS.md](AGENTS.md) and repository skills at `.agents/skills`.
|
|
242
|
+
|
|
226
243
|
## Contributions
|
|
227
244
|
fmdtools is developed primarily by researchers at NASA Ames Research Center. External contributions are welcome under a Contributor License Agreement:
|
|
228
245
|
|
|
@@ -256,12 +273,12 @@ To cite fmdtools in general, you may cite our explanatory publication:
|
|
|
256
273
|
To cite a particular version of the fmdtools, you may use:
|
|
257
274
|
|
|
258
275
|
```
|
|
259
|
-
@software{
|
|
276
|
+
@software{nasa2026fmdtools,
|
|
260
277
|
author = {{NASA}},
|
|
261
278
|
title = {fmdtools},
|
|
262
279
|
url = {https://github.com/nasa/fmdtools},
|
|
263
|
-
version = {2.5.
|
|
264
|
-
date = {2026-
|
|
280
|
+
version = {2.5.2},
|
|
281
|
+
date = {2026-9-28},
|
|
265
282
|
}
|
|
266
283
|
```
|
|
267
284
|
|
|
@@ -88,16 +88,12 @@ class ResponderGeomArchitecture(GeomArchitecture):
|
|
|
88
88
|
self.add_geom('peripheral', PeripheralZone)
|
|
89
89
|
self.add_geom('paracentral', ParacentralZone)
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
ga = ResponderGeomArchitecture()
|
|
93
|
-
|
|
94
|
-
|
|
95
91
|
def check_vision_zones(ga, point):
|
|
96
92
|
"""Return {zone_name: bool} indicating which vision zones contain `point`."""
|
|
97
93
|
return {name: geom.at(point) for name, geom in ga.geoms.items()}
|
|
98
94
|
|
|
99
95
|
|
|
100
|
-
|
|
96
|
+
|
|
101
97
|
|
|
102
98
|
|
|
103
99
|
class ResponderState(State):
|
|
@@ -302,6 +298,9 @@ def plot_combined_response_from(time, history={}, mdl=None, fig=None, ax=None,
|
|
|
302
298
|
return fig, ax
|
|
303
299
|
|
|
304
300
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
301
|
+
if __name__ == "__main__":
|
|
302
|
+
ga = ResponderGeomArchitecture()
|
|
303
|
+
print(check_vision_zones(ga, (400, 10)))
|
|
304
|
+
responder = Responder()
|
|
305
|
+
print(responder.environment.c.find_all_prop("person_to_rescue"))
|
|
306
|
+
#print(responder.create_rescue_path(4))
|
|
@@ -150,7 +150,7 @@ class DroneDisturbanceTest(unittest.TestCase):
|
|
|
150
150
|
amt = self.mdl.fxns['store_ee'].ca.comps['s1p1'].p.amt
|
|
151
151
|
soc_expected = soc_set - 100/amt
|
|
152
152
|
soc_res = self.edp.f2(soc_set)
|
|
153
|
-
self.
|
|
153
|
+
self.assertAlmostEqual(soc_expected, soc_res)
|
|
154
154
|
|
|
155
155
|
# make sure the disturbance wasn't set permanently
|
|
156
156
|
soc_later = self.edp.f1(soc_set)
|
|
@@ -18,6 +18,7 @@ specific language governing permissions and limitations under the License.
|
|
|
18
18
|
from fmdtools_tests.common import CommonTests
|
|
19
19
|
from fmdtools_examples.navigating_rover.script_search_rover import line_dist, line_dist_faster
|
|
20
20
|
import unittest
|
|
21
|
+
import numpy as np
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
class RoverTests(unittest.TestCase, CommonTests):
|
|
@@ -29,9 +30,9 @@ class RoverTests(unittest.TestCase, CommonTests):
|
|
|
29
30
|
dist_int, enddist_int, endpt_int = line_dist_faster(testvalue)
|
|
30
31
|
dist, enddist, endpt = line_dist(testvalue)
|
|
31
32
|
|
|
32
|
-
self.
|
|
33
|
-
self.
|
|
34
|
-
self.
|
|
33
|
+
self.assertTrue(np.isclose(dist, dist_int))
|
|
34
|
+
self.assertTrue(np.isclose(enddist, enddist_int))
|
|
35
|
+
self.assertTrue(np.isclose(endpt, endpt_int).all())
|
|
35
36
|
|
|
36
37
|
|
|
37
38
|
if __name__ == '__main__':
|
|
@@ -632,14 +632,14 @@ def script_sample_faults(track='all', **kwargs):
|
|
|
632
632
|
|
|
633
633
|
gh = mdlhists.get_comp_groups('flows.ee_1.s.current')
|
|
634
634
|
|
|
635
|
-
results, mdlhists_staged = propagate.fault_sample(mdl, faultapp,
|
|
636
|
-
|
|
635
|
+
# results, mdlhists_staged = propagate.fault_sample(mdl, faultapp,
|
|
636
|
+
# staged=True, track='all')
|
|
637
637
|
|
|
638
|
-
tab = an.tabulate.result_summary_fmea(
|
|
639
|
-
|
|
638
|
+
# tab = an.tabulate.result_summary_fmea(
|
|
639
|
+
# results, mdlhists, *mdl.fxns, *mdl.flows)
|
|
640
640
|
|
|
641
641
|
h = mdlhists.get_expected(app=faultapp, with_nominal=True)
|
|
642
|
-
ec = results.get_expected()
|
|
642
|
+
# ec = results.get_expected()
|
|
643
643
|
|
|
644
644
|
# degsumm = h.get_summary(*mdl.fxns, *mdl.flows)
|
|
645
645
|
|
|
@@ -658,7 +658,7 @@ def script_sample_faults(track='all', **kwargs):
|
|
|
658
658
|
fmea = an.tabulate.FMEA(results, faultapp)
|
|
659
659
|
fmea.as_table()
|
|
660
660
|
fmea.sort_by_metric("expected_cost")
|
|
661
|
-
fmea.as_plot("expected_cost", color_factor="
|
|
661
|
+
fmea.as_plot("expected_cost", color_factor="obj")
|
|
662
662
|
|
|
663
663
|
# test cases for multiplot legend/axis sharing
|
|
664
664
|
mdlhists.plot_line("flows.ee_1.s.current", "flows.sig_1.s.power",
|
|
@@ -679,6 +679,8 @@ if __name__ == "__main__":
|
|
|
679
679
|
mdl = Pump()
|
|
680
680
|
res, hist = propagate.nominal(mdl, to_return = {'graph': FunctionArchitectureGraph})
|
|
681
681
|
|
|
682
|
+
# script_sample_faults()
|
|
683
|
+
|
|
682
684
|
"""
|
|
683
685
|
endfaults, mdlhist = propagate.one_fault(mdl, 'export_water', 'block',
|
|
684
686
|
time=10, to_return='faults')
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fmdtools
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.2
|
|
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.5.
|
|
7
|
+
License: fmdtools version 2.5.2
|
|
8
8
|
---------------------------
|
|
9
9
|
Apache License
|
|
10
10
|
Version 2.0, January 2004
|
|
@@ -306,8 +306,8 @@ The fmdtools library provides the computational support needed to perform a simu
|
|
|
306
306
|
|
|
307
307
|
<img align="left" width="100" height="100" src="/docs-source/figures/powerpoint/flexible.svg">
|
|
308
308
|
|
|
309
|
-
### Flexible Modelling Paradigm
|
|
310
|
-
Models in fmdtools use a
|
|
309
|
+
### Flexible, AI-Ready Modelling Paradigm
|
|
310
|
+
Models in fmdtools use a straightforward and composable code-based representation of system structure and behavior. Since fmdtools models are based on open-source Python, models can be readily generated from your AI of choice with the right prompting. Whether you want to model a simple component, a complex system-of-systems, or both, fmdtools can help.
|
|
311
311
|
|
|
312
312
|
<img align="left" width="100" height="100" src="/docs-source/figures/powerpoint/powerful.svg">
|
|
313
313
|
|
|
@@ -394,7 +394,7 @@ More guidance on development installations is provided in [How to Contribute](ht
|
|
|
394
394
|
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`` in the context of a development install you can checkout the tag corresponding to the version you want, e.g.:
|
|
395
395
|
|
|
396
396
|
```
|
|
397
|
-
git checkout v2.5.
|
|
397
|
+
git checkout v2.5.2
|
|
398
398
|
```
|
|
399
399
|
|
|
400
400
|
|
|
@@ -490,10 +490,27 @@ Once fmdtools is installed, use the following to get acquainted with how to use
|
|
|
490
490
|
|
|
491
491
|
- Explore more [examples](https://nasa.github.io/fmdtools/examples/Examples.html) of particular use-cases by going through the [examples folder](https://github.com/nasa/fmdtools/tree/main/examples)
|
|
492
492
|
|
|
493
|
-
- Read about contributions and model development best practices by perusing the [Development Guide](https://nasa.github.io/fmdtools/docs-source/
|
|
493
|
+
- Read about contributions and model development best practices by perusing the [Development Guide](https://nasa.github.io/fmdtools/docs-source/development-guide.html).
|
|
494
494
|
|
|
495
495
|
- Explore the searchable [module reference](https://nasa.github.io/fmdtools/docs-source/fmdtools.html) for syntax and usage documentation.
|
|
496
496
|
|
|
497
|
+
### AI/LLM Tips
|
|
498
|
+
|
|
499
|
+
Decent (but **very imperfect**) results can be achieved using LLMs for model development using the prompt:
|
|
500
|
+
|
|
501
|
+
```prompt
|
|
502
|
+
You are an experienced software engineer learning a new Python library for the first time.
|
|
503
|
+
Make an fmdtools simulation of a <enter your system here> using the latest syntax from `https://github.com/nasa/fmdtools/tree/v2.5.1` for all modeling (`fmdtools.define`), simulation (`fmdtools.sim`), and analysis (`fmdtools.analyze`) classes.
|
|
504
|
+
The output should be a bare bones but well-commented .py file with simple behaviors for each class and a small script at the bottom leveraging the built-in capabilities in the `fmdtools.analyze` package instead of directly using external libraries like matplotlib.
|
|
505
|
+
As you are going, explain the structure of each class, the usage of each function call and how they each leverage the correct fmdtools v2.5.1 syntax.
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
The important aspects of this prompt are specifying the URL and version--otherwise the LLM is likely to hallucinate usage or recall an earlier version of fmdtools. Do not expect perfect output from this--you may have to spend some time identifying the problems so they can be fixed!
|
|
509
|
+
|
|
510
|
+
For somewhat better results, we recommend using an on-machine coding "agent" such as OpenCode/Claude Code/Codex.
|
|
511
|
+
|
|
512
|
+
More elaborate prompts can be found in our [AGENTS.md](AGENTS.md) and repository skills at `.agents/skills`.
|
|
513
|
+
|
|
497
514
|
## Contributions
|
|
498
515
|
fmdtools is developed primarily by researchers at NASA Ames Research Center. External contributions are welcome under a Contributor License Agreement:
|
|
499
516
|
|
|
@@ -527,12 +544,12 @@ To cite fmdtools in general, you may cite our explanatory publication:
|
|
|
527
544
|
To cite a particular version of the fmdtools, you may use:
|
|
528
545
|
|
|
529
546
|
```
|
|
530
|
-
@software{
|
|
547
|
+
@software{nasa2026fmdtools,
|
|
531
548
|
author = {{NASA}},
|
|
532
549
|
title = {fmdtools},
|
|
533
550
|
url = {https://github.com/nasa/fmdtools},
|
|
534
|
-
version = {2.5.
|
|
535
|
-
date = {2026-
|
|
551
|
+
version = {2.5.2},
|
|
552
|
+
date = {2026-9-28},
|
|
536
553
|
}
|
|
537
554
|
```
|
|
538
555
|
|
|
@@ -127,7 +127,31 @@ src/fmdtools/sim/scenario.py
|
|
|
127
127
|
src/fmdtools/sim/search.py
|
|
128
128
|
tests/__init__.py
|
|
129
129
|
tests/common.py
|
|
130
|
+
tests/test_array_random_states.py
|
|
131
|
+
tests/test_calc_metric_ci_constant_outputs.py
|
|
132
|
+
tests/test_comparison_groups.py
|
|
133
|
+
tests/test_confidence_history_clipping.py
|
|
134
|
+
tests/test_error_history_plots.py
|
|
135
|
+
tests/test_fault_sample_without_nominal.py
|
|
136
|
+
tests/test_fault_time_without_traces.py
|
|
137
|
+
tests/test_geom.py
|
|
130
138
|
tests/test_graph.py
|
|
131
139
|
tests/test_hierarchical.py
|
|
140
|
+
tests/test_history_standard_deviation.py
|
|
141
|
+
tests/test_join_phasemaps.py
|
|
142
|
+
tests/test_joint_fault_weights.py
|
|
143
|
+
tests/test_nested_nominal_groups.py
|
|
144
|
+
tests/test_nesting_custom_separators.py
|
|
132
145
|
tests/test_packages.py
|
|
133
|
-
tests/
|
|
146
|
+
tests/test_parameter_sample_seeds.py
|
|
147
|
+
tests/test_parameter_subsampling_types.py
|
|
148
|
+
tests/test_pathplan.py
|
|
149
|
+
tests/test_phase_timestep.py
|
|
150
|
+
tests/test_pruned_fault_times.py
|
|
151
|
+
tests/test_result.py
|
|
152
|
+
tests/test_sample.py
|
|
153
|
+
tests/test_scenario.py
|
|
154
|
+
tests/test_scenario_defaults.py
|
|
155
|
+
tests/test_table_factor_indices.py
|
|
156
|
+
tests/test_time.py
|
|
157
|
+
tests/test_uniform_density.py
|
|
@@ -41,7 +41,7 @@ import matplotlib.pyplot as plt
|
|
|
41
41
|
from matplotlib import rcParams
|
|
42
42
|
import inspect
|
|
43
43
|
from scipy.stats import bootstrap
|
|
44
|
-
from fmdtools.define.base import filter_kwargs
|
|
44
|
+
from fmdtools.define.base import filter_kwargs, round_float
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
plt.rcParams['pdf.fonttype'] = 42
|
|
@@ -229,7 +229,8 @@ def metric_preamble(data, dtype=None, rates=None, r_dtype=None, r_norm=False):
|
|
|
229
229
|
|
|
230
230
|
|
|
231
231
|
def calc_metric(data, method=np.average, args=(), axis=None, dtype=None,
|
|
232
|
-
rates=None, r_dtype=None, r_norm=False,
|
|
232
|
+
rates=None, r_dtype=None, r_norm=False, round_value=True,
|
|
233
|
+
res=1e-6, min_r=7, **kwargs):
|
|
233
234
|
"""
|
|
234
235
|
Calculate a metric from data.
|
|
235
236
|
|
|
@@ -253,12 +254,18 @@ def calc_metric(data, method=np.average, args=(), axis=None, dtype=None,
|
|
|
253
254
|
Datatype to preprocess the rates over. The default is None.
|
|
254
255
|
r_norm : bool, optional
|
|
255
256
|
Whether to normalize rates. The default is False.
|
|
257
|
+
round_value : bool, optional
|
|
258
|
+
Whether to round the value. Default is True.
|
|
259
|
+
res : float
|
|
260
|
+
Resolution to round to. Default is 1e-6.
|
|
261
|
+
min_r : int
|
|
262
|
+
Maximum number of digits to round to (see round_float).
|
|
256
263
|
**kwargs : kwargs
|
|
257
|
-
Keyword arguments to method.
|
|
264
|
+
Keyword arguments to method (see round_float).
|
|
258
265
|
|
|
259
266
|
Returns
|
|
260
267
|
-------
|
|
261
|
-
metric:
|
|
268
|
+
metric: np.float64/np.int64
|
|
262
269
|
Metric calculated by method over data.
|
|
263
270
|
|
|
264
271
|
Examples
|
|
@@ -266,7 +273,7 @@ def calc_metric(data, method=np.average, args=(), axis=None, dtype=None,
|
|
|
266
273
|
>>> calc_metric([1,2,3]) # simple average
|
|
267
274
|
np.float64(2.0)
|
|
268
275
|
>>> calc_metric([1,2,3], rates=[0.1, 0.1, 0.0], method=np.sum) # weighted sum
|
|
269
|
-
np.float64(0.
|
|
276
|
+
np.float64(0.3)
|
|
270
277
|
>>> calc_metric([0, 20, 30], dtype=bool, rates=[0.1, 0.1, 0.1], method=np.sum) # rate of nonzero event
|
|
271
278
|
np.float64(0.2)
|
|
272
279
|
>>> calc_metric([0, 1, 2], "total")
|
|
@@ -276,11 +283,15 @@ def calc_metric(data, method=np.average, args=(), axis=None, dtype=None,
|
|
|
276
283
|
"""
|
|
277
284
|
if isinstance(method, str):
|
|
278
285
|
method = eval("calc_"+method)
|
|
279
|
-
|
|
286
|
+
metric = method(data, args=args, axis=axis, dtype=dtype, rates=rates,
|
|
280
287
|
r_dtype=r_dtype, r_norm=r_norm, **kwargs)
|
|
281
288
|
else:
|
|
282
289
|
vals = metric_preamble(data, dtype, rates, r_dtype, r_norm)
|
|
283
|
-
|
|
290
|
+
metric = method(vals, *args, **filter_kwargs(method, **kwargs, axis=axis))
|
|
291
|
+
if round_value and (isinstance(metric, np.floating) or isinstance(metric, float)):
|
|
292
|
+
return round_float(metric, res=res, min_r=min_r)
|
|
293
|
+
else:
|
|
294
|
+
return metric
|
|
284
295
|
|
|
285
296
|
|
|
286
297
|
def calc_metric_ci(data, method=np.average, return_anyway=False, interval=None,
|
|
@@ -325,15 +336,13 @@ def calc_metric_ci(data, method=np.average, return_anyway=False, interval=None,
|
|
|
325
336
|
bs_kwar['confidence_level'] = interval*0.01
|
|
326
337
|
|
|
327
338
|
vals = metric_preamble(data, **filter_kwargs(metric_preamble, **kwargs))
|
|
328
|
-
|
|
329
|
-
val = vals[axis, 0]
|
|
330
|
-
else:
|
|
331
|
-
val = np.array(vals).flatten()[0]
|
|
339
|
+
val = np.take(vals, [0], axis=axis)
|
|
332
340
|
if "weights" in kwargs and kwargs['weights'] is not None:
|
|
333
341
|
raise Exception("Weights not able to be used w- bootstrap--use rates instead.")
|
|
334
342
|
met_val = method(vals, axis=axis, **filter_kwargs(method, **kwargs))
|
|
335
343
|
vals_vary = vals == val
|
|
336
|
-
|
|
344
|
+
# Preserve the existing policy for globally identical data.
|
|
345
|
+
if not np.all(vals == vals.flat[0]):
|
|
337
346
|
if np.any(np.all(vals_vary, axis=axis)):
|
|
338
347
|
# use more robust/basic algorithm if some indices don't vary
|
|
339
348
|
bs = bootstrap([vals], method, axis=axis, method="basic", **bs_kwar)
|
|
@@ -353,7 +362,7 @@ def calc_rate(data, rates=None, weights=None, **kwargs):
|
|
|
353
362
|
Examples
|
|
354
363
|
--------
|
|
355
364
|
>>> calc_rate([0, 10, 0]) # defaults to equal rate
|
|
356
|
-
np.float64(0.
|
|
365
|
+
np.float64(0.333333)
|
|
357
366
|
>>> calc_rate([0, 10, 100], [0.1, 0.1, 0.1]) # provided rates
|
|
358
367
|
np.float64(0.2)
|
|
359
368
|
"""
|
|
@@ -370,7 +379,7 @@ def calc_percent(data, weights=None, rates=None, **kwargs):
|
|
|
370
379
|
Examples
|
|
371
380
|
--------
|
|
372
381
|
>>> calc_percent([0, 10, 0])
|
|
373
|
-
np.float64(0.
|
|
382
|
+
np.float64(0.333333)
|
|
374
383
|
"""
|
|
375
384
|
return calc_metric(data, **{**kwargs, 'dtype': bool})
|
|
376
385
|
|
|
@@ -386,7 +395,7 @@ def calc_total(data, weights=None, **kwargs):
|
|
|
386
395
|
>>> calc_total([0, 10, 100])
|
|
387
396
|
np.int64(2)
|
|
388
397
|
"""
|
|
389
|
-
return calc_metric(data, **{**kwargs, 'method': np.sum, 'dtype': bool})
|
|
398
|
+
return np.int64(calc_metric(data, **{**kwargs, 'method': np.sum, 'dtype': bool}))
|
|
390
399
|
|
|
391
400
|
|
|
392
401
|
def calc_expected(data, rates=None, weights=None, **kwargs):
|
|
@@ -519,8 +528,8 @@ def plot_err_hist(err_hist, ax=None, fig=None, figsize=(6, 4), boundtype='fill',
|
|
|
519
528
|
fig : mpl figure
|
|
520
529
|
ax :mpl, axis
|
|
521
530
|
"""
|
|
522
|
-
fig, ax = setup_plot(fig, ax, figsize)
|
|
523
|
-
ax.plot(err_hist['stat'], **kwargs)
|
|
531
|
+
fig, ax = setup_plot(fig=fig, ax=ax, figsize=figsize)
|
|
532
|
+
ax.plot(err_hist[time], err_hist['stat'], **kwargs)
|
|
524
533
|
if boundtype == 'fill':
|
|
525
534
|
col = ax.lines[-1].get_color()
|
|
526
535
|
ax.fill_between(err_hist[time], err_hist['low'], err_hist['high'],
|
|
@@ -582,7 +591,7 @@ def plot_err_lines(times, lows, highs, ax=None, fig=None, figsize=(6, 4), **kwar
|
|
|
582
591
|
**kwargs : kwargs
|
|
583
592
|
kwargs for the line
|
|
584
593
|
"""
|
|
585
|
-
fig, ax = setup_plot(
|
|
594
|
+
fig, ax = setup_plot(fig=fig, ax=ax, figsize=figsize)
|
|
586
595
|
ax.plot(times, highs, **kwargs)
|
|
587
596
|
ax.plot(times, lows, **kwargs)
|
|
588
597
|
return fig, ax
|
|
@@ -360,6 +360,9 @@ class History(Result):
|
|
|
360
360
|
"""
|
|
361
361
|
Get the time a fault is present in the system.
|
|
362
362
|
|
|
363
|
+
Only recorded fault traces are considered. Without recorded faults,
|
|
364
|
+
returns zero for ``total`` and ``nan`` for the position metrics.
|
|
365
|
+
|
|
363
366
|
Parameters
|
|
364
367
|
----------
|
|
365
368
|
metric : 'earliest','latest','total', 'times', optional
|
|
@@ -373,6 +376,8 @@ class History(Result):
|
|
|
373
376
|
|
|
374
377
|
Examples
|
|
375
378
|
--------
|
|
379
|
+
>>> History(time=[0, 1, 2]).get_fault_time()
|
|
380
|
+
nan
|
|
376
381
|
>>> History({'m.faults.fault1': [False, False, False]}).get_fault_time()
|
|
377
382
|
nan
|
|
378
383
|
>>> History({'m.faults.fault1': [False, False, True]}).get_fault_time()
|
|
@@ -383,7 +388,7 @@ class History(Result):
|
|
|
383
388
|
if metric == 'total':
|
|
384
389
|
return np.sum(all_faults_hist >= 1)
|
|
385
390
|
else:
|
|
386
|
-
times = np.where(all_faults_hist >= 1)[0]
|
|
391
|
+
times = np.where(np.atleast_1d(all_faults_hist) >= 1)[0]
|
|
387
392
|
if times.size == 0:
|
|
388
393
|
return np.nan
|
|
389
394
|
elif metric == 'times':
|
|
@@ -809,6 +814,8 @@ class History(Result):
|
|
|
809
814
|
"""
|
|
810
815
|
Get aggregated err_hist of means surrounded by std deviation.
|
|
811
816
|
|
|
817
|
+
Calculate the spread across histories separately at each time sample.
|
|
818
|
+
|
|
812
819
|
Parameters
|
|
813
820
|
----------
|
|
814
821
|
value : str
|
|
@@ -829,7 +836,7 @@ class History(Result):
|
|
|
829
836
|
hist = History()
|
|
830
837
|
hist[time] = self.get_metric(time, axis=0)
|
|
831
838
|
hist['stat'] = self.get_metric(value, np.mean, axis=0)
|
|
832
|
-
std_dev = self.get_metric(value, np.std)
|
|
839
|
+
std_dev = self.get_metric(value, np.std, axis=0)
|
|
833
840
|
hist['high'] = hist['stat']+std_dev/2
|
|
834
841
|
hist['low'] = hist['stat']-std_dev/2
|
|
835
842
|
return hist
|
|
@@ -851,7 +858,8 @@ class History(Result):
|
|
|
851
858
|
ci : float
|
|
852
859
|
Fraction for confidence interval. Default is 0.95.
|
|
853
860
|
max_ind : str/int
|
|
854
|
-
|
|
861
|
+
Exclusive slice endpoint for both timestamps and values. Default is
|
|
862
|
+
'max', which uses the shortest history length.
|
|
855
863
|
|
|
856
864
|
Returns
|
|
857
865
|
-------
|
|
@@ -874,6 +882,7 @@ class History(Result):
|
|
|
874
882
|
hist[time] = self.get_metric(time, axis=0)
|
|
875
883
|
if max_ind == 'max':
|
|
876
884
|
max_ind = min([len(h) for h in self.values()])
|
|
885
|
+
hist[time] = hist[time][:max_ind]
|
|
877
886
|
vals = np.array([*self.get_values(value).values()])[:, :max_ind]
|
|
878
887
|
boot_stats = calc_metric_ci(vals, confidence_level=ci, axis=0, **kwargs)
|
|
879
888
|
hist['stat'] = boot_stats[0]
|
|
@@ -80,7 +80,7 @@ class PhaseMap(object):
|
|
|
80
80
|
def __repr__(self):
|
|
81
81
|
return 'PhaseMap(' + str(self.phases) + ', ' + str(self.modephases) + ')'
|
|
82
82
|
|
|
83
|
-
def find_phase(self, time, dt=
|
|
83
|
+
def find_phase(self, time, dt=None):
|
|
84
84
|
"""
|
|
85
85
|
Find the phase that a time occurs in.
|
|
86
86
|
|
|
@@ -88,12 +88,17 @@ class PhaseMap(object):
|
|
|
88
88
|
----------
|
|
89
89
|
time : float
|
|
90
90
|
Occurence time.
|
|
91
|
+
dt : float, optional
|
|
92
|
+
Width of the final sample in each phase. Defaults to this map's dt.
|
|
93
|
+
An explicit value overrides the configured timestep for this lookup.
|
|
91
94
|
|
|
92
95
|
Returns
|
|
93
96
|
-------
|
|
94
97
|
phase : str
|
|
95
98
|
Name of the phase time occurs in.
|
|
96
99
|
"""
|
|
100
|
+
if dt is None:
|
|
101
|
+
dt = self.dt
|
|
97
102
|
for phase, times in self.phases.items():
|
|
98
103
|
if times[0] <= time < times[1]+dt:
|
|
99
104
|
return phase
|
|
@@ -677,8 +682,7 @@ def join_phasemaps(*phasemaps):
|
|
|
677
682
|
joint_phases = {}
|
|
678
683
|
all_combos = [*itertools.product(*[phasemap.phases for phasemap in phasemaps])]
|
|
679
684
|
for combo in all_combos:
|
|
680
|
-
|
|
681
|
-
intervals = [i for i in phases.values()]
|
|
685
|
+
intervals = [phasemaps[i].phases[c] for i, c in enumerate(combo)]
|
|
682
686
|
joined_interval = find_interval_overlap(*intervals)
|
|
683
687
|
if joined_interval:
|
|
684
688
|
joint_phases[combo] = joined_interval
|