Source code for data

import numpy as np
import pandas as pd
from scipy import interpolate
from pyNA.src.settings import Settings
from dataclasses import dataclass
import pdb


[docs]@dataclass() class Data: """ Data class containing the following parameters: * ``f``: 1/3-rd octave frequency bands [Hz] * ``f_sb``: sub-bands of the 1/3rd octave frequency bands [Hz] * ``abs``: table with atmospheric absorption coefficients * ``abs_freq``: frequencies of atmospheric absorption coefficient table * ``abs_alt``: altitudes of atmospheric absorption coefficient table * ``abs_f``: interpolation function for atmospheric absorption coefficient * ``jet_D``: table with jet mixing noise directivity dependency * ``jet_D_angles``: table with jet mixing noise directivity dependency: directivity angles * ``jet_D_velocity``: table with jet mixing noise directivity dependency: jet velocity ratio * ``jet_D_f``: interpolation function for jet mixing noise directivity dependency * ``jet_xi``: table with jet mixing noise Strouhal number correction factor * ``jet_xi_angles``: table with jet mixing noise Strouhal number correction factor: directivity angles * ``jet_xi_velocity``: table with jet mixing noise Strouhal number correction factor: jet velocity ratio * ``jet_xi_f``: interpolation function for jet mixing noise Strouhal number correction factor * ``jet_F``: table with jet mixing noise spectral dependency * ``jet_F_angles``: table with jet mixing noise spectral dependency: directivity angles * ``jet_F_temperature``: table with jet mixing noise spectral dependency: jet temperature ratio * ``jet_F_velocity``: table with jet mixing noise spectral dependency: jet velocity ratio * ``jet_F_strouhal``: table with jet mixing noise spectral dependency: Strouhal number * ``jet_F_f``: interpolation function for jet mixing noise spectral dependency * ``Faddeeva_itau_re``: table with real part of the input to the Faddeeva function (for julia ground reflections) * ``Faddeeva_itau_im``: table with imaginary part of the input to the Faddeeva function (for julia ground reflections) * ``Faddeeva_real``: table with real part of the Faddeeva function (for julia ground reflections) * ``Faddeeva_imag``: table with imaginary part of the Faddeeva function (for julia ground reflections) * ``noy_spl``: sound pressure levels of noy table * ``noy_freq``: 1/3-rd octave frequency bands of noy table * ``noy``: noy table * ``noy_f``: inteprolation function for the noy table * ``supp_fi``: table with suppression factors for fan inlet noise * ``supp_fi_angles``: directivity angles of suppression factors for fan inlet noise table * ``supp_fi_freq``: frequencies of suppression factors for fan inlet noise table * ``supp_fi_f``: interpolation function for fan inlet noise suppression coefficient * ``supp_fd``: table with suppression factors for fan discharge noise * ``supp_fd_angles``: directivity angles of suppression factors for fan discharge noise table * ``supp_fd_freq``: frequencies of suppression factors for fan discharge noise table * ``supp_fd_f``: interpolation function for fan discharge noise suppression coefficient * ``supp_af``: table with HSR suppression factors for airframe noise * ``supp_af_angles``: directivity angles of suppression factors for airframe noise table * ``supp_af_freq``: frequencies of suppression factors for airframe noise table * ``supp_af_f``: interpolation function for HSR airframe noise suppression coefficient * ``shield_l``: lateral microphone airframe shielding delta dB [dB] * ``shield_f``: flyover microphone airframe shielding delta dB [dB] * ``shield_a``: approach microphone airframe shielding delta dB [dB] """ # Frequency spectrum f : np.ndarray f_sb : np.ndarray abs : np.ndarray abs_freq : np.ndarray abs_alt : np.ndarray abs_f : interpolate.interpolate.interp2d jet_D: np.ndarray jet_D_angles: np.ndarray jet_D_velocity: np.ndarray jet_D_f: interpolate.interpolate.interp2d jet_xi: np.ndarray jet_xi_angles: np.ndarray jet_xi_velocity: np.ndarray jet_xi_f: interpolate.interpolate.interp2d jet_F: np.ndarray jet_F_angles: np.ndarray jet_F_temperature: np.ndarray jet_F_velocity: np.ndarray jet_F_strouhal: np.ndarray jet_F_f: interpolate.interpolate.RegularGridInterpolator Faddeeva_itau_re : np.ndarray Faddeeva_itau_im : np.ndarray Faddeeva_real : np.ndarray Faddeeva_imag : np.ndarray noy_spl : np.ndarray noy_freq : np.ndarray noy : np.ndarray noy_f : interpolate.interpolate.interp2d supp_fi : np.ndarray supp_fi_angles : np.ndarray supp_fi_freq : np.ndarray supp_fi_f: interpolate.interpolate.interp2d supp_fd : np.ndarray supp_fd_angles : np.ndarray supp_fd_freq : np.ndarray supp_fd_f: interpolate.interpolate.interp2d supp_af : np.ndarray supp_af_angles : np.ndarray supp_af_freq : np.ndarray supp_af_f: interpolate.interpolate.interp2d shield_l : np.ndarray shield_f : np.ndarray shield_a : np.ndarray
[docs] def __init__(self, settings: Settings) -> None: """ Initialize Data class. :param settings: pyna settings :type settings: Settings :return: None """ # Load data tables Data.compute_frequency_bands(self, settings=settings) Data.load_propagation_tables(self, settings=settings) Data.load_suppression_tables(self, settings=settings) Data.load_jet_data(self, settings=settings) Data.load_noy_data(self, settings=settings) Data.load_shielding_time_series(self, settings=settings) # Initialize verification data self.verification_source = dict() self.verification_source_supp = dict() self.verification_trajectory = dict()
[docs] def compute_frequency_bands(self, settings: Settings) -> None: """ Compute the 1/3rd order frequency bands and with sub-bands. * f: 1/3rd order frequency bands * f_sb: frequency sub-bands :param settings: pyna settings. :type settings: Settings :return: None """ # Load 1/3rd order frequency bands # Generate 1/3rd octave frequency bands [Hz] l_i = 16 # Starting no. of the frequency band [-] self.f = 10 ** (0.1 * np.linspace(1+l_i, 40, settings.N_f)) # Calculate subband frequencies [Hz] # Source: Zorumski report 1982 part 1. Chapter 5.1 Equation 6-7 # Source: Berton 2021 Simultaneous use of Ground Reflection and Lateral Attenuation Noise Models Appendix A Eq. 1 self.f_sb = np.zeros(settings.N_b * settings.N_f) m = (settings.N_b - 1) / 2. w = 2. ** (1 / (3. * settings.N_b)) for k in np.arange(settings.N_f): for h in np.arange(settings.N_b): self.f_sb[k * settings.N_b + h] = w ** (h - m) * self.f[k] return None
[docs] def load_propagation_tables(self, settings: Settings) -> None: """ Load atmospheric absorption coefficient table. :param settings: pyna settings. :type settings: Settings :return: None """ # Load atmospheric absorption coefficient table # Source: validation noise assessment data set of NASA STCA (Berton et al., 2019) self.abs = pd.read_csv(settings.pyNA_directory+'/data/isa/atmospheric_absorption.csv', skiprows=1).values[:, 1:] self.abs_freq = np.array(pd.read_csv(settings.pyNA_directory+'/data/isa/atmospheric_absorption.csv', nrows=1).values[0][1:], dtype=float) self.abs_alt = pd.read_csv(settings.pyNA_directory+'/data/isa/atmospheric_absorption.csv', skiprows=1).values[:, 0] self.abs_f = interpolate.interp2d(self.abs_freq, self.abs_alt, self.abs, kind='linear') # Load Faddeeva tables faddeeva_data_real = pd.read_csv(settings.pyNA_directory+'/data/propagation/Faddeeva_real_small.csv').values faddeeva_data_imag = pd.read_csv(settings.pyNA_directory+'/data/propagation/Faddeeva_imag_small.csv').values self.Faddeeva_itau_re = faddeeva_data_real[0, 1:] self.Faddeeva_itau_im = faddeeva_data_real[1:, 0] self.Faddeeva_real = faddeeva_data_real[1:,1:] self.Faddeeva_imag = faddeeva_data_imag[1:,1:] return None
[docs] def load_suppression_tables(self, settings: Settings) -> None: """ Load the noise suppression tables for: * fan inlet source noise suppression * fan discharge source noise suppression * airframe noise suppression (high-speed research program) :param settings: pyna settings. :type settings: Settings :return: None """ # Load noise source suppression data # Source: validation noise assessment data set of NASA STCA (Berton et al., 2019) self.supp_fi = pd.read_csv(settings.pyNA_directory+'/data/sources/fan/liner_inlet_suppression.csv', skiprows=1).values[:, 1:] self.supp_fi_angles = np.array(pd.read_csv(settings.pyNA_directory+'/data/sources/fan/liner_inlet_suppression.csv', skiprows=0).values[0,1:], dtype=float) self.supp_fi_freq = pd.read_csv(settings.pyNA_directory+'/data/sources/fan/liner_inlet_suppression.csv',skiprows=1).values[:, 0] self.supp_fi_f = interpolate.interp2d(self.supp_fi_angles, self.supp_fi_freq, self.supp_fi, kind='linear') self.supp_fd = pd.read_csv(settings.pyNA_directory+'/data/sources/fan/liner_discharge_suppression.csv', skiprows=1).values[:, 1:] self.supp_fd_angles = np.array(pd.read_csv(settings.pyNA_directory+'/data/sources/fan/liner_discharge_suppression.csv', skiprows=0).values[0,1:], dtype=float) self.supp_fd_freq = pd.read_csv(settings.pyNA_directory+'/data/sources/fan/liner_discharge_suppression.csv',skiprows=1).values[:, 0] self.supp_fd_f = interpolate.interp2d(self.supp_fd_angles, self.supp_fd_freq, self.supp_fd, kind='linear') self.supp_af = pd.read_csv(settings.pyNA_directory+'/data/sources/airframe/hsr_suppression.csv', skiprows=1).values[:,1:] self.supp_af_angles = np.array(pd.read_csv(settings.pyNA_directory+'/data/sources/airframe/hsr_suppression.csv', skiprows=0).values[0,1:], dtype=float) self.supp_af_freq = pd.read_csv(settings.pyNA_directory+'/data/sources/airframe/hsr_suppression.csv', skiprows=1).values[:, 0] self.supp_af_f = interpolate.interp2d(self.supp_af_angles, self.supp_af_freq, self.supp_af, kind='linear') return None
[docs] def load_jet_data(self, settings: Settings) -> None: """ Load the jet source noise model data. :param settings: pyna settings :type settings: Settings :return: None """ # Polar directivity level D # Source: Zorumski report 1982 part 2. Chapter 8.4 Table IV self.jet_D = pd.read_csv(settings.pyNA_directory + '/data/sources/jet/directivity_function.csv').values self.jet_D_angles = self.jet_D[0, 1:] self.jet_D_velocity = self.jet_D[1:, 0] self.jet_D = self.jet_D[1:, 1:] self.jet_D_f = interpolate.interp2d(self.jet_D_angles, self.jet_D_velocity, self.jet_D, kind='linear') # Strouhal number correction factor xi # Source: Zorumski report 1982 part 2. Chapter 8.4 Table V self.jet_xi = pd.read_csv(settings.pyNA_directory + '/data/sources/jet/strouhal_correction.csv').values self.jet_xi_angles = self.jet_xi[0, 1:] self.jet_xi_velocity = self.jet_xi[1:, 0] self.jet_xi = self.jet_xi[1:,1:] self.jet_xi_f = interpolate.interp2d(self.jet_xi_angles, self.jet_xi_velocity, self.jet_xi, kind='linear') # Spectral level F # Source: Zorumski report 1982 part 1. Chapter 8.4 Table VI self.jet_F = np.load(settings.pyNA_directory + '/data/sources/jet/spectral_function_extended_T.npy') self.jet_F_angles = np.array([0, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180]) self.jet_F_temperature = np.array([0, 1, 2, 2.5, 3, 3.5, 4, 5, 6, 7]) self.jet_F_velocity = np.array([-0.4, 0.1, 0.125, 0.15, 0.175, 0.2, 0.225, 0.4]) self.jet_F_strouhal = np.array([-2, -1.6, -1.3, -1.15, -1, -0.824, -0.699, -0.602, -0.5, -0.398, -0.301, -0.222, 0, 0.477, 1, 1.6, 1.7, 2.5]) self.jet_F_f = interpolate.RegularGridInterpolator((self.jet_F_angles, self.jet_F_temperature, self.jet_F_velocity, self.jet_F_strouhal), self.jet_F) return None
[docs] def load_noy_data(self, settings: Settings) -> None: """ Load noy tables for tone-corrected perceived noise level (pnlt) computation. :param settings: pyna settings. :type settings: Settings :return: None """ # Load noise level computation tabular data # Source: ICAO Annex 16 Volume 1 (Edition 8) Table A2-3. # self.Noy = pd.read_csv(settings.pyNA_directory+'/data/levels/pnlt_noy_weighting.csv') noy = pd.read_csv(settings.pyNA_directory+'/data/levels/spl_noy.csv').values self.noy_spl = noy[1:, 0] self.noy_freq = noy[0, 1:] self.noy = noy[1:,1:] self.noy_f = interpolate.interp2d(self.noy_freq, self.noy_spl, self.noy, kind='linear') return None
[docs] def load_trajectory_verification_data(self, settings: Settings) -> None: """ Loads the verification data of the NASA STCA noise assessment (Berton et al., 2019). :param settings: pyNA settings :type settings: Settings :return: data_val :rtype: pd.DataFrame """ # Source: validation noise assessment data set of NASA STCA (Berton et al., 2019) if settings.case_name == 'nasa_stca_standard': # Check if all sources if settings.all_sources: for i, observer in enumerate(settings.observer_lst): if observer in ['lateral', 'flyover']: self.verification_trajectory[observer] = pd.read_excel(settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/55t-Depart-Standard-Total.xlsx', sheet_name=observer, engine="openpyxl") elif observer == 'approach': self.verification_trajectory[observer] = pd.read_excel(settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Approach Levels.xlsx', sheet_name='total', engine="openpyxl") # Check if individual components elif settings.jet_mixing: for i, observer in enumerate(settings.observer_lst): if observer in ['lateral', 'flyover']: self.verification_trajectory[observer] = pd.read_excel(settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/55t-Depart-Standard-Jet CaseA-D.xlsx', sheet_name=observer, engine="openpyxl") elif observer == 'approach': self.verification_trajectory[observer] = pd.read_excel(settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Approach Levels.xlsx', sheet_name='jet', engine="openpyxl") elif settings.core: for i, observer in enumerate(settings.observer_lst): if observer in ['lateral', 'flyover']: self.verification_trajectory[observer] = pd.read_excel(settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/55t-Depart-Standard-Core CaseA-D.xlsx', sheet_name=observer, engine="openpyxl") elif observer == 'approach': self.verification_trajectory[observer] = pd.read_excel(settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Approach Levels.xlsx', sheet_name='core', engine="openpyxl") elif settings.airframe: for i, observer in enumerate(settings.observer_lst): if observer in ['lateral', 'flyover']: self.verification_trajectory[observer] = pd.read_excel(settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/55t-Depart-Standard-Airframe CaseA-D.xlsx', sheet_name=observer, engine="openpyxl") elif observer == 'approach': self.verification_trajectory[observer] = pd.read_excel(settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Approach Levels.xlsx', sheet_name='airframe', engine="openpyxl") elif settings.fan_inlet: for i, observer in enumerate(settings.observer_lst): if observer in ['lateral', 'flyover']: self.verification_trajectory[observer] = pd.read_excel(settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/55t-Depart-Standard-Fan Inlet CaseA-D.xlsx', sheet_name=observer, engine="openpyxl") elif observer == 'approach': self.verification_trajectory[observer] = pd.read_excel(settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Approach Levels.xlsx', sheet_name='fan inlet', engine="openpyxl") elif settings.fan_discharge: for i, observer in enumerate(settings.observer_lst): if observer in ['lateral', 'flyover']: self.verification_trajectory[observer] = pd.read_excel(settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/55t-Depart-Standard-Fan Discharge CaseA-D.xlsx', sheet_name=observer, engine="openpyxl") elif observer == 'approach': self.verification_trajectory[observer] = pd.read_excel(settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Approach Levels.xlsx', sheet_name='fan discharge', engine="openpyxl") else: raise ValueError('Invalid noise component for trajectory validation. Specify core/jet mixing/fan inlet/fan discharge/airframe') else: raise ValueError('No validation data available for this case name. Specify nasa_stca_standard.') return None
[docs] def load_source_verification_data(self, settings: Settings, components: list): """ Load verification data for noise source spectral and directional distributions. :param settings: pyNA settings :type settings: Settings :param components: list of components to run :type components: list :return: (data_val, data_val_s) :rtype: (dict, dict) """ for comp in components: if comp == 'core': self.verification_source[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Core Module Source.xlsx', sheet_name='Full').values self.verification_source_supp[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Core Module Source.xlsx', sheet_name='Suppressed').values elif comp == 'jet_mixing': self.verification_source[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Jet Module Source.xlsx', sheet_name='Full').values self.verification_source_supp[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Jet Module Source.xlsx', sheet_name='Suppressed').values elif comp == 'inlet_BB': self.verification_source[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Fan Module Source.xlsx', sheet_name='Full Inlet BB').values self.verification_source_supp[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Fan Module Source.xlsx', sheet_name='Suppressed Inlet BB').values elif comp == 'discharge_BB': self.verification_source[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Fan Module Source.xlsx', sheet_name='Full Discharge BB').values self.verification_source_supp[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Fan Module Source.xlsx', sheet_name='Suppressed Discharge BB').values elif comp == 'inlet_RS': self.verification_source[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Fan Module Source.xlsx', sheet_name='Full Inlet RS').values self.verification_source_supp[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Fan Module Source.xlsx', sheet_name='Suppressed Inlet RS').values elif comp == 'discharge_RS': self.verification_source[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Fan Module Source.xlsx', sheet_name='Full Discharge RS').values self.verification_source_supp[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Fan Module Source.xlsx', sheet_name='Suppressed Discharge RS').values elif comp == 'fan_inlet': self.verification_source[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Fan Module Source.xlsx', sheet_name='Fan Inlet Full').values self.verification_source_supp[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Fan Module Source.xlsx', sheet_name='Fan Inlet Suppressed').values elif comp == 'fan_discharge': self.verification_source[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Fan Module Source.xlsx', sheet_name='Fan Discharge Full').values self.verification_source_supp[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Fan Module Source.xlsx', sheet_name='Fan Discharge Suppressed').values elif comp == 'airframe': self.verification_source[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Airframe Module Source.xlsx', sheet_name='Full').values self.verification_source_supp[comp] = pd.read_excel( settings.pyNA_directory + '/cases/' + settings.case_name + '/validation/Airframe Module Source.xlsx', sheet_name='Suppressed').values return None
[docs] def load_shielding_time_series(self, settings: Settings): self.shield_l = [] self.shield_f = [] self.shield_a = [] if settings.case_name == 'nasa_stca_standard': for i, observer in enumerate(settings.observer_lst): if observer == 'lateral': self.shield_l = pd.read_csv(settings.pyNA_directory+'/cases/'+settings.case_name + '/shielding/shielding_l.csv').values[:,1:] elif observer == 'flyover': self.shield_f = pd.read_csv(settings.pyNA_directory+'/cases/'+settings.case_name + '/shielding/shielding_f.csv').values[:,1:] elif observer == 'approach': self.shield_a = pd.read_csv(settings.pyNA_directory+'/cases/'+settings.case_name + '/shielding/shielding_a.csv').values[:,1:]