Source code for fastga_he.gui.analysis_and_plots

# This file is part of FAST-OAD_CS23-HE : A framework for rapid Overall Aircraft Design of Hybrid
# Electric Aircraft.
# Copyright (C) 2022 ISAE-SUPAERO

from random import SystemRandom

import numpy as np

import plotly
import plotly.graph_objects as go

from fastoad.io import VariableIO

COLS = plotly.colors.DEFAULT_PLOTLY_COLORS


[docs] def aircraft_geometry_plot( aircraft_file_path: str, name="", fig=None, plot_nacelle: bool = True, file_formatter=None ) -> go.FigureWidget: """ Returns a figure plot of the top view of the wing. Different designs can be superposed by providing an existing fig. Each design can be provided a name. :param aircraft_file_path: path of data file :param name: name to give to the trace added to the figure :param fig: existing figure to which add the plot :param plot_nacelle: boolean to turn on or off the plotting of the nacelles :param file_formatter: the formatter that defines the format of data file. If not provided, default format will be assumed. :return: wing plot figure. """ variables = VariableIO(aircraft_file_path, file_formatter).read() # Wing parameters wing_kink_leading_edge_x = variables["data:geometry:wing:kink:leading_edge:x:local"].value[0] wing_tip_leading_edge_x = variables["data:geometry:wing:tip:leading_edge:x:local"].value[0] wing_root_y = variables["data:geometry:wing:root:y"].value[0] wing_kink_y = variables["data:geometry:wing:kink:y"].value[0] wing_tip_y = variables["data:geometry:wing:tip:y"].value[0] wing_root_chord = variables["data:geometry:wing:root:chord"].value[0] wing_kink_chord = variables["data:geometry:wing:kink:chord"].value[0] wing_tip_chord = variables["data:geometry:wing:tip:chord"].value[0] y_wing = np.array( [0, wing_root_y, wing_kink_y, wing_tip_y, wing_tip_y, wing_kink_y, wing_root_y, 0, 0] ) x_wing = np.array( [ 0, 0, wing_kink_leading_edge_x, wing_tip_leading_edge_x, wing_tip_leading_edge_x + wing_tip_chord, wing_kink_leading_edge_x + wing_kink_chord, wing_root_chord, wing_root_chord, 0, ] ) # Horizontal Tail parameters ht_root_chord = variables["data:geometry:horizontal_tail:root:chord"].value[0] ht_tip_chord = variables["data:geometry:horizontal_tail:tip:chord"].value[0] ht_span = variables["data:geometry:horizontal_tail:span"].value[0] ht_sweep_0 = variables["data:geometry:horizontal_tail:sweep_0"].value[0] ht_tip_leading_edge_x = ht_span / 2.0 * np.tan(ht_sweep_0 * np.pi / 180.0) y_ht = np.array([0, ht_span / 2.0, ht_span / 2.0, 0.0, 0.0]) x_ht = np.array( [ -0.25 * ht_root_chord, ht_tip_leading_edge_x - 0.25 * ht_tip_chord, ht_tip_leading_edge_x + 0.75 * ht_tip_chord, 0.75 * ht_root_chord, -0.25 * ht_root_chord, ] ) # Fuselage parameters fuselage_max_width = variables["data:geometry:fuselage:maximum_width"].value[0] fuselage_length = variables["data:geometry:fuselage:length"].value[0] fuselage_front_length = variables["data:geometry:fuselage:front_length"].value[0] fuselage_rear_length = variables["data:geometry:fuselage:rear_length"].value[0] x_fuselage = np.array( [ 0.0, 0.0, fuselage_front_length, fuselage_length - fuselage_rear_length, fuselage_length, fuselage_length, ] ) y_fuselage = np.array( [ 0.0, fuselage_max_width / 4.0, fuselage_max_width / 2.0, fuselage_max_width / 2.0, fuselage_max_width / 4.0, 0.0, ] ) # CGs wing_25mac_x = variables["data:geometry:wing:MAC:at25percent:x"].value[0] wing_mac_length = variables["data:geometry:wing:MAC:length"].value[0] local_wing_mac_le_x = variables["data:geometry:wing:MAC:leading_edge:x:local"].value[0] local_ht_25mac_x = variables["data:geometry:horizontal_tail:MAC:at25percent:x:local"].value[0] ht_distance_from_wing = variables[ "data:geometry:horizontal_tail:MAC:at25percent:x:from_wingMAC25" ].value[0] x_wing = x_wing + wing_25mac_x - 0.25 * wing_mac_length - local_wing_mac_le_x x_ht = x_ht + wing_25mac_x + ht_distance_from_wing - local_ht_25mac_x # pylint: disable=invalid-name # that's a common naming x = np.concatenate((x_fuselage, x_wing, x_ht)) # pylint: disable=invalid-name # that's a common naming y = np.concatenate((y_fuselage, y_wing, y_ht)) # pylint: disable=invalid-name # that's a common naming y = np.concatenate((-y, y)) # pylint: disable=invalid-name # that's a common naming x = np.concatenate((x, x)) if fig is None: fig = go.Figure() scatter = go.Scatter(x=y, y=x, mode="lines+markers", name=name, showlegend=True) fig.add_trace(scatter) # Nacelle + propeller prop_layout = variables["data:geometry:propulsion:engine:layout"].value[0] nac_width = variables["data:geometry:propulsion:nacelle:width"].value[0] nac_length = variables["data:geometry:propulsion:nacelle:length"].value[0] prop_diam = variables["data:geometry:propeller:diameter"].value[0] pos_y_nacelle = np.array(variables["data:geometry:propulsion:nacelle:y"].value) pos_x_nacelle = np.array(variables["data:geometry:propulsion:nacelle:x"].value) if prop_layout == 1.0: x_nacelle_plot = np.array([0.0, nac_length, nac_length, 0.0, 0.0, 0.0]) y_nacelle_plot = np.array( [ -nac_width / 2, -nac_width / 2, nac_width / 2, nac_width / 2, prop_diam / 2, -prop_diam / 2, ] ) elif prop_layout == 3.0: prop_depth = variables["data:geometry:propeller:depth"].value[0] x_nacelle_plot = np.array([0.0, nac_length, nac_length, 0.0, 0.0, 0.0]) + prop_depth y_nacelle_plot = np.array( [ max(-nac_width / 2, -fuselage_max_width / 4.0), -nac_width / 2, nac_width / 2, min(nac_width / 2, fuselage_max_width / 4.0), prop_diam / 2, -prop_diam / 2, ] ) else: x_nacelle_plot = np.array([]) y_nacelle_plot = np.array([]) if plot_nacelle: if prop_layout == 1.0: random_generator = SystemRandom() trace_colour = COLS[random_generator.randrange(0, len(COLS))] show_legend = True for y_nacelle_local, x_nacelle_local in zip(pos_y_nacelle, pos_x_nacelle): y_nacelle_left = y_nacelle_plot + y_nacelle_local y_nacelle_right = -y_nacelle_plot - y_nacelle_local x_nacelle = x_nacelle_local - x_nacelle_plot if show_legend: scatter_right = go.Scatter( x=y_nacelle_right, y=x_nacelle, name="right nacelle", legendgroup=name + "nacelle", mode="lines+markers", line=dict(color=trace_colour), legendgrouptitle_text=name + " nacelle + propeller", ) fig.add_trace(scatter_right) scatter_left = go.Scatter( x=y_nacelle_left, y=x_nacelle, name="left nacelle", legendgroup=name + "nacelle", mode="lines+markers", line=dict(color=trace_colour), ) fig.add_trace(scatter_left) show_legend = False else: scatter = go.Scatter( x=y_nacelle_plot, y=x_nacelle_plot, mode="lines+markers", name=name + " nacelle + propeller", ) fig.add_trace(scatter) fig.layout = go.Layout(yaxis=dict(scaleanchor="x", scaleratio=1)) fig = go.FigureWidget(fig) fig.update_layout( title_text="Aircraft Geometry", title_x=0.5, xaxis_title="y", yaxis_title="x", legend=dict(yanchor="top", y=0.99, xanchor="right", x=0.99), ) return fig