fmdtools 2.5.4__tar.gz → 2.5.5__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 (271) hide show
  1. {fmdtools-2.5.4 → fmdtools-2.5.5}/LICENSE +1 -1
  2. {fmdtools-2.5.4/fmdtools.egg-info → fmdtools-2.5.5}/PKG-INFO +7 -7
  3. {fmdtools-2.5.4 → fmdtools-2.5.5}/README.md +5 -5
  4. {fmdtools-2.5.4 → fmdtools-2.5.5/fmdtools.egg-info}/PKG-INFO +7 -7
  5. {fmdtools-2.5.4 → fmdtools-2.5.5}/fmdtools.egg-info/SOURCES.txt +31 -0
  6. {fmdtools-2.5.4 → fmdtools-2.5.5}/pyproject.toml +79 -1
  7. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/__init__.py +1 -1
  8. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/analyze/common.py +47 -5
  9. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/analyze/graph/base.py +2 -2
  10. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/analyze/history.py +11 -6
  11. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/analyze/result.py +17 -6
  12. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/analyze/tabulate.py +17 -10
  13. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/base.py +8 -3
  14. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/block/base.py +7 -2
  15. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/container/mode.py +19 -1
  16. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/container/rand.py +26 -12
  17. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/container/state.py +11 -5
  18. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/sim/sample.py +77 -29
  19. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/sim/scenario.py +5 -3
  20. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/sim/search.py +3 -1
  21. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_approach_joint_domains.py +6 -1
  22. fmdtools-2.5.5/tests/test_architecture_vector_inputs.py +176 -0
  23. fmdtools-2.5.5/tests/test_array_state_rounding.py +131 -0
  24. fmdtools-2.5.5/tests/test_binomial_trial_counts.py +189 -0
  25. fmdtools-2.5.5/tests/test_comparison_ci_metrics.py +208 -0
  26. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_default_fault_sample_timestep.py +23 -1
  27. fmdtools-2.5.5/tests/test_discrete_grid_values.py +171 -0
  28. fmdtools-2.5.5/tests/test_even_sampling_mass.py +159 -0
  29. fmdtools-2.5.5/tests/test_expectation_without_nominal.py +120 -0
  30. fmdtools-2.5.5/tests/test_explicit_history_times.py +137 -0
  31. fmdtools-2.5.5/tests/test_fault_object_overrides.py +205 -0
  32. fmdtools-2.5.5/tests/test_fault_space_ownership.py +151 -0
  33. fmdtools-2.5.5/tests/test_fault_space_sample_limits.py +124 -0
  34. fmdtools-2.5.5/tests/test_fault_summary_paths.py +170 -0
  35. fmdtools-2.5.5/tests/test_graph_zero_seed.py +117 -0
  36. fmdtools-2.5.5/tests/test_history_alignment_ownership.py +136 -0
  37. fmdtools-2.5.5/tests/test_history_sample_indices.py +147 -0
  38. fmdtools-2.5.5/tests/test_hypergeometric_count_conversion.py +167 -0
  39. fmdtools-2.5.5/tests/test_immutable_fault_injection.py +185 -0
  40. fmdtools-2.5.5/tests/test_implicit_sampling_start.py +158 -0
  41. fmdtools-2.5.5/tests/test_integer_bound_conversion.py +177 -0
  42. fmdtools-2.5.5/tests/test_integer_history_differences.py +196 -0
  43. fmdtools-2.5.5/tests/test_integer_rate_metrics.py +176 -0
  44. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_joint_fault_metadata_order.py +1 -1
  45. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_joint_fault_phase_map.py +2 -2
  46. fmdtools-2.5.5/tests/test_joint_scenario_quadrature.py +229 -0
  47. fmdtools-2.5.5/tests/test_named_parameter_maps.py +129 -0
  48. fmdtools-2.5.5/tests/test_nested_comparison_inputs.py +173 -0
  49. fmdtools-2.5.5/tests/test_nested_comparison_parentage.py +213 -0
  50. fmdtools-2.5.5/tests/test_nested_sample_metrics.py +173 -0
  51. fmdtools-2.5.5/tests/test_offset_time_grids.py +119 -0
  52. fmdtools-2.5.5/tests/test_permuted_nan_probabilities.py +193 -0
  53. fmdtools-2.5.5/tests/test_reference_risk_calculations.py +124 -0
  54. fmdtools-2.5.5/tests/test_scenario_metric_mappings.py +184 -0
  55. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_simulation_exposure.py +1 -1
  56. fmdtools-2.5.5/tests/test_uniform_bound_dtypes.py +174 -0
  57. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/__init__.py +0 -0
  58. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airport_taxiway/model_asset.py +0 -0
  59. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airport_taxiway/model_atc.py +0 -0
  60. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airport_taxiway/model_common.py +0 -0
  61. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airport_taxiway/model_main.py +0 -0
  62. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airport_taxiway/test_asset.py +0 -0
  63. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airport_taxiway/test_model.py +0 -0
  64. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/__init__.py +0 -0
  65. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/base/__init__.py +0 -0
  66. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/base/aircraft.py +0 -0
  67. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/base/aircraftarchitecture.py +0 -0
  68. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/base/arch/__init__.py +0 -0
  69. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/base/arch/aviate.py +0 -0
  70. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/base/arch/controlflight.py +0 -0
  71. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/base/arch/flows.py +0 -0
  72. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/base/arch/holdpayload.py +0 -0
  73. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/base/arch/perceiveenvironment.py +0 -0
  74. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/base/arch/storeee.py +0 -0
  75. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/base/parameter.py +0 -0
  76. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/base/state.py +0 -0
  77. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/contingency_management/__init__.py +0 -0
  78. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/contingency_management/model_aircraft.py +0 -0
  79. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/contingency_management/model_environment.py +0 -0
  80. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/contingency_management/model_flightplanner.py +0 -0
  81. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/water_rescue/__init__.py +0 -0
  82. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/water_rescue/model_drone.py +0 -0
  83. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/water_rescue/model_environment.py +0 -0
  84. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/water_rescue/model_main.py +0 -0
  85. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/water_rescue/model_responder.py +0 -0
  86. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/wildfire_response/__init__.py +0 -0
  87. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/wildfire_response/model_aircraft.py +0 -0
  88. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/wildfire_response/model_environment.py +0 -0
  89. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/airspacelib/wildfire_response/model_main.py +0 -0
  90. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/cooling_tank/__init__.py +0 -0
  91. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/cooling_tank/model_main.py +0 -0
  92. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/cooling_tank/model_optimization.py +0 -0
  93. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/cooling_tank/test_tank.py +0 -0
  94. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/electric_power_system/__init__.py +0 -0
  95. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/electric_power_system/model_main.py +0 -0
  96. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/electric_power_system/test_model.py +0 -0
  97. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/human_hazard_mitigation/__init__.py +0 -0
  98. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/human_hazard_mitigation/model_main.py +0 -0
  99. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/multirotor_drone/__init__.py +0 -0
  100. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/multirotor_drone/model_dynamic.py +0 -0
  101. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/multirotor_drone/model_hierarchical.py +0 -0
  102. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/multirotor_drone/model_rural.py +0 -0
  103. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/multirotor_drone/model_static.py +0 -0
  104. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/multirotor_drone/model_urban.py +0 -0
  105. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/multirotor_drone/script_opt_model_rural.py +0 -0
  106. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/multirotor_drone/test_multirotor.py +0 -0
  107. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/navigating_rover/__init__.py +0 -0
  108. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/navigating_rover/model_degradation.py +0 -0
  109. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/navigating_rover/model_human.py +0 -0
  110. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/navigating_rover/model_main.py +0 -0
  111. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/navigating_rover/model_troupe.py +0 -0
  112. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/navigating_rover/script_ea_analysis.py +0 -0
  113. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/navigating_rover/script_mode_space.py +0 -0
  114. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/navigating_rover/script_search_rover.py +0 -0
  115. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/navigating_rover/test_rover.py +0 -0
  116. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/state_communication/__init__.py +0 -0
  117. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/state_communication/model_main.py +0 -0
  118. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/state_communication/test_multiflow.py +0 -0
  119. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/water_pump/__init__.py +0 -0
  120. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/water_pump/model_indiv.py +0 -0
  121. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/water_pump/model_main.py +0 -0
  122. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/water_pump/model_stochastic.py +0 -0
  123. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/water_pump/script_jointfaults.py +0 -0
  124. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/water_pump/script_parallelism.py +0 -0
  125. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/water_pump/test_pump.py +0 -0
  126. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/water_pump/test_pump_example.py +0 -0
  127. {fmdtools-2.5.4 → fmdtools-2.5.5}/examples/water_pump/test_pump_stochastic.py +0 -0
  128. {fmdtools-2.5.4 → fmdtools-2.5.5}/fmdtools.egg-info/dependency_links.txt +0 -0
  129. {fmdtools-2.5.4 → fmdtools-2.5.5}/fmdtools.egg-info/requires.txt +0 -0
  130. {fmdtools-2.5.4 → fmdtools-2.5.5}/fmdtools.egg-info/top_level.txt +0 -0
  131. {fmdtools-2.5.4 → fmdtools-2.5.5}/setup.cfg +0 -0
  132. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/analyze/__init__.py +0 -0
  133. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/analyze/graph/__init__.py +0 -0
  134. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/analyze/graph/label.py +0 -0
  135. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/analyze/graph/model.py +0 -0
  136. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/analyze/graph/style.py +0 -0
  137. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/analyze/phases.py +0 -0
  138. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/__init__.py +0 -0
  139. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/architecture/__init__.py +0 -0
  140. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/architecture/action.py +0 -0
  141. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/architecture/base.py +0 -0
  142. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/architecture/component.py +0 -0
  143. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/architecture/function.py +0 -0
  144. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/architecture/geom.py +0 -0
  145. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/block/__init__.py +0 -0
  146. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/block/action.py +0 -0
  147. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/block/component.py +0 -0
  148. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/block/function.py +0 -0
  149. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/container/__init__.py +0 -0
  150. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/container/base.py +0 -0
  151. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/container/parameter.py +0 -0
  152. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/container/time.py +0 -0
  153. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/environment.py +0 -0
  154. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/flow/__init__.py +0 -0
  155. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/flow/base.py +0 -0
  156. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/flow/commsflow.py +0 -0
  157. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/flow/multiflow.py +0 -0
  158. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/object/__init__.py +0 -0
  159. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/object/base.py +0 -0
  160. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/object/coords.py +0 -0
  161. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/object/geom.py +0 -0
  162. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/object/timer.py +0 -0
  163. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/define/pathplan.py +0 -0
  164. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/sim/__init__.py +0 -0
  165. {fmdtools-2.5.4 → fmdtools-2.5.5}/src/fmdtools/sim/propagate.py +0 -0
  166. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/__init__.py +0 -0
  167. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/common.py +0 -0
  168. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_appended_history_snapshots.py +0 -0
  169. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_approach_model_timestep.py +0 -0
  170. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_approach_phase_map_ownership.py +0 -0
  171. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_array_differences.py +0 -0
  172. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_array_random_states.py +0 -0
  173. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_array_result_equality.py +0 -0
  174. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_array_state_limits.py +0 -0
  175. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_bootstrap_statistic_arguments.py +0 -0
  176. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_bounded_array_increments.py +0 -0
  177. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_calc_metric_ci_constant_outputs.py +0 -0
  178. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_callable_parameter_domains.py +0 -0
  179. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_choice_draw_mass.py +0 -0
  180. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_choice_probability_precision.py +0 -0
  181. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_common.py +0 -0
  182. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_comparison_groups.py +0 -0
  183. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_confidence_history_clipping.py +0 -0
  184. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_coordinate_cell_boundaries.py +0 -0
  185. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_degradation_path_boundaries.py +0 -0
  186. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_dirichlet_batches.py +0 -0
  187. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_disconnected_graph_robustness.py +0 -0
  188. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_discrete_sample_sizes.py +0 -0
  189. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_error_history_plots.py +0 -0
  190. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_exact_nominal_expectation.py +0 -0
  191. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_explicit_result_file_formats.py +0 -0
  192. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_exponential_rayleigh_draw_sizes.py +0 -0
  193. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_factor_sort_priority.py +0 -0
  194. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_fault_history_paths.py +0 -0
  195. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_fault_sample_without_nominal.py +0 -0
  196. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_fault_time_without_traces.py +0 -0
  197. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_fault_weight_arrays.py +0 -0
  198. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_faulty_scenario_selection.py +0 -0
  199. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_fmea_input_ownership.py +0 -0
  200. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_gamma_sampling_density.py +0 -0
  201. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_generated_history_phase_timestep.py +0 -0
  202. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_geom.py +0 -0
  203. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_graph.py +0 -0
  204. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_graph_edge_comparison.py +0 -0
  205. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_hierarchical.py +0 -0
  206. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_history_phase_identifiers.py +0 -0
  207. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_history_standard_deviation.py +0 -0
  208. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_independent_single_replicate_seeds.py +0 -0
  209. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_individual_result_paths.py +0 -0
  210. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_integer_draw_mass.py +0 -0
  211. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_join_phase_timestep.py +0 -0
  212. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_join_phasemaps.py +0 -0
  213. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_joint_fault_weights.py +0 -0
  214. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_json_result_arrays.py +0 -0
  215. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_location_scale_draw_sizes.py +0 -0
  216. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_lognormal_defaults.py +0 -0
  217. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_metric_weight_alignment.py +0 -0
  218. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_mixed_shape_degradation.py +0 -0
  219. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_multidimensional_state_comparison.py +0 -0
  220. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_multinomial_sampling_arguments.py +0 -0
  221. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_multivariate_hypergeometric_options.py +0 -0
  222. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_multivariate_normal_arguments.py +0 -0
  223. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_named_default_restoration.py +0 -0
  224. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_named_metric_rounding.py +0 -0
  225. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_nearest_point_exclusion.py +0 -0
  226. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_nested_history_summary.py +0 -0
  227. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_nested_nominal_groups.py +0 -0
  228. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_nested_parameter_constraints.py +0 -0
  229. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_nested_scenario_parameters.py +0 -0
  230. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_nesting_custom_separators.py +0 -0
  231. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_not_equal_constraints.py +0 -0
  232. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_object_history_copy.py +0 -0
  233. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_packages.py +0 -0
  234. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_parameter_grid_bounds.py +0 -0
  235. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_parameter_sample_defaults.py +0 -0
  236. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_parameter_sample_seeds.py +0 -0
  237. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_parameter_subsampling_types.py +0 -0
  238. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_pareto_density.py +0 -0
  239. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_pathplan.py +0 -0
  240. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_permutation_axis_probabilities.py +0 -0
  241. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_permuted_slice_probabilities.py +0 -0
  242. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_phase_map_default_isolation.py +0 -0
  243. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_phase_timestep.py +0 -0
  244. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_pruned_fault_times.py +0 -0
  245. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_ragged_confidence_histories.py +0 -0
  246. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_rand.py +0 -0
  247. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_random_combination_types.py +0 -0
  248. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_result.py +0 -0
  249. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_result_constructor_input.py +0 -0
  250. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_result_folder_selection.py +0 -0
  251. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_sample.py +0 -0
  252. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_scenario.py +0 -0
  253. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_scenario_defaults.py +0 -0
  254. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_shape_distribution_sizes.py +0 -0
  255. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_simple_problem_vector_inputs.py +0 -0
  256. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_standard_draw_arguments.py +0 -0
  257. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_standard_t_density.py +0 -0
  258. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_string_state_histories.py +0 -0
  259. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_table_factor_indices.py +0 -0
  260. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_time.py +0 -0
  261. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_time_reset.py +0 -0
  262. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_triangular_arraylike_parameters.py +0 -0
  263. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_tuple_table_factors.py +0 -0
  264. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_uniform_density.py +0 -0
  265. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_unit_random_density.py +0 -0
  266. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_vonmises_density.py +0 -0
  267. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_wald_density.py +0 -0
  268. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_weighted_percent_metrics.py +0 -0
  269. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_zero_fault_start_times.py +0 -0
  270. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_zero_time_objectives.py +0 -0
  271. {fmdtools-2.5.4 → fmdtools-2.5.5}/tests/test_zero_timer_increment.py +0 -0
@@ -1,4 +1,4 @@
1
- fmdtools version 2.5.4
1
+ fmdtools version 2.5.5
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.5.4
3
+ Version: 2.5.5
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.4
7
+ License: fmdtools version 2.5.5
8
8
  ---------------------------
9
9
  Apache License
10
10
  Version 2.0, January 2004
@@ -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.4
397
+ git checkout v2.5.5
398
398
  ```
399
399
 
400
400
 
@@ -500,9 +500,9 @@ Decent (but **very imperfect**) results can be achieved using LLMs for model dev
500
500
 
501
501
  ```prompt
502
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.
503
+ Make an fmdtools simulation of a <enter your system here> using the latest syntax from `https://github.com/nasa/fmdtools/tree/v2.5.5` for all modeling (`fmdtools.define`), simulation (`fmdtools.sim`), and analysis (`fmdtools.analyze`) classes.
504
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.
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.5 syntax.
506
506
  ```
507
507
 
508
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!
@@ -548,8 +548,8 @@ To cite a particular version of the fmdtools, you may use:
548
548
  author = {{NASA}},
549
549
  title = {fmdtools},
550
550
  url = {https://github.com/nasa/fmdtools},
551
- version = {2.5.4},
552
- date = {2026-10-5},
551
+ version = {2.5.5},
552
+ date = {2026-10-08},
553
553
  }
554
554
  ```
555
555
 
@@ -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.4
126
+ git checkout v2.5.5
127
127
  ```
128
128
 
129
129
 
@@ -229,9 +229,9 @@ Decent (but **very imperfect**) results can be achieved using LLMs for model dev
229
229
 
230
230
  ```prompt
231
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.
232
+ Make an fmdtools simulation of a <enter your system here> using the latest syntax from `https://github.com/nasa/fmdtools/tree/v2.5.5` for all modeling (`fmdtools.define`), simulation (`fmdtools.sim`), and analysis (`fmdtools.analyze`) classes.
233
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.
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.5 syntax.
235
235
  ```
236
236
 
237
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!
@@ -277,8 +277,8 @@ To cite a particular version of the fmdtools, you may use:
277
277
  author = {{NASA}},
278
278
  title = {fmdtools},
279
279
  url = {https://github.com/nasa/fmdtools},
280
- version = {2.5.4},
281
- date = {2026-10-5},
280
+ version = {2.5.5},
281
+ date = {2026-10-08},
282
282
  }
283
283
  ```
284
284
 
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fmdtools
3
- Version: 2.5.4
3
+ Version: 2.5.5
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.4
7
+ License: fmdtools version 2.5.5
8
8
  ---------------------------
9
9
  Apache License
10
10
  Version 2.0, January 2004
@@ -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.4
397
+ git checkout v2.5.5
398
398
  ```
399
399
 
400
400
 
@@ -500,9 +500,9 @@ Decent (but **very imperfect**) results can be achieved using LLMs for model dev
500
500
 
501
501
  ```prompt
502
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.
503
+ Make an fmdtools simulation of a <enter your system here> using the latest syntax from `https://github.com/nasa/fmdtools/tree/v2.5.5` for all modeling (`fmdtools.define`), simulation (`fmdtools.sim`), and analysis (`fmdtools.analyze`) classes.
504
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.
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.5 syntax.
506
506
  ```
507
507
 
508
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!
@@ -548,8 +548,8 @@ To cite a particular version of the fmdtools, you may use:
548
548
  author = {{NASA}},
549
549
  title = {fmdtools},
550
550
  url = {https://github.com/nasa/fmdtools},
551
- version = {2.5.4},
552
- date = {2026-10-5},
551
+ version = {2.5.5},
552
+ date = {2026-10-08},
553
553
  }
554
554
  ```
555
555
 
@@ -131,10 +131,13 @@ tests/test_appended_history_snapshots.py
131
131
  tests/test_approach_joint_domains.py
132
132
  tests/test_approach_model_timestep.py
133
133
  tests/test_approach_phase_map_ownership.py
134
+ tests/test_architecture_vector_inputs.py
134
135
  tests/test_array_differences.py
135
136
  tests/test_array_random_states.py
136
137
  tests/test_array_result_equality.py
137
138
  tests/test_array_state_limits.py
139
+ tests/test_array_state_rounding.py
140
+ tests/test_binomial_trial_counts.py
138
141
  tests/test_bootstrap_statistic_arguments.py
139
142
  tests/test_bounded_array_increments.py
140
143
  tests/test_calc_metric_ci_constant_outputs.py
@@ -142,6 +145,7 @@ tests/test_callable_parameter_domains.py
142
145
  tests/test_choice_draw_mass.py
143
146
  tests/test_choice_probability_precision.py
144
147
  tests/test_common.py
148
+ tests/test_comparison_ci_metrics.py
145
149
  tests/test_comparison_groups.py
146
150
  tests/test_confidence_history_clipping.py
147
151
  tests/test_coordinate_cell_boundaries.py
@@ -149,14 +153,22 @@ tests/test_default_fault_sample_timestep.py
149
153
  tests/test_degradation_path_boundaries.py
150
154
  tests/test_dirichlet_batches.py
151
155
  tests/test_disconnected_graph_robustness.py
156
+ tests/test_discrete_grid_values.py
152
157
  tests/test_discrete_sample_sizes.py
153
158
  tests/test_error_history_plots.py
159
+ tests/test_even_sampling_mass.py
154
160
  tests/test_exact_nominal_expectation.py
161
+ tests/test_expectation_without_nominal.py
162
+ tests/test_explicit_history_times.py
155
163
  tests/test_explicit_result_file_formats.py
156
164
  tests/test_exponential_rayleigh_draw_sizes.py
157
165
  tests/test_factor_sort_priority.py
158
166
  tests/test_fault_history_paths.py
167
+ tests/test_fault_object_overrides.py
159
168
  tests/test_fault_sample_without_nominal.py
169
+ tests/test_fault_space_ownership.py
170
+ tests/test_fault_space_sample_limits.py
171
+ tests/test_fault_summary_paths.py
160
172
  tests/test_fault_time_without_traces.py
161
173
  tests/test_fault_weight_arrays.py
162
174
  tests/test_faulty_scenario_selection.py
@@ -166,17 +178,27 @@ tests/test_generated_history_phase_timestep.py
166
178
  tests/test_geom.py
167
179
  tests/test_graph.py
168
180
  tests/test_graph_edge_comparison.py
181
+ tests/test_graph_zero_seed.py
169
182
  tests/test_hierarchical.py
183
+ tests/test_history_alignment_ownership.py
170
184
  tests/test_history_phase_identifiers.py
185
+ tests/test_history_sample_indices.py
171
186
  tests/test_history_standard_deviation.py
187
+ tests/test_hypergeometric_count_conversion.py
188
+ tests/test_immutable_fault_injection.py
189
+ tests/test_implicit_sampling_start.py
172
190
  tests/test_independent_single_replicate_seeds.py
173
191
  tests/test_individual_result_paths.py
192
+ tests/test_integer_bound_conversion.py
174
193
  tests/test_integer_draw_mass.py
194
+ tests/test_integer_history_differences.py
195
+ tests/test_integer_rate_metrics.py
175
196
  tests/test_join_phase_timestep.py
176
197
  tests/test_join_phasemaps.py
177
198
  tests/test_joint_fault_metadata_order.py
178
199
  tests/test_joint_fault_phase_map.py
179
200
  tests/test_joint_fault_weights.py
201
+ tests/test_joint_scenario_quadrature.py
180
202
  tests/test_json_result_arrays.py
181
203
  tests/test_location_scale_draw_sizes.py
182
204
  tests/test_lognormal_defaults.py
@@ -188,14 +210,19 @@ tests/test_multivariate_hypergeometric_options.py
188
210
  tests/test_multivariate_normal_arguments.py
189
211
  tests/test_named_default_restoration.py
190
212
  tests/test_named_metric_rounding.py
213
+ tests/test_named_parameter_maps.py
191
214
  tests/test_nearest_point_exclusion.py
215
+ tests/test_nested_comparison_inputs.py
216
+ tests/test_nested_comparison_parentage.py
192
217
  tests/test_nested_history_summary.py
193
218
  tests/test_nested_nominal_groups.py
194
219
  tests/test_nested_parameter_constraints.py
220
+ tests/test_nested_sample_metrics.py
195
221
  tests/test_nested_scenario_parameters.py
196
222
  tests/test_nesting_custom_separators.py
197
223
  tests/test_not_equal_constraints.py
198
224
  tests/test_object_history_copy.py
225
+ tests/test_offset_time_grids.py
199
226
  tests/test_packages.py
200
227
  tests/test_parameter_grid_bounds.py
201
228
  tests/test_parameter_sample_defaults.py
@@ -204,6 +231,7 @@ tests/test_parameter_subsampling_types.py
204
231
  tests/test_pareto_density.py
205
232
  tests/test_pathplan.py
206
233
  tests/test_permutation_axis_probabilities.py
234
+ tests/test_permuted_nan_probabilities.py
207
235
  tests/test_permuted_slice_probabilities.py
208
236
  tests/test_phase_map_default_isolation.py
209
237
  tests/test_phase_timestep.py
@@ -211,12 +239,14 @@ tests/test_pruned_fault_times.py
211
239
  tests/test_ragged_confidence_histories.py
212
240
  tests/test_rand.py
213
241
  tests/test_random_combination_types.py
242
+ tests/test_reference_risk_calculations.py
214
243
  tests/test_result.py
215
244
  tests/test_result_constructor_input.py
216
245
  tests/test_result_folder_selection.py
217
246
  tests/test_sample.py
218
247
  tests/test_scenario.py
219
248
  tests/test_scenario_defaults.py
249
+ tests/test_scenario_metric_mappings.py
220
250
  tests/test_shape_distribution_sizes.py
221
251
  tests/test_simple_problem_vector_inputs.py
222
252
  tests/test_simulation_exposure.py
@@ -228,6 +258,7 @@ tests/test_time.py
228
258
  tests/test_time_reset.py
229
259
  tests/test_triangular_arraylike_parameters.py
230
260
  tests/test_tuple_table_factors.py
261
+ tests/test_uniform_bound_dtypes.py
231
262
  tests/test_uniform_density.py
232
263
  tests/test_unit_random_density.py
233
264
  tests/test_vonmises_density.py
@@ -18,7 +18,7 @@ classifiers = [
18
18
  description = "System resilience modelling, simulation, and assessment in Python"
19
19
  license = {file="LICENSE"}
20
20
  name = "fmdtools"
21
- version="2.5.4"
21
+ version="2.5.5"
22
22
  readme = "README.md"
23
23
  requires-python = ">=3.12"
24
24
 
@@ -109,3 +109,81 @@ omit = [
109
109
  "*/Temp/*"
110
110
  ]
111
111
 
112
+ [tool.bumpversion]
113
+ current_version = "2.5.5"
114
+ parse = """(?x)
115
+ (?P<major>0|[1-9]\\d*)\\.
116
+ (?P<minor>0|[1-9]\\d*)\\.
117
+ (?P<patch>0|[1-9]\\d*)
118
+ (?:
119
+ . # dot for pre-release section
120
+ (?P<stage>[a-zA-Z-]+) # pre-release label
121
+ (?P<num>0|[1-9]\\d*) # pre-release version number
122
+ )? # pre-release section is optional
123
+ """
124
+ serialize = [
125
+ "{major}.{minor}.{patch}.{stage}{num}",
126
+ "{major}.{minor}.{patch}",
127
+ ]
128
+ search = "{current_version}"
129
+ replace = "{new_version}"
130
+ regex = false
131
+ ignore_missing_version = false
132
+ tag = true
133
+ sign_tags = true
134
+ tag_name = "v{new_version}"
135
+ tag_message = "Bump version: {current_version} → {new_version}"
136
+ allow_dirty = false
137
+ commit = true
138
+ message = "Bump version: {current_version} → {new_version}"
139
+ commit_args = ""
140
+
141
+ [tool.bumpversion.parts.stage]
142
+ values = ["dev", "rc", "final"]
143
+ optional_value = "final"
144
+
145
+ [[tool.bumpversion.files]]
146
+ filename = "src/fmdtools/__init__.py"
147
+ search = "__version__ = '{current_version}'"
148
+ replace = "__version__ = '{new_version}'"
149
+
150
+ [[tool.bumpversion.files]]
151
+ filename = "conf.py"
152
+ search = "release = '{current_version}'"
153
+ replace = "release = '{new_version}'"
154
+
155
+ [[tool.bumpversion.files]]
156
+ filename = "LICENSE"
157
+ search = "fmdtools version {current_version}"
158
+ replace = "fmdtools version {new_version}"
159
+
160
+ [[tool.bumpversion.files]]
161
+ filename = "README.md"
162
+ search = "git checkout v{current_version}"
163
+ replace = "git checkout v{new_version}"
164
+
165
+ [[tool.bumpversion.files]]
166
+ filename = "README.md"
167
+ search = "https://github.com/nasa/fmdtools/tree/v{current_version}"
168
+ replace = "https://github.com/nasa/fmdtools/tree/v{new_version}"
169
+
170
+ [[tool.bumpversion.files]]
171
+ filename = "README.md"
172
+ search = "fmdtools v{current_version}"
173
+ replace = "fmdtools v{new_version}"
174
+
175
+ [[tool.bumpversion.files]]
176
+ filename = "README.md"
177
+ search = "version = {{{current_version}}}"
178
+ replace = "version = {{{new_version}}}"
179
+
180
+ [[tool.bumpversion.files]]
181
+ filename = "README.md"
182
+ search = "date = {{\\d{{4}}-\\d{{2}}-\\d{{2}}}}"
183
+ replace = "date = {{{now:%Y-%m-%d}}}"
184
+ regex = true
185
+
186
+ [[tool.bumpversion.files]]
187
+ filename = "docs-source/Intro_to_fmdtools.md"
188
+ search = "fmdtools v{current_version}"
189
+ replace = "fmdtools v{new_version}"
@@ -22,6 +22,6 @@ import fmdtools.sim as sim
22
22
  import fmdtools.analyze as analyze
23
23
 
24
24
  __all__ = ['analyze', 'sim', 'define']
25
- __version__ = '2.5.4'
25
+ __version__ = '2.5.5'
26
26
  __copyright__ = "Copyright 2024 United States Government"
27
27
  __license__ = "Apache-2.0"
@@ -95,6 +95,23 @@ def to_include_keys(to_include):
95
95
  return tuple(keys)
96
96
 
97
97
 
98
+ def _integer_difference(val1, val2, compact=False):
99
+ """Subtract integer values without overflowing their storage dtype."""
100
+ left, right = np.asarray(val1), np.asarray(val2)
101
+ dtype = (
102
+ object
103
+ if max(left.dtype.itemsize, right.dtype.itemsize) >= 8
104
+ else np.int64
105
+ )
106
+ delta = np.subtract(left, right, dtype=dtype)
107
+
108
+ if compact and np.asarray(delta).dtype == object:
109
+ limits = np.iinfo(np.int64)
110
+ if np.all((delta >= limits.min) & (delta <= limits.max)):
111
+ return np.asarray(delta, dtype=np.int64)[()]
112
+ return delta
113
+
114
+
98
115
  def diff(val1, val2, difftype='bool'):
99
116
  """
100
117
  Find inconsistent states between val1, val2.
@@ -102,6 +119,10 @@ def diff(val1, val2, difftype='bool'):
102
119
  The difftype option ('diff' (takes the difference), 'bool' (checks if the same),
103
120
  and float (checks if under the provided tolerance))
104
121
 
122
+ Integer arithmetic is widened before subtraction and absolute value. Numeric
123
+ differences use int64 where possible, or exact Python integers for values
124
+ outside its range. Boolean comparisons and floating arithmetic are unchanged.
125
+
105
126
  Examples
106
127
  --------
107
128
  >>> diff([1, 2, 3], [2, 2, 3])
@@ -114,12 +135,25 @@ def diff(val1, val2, difftype='bool'):
114
135
  val1 = np.array(val1)
115
136
  if isinstance(val2, list):
116
137
  val2 = np.array(val2)
138
+
139
+ if difftype == 'bool':
140
+ return val1 != val2
141
+
142
+ left, right = np.asarray(val1), np.asarray(val2)
143
+ integer_values = left.dtype.kind in 'iu' and right.dtype.kind in 'iu'
144
+
117
145
  if difftype == 'diff':
146
+ if integer_values:
147
+ return _integer_difference(left, right, compact=True)
118
148
  return val1-val2
119
- elif difftype == 'bool':
120
- return val1 != val2
121
- elif isinstance(difftype, float):
122
- return abs(val1-val2) > difftype
149
+
150
+ if isinstance(difftype, float):
151
+ if integer_values:
152
+ return np.abs(_integer_difference(left, right)) > difftype
153
+ close = np.isclose(
154
+ left, right, atol=difftype, rtol=0.0, equal_nan=True
155
+ )
156
+ return ~close & ~np.isnan(left) & ~np.isnan(right)
123
157
  except ValueError as e:
124
158
  raise Exception("Unable to diff "+str(val1)+" and "+str(val2)) from e
125
159
 
@@ -214,10 +248,18 @@ def load_folder(folder, filetype):
214
248
 
215
249
 
216
250
  def metric_preamble(data, dtype=None, rates=None, r_dtype=None, r_norm=False):
217
- """Process data for weighted metrics used by calc_metric and calc_metric_ci."""
251
+ """Process data for weighted metrics used by calc_metric and calc_metric_ci.
252
+
253
+ Integer and boolean rate factors are promoted to float64 before normalization
254
+ or multiplication, avoiding fixed-width overflow in risk calculations.
255
+ Unweighted data and floating/object rate arithmetic are unchanged.
256
+ """
218
257
  vals = np.array(data, dtype=dtype)
219
258
  if rates is not None:
220
259
  rates = np.array(rates, dtype=r_dtype)
260
+ if rates.dtype.kind in 'biu':
261
+ # Weight in floating arithmetic before summing or multiplying counts.
262
+ rates = rates.astype(np.float64)
221
263
  if r_norm:
222
264
  rates = rates/np.sum(rates)
223
265
  if np.size(rates) > 1 and np.size(vals) > 1:
@@ -850,14 +850,14 @@ class Graph(object):
850
850
  number of times to run robustness coefficient algorithm
851
851
  (result is averaged over all trials)
852
852
  seed : int
853
- optional seed to instantiate test with
853
+ Optional integer seed, including zero. False or None leaves trials unseeded.
854
854
 
855
855
  Returns
856
856
  -------
857
857
  RC : robustness coefficient
858
858
  """
859
859
  g = self.g.to_undirected()
860
- if seed:
860
+ if seed is not False and seed is not None:
861
861
  rng = np.random.default_rng(seed=seed)
862
862
  else:
863
863
  rng = np.random.default_rng()
@@ -424,12 +424,12 @@ class History(Result):
424
424
  return self
425
425
 
426
426
  def _prep_nom_faulty(self, nomhist={}, align=True):
427
- """Create a nominal history of states from the current history."""
427
+ """Prepare local flattened histories so alignment leaves inputs unchanged."""
428
428
  if not nomhist:
429
429
  nomhist = self.nominal.flatten()
430
430
  else:
431
431
  nomhist = nomhist.flatten()
432
- faulthist = self._prep_faulty()
432
+ faulthist = self._prep_faulty().flatten()
433
433
  if align:
434
434
  faulthist._align(nomhist)
435
435
  return nomhist, faulthist
@@ -466,6 +466,9 @@ class History(Result):
466
466
  """
467
467
  Get history of times when the attributes *attrs deviate from nominal values.
468
468
 
469
+ Align the comparison on local flattened views without truncating either
470
+ source history. Returned values use the common time range.
471
+
469
472
  Parameters
470
473
  ----------
471
474
  *attrs : names of attributes
@@ -535,6 +538,9 @@ class History(Result):
535
538
  """
536
539
  Get fault names associated with the given attributes.
537
540
 
541
+ Match complete fault-container paths in flat or nested histories, including
542
+ root-level sub-fault flags.
543
+
538
544
  Parameters
539
545
  ----------
540
546
  *attrs : strs
@@ -545,15 +551,14 @@ class History(Result):
545
551
  faults_hist : History
546
552
  History of the attrs and their corresponding faults
547
553
  """
548
- faulthist = self._prep_faulty()
554
+ faulthist = self._prep_faulty().flatten()
549
555
  faults_hist = History()
550
556
  if not attrs:
551
557
  attrs = self.keys()
552
558
  for att in attrs:
553
559
  faults_hist[att] = History({k.split('.')[-1]: v for k, v in faulthist.items()
554
- if ('.'+att+'.m.faults' in k) or
555
- ('.'+att+'.m.sub_faults' in k) or
556
- (att+'.m.faults' in k and k.startswith(att))})
560
+ if ('.'+att+'.m.faults.' in '.'+k+'.') or
561
+ ('.'+k).endswith('.'+att+'.m.sub_faults')})
557
562
  return faults_hist
558
563
 
559
564
  def get_faulty_hist(self, *attrs, withtime=True, withtotal=True, operator=np.any):
@@ -584,29 +584,31 @@ class Result(UserDict):
584
584
  **groups : list
585
585
  Sets of scenarios to group (e.g. set_1=['scen1', 'scen2'...]).
586
586
  Scenario names match at dot-separated path boundaries; selecting a
587
- parent scenario also includes its nested scenarios.
587
+ parent scenario also includes its nested scenarios. Flattened, nested
588
+ and mixed result storage produce the same groups of leaf paths.
588
589
 
589
590
  Returns
590
591
  -------
591
592
  group_hist : History
592
593
  Single-level history with structure {group:{scenname.valuename}}
593
594
  """
595
+ flat = self.flatten()
594
596
  if not groups:
595
- groups = self.get_default_comp_groups()
597
+ groups = flat.get_default_comp_groups()
596
598
  if time not in values:
597
599
  values = values + (time, )
598
600
  group_hist = self.__class__()
599
601
  for group, scens in groups.items():
600
602
  if scens == 'default':
601
- scens = {k.split('.')[0] for k in self.keys()}
603
+ scens = {k.split('.')[0] for k in flat.keys()}
602
604
  elif isinstance(scens, str):
603
605
  scens = [scens]
604
- k_vs = [k for k in self.keys() for scen in scens for v in values
606
+ k_vs = [k for k in flat.keys() for scen in scens for v in values
605
607
  if k.startswith(scen+'.') and k.endswith(v) and '.t.' not in k]
606
608
  if len(k_vs) > 0 and (group not in group_hist):
607
609
  group_hist[group] = self.__class__()
608
610
  for k in k_vs:
609
- group_hist[group][k] = self[k]
611
+ group_hist[group][k] = flat[k]
610
612
  # Sort into comparison groups
611
613
  if not group_hist:
612
614
  raise Exception("Invalid comp_groups: " + str(groups) +
@@ -837,6 +839,10 @@ class Result(UserDict):
837
839
  """
838
840
  Take the expectation of numeric metrics in the result over given scenarios.
839
841
 
842
+ Without a nominal scenario, use the first scenario's numeric fields.
843
+ A nominal reference is required only for differences from nominal.
844
+ An empty result returns an empty result of the same type.
845
+
840
846
  Parameters
841
847
  ----------
842
848
  app : SampleApproach, optional
@@ -859,7 +865,12 @@ class Result(UserDict):
859
865
  """
860
866
  mh = self.nest(levels=1)
861
867
 
862
- nomhist = {k: v for k, v in mh.nominal.items() if is_numeric(v)}
868
+ if difference_from_nominal and 'nominal' not in mh:
869
+ raise ValueError("A nominal scenario is required for nominal differences.")
870
+ if not mh:
871
+ return self.__class__()
872
+ reference = mh['nominal'] if 'nominal' in mh else next(iter(mh.values()))
873
+ nomhist = {k: v for k, v in reference.items() if is_numeric(v)}
863
874
  newhists = {k: hist for k, hist in mh.items()
864
875
  if with_nominal or k != 'nominal'}
865
876
  if app:
@@ -475,10 +475,10 @@ class FMEA(BaseTab):
475
475
 
476
476
  >>> FMEA(res, exfs, average_metric=["rate"], sum_metric=["cost"], expected_metric=["cost"], rates="rate").as_table()
477
477
  average_rate sum_cost expected_cost
478
- exfxnarch.fxns.ex_fxn2 short 1.5 13 20
479
- exfxnarch.fxns.ex_fxn short 1.5 9 14
480
- exfxnarch.fxns.ex_fxn2 no_charge 1.5 5 8
481
- exfxnarch.fxns.ex_fxn no_charge 1.5 1 2
478
+ exfxnarch.fxns.ex_fxn2 short 1.5 13 20.0
479
+ exfxnarch.fxns.ex_fxn short 1.5 9 14.0
480
+ exfxnarch.fxns.ex_fxn2 no_charge 1.5 5 8.0
481
+ exfxnarch.fxns.ex_fxn no_charge 1.5 1 2.0
482
482
  >>> FMEA(res, exfs, sum_metric=["rate"], average_metric=["cost"]).as_table()
483
483
  sum_rate average_cost
484
484
  exfxnarch.fxns.ex_fxn2 short 3 6.5
@@ -543,6 +543,8 @@ class BaseComparison(BaseTab):
543
543
  e.g. {'cost': 'average'}. Default is {}
544
544
  ci_metrics : list
545
545
  Metrics to calculate a confidence interval for (using bootstrap_ci).
546
+ Each has a point estimate and lower/upper bounds, whether or not it is
547
+ also listed in metrics. Each distinct metric is calculated once.
546
548
  Default is [].
547
549
  ci_kwargs : dict
548
550
  kwargs to bootstrap_ci
@@ -551,13 +553,14 @@ class BaseComparison(BaseTab):
551
553
  def __init__(self, res, scen_groups, metrics=['cost'],
552
554
  default_stat="expected", stats={}, ci_metrics=[], ci_kwargs={}):
553
555
 
554
- met_dict = {met: {} for met in metrics}
556
+ all_metrics = list(dict.fromkeys([*metrics, *ci_metrics]))
557
+ met_dict = {met: {} for met in all_metrics}
555
558
  met_dict.update({met+"_lb": {} for met in ci_metrics})
556
559
  met_dict.update({met+"_ub": {} for met in ci_metrics})
557
560
 
558
561
  for fact_tup, scens in scen_groups.items():
559
562
  sub_res = res.get_scens(*scens)
560
- for met in metrics+ci_metrics:
563
+ for met in all_metrics:
561
564
  if met in stats:
562
565
  stat = stats[met]
563
566
  else:
@@ -702,7 +705,9 @@ class NestedComparison(BaseComparison):
702
705
  Factors (Scenario properties e.g., 'name', 'time', 'var') in samp to take
703
706
  statistic over. Default is ['time']
704
707
  samps : dict
705
- Sample objects used to generate the scenarios. {'name': samp}
708
+ Sample objects keyed by their parent scenario name, {'name': samp}.
709
+ Each inner sample contributes only to that parent's factor group;
710
+ matching factor groups accumulate scenarios across parents.
706
711
  samps_factors : list
707
712
  Factors (Scenario properties e.g., 'name', 'time', 'var') in samp to take
708
713
  statistic over in the apps. Default is ['time']
@@ -713,13 +718,15 @@ class NestedComparison(BaseComparison):
713
718
  def __init__(self, res, samp, samp_factors, samps, samps_factors, **kwargs):
714
719
  overall_scen_groups = {}
715
720
  scen_groups = samp.get_scen_groups(*samp_factors)
716
- for n_samp in samps.values():
721
+ for parent, n_samp in samps.items():
717
722
  n_scen_groups = n_samp.get_scen_groups(*samps_factors)
718
723
  for scen_group, scens in scen_groups.items():
724
+ if parent not in scens:
725
+ continue
719
726
  for n_scen_group, n_scens in n_scen_groups.items():
720
727
  k = tuple(list(scen_group)+list(n_scen_group))
721
- v = [s+"."+ns for s in scens for ns in n_scens]
722
- overall_scen_groups[k] = v
728
+ v = [parent+"."+ns for ns in n_scens]
729
+ overall_scen_groups.setdefault(k, []).extend(v)
723
730
 
724
731
  self.factors = samp_factors + samps_factors
725
732
  super().__init__(res, overall_scen_groups, **kwargs)
@@ -441,9 +441,14 @@ def nan_to_x(metric, x=0.0):
441
441
 
442
442
 
443
443
  def gen_timerange(start_time, end_time, dt=1.0, min_r=7):
444
- """Generate the times in a given interval given the timestep dt."""
445
- return round_float(np.arange(start_time, end_time + np.power(10.0, -min_r), dt),
446
- res=dt, min_r=min_r)
444
+ """Generate a timestep grid anchored at start_time, not at zero.
445
+
446
+ Round elapsed steps before restoring the origin so non-grid-aligned starts
447
+ do not shift or duplicate the generated times. Decimal cleanup and the
448
+ inclusive endpoint tolerance retain their min_r precision.
449
+ """
450
+ elapsed = np.arange(0.0, end_time - start_time + np.power(10.0, -min_r), dt)
451
+ return np.round(start_time + round_float(elapsed, res=dt, min_r=min_r), min_r)
447
452
 
448
453
 
449
454
  def get_code_attrs(obj):