def get_along(self, *args, unit="SI", is_norm=False, axis_data=[]): """Returns the ndarray of the field, using conversions and symmetries if needed. Parameters ---------- self: Data a Data object *args: list of strings List of axes requested by the user, their units and values (optional) unit: str Unit requested by the user ("SI" by default) is_norm: bool Boolean indicating if the field must be normalized (False by default) axis_data: list list of ndarray corresponding to user-input data Returns ------- list of 1Darray of axes values, ndarray of field values """ # Read the axes input in args if len(args) == 1 and type(args[0]) == tuple: args = args[0] # if called from another script with *args axes_list = read_input_strings(args, axis_data) # Extract the requested axes (symmetries + unit) axes_list, transforms = self.comp_axes(axes_list) # Get the field values = self.get_field(axes_list) # Inverse fft if "ifft" in transforms: values = comp_ifftn(values, axes_list) # Slices along time/space axes values, axes_dict_other = self.extract_slices(values, axes_list) # fft if "fft" in transforms: values = comp_fftn(values, axes_list) # Slices along fft axes values = self.extract_slices_fft(values, axes_list) # Rebuild symmetries values = self.rebuild_symmetries(values, axes_list) # Interpolate over axis values values = self.interpolate(values, axes_list) # Conversions values = self.convert(values, unit, is_norm) # Return axes and values return_dict = {} for axis_requested in axes_list: return_dict[axis_requested.name] = axis_requested.values return_dict[self.symbol] = values return_dict["axes_list"] = axes_list return_dict["axes_dict_other"] = axes_dict_other return return_dict
def get_harmonics(self, N_harm, *args, unit="SI", is_norm=False, is_flat=False): """Returns the complex Fourier Transform of the field, using conversions and symmetries if needed. Parameters ---------- self: Data a Data object N_harm: int Number of largest harmonics to be extracted args: list Axes names, ranges and units unit: str Unit demanded by the user ("SI" by default) is_norm: bool Boolean indicating if the field must be normalized (False by default) is_flat: bool Boolean if the output data remains flattened (for 2D cases) Returns ------- list of 1Darray of axes values, ndarray of magnitude of FT """ # Read the axes input in args if len(args) == 1 and type(args[0]) == tuple: args = args[0] # if called from another script with *args axes_list = read_input_strings(args, []) # Extract the requested axes (symmetries + unit) for axis_requested in axes_list: if axis_requested[3] == "values": # Get original values of the axis axis_requested.append( self.get_FT_axis(axis_requested[0] + axis_requested[1])) # Interpolate axis with input data if str(axis_requested[4]) == "whole": axis_requested[4] = axis_requested[5] axis_requested[5] = "whole" else: axis_requested[4] = get_common_base(axis_requested[5], axis_requested[4]) # Change fft name for the slices of the field if axis_requested[0] == "freqs": axis_requested[0] = "time" elif axis_requested[0] == "wavenumber": axis_requested[0] = "angle" # Check if the requested axis is defined in the Data object for axis_requested in axes_list: axis_name = axis_requested[0] is_match = False for index, axis in enumerate(self.axes): if axis.name == axis_name: is_match = True if not is_match: axes_list.remove(axis_requested) # Rebuild symmetries of field if axis is extracted values = self.values for index, axis in enumerate(self.axes): for axis_requested in axes_list: if axis.name in self.symmetries.keys( ) and axis.name == axis_requested[0]: values = rebuild_symmetries(values, index, self.symmetries.get(axis.name)) # Extract the slices of the field (single values) for index, axis in enumerate(self.axes): is_match = False for axis_requested in axes_list: if axis.name == axis_requested[0]: is_match = True if axis_requested[3] == "indices" and axis_requested[ 2] == "single": values = take(values, axis_requested[4], axis=index) if not is_match: # Axis was not specified -> take slice at the first value values = take(values, [0], axis=index) # Interpolate over axis values (single values) for index, axis in enumerate(self.axes): for axis_requested in axes_list: if (axis.name == axis_requested[0] and axis_requested[3] == "values" and axis_requested[2] == "single"): values = apply_along_axis( get_interpolation, index, values, axis_requested[5], axis_requested[4], ) # Perform Fourier Transform values = np_abs(comp_fft(values)) # Extract slices again (intervals) for index, axis in enumerate(self.axes): for axis_requested in axes_list: if axis.name == axis_requested[0]: if axis_requested[2] == "indices" and axis_requested[ 2] == "interval": values = take(values, axis_requested[4], axis=index) # Interpolate over axis values again (intervals) for index, axis in enumerate(self.axes): for axis_requested in axes_list: if axis.name == axis_requested[0]: if axis_requested[3] == "values" and axis_requested[ 2] == "interval": values = apply_along_axis( get_interpolation, index, values, axis_requested[5], axis_requested[4], ) # Eliminate dimensions=1 values = squeeze(values) # Test if data is 1D or 2D if len(values.shape) > 2: raise AxisError("ERROR: only 1D or 2D implemented") else: # Convert into right unit if unit == self.unit or unit == "SI": if is_norm: try: values = values / self.normalizations.get("ref") except: raise NormError( "ERROR: Reference value not specified for normalization" ) elif unit == "dB": ref_value = 1.0 if "ref" in self.normalizations.keys(): ref_value *= self.normalizations.get("ref") values = to_dB(values, self.unit, ref_value) elif unit == "dBA": ref_value = 1.0 is_match = False if "ref" in self.normalizations.keys(): ref_value *= self.normalizations.get("ref") for axis_requested in axes_list: if axis_requested[0] == "time": is_match = True values = to_dBA(values, axis_requested[4], self.unit, ref_value) if not is_match: raise UnitError( "ERROR: dBA conversion only available for fft with frequencies" ) elif unit in self.normalizations: values = values / self.normalizations.get(unit) else: values = convert(values, self.unit, unit) # 1D case if len(values.shape) == 1: for axis_requested in axes_list: if axis_requested[2] == "interval": axis_values = axis_requested[4] indices = argsort(negative(values)) indices = indices[:N_harm] axis_values = axis_values[indices] values = values[indices] return [axis_values, values] # 2D case else: for axis_requested in axes_list: if axis_requested[0] == "angle": r = axis_requested[4] elif axis_requested[0] == "time": f = axis_requested[4] # Flatten the data values_flat = values.flatten() R, F = meshgrid(r, f) f = F.flatten() r = R.flatten() # Get the N_harm largest peaks indices = argsort(negative(values_flat)) indices = indices[:N_harm] values = values_flat[indices] f = f[indices] r = r[indices] if len(values.shape) == 2 and not is_flat: f.reshape((N_harm, N_harm)) r.reshape((N_harm, N_harm)) values.reshape((N_harm, N_harm)) return [f, r, values]
def get_along(self, *args, unit="SI", is_norm=False, axis_data=[], is_squeeze=True): """Returns the ndarray of the field, using conversions and symmetries if needed. Parameters ---------- self: Data a Data object *args: list of strings List of axes requested by the user, their units and values (optional) unit: str Unit requested by the user ("SI" by default) is_norm: bool Boolean indicating if the field must be normalized (False by default) axis_data: list list of ndarray corresponding to user-input data Returns ------- list of 1Darray of axes values, ndarray of field values """ # Read the axes input in args if len(args) == 1 and type(args[0]) == tuple: args = args[0] # if called from another script with *args axes_list = read_input_strings(args, axis_data) # Extract the requested axes (symmetries + unit) axes_list, transforms = self.comp_axes(axes_list) # Get the field values = self.get_field(axes_list) # If DataFreq + 1 ifft axis + 1 fft axis: perform ifft on all axes then fft save_transforms = None save_names = None if "ifft" in transforms and "fft" in transforms: save_transforms = [axis.transform for axis in axes_list] save_names = [axis.name for axis in axes_list] for axis in axes_list: if axis.name == "freqs": axis.transform = "ifft" axis.name = "time" elif axis.name == "wavenumber": axis.transform = "ifft" axis.name = "angle" # Inverse fft if "ifft" in transforms: values = comp_ifftn(values, axes_list, is_real=self.is_real) # Prepare fft in ifft/fft case if save_transforms is not None: for i, transform in enumerate(save_transforms): axes_list[i].name = save_names[i] if transform == "fft_axis": axes_list[i].transform = "fft" save_transforms[i] = "fft" else: axes_list[i].transform = transform # Slices along time/space axes values, axes_dict_other = self.extract_slices(values, axes_list) # fft if "fft" in transforms: values = comp_fftn(values, axes_list, is_real=self.is_real) # Slices along fft axes values = self.extract_slices_fft(values, axes_list) # Rebuild symmetries values = self.rebuild_symmetries(values, axes_list) # Interpolate over axis values values = self.interpolate(values, axes_list, is_squeeze=is_squeeze) # Conversions values = self.convert(values, unit, is_norm, axes_list) # Return axes and values return_dict = {} for axis_requested in axes_list: if axis_requested.extension in [ "sum", "rss", "mean", "rms", "integrate" ]: return_dict[axis_requested.name] = axis_requested.extension else: return_dict[axis_requested.name] = axis_requested.values return_dict[self.symbol] = values return_dict["axes_list"] = axes_list return_dict["axes_dict_other"] = axes_dict_other return return_dict