RCAIDE-GUI 1.0.3__tar.gz → 1.0.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 (192) hide show
  1. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/PKG-INFO +1 -1
  2. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/RCAIDE_GUI.egg-info/PKG-INFO +1 -1
  3. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/RCAIDE_GUI.egg-info/SOURCES.txt +20 -2
  4. rcaide_gui-1.0.5/VERSION +1 -0
  5. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/common_widgets/data_entry_widget.py +108 -106
  6. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/main.py +13 -6
  7. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/rcaide_io.py +162 -33
  8. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/__init__.py +13 -10
  9. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/fuselages/fuselage_frame.py +1 -0
  10. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/powertrain/distributors/distributor_frame.py +11 -0
  11. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/powertrain/powertrain_frame.py +28 -63
  12. rcaide_gui-1.0.5/tabs/geometry/frames/powertrain/systems/__init__.py +1 -0
  13. rcaide_gui-1.0.5/tabs/geometry/frames/powertrain/systems/system_frame.py +85 -0
  14. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/geometry.py +86 -71
  15. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/powertrain/__init__.py +1 -0
  16. rcaide_gui-1.0.5/tabs/geometry/widgets/powertrain/distributors/fuel_line_widget.py +130 -0
  17. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/powertrain/powertrain_connector_widget.py +13 -10
  18. rcaide_gui-1.0.5/tabs/geometry/widgets/powertrain/powertrain_widget.py +186 -0
  19. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/powertrain/propulsors/turbofan_widget.py +3 -1
  20. rcaide_gui-1.0.5/tabs/geometry/widgets/powertrain/systems/__init__.py +1 -0
  21. rcaide_gui-1.0.5/tabs/geometry/widgets/powertrain/systems/system_widget.py +124 -0
  22. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/home/home.py +37 -24
  23. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/mission/mission.py +23 -9
  24. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/mission/widgets/flight_controls_widget.py +9 -9
  25. rcaide_gui-1.0.5/tabs/performance/__init__.py +3 -0
  26. rcaide_gui-1.0.5/tabs/performance/analysis_registry.py +563 -0
  27. rcaide_gui-1.0.5/tabs/performance/performance.py +885 -0
  28. rcaide_gui-1.0.5/tabs/performance/results_tracker.py +89 -0
  29. rcaide_gui-1.0.5/tabs/results_viewer/__init__.py +1 -0
  30. rcaide_gui-1.0.5/tabs/results_viewer/results_viewer.py +1059 -0
  31. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/solve.py +13 -30
  32. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/visualize_geometry/__init__.py +0 -1
  33. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/visualize_geometry/visualize_geometry.py +190 -90
  34. rcaide_gui-1.0.3/VERSION +0 -1
  35. rcaide_gui-1.0.3/tabs/geometry/widgets/powertrain/distributors/fuel_line_widget.py +0 -81
  36. rcaide_gui-1.0.3/tabs/geometry/widgets/powertrain/powertrain_widget.py +0 -206
  37. rcaide_gui-1.0.3/tabs/visualize_geometry/core_3d_viewer.py +0 -253
  38. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/LICENSE +0 -0
  39. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/RCAIDE_GUI.egg-info/dependency_links.txt +0 -0
  40. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/RCAIDE_GUI.egg-info/entry_points.txt +0 -0
  41. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/RCAIDE_GUI.egg-info/requires.txt +0 -0
  42. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/RCAIDE_GUI.egg-info/top_level.txt +0 -0
  43. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/README.md +0 -0
  44. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/README_PyPI.md +0 -0
  45. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/common_widgets/__init__.py +0 -0
  46. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/common_widgets/animated_toggle.py +0 -0
  47. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/common_widgets/color.py +0 -0
  48. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/common_widgets/image_widget.py +0 -0
  49. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/common_widgets/unit_picker_widget.py +0 -0
  50. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/pyproject.toml +0 -0
  51. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/setup.cfg +0 -0
  52. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/setup.py +0 -0
  53. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/aircraft_configs/__init__.py +0 -0
  54. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/aircraft_configs/aircraft_configs.py +0 -0
  55. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/analysis/__init__.py +0 -0
  56. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/analysis/analysis.py +0 -0
  57. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/analysis/widgets/__init__.py +0 -0
  58. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/analysis/widgets/aeroacoustics_widget.py +0 -0
  59. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/analysis/widgets/aerodynamics_widget.py +0 -0
  60. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/analysis/widgets/analysis_data_widget.py +0 -0
  61. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/analysis/widgets/atmosphere_widget.py +0 -0
  62. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/analysis/widgets/costs_widget.py +0 -0
  63. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/analysis/widgets/energy_widget.py +0 -0
  64. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/analysis/widgets/geometry_widget.py +0 -0
  65. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/analysis/widgets/planets_widget.py +0 -0
  66. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/analysis/widgets/propulsion_widget.py +0 -0
  67. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/analysis/widgets/stability_widget.py +0 -0
  68. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/analysis/widgets/weights_widget.py +0 -0
  69. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/__init__.py +0 -0
  70. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/aircraft_configs.py +0 -0
  71. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/__init__.py +0 -0
  72. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/booms/__init__.py +0 -0
  73. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/booms/boom_frame.py +0 -0
  74. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/cargo_bays/__init__.py +0 -0
  75. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/cargo_bays/cargo_bay_frame.py +0 -0
  76. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/default_frame.py +0 -0
  77. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/energy_network/__init__.py +0 -0
  78. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/energy_network/turbofan_network/__init__.py +0 -0
  79. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/energy_network/turbofan_network/frames/__init__.py +0 -0
  80. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/energy_network/turbofan_network/widgets/__init__.py +0 -0
  81. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/fuselages/__init__.py +0 -0
  82. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/geometry_frame.py +0 -0
  83. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/landing_gears/__init__.py +0 -0
  84. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/landing_gears/landing_gear_frame.py +0 -0
  85. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/nacelles/__init__.py +0 -0
  86. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/powertrain/__init__.py +0 -0
  87. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/powertrain/converters/__init__.py +0 -0
  88. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/powertrain/converters/converter_frame.py +0 -0
  89. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/powertrain/distributors/__init__.py +0 -0
  90. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/powertrain/nacelles/__init__.py +0 -0
  91. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/powertrain/nacelles/nacelle_frame.py +0 -0
  92. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/powertrain/propulsors/__init__.py +0 -0
  93. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/powertrain/propulsors/propulsor_frame.py +0 -0
  94. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/powertrain/sources/__init__.py +0 -0
  95. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/powertrain/sources/energy_source_frame.py +0 -0
  96. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/vehicle_frame.py +0 -0
  97. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/wings/__init__.py +0 -0
  98. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/frames/wings/wings_frame.py +0 -0
  99. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/__init__.py +0 -0
  100. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/booms/__init__.py +0 -0
  101. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/booms/boom_section_widget.py +0 -0
  102. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/cargo_bays/__init__.py +0 -0
  103. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/fuselages/__init__.py +0 -0
  104. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/fuselages/cabin_class_widget.py +0 -0
  105. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/fuselages/cabin_widget.py +0 -0
  106. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/fuselages/fuselage_section_widget.py +0 -0
  107. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/geometry_data_widget.py +0 -0
  108. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/landing_gears/__init__.py +0 -0
  109. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/nacelles/__init__.py +0 -0
  110. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/powertrain/converters/__init__.py +0 -0
  111. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/powertrain/converters/turboelectric_generator_widget.py +0 -0
  112. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/powertrain/distributors/__init__.py +0 -0
  113. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/powertrain/modulators/__init__.py +0 -0
  114. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/powertrain/modulators/esc_widget.py +0 -0
  115. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/powertrain/nacelles/__init__.py +0 -0
  116. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/powertrain/nacelles/nacelle_section_widget.py +0 -0
  117. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/powertrain/propulsors/__init__.py +0 -0
  118. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/powertrain/sources/__init__.py +0 -0
  119. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/powertrain/sources/fuel_tank_widget.py +0 -0
  120. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/powertrain/sources/source_selector_widget.py +0 -0
  121. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/wings/__init__.py +0 -0
  122. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/wings/wing_cs_widget.py +0 -0
  123. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/geometry/widgets/wings/wing_section_widget.py +0 -0
  124. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/home/__init__.py +0 -0
  125. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/mission/__init__.py +0 -0
  126. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/mission/widgets/__init__.py +0 -0
  127. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/mission/widgets/mission_analysis_widget.py +0 -0
  128. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/mission/widgets/mission_segment_helper.py +0 -0
  129. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/mission/widgets/mission_segment_widget.py +0 -0
  130. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/__init__.py +0 -0
  131. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/__init__.py +0 -0
  132. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/aeroacoustics/__init__.py +0 -0
  133. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/aeroacoustics/plot_2D_noise_contour.py +0 -0
  134. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/aeroacoustics/plot_3D_noise_contour.py +0 -0
  135. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/aeroacoustics/plot_noise_certification_contour.py +0 -0
  136. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/aeroacoustics/plot_noise_level.py +0 -0
  137. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/aerodynamics/__init__.py +0 -0
  138. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/aerodynamics/plot_aerodynamic_coefficients.py +0 -0
  139. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/aerodynamics/plot_aerodynamic_forces.py +0 -0
  140. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/aerodynamics/plot_aircraft_aerodynamics.py +0 -0
  141. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/aerodynamics/plot_drag_components.py +0 -0
  142. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/aerodynamics/plot_lift_distribution.py +0 -0
  143. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/aerodynamics/plot_rotor_conditions.py +0 -0
  144. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/aerodynamics/plot_rotor_disc_performance.py +0 -0
  145. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/aerodynamics/plot_rotor_performance.py +0 -0
  146. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/common/__init__.py +0 -0
  147. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/common/plot_style.py +0 -0
  148. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/common/set_axes.py +0 -0
  149. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/create_plot_widgets.py +0 -0
  150. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/emissions/__init__.py +0 -0
  151. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/emissions/plot_emissions.py +0 -0
  152. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/energy/__init__.py +0 -0
  153. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/energy/plot_altitude_sfc_weight.py +0 -0
  154. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/energy/plot_battery_cell_conditions.py +0 -0
  155. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/energy/plot_battery_degradation.py +0 -0
  156. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/energy/plot_battery_module_C_rates.py +0 -0
  157. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/energy/plot_battery_module_conditions.py +0 -0
  158. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/energy/plot_battery_pack_conditions.py +0 -0
  159. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/energy/plot_battery_ragone_diagram.py +0 -0
  160. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/energy/plot_battery_temperature.py +0 -0
  161. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/energy/plot_electric_propulsor_efficiencies.py +0 -0
  162. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/energy/plot_propulsor_throttles.py +0 -0
  163. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/mission/__init__.py +0 -0
  164. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/mission/plot_aircraft_velocities.py +0 -0
  165. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/mission/plot_flight_conditions.py +0 -0
  166. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/mission/plot_flight_trajectory.py +0 -0
  167. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/stability/__init__.py +0 -0
  168. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/stability/plot_flight_forces_and_moments.py +0 -0
  169. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/stability/plot_lateral_stability.py +0 -0
  170. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/stability/plot_longitudinal_stability.py +0 -0
  171. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/thermal_management/__init__.py +0 -0
  172. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/thermal_management/plot_air_cooled_conditions.py +0 -0
  173. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/thermal_management/plot_cross_flow_heat_exchanger_conditions.py +0 -0
  174. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/thermal_management/plot_reservoir_conditions.py +0 -0
  175. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/thermal_management/plot_thermal_management_performance.py +0 -0
  176. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/thermal_management/plot_wavy_channel_conditions.py +0 -0
  177. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/weights/__init__.py +0 -0
  178. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/weights/plot_load_diagram.py +0 -0
  179. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/solve/plots/weights/plot_weight_breakdown.py +0 -0
  180. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/style_sheet.py +0 -0
  181. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/tab_widget.py +0 -0
  182. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/visualize_geometry/features/__init__.py +0 -0
  183. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/visualize_geometry/features/axes_gizmo.py +0 -0
  184. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/visualize_geometry/features/background.py +0 -0
  185. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/visualize_geometry/features/blueprint.py +0 -0
  186. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/visualize_geometry/features/camera.py +0 -0
  187. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/visualize_geometry/features/drag_aircraft.py +0 -0
  188. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/visualize_geometry/features/grid.py +0 -0
  189. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/visualize_geometry/features/measurement.py +0 -0
  190. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/visualize_geometry/features/screenshot.py +0 -0
  191. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/tabs/visualize_geometry/geometry_helper_functions.py +0 -0
  192. {rcaide_gui-1.0.3 → rcaide_gui-1.0.5}/utilities.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: RCAIDE-GUI
3
- Version: 1.0.3
3
+ Version: 1.0.5
4
4
  Summary: RCAIDE Graphical User Interface: interactive desktop application for aircraft design and analysis
5
5
  License: MIT License
6
6
  Classifier: Development Status :: 4 - Beta
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: RCAIDE-GUI
3
- Version: 1.0.3
3
+ Version: 1.0.5
4
4
  Summary: RCAIDE Graphical User Interface: interactive desktop application for aircraft design and analysis
5
5
  License: MIT License
6
6
  Classifier: Development Status :: 4 - Beta
@@ -67,6 +67,8 @@ utilities.py
67
67
  ./tabs/geometry/frames/powertrain/propulsors/propulsor_frame.py
68
68
  ./tabs/geometry/frames/powertrain/sources/__init__.py
69
69
  ./tabs/geometry/frames/powertrain/sources/energy_source_frame.py
70
+ ./tabs/geometry/frames/powertrain/systems/__init__.py
71
+ ./tabs/geometry/frames/powertrain/systems/system_frame.py
70
72
  ./tabs/geometry/frames/wings/__init__.py
71
73
  ./tabs/geometry/frames/wings/wings_frame.py
72
74
  ./tabs/geometry/widgets/__init__.py
@@ -96,6 +98,8 @@ utilities.py
96
98
  ./tabs/geometry/widgets/powertrain/sources/__init__.py
97
99
  ./tabs/geometry/widgets/powertrain/sources/fuel_tank_widget.py
98
100
  ./tabs/geometry/widgets/powertrain/sources/source_selector_widget.py
101
+ ./tabs/geometry/widgets/powertrain/systems/__init__.py
102
+ ./tabs/geometry/widgets/powertrain/systems/system_widget.py
99
103
  ./tabs/geometry/widgets/wings/__init__.py
100
104
  ./tabs/geometry/widgets/wings/wing_cs_widget.py
101
105
  ./tabs/geometry/widgets/wings/wing_section_widget.py
@@ -108,6 +112,12 @@ utilities.py
108
112
  ./tabs/mission/widgets/mission_analysis_widget.py
109
113
  ./tabs/mission/widgets/mission_segment_helper.py
110
114
  ./tabs/mission/widgets/mission_segment_widget.py
115
+ ./tabs/performance/__init__.py
116
+ ./tabs/performance/analysis_registry.py
117
+ ./tabs/performance/performance.py
118
+ ./tabs/performance/results_tracker.py
119
+ ./tabs/results_viewer/__init__.py
120
+ ./tabs/results_viewer/results_viewer.py
111
121
  ./tabs/solve/__init__.py
112
122
  ./tabs/solve/solve.py
113
123
  ./tabs/solve/plots/__init__.py
@@ -160,7 +170,6 @@ utilities.py
160
170
  ./tabs/solve/plots/weights/plot_load_diagram.py
161
171
  ./tabs/solve/plots/weights/plot_weight_breakdown.py
162
172
  ./tabs/visualize_geometry/__init__.py
163
- ./tabs/visualize_geometry/core_3d_viewer.py
164
173
  ./tabs/visualize_geometry/geometry_helper_functions.py
165
174
  ./tabs/visualize_geometry/visualize_geometry.py
166
175
  ./tabs/visualize_geometry/features/__init__.py
@@ -235,6 +244,8 @@ tabs/geometry/frames/powertrain/propulsors/__init__.py
235
244
  tabs/geometry/frames/powertrain/propulsors/propulsor_frame.py
236
245
  tabs/geometry/frames/powertrain/sources/__init__.py
237
246
  tabs/geometry/frames/powertrain/sources/energy_source_frame.py
247
+ tabs/geometry/frames/powertrain/systems/__init__.py
248
+ tabs/geometry/frames/powertrain/systems/system_frame.py
238
249
  tabs/geometry/frames/wings/__init__.py
239
250
  tabs/geometry/frames/wings/wings_frame.py
240
251
  tabs/geometry/widgets/__init__.py
@@ -264,6 +275,8 @@ tabs/geometry/widgets/powertrain/propulsors/turbofan_widget.py
264
275
  tabs/geometry/widgets/powertrain/sources/__init__.py
265
276
  tabs/geometry/widgets/powertrain/sources/fuel_tank_widget.py
266
277
  tabs/geometry/widgets/powertrain/sources/source_selector_widget.py
278
+ tabs/geometry/widgets/powertrain/systems/__init__.py
279
+ tabs/geometry/widgets/powertrain/systems/system_widget.py
267
280
  tabs/geometry/widgets/wings/__init__.py
268
281
  tabs/geometry/widgets/wings/wing_cs_widget.py
269
282
  tabs/geometry/widgets/wings/wing_section_widget.py
@@ -276,6 +289,12 @@ tabs/mission/widgets/flight_controls_widget.py
276
289
  tabs/mission/widgets/mission_analysis_widget.py
277
290
  tabs/mission/widgets/mission_segment_helper.py
278
291
  tabs/mission/widgets/mission_segment_widget.py
292
+ tabs/performance/__init__.py
293
+ tabs/performance/analysis_registry.py
294
+ tabs/performance/performance.py
295
+ tabs/performance/results_tracker.py
296
+ tabs/results_viewer/__init__.py
297
+ tabs/results_viewer/results_viewer.py
279
298
  tabs/solve/__init__.py
280
299
  tabs/solve/solve.py
281
300
  tabs/solve/plots/__init__.py
@@ -328,7 +347,6 @@ tabs/solve/plots/weights/__init__.py
328
347
  tabs/solve/plots/weights/plot_load_diagram.py
329
348
  tabs/solve/plots/weights/plot_weight_breakdown.py
330
349
  tabs/visualize_geometry/__init__.py
331
- tabs/visualize_geometry/core_3d_viewer.py
332
350
  tabs/visualize_geometry/geometry_helper_functions.py
333
351
  tabs/visualize_geometry/visualize_geometry.py
334
352
  tabs/visualize_geometry/features/__init__.py
@@ -0,0 +1 @@
1
+ 1.0.5
@@ -1,10 +1,10 @@
1
1
  # RCAIDE_GUI/tabs/visualize_geometry/features/axes_gizmo.py
2
2
 
3
- # Created: M Clarke, LEADS, 2024
4
- # Python imports
5
- import ast
6
-
7
- from PyQt6.QtCore import Qt, pyqtSignal
3
+ # Created: M Clarke, LEADS, 2024
4
+ # Python imports
5
+ import ast
6
+
7
+ from PyQt6.QtCore import Qt, pyqtSignal
8
8
  from PyQt6.QtGui import QDoubleValidator
9
9
  from PyQt6.QtWidgets import QLineEdit, QLabel, QGridLayout, QWidget, QSizePolicy, QSpacerItem, QCheckBox, QHBoxLayout, \
10
10
  QVBoxLayout
@@ -94,12 +94,12 @@ class DataEntryWidget(QWidget):
94
94
  grid_layout.addLayout(layout, row, 0, 1, 4)
95
95
  col = num_cols - 1
96
96
  self.data_fields[label[0]] = ()
97
- else:
98
- line_edit = QLineEdit(self)
99
- # Inertia tensors are entered as list/matrix text, not scalar floats.
100
- if label[1] != Units.Intertia:
101
- line_edit.setValidator(QDoubleValidator())
102
- line_edit.setMinimumWidth(150)
97
+ else:
98
+ line_edit = QLineEdit(self)
99
+ # Inertia tensors are entered as list/matrix text, not scalar floats.
100
+ if label[1] != Units.Intertia:
101
+ line_edit.setValidator(QDoubleValidator())
102
+ line_edit.setMinimumWidth(150)
103
103
 
104
104
  unit_picker = UnitPickerWidget(label[1])
105
105
  unit_picker.on_change_callback = self._make_unit_change_handler(
@@ -143,17 +143,17 @@ class DataEntryWidget(QWidget):
143
143
  return si_value
144
144
  return (si_value - zero) / scale
145
145
 
146
- @staticmethod
147
- def _format_converted_value(value):
148
- return f"{value:.15g}"
149
-
150
- @staticmethod
151
- def _parse_list_value(text):
152
- # Use literal_eval so list-like fields become Python lists without eval.
153
- value = ast.literal_eval(text)
154
- if not isinstance(value, list):
155
- raise ValueError(f"Expected a list value, got {type(value).__name__}")
156
- return value
146
+ @staticmethod
147
+ def _format_converted_value(value):
148
+ return f"{value:.15g}"
149
+
150
+ @staticmethod
151
+ def _parse_list_value(text):
152
+ # Use literal_eval so list-like fields become Python lists without eval.
153
+ value = ast.literal_eval(text)
154
+ if not isinstance(value, list):
155
+ raise ValueError(f"Expected a list value, got {type(value).__name__}")
156
+ return value
157
157
 
158
158
  def _make_unit_change_handler(self, unit_picker, *line_edits):
159
159
  def convert_display_values(previous_index, new_index):
@@ -216,30 +216,30 @@ class DataEntryWidget(QWidget):
216
216
  z_value]], unit_picker.current_index
217
217
  elif self.data_units_labels[i][1] == Units.Heading:
218
218
  continue
219
- elif self.data_units_labels[i][1] == Units.Count:
220
- data_field = self.data_fields[label]
221
- line_edit, unit_picker = data_field
222
- text = line_edit.text()
223
- # Count fields should remain integers for RCAIDE.
224
- value = int(text) if text else 0
225
- data[label] = value, unit_picker.current_index
226
- elif self.data_units_labels[i][1] == Units.Intertia:
227
- data_field = self.data_fields[label]
228
- line_edit, unit_picker = data_field
229
- text = line_edit.text()
230
- # Inertia is stored as a tensor/list, not a single scalar.
231
- value = self._parse_list_value(text) if text else None
232
- data[label] = value, unit_picker.current_index
233
- else:
234
- data_field = self.data_fields[label]
235
- line_edit, unit_picker = data_field
236
- text = line_edit.text()
237
- # Most fields are numeric, but some Unitless fields are text labels.
238
- try:
239
- value = float(text) if text else None
240
- except ValueError:
241
- value = text
242
- data[label] = value, unit_picker.current_index
219
+ elif self.data_units_labels[i][1] == Units.Count:
220
+ data_field = self.data_fields[label]
221
+ line_edit, unit_picker = data_field
222
+ text = line_edit.text()
223
+ # Count fields should remain integers for RCAIDE.
224
+ value = int(text) if text else 0
225
+ data[label] = value, unit_picker.current_index
226
+ elif self.data_units_labels[i][1] == Units.Intertia:
227
+ data_field = self.data_fields[label]
228
+ line_edit, unit_picker = data_field
229
+ text = line_edit.text()
230
+ # Inertia is stored as a tensor/list, not a single scalar.
231
+ value = self._parse_list_value(text) if text else None
232
+ data[label] = value, unit_picker.current_index
233
+ else:
234
+ data_field = self.data_fields[label]
235
+ line_edit, unit_picker = data_field
236
+ text = line_edit.text()
237
+ # Most fields are numeric, but some Unitless fields are text labels.
238
+ try:
239
+ value = float(text) if text else None
240
+ except ValueError:
241
+ value = text
242
+ data[label] = value, unit_picker.current_index
243
243
  return data
244
244
 
245
245
  def get_values_si(self):
@@ -266,68 +266,70 @@ class DataEntryWidget(QWidget):
266
266
  z_value]], unit_picker.current_index
267
267
  elif self.data_units_labels[i][1] == Units.Heading:
268
268
  continue
269
- elif self.data_units_labels[i][1] == Units.Count:
270
- data_field = self.data_fields[label]
271
- line_edit, unit_picker = data_field
272
- text = line_edit.text()
273
- # Count fields should remain integers for RCAIDE.
274
- value = int(text) if text else 0
275
- data[label] = value, unit_picker.current_index
276
- elif self.data_units_labels[i][1] == Units.Intertia:
277
- data_field = self.data_fields[label]
278
- line_edit, unit_picker = data_field
279
- text = line_edit.text()
280
- # Inertia is stored as a tensor/list, not a single scalar.
281
- value = self._parse_list_value(text) if text else None
282
- data[label] = value, unit_picker.current_index
283
- else:
284
- data_field = self.data_fields[label]
285
- line_edit, unit_picker = data_field
286
- text = line_edit.text()
287
- # Numeric fields are converted to SI; text fields are preserved.
288
- try:
289
- value = unit_picker.apply_unit(float(text)) if text else None
290
- except ValueError:
291
- value = text
292
- data[label] = value, unit_picker.current_index
269
+ elif self.data_units_labels[i][1] == Units.Count:
270
+ data_field = self.data_fields[label]
271
+ line_edit, unit_picker = data_field
272
+ text = line_edit.text()
273
+ # Count fields should remain integers for RCAIDE.
274
+ value = int(text) if text else 0
275
+ data[label] = value, unit_picker.current_index
276
+ elif self.data_units_labels[i][1] == Units.Intertia:
277
+ data_field = self.data_fields[label]
278
+ line_edit, unit_picker = data_field
279
+ text = line_edit.text()
280
+ # Inertia is stored as a tensor/list, not a single scalar.
281
+ value = self._parse_list_value(text) if text else None
282
+ data[label] = value, unit_picker.current_index
283
+ else:
284
+ data_field = self.data_fields[label]
285
+ line_edit, unit_picker = data_field
286
+ text = line_edit.text()
287
+ # Numeric fields are converted to SI; text fields are preserved.
288
+ try:
289
+ value = unit_picker.apply_unit(float(text)) if text else None
290
+ except ValueError:
291
+ value = text
292
+ data[label] = value, unit_picker.current_index
293
293
  return data
294
294
 
295
- def load_data(self, data):
296
- # Loading saved data should not trigger auto-save.
297
- old_block_state = self.blockSignals(True)
298
- try:
299
- # Load each field based on its input type.
300
- for i, label in enumerate(self.data_fields.keys()):
301
- if self.data_units_labels[i][1] == Units.Boolean:
302
- # Checkbox field.
303
- self.data_fields[label].setChecked(data[label][0])
304
- elif self.data_units_labels[i][1] == Units.Position:
305
- # Three coordinate boxes and one unit picker.
306
- x_line_edit, y_line_edit, z_line_edit, unit_picker = self.data_fields[label]
307
- value, index = data[label]
308
- # Unwrap [[x, y, z]] if needed.
309
- if isinstance(value, list) and value and isinstance(value[0], list):
310
- value = value[0]
311
- # Use origin if the saved value is invalid.
312
- elif not isinstance(value, list):
313
- value = [0, 0, 0]
314
- x_line_edit.setText(str(value[0]))
315
- y_line_edit.setText(str(value[1]))
316
- z_line_edit.setText(str(value[2]))
317
- unit_picker.set_index(index)
318
- elif self.data_units_labels[i][1] == Units.Heading:
319
- # Heading label only.
320
- pass
321
- else:
322
- # Normal value field and unit picker.
323
- line_edit, unit_picker = self.data_fields[label]
324
- value, index = data[label]
325
- # Show None as an empty field.
326
- line_edit.setText("" if value is None else str(value))
327
- unit_picker.set_index(index)
328
- finally:
329
- # Restore signal behavior.
330
- self.blockSignals(old_block_state)
295
+ def load_data(self, data):
296
+ # Loading saved data should not trigger auto-save.
297
+ old_block_state = self.blockSignals(True)
298
+ try:
299
+ # Load each field based on its input type.
300
+ for i, label in enumerate(self.data_fields.keys()):
301
+ if label not in data:
302
+ continue
303
+ if self.data_units_labels[i][1] == Units.Boolean:
304
+ # Checkbox field.
305
+ self.data_fields[label].setChecked(data[label][0])
306
+ elif self.data_units_labels[i][1] == Units.Position:
307
+ # Three coordinate boxes and one unit picker.
308
+ x_line_edit, y_line_edit, z_line_edit, unit_picker = self.data_fields[label]
309
+ value, index = data[label]
310
+ # Unwrap [[x, y, z]] if needed.
311
+ if isinstance(value, list) and value and isinstance(value[0], list):
312
+ value = value[0]
313
+ # Use origin if the saved value is invalid.
314
+ elif not isinstance(value, list):
315
+ value = [0, 0, 0]
316
+ x_line_edit.setText(str(value[0]))
317
+ y_line_edit.setText(str(value[1]))
318
+ z_line_edit.setText(str(value[2]))
319
+ unit_picker.set_index(index)
320
+ elif self.data_units_labels[i][1] == Units.Heading:
321
+ # Heading label only.
322
+ pass
323
+ else:
324
+ # Normal value field and unit picker.
325
+ line_edit, unit_picker = self.data_fields[label]
326
+ value, index = data[label]
327
+ # Show None as an empty field.
328
+ line_edit.setText("" if value is None else str(value))
329
+ unit_picker.set_index(index)
330
+ finally:
331
+ # Restore signal behavior.
332
+ self.blockSignals(old_block_state)
331
333
 
332
334
  # TODO implement mark_save and changed_since_save
333
335
  def mark_save(self):
@@ -57,18 +57,25 @@ class App(QMainWindow):
57
57
  self.widgets = []
58
58
  self.widgets.append((home.get_widget(), "Home"))
59
59
  self.widgets.append((geometry.get_widget(), "Vehicle Setup"))
60
- self.widgets.append((visualize_geometry.get_widget(), "Geometry Visualization"))
61
- self.widgets.append((aircraft_configs.get_widget(), "Configurations Setup"))
60
+ self.widgets.append((visualize_geometry.get_widget(), "Geometry"))
61
+ self.widgets.append((aircraft_configs.get_widget(), "Configurations"))
62
62
  self.widgets.append((analysis.get_widget(), "Analyses Setup"))
63
63
  self.widgets.append((mission.get_widget(), "Mission Setup"))
64
- self.widgets.append((solve.get_widget(), "Mission Simulation"))
65
- # self.widgets.append((shared_analysis_widget, "Multidisciplinary Analyses"))
64
+ self.widgets.append((performance.get_widget(), "Performance"))
65
+ self.widgets.append((solve.get_widget(), "Run Mission"))
66
+ self.widgets.append((results_viewer.get_widget(), "Results Viewer"))
66
67
 
67
68
  for widget, name in self.widgets:
68
69
  self.tabs.addTab(widget, name)
69
70
 
70
71
  self.setCentralWidget(self.tabs)
71
- self.resize(1280, 720)
72
+ screen = QApplication.primaryScreen()
73
+ if screen:
74
+ ag = screen.availableGeometry()
75
+ self.resize(min(1280, ag.width()), min(ag.height() - 30, 836))
76
+ else:
77
+ self.resize(1280, 836)
78
+ self.setMinimumSize(700, 480)
72
79
 
73
80
  def on_tab_change(self, index: int):
74
81
  current_frame = self.tabs.currentWidget()
@@ -134,7 +141,7 @@ class App(QMainWindow):
134
141
 
135
142
  def _go_to_geometry_visualization_tab(self):
136
143
  for index in range(self.tabs.count()):
137
- if self.tabs.tabText(index).strip().lower() == "geometry visualization":
144
+ if self.tabs.tabText(index).strip().lower() == "geometry":
138
145
  self.tabs.setCurrentIndex(index)
139
146
  current_widget = self.tabs.widget(index)
140
147
  if isinstance(current_widget, TabWidget):
@@ -99,7 +99,7 @@ def repair_local_file_paths(value, source_dir=None):
99
99
 
100
100
 
101
101
  def repair_airfoil_path(path, source_dir=None):
102
- if not path or os.path.exists(path):
102
+ if not path:
103
103
  return path
104
104
  basename = os.path.basename(path)
105
105
  if source_dir:
@@ -110,7 +110,7 @@ def repair_airfoil_path(path, source_dir=None):
110
110
  candidate = os.path.join(search_dir, basename)
111
111
  if os.path.exists(candidate):
112
112
  return candidate
113
- return path
113
+ return basename if basename else path
114
114
 
115
115
 
116
116
  # ----------------------------------------------------------------------------------------------------------------------
@@ -344,7 +344,7 @@ def _build_dict_r_with_types(v):
344
344
  if module and qualname and not qualname.startswith('<'):
345
345
  ret['__type__'] = f"{module}.{qualname}"
346
346
 
347
- _skip = ('_component_root_map', '_energy_network_root_map', '_base', '_diff')
347
+ _skip = ('_component_root_map', '_energy_network_root_map', '_base', '_diff', 'vehicle')
348
348
  for k in keys:
349
349
  if k in _skip:
350
350
  continue
@@ -354,7 +354,7 @@ def _build_dict_r_with_types(v):
354
354
 
355
355
  def _build_dict_base_with_types(base):
356
356
  """Top-level serialisation: like RCAIDE.Input_Output.save.build_dict_base but includes __type__."""
357
- _skip = ('_component_root_map', '_energy_network_root_map', '_base', '_diff')
357
+ _skip = ('_component_root_map', '_energy_network_root_map', '_base', '_diff', 'vehicle')
358
358
  base_dict = {}
359
359
  for k in base.keys():
360
360
  if k in _skip:
@@ -412,6 +412,13 @@ rcaide_analyses = RCAIDE.Framework.Analyses.Analysis.Container() # type:
412
412
 
413
413
  mission_data = []
414
414
  rcaide_mission = RCAIDE.Framework.Mission.Sequential_Segments()
415
+ # Last in-memory mission output. Set by the Solve tab after mission.evaluate()
416
+ # and browsed by the Results Viewer so users can inspect values without rerunning.
417
+ rcaide_results = None
418
+ # Last raw result from the Performance tab. Set after each analysis run so the
419
+ # Results Viewer can browse it (stability derivatives, polar arrays, etc.).
420
+ last_performance_result = None
421
+ last_performance_label = ""
415
422
 
416
423
 
417
424
  # ----------------------------------------------------------------------------------------------------------------------
@@ -438,6 +445,138 @@ def vehicle_to_ui_format(vehicle_obj):
438
445
  return ui_dict
439
446
 
440
447
 
448
+ _NETWORK_TYPE_LABEL = {
449
+ 'Fuel': 'Fuel',
450
+ 'Electric': 'Electric',
451
+ 'Hybrid': 'Hybrid',
452
+ 'Hydrogen': 'Hydrogen',
453
+ 'Fuel_Cell': 'Fuel Cell',
454
+ }
455
+
456
+
457
+ def _network_type_for_ui(network_dict):
458
+ type_str = network_dict.get('__type__', '')
459
+ class_name = type_str.rsplit('.', 1)[-1] if type_str else ''
460
+ return _NETWORK_TYPE_LABEL.get(class_name, 'Fuel')
461
+
462
+
463
+ def _propulsor_dict_to_ui(p):
464
+ """Convert a RCAIDE Turbofan JSON dict (unit-argument format) to TurbofanWidget GUI format."""
465
+ def g(d, *keys):
466
+ for k in keys[:-1]:
467
+ d = d.get(k, {}) if isinstance(d, dict) else {}
468
+ return d.get(keys[-1], [0, 0]) if isinstance(d, dict) else [0, 0]
469
+
470
+ return {
471
+ 'Propulsor Tag': p.get('tag', ''),
472
+ 'Origin': g(p, 'origin'),
473
+ 'Engine Length': g(p, 'length'),
474
+ 'Diameter': g(p, 'diameter'),
475
+ 'Bypass Ratio': g(p, 'bypass_ratio'),
476
+ 'Design Altitude': g(p, 'design_altitude'),
477
+ 'Design Mach Number': g(p, 'design_mach_number'),
478
+ 'Design Thrust': g(p, 'design_thrust'),
479
+ 'Fan Polytropic Efficiency': g(p, 'fan', 'polytropic_efficiency'),
480
+ 'Fan Pressure Ratio': g(p, 'fan', 'pressure_ratio'),
481
+ 'Inlet Nozzle Polytropic Efficiency': g(p, 'inlet_nozzle', 'polytropic_efficiency'),
482
+ 'Inlet Nozzle Pressure Ratio': g(p, 'inlet_nozzle', 'pressure_ratio'),
483
+ 'LPC Polytropic Efficiency': g(p, 'low_pressure_compressor', 'polytropic_efficiency'),
484
+ 'LPC Pressure Ratio': g(p, 'low_pressure_compressor', 'pressure_ratio'),
485
+ 'HPC Polytropic Efficiency': g(p, 'high_pressure_compressor', 'polytropic_efficiency'),
486
+ 'HPC Pressure Ratio': g(p, 'high_pressure_compressor', 'pressure_ratio'),
487
+ 'LPT Mechanical Efficiency': g(p, 'low_pressure_turbine', 'mechanical_efficiency'),
488
+ 'LPT Polytropic Efficiency': g(p, 'low_pressure_turbine', 'polytropic_efficiency'),
489
+ 'HPT Mechanical Efficiency': g(p, 'high_pressure_turbine', 'mechanical_efficiency'),
490
+ 'HPT Polytropic Efficiency': g(p, 'high_pressure_turbine', 'polytropic_efficiency'),
491
+ 'Combustor Efficiency': g(p, 'combustor', 'efficiency'),
492
+ 'Combustor Pressure Loss Coeff': g(p, 'combustor', 'alphac'),
493
+ 'Combustor Turbine Inlet Temp': g(p, 'combustor', 'turbine_inlet_temperature'),
494
+ 'Combustor Pressure Ratio': g(p, 'combustor', 'pressure_ratio'),
495
+ 'Core Nozzle Polytropic Efficiency': g(p, 'core_nozzle', 'polytropic_efficiency'),
496
+ 'Core Nozzle Pressure Ratio': g(p, 'core_nozzle', 'pressure_ratio'),
497
+ 'Fan Nozzle Polytropic Efficiency': g(p, 'fan_nozzle', 'polytropic_efficiency'),
498
+ 'Fan Nozzle Pressure Ratio': g(p, 'fan_nozzle', 'pressure_ratio'),
499
+ }
500
+
501
+
502
+ def _distributor_dict_to_ui(fl):
503
+ """Convert a RCAIDE Fuel_Line/Bus/Coolant_Line JSON dict to distributor GUI format."""
504
+ assigned_raw = fl.get('assigned_propulsors', [])
505
+ if is_unit_argument_pair(assigned_raw):
506
+ assigned_raw = assigned_raw[0]
507
+ if assigned_raw and isinstance(assigned_raw[0], list):
508
+ assigned_propulsors = list(assigned_raw[0])
509
+ else:
510
+ assigned_propulsors = [x for x in assigned_raw if isinstance(x, str)]
511
+
512
+ tanks = fl.get('fuel_tanks', {})
513
+ assigned_sources = (
514
+ [k for k in tanks.keys() if k != '__type__']
515
+ if isinstance(tanks, dict) else []
516
+ )
517
+ return {
518
+ 'distributor name': fl.get('tag', ''),
519
+ 'assigned_propulsors': assigned_propulsors,
520
+ 'assigned_sources': assigned_sources,
521
+ }
522
+
523
+
524
+ def _fuel_tank_dict_to_ui(tank):
525
+ """Convert a RCAIDE Fuel_Tank JSON dict to FuelTankWidget GUI format."""
526
+ def g(d, key):
527
+ return d.get(key, [0, 0]) if isinstance(d, dict) else [0, 0]
528
+ return {
529
+ 'Source Name': tank.get('tag', ''),
530
+ 'Fuel Tank Origin': g(tank, 'origin'),
531
+ 'Fuel Origin': g(tank, 'fuel_origin'),
532
+ 'Center of Gravity': g(tank, 'center_of_gravity'),
533
+ 'Mass': g(tank, 'mass_of_fuel'),
534
+ 'Internal Volume': g(tank, 'volume'),
535
+ }
536
+
537
+
538
+ def _network_dict_to_ui(net_dict):
539
+ """Convert one RCAIDE network JSON dict to the PowertrainFrame GUI data format."""
540
+ net_type = _network_type_for_ui(net_dict)
541
+
542
+ propulsor_data = []
543
+ propulsors = net_dict.get('propulsors', {})
544
+ if isinstance(propulsors, dict):
545
+ for k, v in propulsors.items():
546
+ if k == '__type__' or not isinstance(v, dict):
547
+ continue
548
+ propulsor_data.append(_propulsor_dict_to_ui(v))
549
+
550
+ distributor_data = []
551
+ source_by_tag = {}
552
+ for container_key in ('fuel_lines', 'busses', 'coolant_lines'):
553
+ container = net_dict.get(container_key, {})
554
+ if not isinstance(container, dict):
555
+ continue
556
+ for k, fl in container.items():
557
+ if k == '__type__' or not isinstance(fl, dict):
558
+ continue
559
+ distributor_data.append(_distributor_dict_to_ui(fl))
560
+ tanks = fl.get('fuel_tanks', {})
561
+ if isinstance(tanks, dict):
562
+ for t_key, t_val in tanks.items():
563
+ if t_key != '__type__' and isinstance(t_val, dict) and t_key not in source_by_tag:
564
+ source_by_tag[t_key] = t_val
565
+
566
+ source_data = [_fuel_tank_dict_to_ui(v) for v in source_by_tag.values()]
567
+
568
+ return {
569
+ 'energy network selected': net_type,
570
+ 'powertrain': {
571
+ 'distributor data': distributor_data,
572
+ 'source data': source_data,
573
+ 'propulsor data': propulsor_data,
574
+ 'system data': [],
575
+ 'converter data': [],
576
+ }
577
+ }
578
+
579
+
441
580
  def vehicle_dict_to_ui_list_structure(vehicle_dict):
442
581
  """Convert a stripped rcaide_vehicle dict to the 7-slot UI structure."""
443
582
  from tabs.geometry.frames.booms.boom_frame import BoomFrame
@@ -660,34 +799,10 @@ def vehicle_dict_to_ui_list_structure(vehicle_dict):
660
799
  if "powertrains" in vehicle_dict and vehicle_dict["powertrains"]:
661
800
  ui_structure[5] = [to_ui_format(p, PowertrainFrame) for p in vehicle_dict["powertrains"].values() if is_mapping(p)]
662
801
  elif "networks" in vehicle_dict and vehicle_dict["networks"]:
663
- for network in vehicle_dict["networks"].values():
664
- if not is_mapping(network):
802
+ for k, network in vehicle_dict["networks"].items():
803
+ if k == "__type__" or not is_mapping(network):
665
804
  continue
666
- network_tag = network.get("tag", "Fuel").title()
667
- propulsors = network.get("propulsors", {})
668
- if propulsors:
669
- for propulsor in propulsors.values():
670
- if not is_mapping(propulsor):
671
- continue
672
- ui_structure[5].append({
673
- "name": propulsor.get("tag", network_tag),
674
- "energy network selected": network_tag,
675
- "powertrain": {
676
- "distributor data": [], "source data": [],
677
- "propulsor data": [], "converter data": [],
678
- "connections": [],
679
- }
680
- })
681
- else:
682
- ui_structure[5].append({
683
- "name": network_tag,
684
- "energy network selected": network_tag,
685
- "powertrain": {
686
- "distributor data": [], "source data": [],
687
- "propulsor data": [], "converter data": [],
688
- "connections": [],
689
- }
690
- })
805
+ ui_structure[5].append(_network_dict_to_ui(network))
691
806
 
692
807
  if "wings" in vehicle_dict and vehicle_dict["wings"]:
693
808
  ui_structure[6] = [to_ui_format(w, WingsFrame) for w in vehicle_dict["wings"].values() if is_mapping(w)]
@@ -702,6 +817,17 @@ def vehicle_dict_to_ui_list_structure(vehicle_dict):
702
817
  _DIFF_SKIP = frozenset({'_component_root_map', '_energy_network_root_map', '_base', '_diff'})
703
818
 
704
819
 
820
+ def _coerce_leaf(new_val, obj, key):
821
+ """Coerce a JSON list back to numpy array when the target attribute is already an ndarray."""
822
+ if isinstance(new_val, list):
823
+ try:
824
+ if isinstance(obj[key], np.ndarray):
825
+ return np.array(new_val)
826
+ except Exception:
827
+ pass
828
+ return new_val
829
+
830
+
705
831
  def _apply_diff_to_obj(obj, diff_dict):
706
832
  """Walk a stripped diff dict and apply every leaf value to obj via key navigation."""
707
833
  for key, value in diff_dict.items():
@@ -715,7 +841,7 @@ def _apply_diff_to_obj(obj, diff_dict):
715
841
  pass
716
842
  else:
717
843
  try:
718
- obj[key] = value
844
+ obj[key] = _coerce_leaf(value, obj, key)
719
845
  except (KeyError, TypeError, AttributeError):
720
846
  pass
721
847
 
@@ -768,7 +894,7 @@ def write_to_json():
768
894
 
769
895
 
770
896
  def read_from_json(data_str, source_dir=None):
771
- global rcaide_vehicle, vehicle, rcaide_configs, config_data, analysis_data, mission_data, propulsor_names, rcaide_analyses
897
+ global rcaide_vehicle, vehicle, rcaide_configs, config_data, analysis_data, mission_data, propulsor_names, rcaide_analyses, rcaide_results
772
898
  from RCAIDE.Library.Components.Configs.Config import Config
773
899
  from RCAIDE.Input_Output.import_data import analyses_setup as _analyses_setup
774
900
 
@@ -806,6 +932,9 @@ def read_from_json(data_str, source_dir=None):
806
932
  config_data = []
807
933
  analysis_data = data.get("analysis_data", [])
808
934
  mission_data = data.get("mission_data", [])
935
+ # Loaded aircraft files do not include runtime mission results; clear any
936
+ # previous run so the Results Viewer cannot show stale data for a new file.
937
+ rcaide_results = None
809
938
 
810
939
  rcaide_analyses = _analyses_setup(analysis_data, rcaide_configs)
811
940