From 2b4ea98fb753696a1642bd92d9a844ef4f5713ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Boisselier?= Date: Sun, 15 Dec 2024 17:19:24 +0000 Subject: [PATCH] k_shapers imports refactor (#174) * small refactoring of k_shapers imports and variables to be easier to read * added draft for tradeoff shaper plots (commented for now as it's a WIP for later use) --- shaketune/cli.py | 1 + shaketune/graph_creators/__init__.py | 5 +- .../graph_creators/belts_graph_creator.py | 4 +- shaketune/graph_creators/plotter.py | 167 ++++++--------- .../graph_creators/shaper_graph_creator.py | 202 +++++++++++------- .../vibrations_graph_creator.py | 4 +- 6 files changed, 203 insertions(+), 180 deletions(-) diff --git a/shaketune/cli.py b/shaketune/cli.py index cd93276..345d287 100644 --- a/shaketune/cli.py +++ b/shaketune/cli.py @@ -44,6 +44,7 @@ def load_klipper_module(args): kdir = os.path.expanduser(args.klipper_dir) sys.path.append(os.path.join(kdir, 'klippy')) sys.modules['shaper_calibrate'] = import_module('.shaper_calibrate', 'extras') + sys.modules['shaper_defs'] = import_module('.shaper_defs', 'extras') def main(): diff --git a/shaketune/graph_creators/__init__.py b/shaketune/graph_creators/__init__.py index f921996..d8b8a6d 100644 --- a/shaketune/graph_creators/__init__.py +++ b/shaketune/graph_creators/__init__.py @@ -12,10 +12,11 @@ def get_shaper_calibrate_module(): if os.environ.get('SHAKETUNE_IN_CLI') != '1': - from ... import shaper_calibrate + from ... import shaper_calibrate, shaper_defs else: shaper_calibrate = sys.modules['shaper_calibrate'] - return shaper_calibrate + shaper_defs = sys.modules['shaper_defs'] + return shaper_calibrate.ShaperCalibrate(printer=None), shaper_defs from .axes_map_graph_creator import AxesMapGraphCreator as AxesMapGraphCreator # noqa: E402 diff --git a/shaketune/graph_creators/belts_graph_creator.py b/shaketune/graph_creators/belts_graph_creator.py index 28195cf..52d6b61 100644 --- a/shaketune/graph_creators/belts_graph_creator.py +++ b/shaketune/graph_creators/belts_graph_creator.py @@ -135,8 +135,8 @@ def compute(self): } def _compute_signal_data(self, data: np.ndarray, common_freqs: np.ndarray, max_freq: float): - helper = get_shaper_calibrate_module().ShaperCalibrate(printer=None) - calibration_data = helper.process_accelerometer_data(data) + shaper_calibrate, _ = get_shaper_calibrate_module() + calibration_data = shaper_calibrate.process_accelerometer_data(data) freqs = calibration_data.freq_bins[calibration_data.freq_bins <= max_freq] psd = calibration_data.get_psd('all')[calibration_data.freq_bins <= max_freq] diff --git a/shaketune/graph_creators/plotter.py b/shaketune/graph_creators/plotter.py index b023fb2..93c134f 100644 --- a/shaketune/graph_creators/plotter.py +++ b/shaketune/graph_creators/plotter.py @@ -16,7 +16,6 @@ import matplotlib.pyplot as plt import matplotlib.ticker import numpy as np -from scipy.interpolate import interp1d matplotlib.use('Agg') # Use 'Agg' backend for non-GUI environments @@ -641,7 +640,7 @@ def plot_input_shaper_graph(self, data): t = data['t'] bins = data['bins'] pdata = data['pdata'] - additional_shapers = data['additional_shapers'] + # shapers_tradeoff_data = data['shapers_tradeoff_data'] accel_per_hz = data['accel_per_hz'] max_smoothing = data['max_smoothing'] scv = data['scv'] @@ -662,7 +661,7 @@ def plot_input_shaper_graph(self, data): ) ax_1 = fig.add_subplot(gs[0, 0]) ax_2 = fig.add_subplot(gs[1, 0]) - ax_3 = fig.add_subplot(gs[0, 1]) + ax_3 = fig.add_subplot(gs[1, 1]) # Add titles and logo try: @@ -796,95 +795,57 @@ def plot_input_shaper_graph(self, data): ax_2, xlabel='Frequency (Hz)', ylabel='Time (s)', title='Time-Frequency Spectrogram', grid=False ) - # Plot Filters performances over acceleration - shaper_data = {} - for shaper_list in additional_shapers.values(): - for shaper in shaper_list: - shaper_type = shaper.name.upper() - shaper_data.setdefault(shaper_type, []).append( - { - 'max_accel': shaper.max_accel, - 'vibrs': shaper.vibrs * 100.0, - } - ) - max_shaper_vibrations = 0 - for shaper in shaper_table_data['shapers']: - shaper_type = shaper['type'].upper() - shaper_data.setdefault(shaper_type, []).append( - { - 'max_accel': shaper['max_accel'], - 'vibrs': shaper['vibrations'] * 100.0, - } - ) - max_shaper_vibrations = max(max_shaper_vibrations, shaper['vibrations'] * 100.0) - - # Calculate the maximum `max_accel` for points below the thresholds to get a good plot with - # continuous lines and a zoom on the graph to show details at low vibrations - min_accel_limit = min(min(d['max_accel'] for d in data_list) for data_list in shaper_data.values()) - max_accel_limit = max( - max(d['max_accel'] for d in data_list if d['vibrs'] <= self.MAX_VIBRATIONS_PLOTTED) - for data_list in shaper_data.values() - ) - max_accel_limit_zoom = max( - max( - d['max_accel'] - for d in data_list - if d['vibrs'] <= max_shaper_vibrations * self.MAX_VIBRATIONS_PLOTTED_ZOOM - ) - for data_list in shaper_data.values() - ) - - # Add a zoom axes on the graph to show details at low vibrations - zoomed_window = np.clip(max_shaper_vibrations * self.MAX_VIBRATIONS_PLOTTED_ZOOM, 0, 20) - axins = ax_3.inset_axes( - [0.575, 0.125, 0.40, 0.45], - xlim=(min_accel_limit * 0.95, max_accel_limit_zoom * 1.1), - ylim=(-0.5, zoomed_window), - ) - ax_3.indicate_inset_zoom(axins, edgecolor=self.KLIPPAIN_COLORS['purple'], linewidth=3) - axins.xaxis.set_minor_locator(matplotlib.ticker.MultipleLocator(500)) - axins.yaxis.set_minor_locator(matplotlib.ticker.AutoMinorLocator()) - axins.grid(which='major', color='grey') - axins.grid(which='minor', color='lightgrey') - - # Draw the green zone on both axes to highlight the low vibrations zone - x_fill = np.linspace(min_accel_limit * 0.95, max_accel_limit * 1.1, 100) - y_fill = np.full_like(x_fill, 5.0) - ax_3.axhline(y=5.0, color='black', linestyle='--', linewidth=0.5) - ax_3.fill_between(x_fill, -0.5, y_fill, color='green', alpha=0.15) - if zoomed_window > 5.0: - axins.axhline(y=5.0, color='black', linestyle='--', linewidth=0.5) - axins.fill_between(x_fill, -0.5, y_fill, color='green', alpha=0.15) - - # Plot each shaper remaining vibrations response over acceleration - max_vibrations = 0 - for _, (shaper_type, data) in enumerate(shaper_data.items()): - max_accel_values = np.array([d['max_accel'] for d in data]) - vibrs_values = np.array([d['vibrs'] for d in data]) - - # remove duplicate values in max_accel_values and delete the corresponding vibrs_values - # and interpolate the curves to get them smoother with more datapoints - unique_max_accel_values, unique_indices = np.unique(max_accel_values, return_index=True) - max_accel_values = unique_max_accel_values - vibrs_values = vibrs_values[unique_indices] - interp_func = interp1d(max_accel_values, vibrs_values, kind='cubic') - max_accel_fine = np.linspace(max_accel_values.min(), max_accel_values.max(), 100) - vibrs_fine = interp_func(max_accel_fine) - - ax_3.plot(max_accel_fine, vibrs_fine, label=shaper_type, zorder=10) - axins.plot(max_accel_fine, vibrs_fine, label=shaper_type, zorder=15) - max_vibrations = max(max_vibrations, max(vibrs_fine)) - - ax_3.set_xlim([min_accel_limit * 0.95, max_accel_limit * 1.1]) - ax_3.set_ylim([-0.5, np.clip(max_vibrations * 1.05, 50, self.MAX_VIBRATIONS_PLOTTED)]) - ax_3.legend(loc='best', prop=fontP) - self.configure_axes( - ax_3, - xlabel='Max Acceleration', - ylabel='Remaining Vibrations (%)', - title='Filters performance over acceleration', - legend=False, # It's already configured to be at "best" location the line above - ) + # TODO: re-add this in next release + # -------------------------------------------------------------------------------------------------------------- + ax_3.remove() + # -------------------------------------------------------------------------------------------------------------- + # # Plot the vibrations vs acceleration curves for each shaper + # max_shaper_accel = 0 + # for shaper_name, data in shapers_tradeoff_data.items(): + # ax_3.plot(data['accels'], data['vibrs'], label=shaper_name, zorder=10) + # # find the accel of the same shaper in the standard k_shapers and use it as max_shaper_accel + # shaper = next(s for s in shapers if s.name == shaper_name) + # max_shaper_accel = max(max_shaper_accel, shaper.max_accel) + + # # Configure the main axes + # ax_3.set_xlim([0, max_shaper_accel * 1.75]) # ~2x of the standard shapers (to see higher accels) + # ax_3.set_ylim([0, None]) + # ax_3.legend(loc='best', prop=fontP) + # self.configure_axes( + # ax_3, + # xlabel='Acceleration (mm/s²)', + # ylabel='Remaining Vibrations (%)', + # title='Filters Performance', + # legend=False, # Legend is configured to be at the "best" location + # ) + + # -------------------------------------------------------------------------------------------------------------- + # Plot the vibrations vs acceleration curves for each shaper + # ax_3.set_title('Remaining Vibrations vs Acceleration and Smoothing') + # shaper_name = 'mzv' # Choose the shaper you're interested in + # shaper_data = shapers_tradeoff_data[shaper_name] + + # # Prepare data for the heatmap + # X, Y = np.meshgrid(shaper_data['smoothings'], shaper_data['accels']) + # Z = shaper_data['vibrations_grid'] + + # # Create the heatmap + # heatmap = ax_3.pcolormesh(Y, X, Z, shading='gouraud', cmap='inferno', vmin=0, vmax=100) + # fig.colorbar(heatmap, ax=ax_3, label='Remaining Vibrations (%)') + + # ax_3.set_xlabel('Acceleration (mm/s²)') + # ax_3.set_ylabel('Smoothing (mm/s²)') + # # ax_3.set_xlim([shaper_data['smoothings'][0], shaper_data['smoothings'][-1]]) + # ax_3.set_ylim([0.0, None]) + # # ax_3.set_ylim([shaper_data['accels'][0], shaper_data['accels'][-1]]) + # ax_3.set_xlim([0.0, None]) + + # # Optionally, overlay contours for specific vibration levels + # contours = ax_3.contour(Y, X, Z, levels=[5, 10, 20, 30], colors='white', linewidths=0.5) + # ax_3.clabel(contours, inline=True, fontsize=8, fmt='%1.0f%%') + + # ax_3.set_title(f'Heatmap of Remaining Vibrations for {shaper_name.upper()}') + # -------------------------------------------------------------------------------------------------------------- # Print shaper table columns = ['Type', 'Frequency', 'Vibrations', 'Smoothing', 'Max Accel'] @@ -899,16 +860,26 @@ def plot_input_shaper_graph(self, data): for shaper in shaper_table_data['shapers'] ] - table = plt.table(cellText=table_data, colLabels=columns, bbox=[1.130, -0.4, 0.803, 0.25], cellLoc='center') + table = plt.table(cellText=table_data, colLabels=columns, bbox=[1.100, 0.535, 0.830, 0.240], cellLoc='center') table.auto_set_font_size(False) table.set_fontsize(10) table.auto_set_column_width([0, 1, 2, 3, 4]) table.set_zorder(100) + bold_font = matplotlib.font_manager.FontProperties(weight='bold') + for key, cell in table.get_celld().items(): + row, col = key + cell.set_text_props(ha='center', va='center') + if col == 0: + cell.get_text().set_fontproperties(bold_font) + cell.get_text().set_color(self.KLIPPAIN_COLORS['dark_purple']) + if row == 0: + cell.get_text().set_fontproperties(bold_font) + cell.get_text().set_color(self.KLIPPAIN_COLORS['dark_orange']) # Add the filter general recommendations and estimated damping ratio fig.text( - 0.585, - 0.155, + 0.575, + 0.897, 'Recommended filters:', fontsize=15, fontweight='bold', @@ -916,11 +887,11 @@ def plot_input_shaper_graph(self, data): ) recommendations = shaper_table_data['recommendations'] for idx, rec in enumerate(recommendations): - fig.text(0.590, 0.125 - idx * 0.025, rec, fontsize=14, color=self.KLIPPAIN_COLORS['purple']) + fig.text(0.580, 0.867 - idx * 0.025, rec, fontsize=14, color=self.KLIPPAIN_COLORS['purple']) new_idx = len(recommendations) fig.text( - 0.590, - 0.125 - new_idx * 0.025, + 0.580, + 0.867 - new_idx * 0.025, f' -> Estimated damping ratio (ζ): {shaper_table_data["damping_ratio"]:.3f}', fontsize=14, color=self.KLIPPAIN_COLORS['purple'], diff --git a/shaketune/graph_creators/shaper_graph_creator.py b/shaketune/graph_creators/shaper_graph_creator.py index 1b8c248..0e24e09 100644 --- a/shaketune/graph_creators/shaper_graph_creator.py +++ b/shaketune/graph_creators/shaper_graph_creator.py @@ -28,8 +28,12 @@ PEAKS_DETECTION_THRESHOLD = 0.05 PEAKS_EFFECT_THRESHOLD = 0.12 -SMOOTHING_TESTS = 10 # Number of smoothing values to test (it will significantly increase the computation time) MAX_VIBRATIONS = 5.0 +MIN_ACCEL = 100.0 +MIN_SMOOTHING = 0.001 +TARGET_SMOOTHING = 0.12 +MIN_FREQ = 5.0 +MAX_SHAPER_FREQ = 150.0 @GraphCreator.register('input shaper') @@ -101,13 +105,12 @@ def compute(self): # Compute shapers, PSD outputs and spectrogram ( - klipper_shaper_choice, - shapers, - additional_shapers, + k_shaper_choice, + k_shapers, + shapers_tradeoff_data, calibration_data, fr, zeta, - max_smoothing_computed, compat, ) = self._calibrate_shaper(datas[0], self.max_smoothing, self.scv, self.max_freq) pdata, bins, t = compute_spectrogram(datas[0]) @@ -148,7 +151,8 @@ def compute(self): perf_shaper_choice = None perf_shaper_freq = None perf_shaper_accel = 0 - for shaper in shapers: + max_smoothing_computed = 0 + for shaper in k_shapers: shaper_info = { 'type': shaper.name.upper(), 'frequency': shaper.freq, @@ -158,9 +162,10 @@ def compute(self): 'vals': shaper.vals, } shaper_table_data['shapers'].append(shaper_info) + max_smoothing_computed = max(max_smoothing_computed, shaper.smoothing) # Get the Klipper recommended shaper (usually it's a good low vibration compromise) - if shaper.name == klipper_shaper_choice: + if shaper.name == k_shaper_choice: klipper_shaper_freq = shaper.freq klipper_shaper_accel = shaper.max_accel @@ -178,22 +183,22 @@ def compute(self): ConsoleOutput.print('Recommended filters:') if ( perf_shaper_choice is not None - and perf_shaper_choice != klipper_shaper_choice + and perf_shaper_choice != k_shaper_choice and perf_shaper_accel >= klipper_shaper_accel ): perf_shaper_string = f' -> For performance: {perf_shaper_choice.upper()} @ {perf_shaper_freq:.1f} Hz' lowvibr_shaper_string = ( - f' -> For low vibrations: {klipper_shaper_choice.upper()} @ {klipper_shaper_freq:.1f} Hz' + f' -> For low vibrations: {k_shaper_choice.upper()} @ {klipper_shaper_freq:.1f} Hz' ) shaper_table_data['recommendations'].append(perf_shaper_string) shaper_table_data['recommendations'].append(lowvibr_shaper_string) - shaper_choices = [klipper_shaper_choice.upper(), perf_shaper_choice.upper()] + shaper_choices = [k_shaper_choice.upper(), perf_shaper_choice.upper()] ConsoleOutput.print(f'{perf_shaper_string} (with a damping ratio of {zeta:.3f})') ConsoleOutput.print(f'{lowvibr_shaper_string} (with a damping ratio of {zeta:.3f})') else: - shaper_string = f' -> Best shaper: {klipper_shaper_choice.upper()} @ {klipper_shaper_freq:.1f} Hz' + shaper_string = f' -> Best shaper: {k_shaper_choice.upper()} @ {klipper_shaper_freq:.1f} Hz' shaper_table_data['recommendations'].append(shaper_string) - shaper_choices = [klipper_shaper_choice.upper()] + shaper_choices = [k_shaper_choice.upper()] ConsoleOutput.print(f'{shaper_string} (with a damping ratio of {zeta:.3f})') return { @@ -202,7 +207,7 @@ def compute(self): 'max_smoothing_computed': max_smoothing_computed, 'max_freq': self.max_freq, 'calibration_data': calibration_data, - 'shapers': shapers, + 'shapers': k_shapers, 'shaper_table_data': shaper_table_data, 'shaper_choices': shaper_choices, 'peaks': peaks, @@ -213,7 +218,7 @@ def compute(self): 't': t, 'bins': bins, 'pdata': pdata, - 'additional_shapers': additional_shapers, + 'shapers_tradeoff_data': shapers_tradeoff_data, 'accel_per_hz': self.accel_per_hz, 'max_smoothing': self.max_smoothing, 'scv': self.scv, @@ -224,18 +229,20 @@ def compute(self): # a proper precomputed damping ratio (zeta) and using the configured printer SQV value # This function also sweep around the smoothing values to help you find the best compromise def _calibrate_shaper(self, datas: List[np.ndarray], max_smoothing: Optional[float], scv: float, max_freq: float): - helper = get_shaper_calibrate_module().ShaperCalibrate(printer=None) - calibration_data = helper.process_accelerometer_data(datas) - calibration_data.normalize_to_frequencies() + shaper_calibrate, shaper_defs = get_shaper_calibrate_module() + calib_data = shaper_calibrate.process_accelerometer_data(datas) + calib_data.normalize_to_frequencies() # We compute the damping ratio using the Klipper's default value if it fails - fr, zeta, _, _ = compute_mechanical_parameters(calibration_data.psd_sum, calibration_data.freq_bins) + fr, zeta, _, _ = compute_mechanical_parameters(calib_data.psd_sum, calib_data.freq_bins) zeta = zeta if zeta is not None else 0.1 + # First we find the best shapers using the Klipper's standard algorithms. This will give us Klipper's + # best shaper choice and the full list of shapers that are set to the current machine response compat = False try: - k_shaper_choice, all_shapers = helper.find_best_shaper( - calibration_data, + k_shaper_choice, k_shapers = shaper_calibrate.find_best_shaper( + calib_data, shapers=None, damping_ratio=zeta, scv=scv, @@ -260,68 +267,111 @@ def _calibrate_shaper(self, datas: List[np.ndarray], max_smoothing: Optional[flo ) ) compat = True - k_shaper_choice, all_shapers = helper.find_best_shaper(calibration_data, max_smoothing, None) - - # If max_smoothing is not None, we run the same computation but without a smoothing value - # to get the max smoothing values from the filters and create the testing list - all_shapers_nosmoothing = None - if max_smoothing is not None: - if compat: - _, all_shapers_nosmoothing = helper.find_best_shaper(calibration_data, None, None) - else: - _, all_shapers_nosmoothing = helper.find_best_shaper( - calibration_data, - shapers=None, - damping_ratio=zeta, - scv=scv, - shaper_freqs=None, - max_smoothing=None, - test_damping_ratios=None, - max_freq=max_freq, - logger=None, - ) + k_shaper_choice, k_shapers = shaper_calibrate.find_best_shaper(calib_data, max_smoothing, None) - # Then we iterate over the all_shaperts_nosmoothing list to get the max of the smoothing values - max_smoothing = 0.0 - if all_shapers_nosmoothing is not None: - for shaper in all_shapers_nosmoothing: - if shaper.smoothing > max_smoothing: - max_smoothing = shaper.smoothing + # Then in a second time, we run again the same computation but with a super low smoothing value to + # get the maximum accelerations values for each algorithms. + if compat: + _, k_shapers_max = shaper_calibrate.find_best_shaper(calib_data, MIN_SMOOTHING, None) else: - for shaper in all_shapers: - if shaper.smoothing > max_smoothing: - max_smoothing = shaper.smoothing - - # Then we create a list of smoothing values to test (no need to test the max smoothing value as it was already tested) - smoothing_test_list = np.linspace(0.001, max_smoothing, SMOOTHING_TESTS)[:-1] - additional_all_shapers = {} - for smoothing in smoothing_test_list: - if compat: - _, all_shapers_bis = helper.find_best_shaper(calibration_data, smoothing, None) - else: - _, all_shapers_bis = helper.find_best_shaper( - calibration_data, - shapers=None, - damping_ratio=zeta, - scv=scv, - shaper_freqs=None, - max_smoothing=smoothing, - test_damping_ratios=None, - max_freq=max_freq, - logger=None, - ) - additional_all_shapers[f'sm_{smoothing}'] = all_shapers_bis - additional_all_shapers['max_smoothing'] = ( - all_shapers_nosmoothing if all_shapers_nosmoothing is not None else all_shapers - ) + _, k_shapers_max = shaper_calibrate.find_best_shaper( + calib_data, + shapers=None, + damping_ratio=zeta, + scv=scv, + shaper_freqs=None, + max_smoothing=MIN_SMOOTHING, + test_damping_ratios=None, + max_freq=max_freq, + logger=None, + ) + + # TODO: re-add this in next release + # -------------------------------------------------------------------------------------------------------------- + # # Finally we create the data structure to plot the additional graphs (tradeoffs for vibrs and smoothing) + # shapers_tradeoff_data = {} + # for shaper in k_shapers_max: + # shaper_cfg = next(cfg for cfg in shaper_defs.INPUT_SHAPERS if cfg.name == shaper.name) + + # accels_to_plot = np.linspace(MIN_ACCEL, shaper.max_accel, 100) + # smoothing_to_plot = np.linspace(MIN_SMOOTHING, 0.20, 100) + # # smoothing_to_plot = np.linspace(MIN_SMOOTHING, shaper.smoothing * 10, 100) + + # shapers_tradeoff_data[shaper.name] = self._compute_tradeoff_data( + # shaper_calibrate, + # shaper_cfg, + # zeta, + # scv, + # calib_data, + # accels_to_plot, + # smoothing_to_plot, + # ) + # -------------------------------------------------------------------------------------------------------------- return ( k_shaper_choice.name, - all_shapers, - additional_all_shapers, - calibration_data, + k_shapers, + None, # shapers_tradeoff_data, + calib_data, fr, zeta, - max_smoothing, compat, ) + + # # For a given shaper type and machine damping ratio, this compute the remaining vibration and smoothing + # # the machine will experience for a given range of acceleration values and target smoothing values. + # def _compute_tradeoff_data( + # self, shaper_calibrate, shaper_cfg, zeta, scv, calib_data, accels_to_plot, smoothing_to_plot + # ): + # # Initialize grids to store computed values + # vibrations_grid = np.zeros((len(accels_to_plot), len(smoothing_to_plot))) + # shaper_freqs_grid = np.zeros_like(vibrations_grid) + + # # Loop over acceleration and smoothing values + # for i, accel in enumerate(accels_to_plot): + # for j, smoothing in enumerate(smoothing_to_plot): + # # Find the shaper frequency that results in the target smoothing at this acceleration + # shaper_freq = self._fit_shaper( + # shaper_calibrate, + # shaper_cfg, + # accel, + # zeta, + # scv, + # target_smoothing=smoothing, + # min_freq=MIN_FREQ, + # max_freq=MAX_SHAPER_FREQ, + # ) + # if shaper_freq is not None: + # A, T = shaper_cfg.init_func(shaper_freq, zeta) + # vibration, _ = shaper_calibrate._estimate_remaining_vibrations( + # (A, T), zeta, calib_data.freq_bins, calib_data.psd_sum + # ) + # vibrations_grid[i, j] = vibration * 100.0 # Convert to percentage + # shaper_freqs_grid[i, j] = shaper_freq + # else: + # # If no valid frequency is found, store NaN values + # vibrations_grid[i, j] = np.nan + # shaper_freqs_grid[i, j] = np.nan + + # return { + # 'accels': accels_to_plot, + # 'smoothings': smoothing_to_plot, + # 'vibrations_grid': vibrations_grid, + # 'shaper_freqs_grid': shaper_freqs_grid, + # } + + # # Fit a shaper filter to the accelerometer recording in order to find the shaper frequency that results + # # (or is close) to the target smoothing at the given acceleration. + # def _fit_shaper(self, shaper_calibrate, shaper_cfg, accel, zeta, scv, target_smoothing, min_freq, max_freq): + # def smoothing_loss(freq): + # # Compute shaper parameters + # shaper = shaper_cfg.init_func(freq, zeta) + # smoothing = shaper_calibrate._get_shaper_smoothing(shaper, accel, scv) + # return smoothing - target_smoothing + + # # Use a root-finding method to solve for freq where smoothing equals target_smoothing + # try: + # shaper_freq = optimize.brentq(smoothing_loss, min_freq, max_freq) + # except ValueError: + # shaper_freq = None + # return shaper_freq diff --git a/shaketune/graph_creators/vibrations_graph_creator.py b/shaketune/graph_creators/vibrations_graph_creator.py index 0208dc2..32e9696 100644 --- a/shaketune/graph_creators/vibrations_graph_creator.py +++ b/shaketune/graph_creators/vibrations_graph_creator.py @@ -95,7 +95,7 @@ def compute(self): target_freqs_initialized = False target_freqs = None - helper = get_shaper_calibrate_module().ShaperCalibrate(printer=None) + shaper_calibrate, _ = get_shaper_calibrate_module() for measurement in self.measurements: data = np.array(measurement['samples']) @@ -103,7 +103,7 @@ def compute(self): continue # Measurement data is not in the expected format or is empty, skip it angle, speed = self._extract_angle_and_speed(measurement['name']) - freq_response = helper.process_accelerometer_data(data) + freq_response = shaper_calibrate.process_accelerometer_data(data) first_freqs = freq_response.freq_bins psd_sum = freq_response.psd_sum