Source code for RCAIDE.Library.Plots.Noise.post_process_noise_data

# RCAIDE/Framework/Analyses/Noise/Frequency_Domain_Buildup.py
# 
# Mod:  Oct 2024, A. Molloy
# Created:  Jul 2023, M. Clarke

# ----------------------------------------------------------------------------------------------------------------------
#  IMPORT
# ----------------------------------------------------------------------------------------------------------------------  
# noise imports
from RCAIDE.Framework.Core import  Data
from RCAIDE.Library.Methods.Noise.Common.background_noise     import background_noise
from RCAIDE.Library.Methods.Noise.Metrics import * 
from RCAIDE.Library.Methods.Noise.Metrics.PNL_noise_metric                            import PNL_noise_metric 
from RCAIDE.Library.Methods.Noise.Metrics.EPNL_noise_metric                           import EPNL_noise_metric 
from RCAIDE.Library.Methods.Noise.Metrics.Equivalent_SENEL_SEL_noise_metrics          import Equivalent_SENEL_SEL_noise_metrics
from RCAIDE.Library.Methods.Noise.Common.generate_zero_elevation_microphone_locations import generate_zero_elevation_microphone_locations 
from RCAIDE.Library.Methods.Noise.Common.generate_terrain_microphone_locations        import generate_terrain_microphone_locations     
from RCAIDE.Library.Methods.Noise.Common.compute_relative_noise_evaluation_locations  import compute_relative_noise_evaluation_locations
from RCAIDE.Library.Methods.Geodesics.compute_point_to_point_geospacial_data          import compute_point_to_point_geospacial_data

# package imports
import numpy as np
from scipy.interpolate                                           import RegularGridInterpolator


# ----------------------------------------------------------------------------------------------------------------------
#  PLOTS
# ---------------------------------------------------------------------------------------------------------------------- 
[docs] def post_process_noise_data(results, flight_times = np.array(['06:00:00','06:30:00','07:00:00','07:30:00', '08:00:00','08:30:00','09:00:00','09:30:00', '10:00:00','10:30:00','11:00:00','11:30:00', '12:00:00','12:30:00','13:00:00','13:30:00', '14:00:00','14:30:00','15:00:00']), time_period = ['06:00:00','20:00:00'], compute_SENEL = False, compute_SEL = False, compute_eqivalent_noise= False, compute_PNL = False, compute_EPNL = False, ): """ Processes raw noise simulation results into formatted data for visualization. Parameters ---------- results : Results RCAIDE results data structure containing: - segments[i].analyses.noise.settings Noise analysis settings including: - number_of_microphone_in_stencil - microphone_x_resolution - microphone_y_resolution - topography_file - noise_times_steps - segments[i].state.conditions Flight conditions including: - frames.inertial.time - noise.hemisphere_SPL_dBA flight_times : ndarray of str, optional Array of time strings for noise evaluation (default: hourly from 06:00 to 15:00) time_period : list of str, optional Start and end times for analysis period (default: ['06:00:00','20:00:00']) evalaute_noise_metrics : bool, optional Flag to compute additional noise metrics (default: True) Returns ------- noise_data : Data Processed noise data structure containing: - SPL_dBA : ndarray Sound pressure levels at each grid point - time : ndarray Time history array - aircraft_position : ndarray Aircraft trajectory points - microphone_locations : ndarray Measurement grid coordinates - topography_file : str, optional Path to terrain data if used - microphone_coordinates : ndarray, optional Geographic coordinates if terrain used Notes ----- Processing steps include: 1. Unpacking analysis settings 2. Generating microphone grid 3. Interpolating noise levels 4. Computing metrics 5. Formatting for visualization **Major Assumptions** * Regular measurement grid spacing * Continuous noise between segments * Background noise floor exists * Spherical spreading of sound **Definitions** 'SPL_dBA' A-weighted Sound Pressure Level 'Hemisphere' Directivity pattern around source 'Stencil' Local group of evaluation points See Also -------- RCAIDE.Library.Plots.Noise.plot_noise_level : Visualization of processed data RCAIDE.Library.Methods.Noise.Common.background_noise : Background noise floor function """ # Step 1: Unpack settings settings = results.segments[0].analyses.noise.settings n = settings.number_of_microphone_in_stencil N_gm_x = settings.microphone_x_resolution N_gm_y = settings.microphone_y_resolution noise_data = Data() # Step 2: Determing microhpone points where noise is to be computed microphone_coordinates = None if settings.topography_file != None: compute_point_to_point_geospacial_data(settings) microphone_locations ,microphone_coordinates = generate_terrain_microphone_locations(settings) noise_data.topography_file = settings.topography_file noise_data.microphone_coordinates = microphone_coordinates.reshape(N_gm_x,N_gm_y,3) noise_data.aircraft_origin_coordinates = settings.aircraft_origin_coordinates noise_data.aircraft_destination_coordinates = settings.aircraft_destination_coordinates else: microphone_locations = generate_zero_elevation_microphone_locations(settings) noise_data.microphone_y_resolution = N_gm_y noise_data.microphone_x_resolution = N_gm_x noise_data.microphone_locations = microphone_locations.reshape(N_gm_x,N_gm_y,3) # Step 3: Create empty arrays to store noise data N_segs = len(results.segments) num_gm_mic = len(microphone_locations) num_noise_time = settings.noise_times_steps num_f = len(settings.center_frequencies) # Step 4: Initalize Arrays N_ctrl_pts = ( N_segs-1) * (num_noise_time -1) + num_noise_time # ensures that noise is computed continuously across segments SPL_dBA = np.ones((N_ctrl_pts,N_gm_x,N_gm_y))*background_noise() SPL_dBA_1_3_spectrum = np.ones((N_ctrl_pts,N_gm_x,N_gm_y,num_f))*background_noise() Aircraft_pos = np.empty((0,3)) Time = np.empty((0)) mic_locs = np.zeros((N_ctrl_pts,n)) idx = 0 # Step 5: loop through segments and store noise for seg in range(N_segs): segment = results.segments[seg] settings = segment.analyses.noise.settings phi = settings.noise_hemisphere_phi_angles theta = settings.noise_hemisphere_theta_angles conditions = segment.state.conditions time = conditions.frames.inertial.time[:,0] # Step 5.1 : Compute relative microhpone locations noise_time,noise_pos,RML,PHI,THETA,num_gm_mic = compute_relative_noise_evaluation_locations(settings, microphone_locations,segment) # Step 5.2: Compute aircraft position and npose at interpolated hemisphere locations cpt = 0 if seg == (N_segs - 1): noise_time_ = noise_time else: noise_time_ = noise_time[:-1] Aircraft_pos = np.vstack((Aircraft_pos,noise_pos)) Time = np.hstack((Time,noise_time_)) for i in range(len(noise_time_)): # Step 5.2.1 :Noise interpolation delta_t = (noise_time[i] -time[cpt]) / (time[cpt+1] - time[cpt]) SPL_lower = conditions.noise.hemisphere_SPL_dBA[cpt].reshape(len(phi),len(theta)) SPL_uppper = conditions.noise.hemisphere_SPL_dBA[cpt+1].reshape(len(phi),len(theta)) SPL_gradient = SPL_uppper - SPL_lower SPL_interp = SPL_lower + SPL_gradient *delta_t SPL_lower_1_3_spectrum = conditions.noise.hemisphere_SPL_1_3_spectrum_dBA[cpt].reshape(len(phi),len(theta),num_f) SPL_uppper_1_3_spectrum = conditions.noise.hemisphere_SPL_1_3_spectrum_dBA[cpt+1].reshape(len(phi),len(theta),num_f) SPL_gradient_1_3_spectrum = SPL_uppper_1_3_spectrum - SPL_lower_1_3_spectrum SPL_interp_1_3_spectrum = SPL_lower_1_3_spectrum + SPL_gradient_1_3_spectrum *delta_t # Step 5.2.2 Create surrogate SPL_dBA_surrogate = RegularGridInterpolator((phi, theta),SPL_interp ,method = 'linear', bounds_error=False, fill_value=None) SPL_dBA_1_3_spectrum_surrogate = RegularGridInterpolator((phi, theta),SPL_interp_1_3_spectrum ,method = 'linear', bounds_error=False, fill_value=None) # Step 5.2.3 Query surrogate R = np.linalg.norm(RML[i], axis=1) locs = np.argsort(R)[:n] pts = (PHI[i][locs],THETA[i][locs]) SPL_dBA_unscaled = SPL_dBA_surrogate(pts) SPL_dBA_1_3_spectrum_unscaled = SPL_dBA_1_3_spectrum_surrogate(pts) # Step 5.2.4 Scale data using radius R_ref = settings.noise_hemisphere_radius SPL_dBA_scaled = SPL_dBA_unscaled - 20*np.log10(R[locs]/R_ref) SPL_dBA_1_3_spectrum_scaled = SPL_dBA_1_3_spectrum_unscaled - np.tile(20*np.log10(R[locs]/R_ref)[:, None], (1, num_f)) # insert noise incorrect mic locations SPL_dBA_temp = SPL_dBA[idx].flatten() SPL_dBA_temp[locs] = SPL_dBA_scaled SPL_dBA[idx] = SPL_dBA_temp.reshape(N_gm_x,N_gm_y) SPL_dBA_1_3_spectrum_temp = SPL_dBA_1_3_spectrum[idx].reshape(N_gm_x*N_gm_y,num_f) SPL_dBA_1_3_spectrum_temp[locs] = SPL_dBA_1_3_spectrum_scaled SPL_dBA_1_3_spectrum[idx] = SPL_dBA_1_3_spectrum_temp.reshape(N_gm_x,N_gm_y,num_f) mic_locs[idx] = locs idx += 1 if noise_time[i] >= time[cpt+1]: cpt += 1 # Step 6: Make any readings less that background noise equal to background noise SPL_dBA = np.nan_to_num(SPL_dBA) SPL_dBA[SPL_dBA<background_noise()] = background_noise() SPL_dBA_1_3_spectrum = np.nan_to_num(SPL_dBA_1_3_spectrum) SPL_dBA_1_3_spectrum[SPL_dBA_1_3_spectrum<background_noise()] = background_noise() # Step 7: Store data noise_data.SPL_dBA = SPL_dBA noise_data.SPL_dBA_1_3_spectrum = SPL_dBA_1_3_spectrum noise_data.time = Time noise_data.aircraft_position = Aircraft_pos noise_data.microhpone_locations = mic_locs # Step 8: Perform noise metric calculations if (compute_SENEL or compute_SEL) or compute_eqivalent_noise: Equivalent_SENEL_SEL_noise_metrics(noise_data, flight_times) if compute_PNL or compute_EPNL: noise_data.PLN = PNL_noise_metric(noise_data.SPL_dBA_1_3_spectrum) noise_data.EPNL = EPNL_noise_metric(noise_data.PLN) return noise_data