switched to accel vs vibrations with a zoomed plot for details
This commit is contained in:
@@ -29,6 +29,7 @@ import matplotlib.font_manager
|
|||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import matplotlib.ticker
|
import matplotlib.ticker
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
from scipy.interpolate import interp1d
|
||||||
|
|
||||||
matplotlib.use('Agg')
|
matplotlib.use('Agg')
|
||||||
|
|
||||||
@@ -47,8 +48,9 @@ PEAKS_DETECTION_THRESHOLD = 0.05
|
|||||||
PEAKS_EFFECT_THRESHOLD = 0.12
|
PEAKS_EFFECT_THRESHOLD = 0.12
|
||||||
SPECTROGRAM_LOW_PERCENTILE_FILTER = 5
|
SPECTROGRAM_LOW_PERCENTILE_FILTER = 5
|
||||||
MAX_VIBRATIONS = 5.0
|
MAX_VIBRATIONS = 5.0
|
||||||
SMOOTHING_LIST = [0.1]
|
MAX_VIBRATIONS_PLOTTED = 80.0
|
||||||
# SMOOTHING_LIST = np.arange(0.001, 0.80, 0.05)
|
MAX_VIBRATIONS_PLOTTED_ZOOM = 1.25 # 1.25x max vibs values from the standard filters selection
|
||||||
|
SMOOTHING_TESTS = 10 # Number of smoothing values to test (it will significantly increase the computation time)
|
||||||
KLIPPAIN_COLORS = {
|
KLIPPAIN_COLORS = {
|
||||||
'purple': '#70088C',
|
'purple': '#70088C',
|
||||||
'orange': '#FF8D32',
|
'orange': '#FF8D32',
|
||||||
@@ -178,7 +180,7 @@ def calibrate_shaper(datas: List[np.ndarray], max_smoothing: Optional[float], sc
|
|||||||
max_smoothing = shaper.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)
|
# 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, 10)[:-1]
|
smoothing_test_list = np.linspace(0.001, max_smoothing, SMOOTHING_TESTS)[:-1]
|
||||||
additional_all_shapers = {}
|
additional_all_shapers = {}
|
||||||
for smoothing in smoothing_test_list:
|
for smoothing in smoothing_test_list:
|
||||||
if compat:
|
if compat:
|
||||||
@@ -294,9 +296,9 @@ def plot_freq_response(
|
|||||||
and perf_shaper_choice != klipper_shaper_choice
|
and perf_shaper_choice != klipper_shaper_choice
|
||||||
and perf_shaper_accel >= klipper_shaper_accel
|
and perf_shaper_accel >= klipper_shaper_accel
|
||||||
):
|
):
|
||||||
perf_shaper_string = f'Recommended performance shaper: {perf_shaper_choice.upper()} @ {perf_shaper_freq:.1f} Hz'
|
perf_shaper_string = f'Recommended for performance: {perf_shaper_choice.upper()} @ {perf_shaper_freq:.1f} Hz'
|
||||||
lowvibr_shaper_string = (
|
lowvibr_shaper_string = (
|
||||||
f'Recommended low vibrations shaper: {klipper_shaper_choice.upper()} @ {klipper_shaper_freq:.1f} Hz'
|
f'Recommended for low vibrations: {klipper_shaper_choice.upper()} @ {klipper_shaper_freq:.1f} Hz'
|
||||||
)
|
)
|
||||||
shaper_table_data['recommendations'].append(perf_shaper_string)
|
shaper_table_data['recommendations'].append(perf_shaper_string)
|
||||||
shaper_table_data['recommendations'].append(lowvibr_shaper_string)
|
shaper_table_data['recommendations'].append(lowvibr_shaper_string)
|
||||||
@@ -436,47 +438,93 @@ def plot_smoothing_vs_accel(
|
|||||||
shaper_data[shaper_type] = []
|
shaper_data[shaper_type] = []
|
||||||
shaper_data[shaper_type].append(
|
shaper_data[shaper_type].append(
|
||||||
{
|
{
|
||||||
'smoothing': shaper.smoothing,
|
|
||||||
'max_accel': shaper.max_accel,
|
'max_accel': shaper.max_accel,
|
||||||
'vibrs': shaper.vibrs * 100.0,
|
'vibrs': shaper.vibrs * 100.0,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# Extract data from shaper_table_data and insert into shaper_data
|
# Extract data from shaper_table_data and insert into shaper_data
|
||||||
|
max_shaper_vibrations = 0
|
||||||
for shaper in shaper_table_data['shapers']:
|
for shaper in shaper_table_data['shapers']:
|
||||||
shaper_type = shaper['type']
|
shaper_type = shaper['type']
|
||||||
if shaper_type not in shaper_data:
|
if shaper_type not in shaper_data:
|
||||||
shaper_data[shaper_type] = []
|
shaper_data[shaper_type] = []
|
||||||
|
max_shaper_vibrations = max(max_shaper_vibrations, float(shaper['vibrations']) * 100.0)
|
||||||
shaper_data[shaper_type].append(
|
shaper_data[shaper_type].append(
|
||||||
{
|
{
|
||||||
'smoothing': float(shaper['smoothing']),
|
|
||||||
'max_accel': float(shaper['max_accel']),
|
'max_accel': float(shaper['max_accel']),
|
||||||
'vibrs': float(shaper['vibrations']) * 100.0,
|
'vibrs': float(shaper['vibrations']) * 100.0,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# Plot each shaper type and add colorbar for vibrations
|
# Calculate the maximum `max_accel` for points below the thresholds to get a good plot with
|
||||||
for _, (shaper_type, data) in enumerate(shaper_data.items()):
|
# continuous lines and a zoom on the graph to show details at low vibrations
|
||||||
smoothing_values = [d['smoothing'] for d in data]
|
min_accel_limit = 99999
|
||||||
max_accel_values = [d['max_accel'] for d in data]
|
max_accel_limit = 0
|
||||||
vibrs_values = [d['vibrs'] for d in data]
|
max_accel_limit_zoom = 0
|
||||||
ax.plot(max_accel_values, smoothing_values, linestyle=':', label=f'{shaper_type}', zorder=10)
|
for data in shaper_data.values():
|
||||||
scatter = ax.scatter(
|
min_accel_limit = min(min_accel_limit, min(d['max_accel'] for d in data))
|
||||||
max_accel_values, smoothing_values, c=vibrs_values, cmap='plasma', s=100, edgecolors='w', zorder=15
|
max_accel_limit = max(
|
||||||
|
max_accel_limit, max(d['max_accel'] for d in data if d['vibrs'] <= MAX_VIBRATIONS_PLOTTED)
|
||||||
|
)
|
||||||
|
max_accel_limit_zoom = max(
|
||||||
|
max_accel_limit_zoom,
|
||||||
|
max(d['max_accel'] for d in data if d['vibrs'] <= max_shaper_vibrations * MAX_VIBRATIONS_PLOTTED_ZOOM),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add colorbar for vibrations
|
# Add a zoom axes on the graph to show details at low vibrations
|
||||||
cbar = plt.colorbar(scatter, ax=ax)
|
zoomed_window = np.clip(max_shaper_vibrations * MAX_VIBRATIONS_PLOTTED_ZOOM, 0, 20)
|
||||||
cbar.set_label('Remaining Vibrations (%)')
|
axins = ax.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.indicate_inset_zoom(axins, edgecolor=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
|
||||||
|
number_of_interpolated_points = 100
|
||||||
|
x_fill = np.linspace(min_accel_limit * 0.95, max_accel_limit * 1.1, number_of_interpolated_points)
|
||||||
|
y_fill = np.full_like(x_fill, 5.0)
|
||||||
|
ax.axhline(y=5.0, color='black', linestyle='--', linewidth=0.5)
|
||||||
|
ax.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(), number_of_interpolated_points)
|
||||||
|
vibrs_fine = interp_func(max_accel_fine)
|
||||||
|
|
||||||
|
ax.plot(max_accel_fine, vibrs_fine, label=f'{shaper_type}', zorder=10)
|
||||||
|
axins.plot(max_accel_fine, vibrs_fine, label=f'{shaper_type}', zorder=15)
|
||||||
|
max_vibrations = max(max_vibrations, max(vibrs_fine))
|
||||||
|
|
||||||
ax.set_xlabel('Max Acceleration')
|
ax.set_xlabel('Max Acceleration')
|
||||||
ax.set_ylabel('Smoothing')
|
ax.set_ylabel('Remaining Vibrations (%)')
|
||||||
|
ax.set_xlim([min_accel_limit * 0.95, max_accel_limit * 1.1])
|
||||||
|
ax.set_ylim([-0.5, np.clip(max_vibrations * 1.05, 50, MAX_VIBRATIONS_PLOTTED)])
|
||||||
ax.set_title(
|
ax.set_title(
|
||||||
'Smoothing vs Max Acceleration',
|
'Filters performances over acceleration',
|
||||||
fontsize=14,
|
fontsize=14,
|
||||||
color=KLIPPAIN_COLORS['dark_orange'],
|
color=KLIPPAIN_COLORS['dark_orange'],
|
||||||
weight='bold',
|
weight='bold',
|
||||||
)
|
)
|
||||||
ax.legend(loc='upper right', prop=fontP)
|
ax.legend(loc='best', prop=fontP)
|
||||||
|
|
||||||
|
|
||||||
def print_shaper_table(fig: plt.Figure, shaper_table_data: Dict[str, List[Dict[str, str]]]) -> None:
|
def print_shaper_table(fig: plt.Figure, shaper_table_data: Dict[str, List[Dict[str, str]]]) -> None:
|
||||||
@@ -492,15 +540,43 @@ def print_shaper_table(fig: plt.Figure, shaper_table_data: Dict[str, List[Dict[s
|
|||||||
f'{round(shaper_info["max_accel"] / 10) * 10:.0f}',
|
f'{round(shaper_info["max_accel"] / 10) * 10:.0f}',
|
||||||
]
|
]
|
||||||
table_data.append(row)
|
table_data.append(row)
|
||||||
table = plt.table(cellText=table_data, colLabels=columns, bbox=[1.12, -0.4, 0.75, 0.25], cellLoc='center')
|
table = plt.table(cellText=table_data, colLabels=columns, bbox=[1.130, -0.4, 0.803, 0.25], cellLoc='center')
|
||||||
table.auto_set_font_size(False)
|
table.auto_set_font_size(False)
|
||||||
table.set_fontsize(10)
|
table.set_fontsize(10)
|
||||||
table.auto_set_column_width([0, 1, 2, 3, 4])
|
table.auto_set_column_width([0, 1, 2, 3, 4])
|
||||||
table.set_zorder(100)
|
table.set_zorder(100)
|
||||||
|
|
||||||
# Add the recommendations and damping ratio using fig.text
|
# Add the recommendations and damping ratio using fig.text
|
||||||
fig.text(0.58, 0.235, f'Estimated damping ratio (ζ): {shaper_table_data["damping_ratio"]:.3f}', fontsize=14)
|
fig.text(
|
||||||
fig.text(0.58, 0.210, '\n'.join(shaper_table_data['recommendations']), fontsize=14)
|
0.585,
|
||||||
|
0.235,
|
||||||
|
f'Estimated damping ratio (ζ): {shaper_table_data["damping_ratio"]:.3f}',
|
||||||
|
fontsize=14,
|
||||||
|
color=KLIPPAIN_COLORS['purple'],
|
||||||
|
)
|
||||||
|
if len(shaper_table_data['recommendations']) == 1:
|
||||||
|
fig.text(
|
||||||
|
0.585,
|
||||||
|
0.200,
|
||||||
|
shaper_table_data['recommendations'][0],
|
||||||
|
fontsize=14,
|
||||||
|
color=KLIPPAIN_COLORS['red_pink'],
|
||||||
|
)
|
||||||
|
elif len(shaper_table_data['recommendations']) == 2:
|
||||||
|
fig.text(
|
||||||
|
0.585,
|
||||||
|
0.200,
|
||||||
|
shaper_table_data['recommendations'][0],
|
||||||
|
fontsize=14,
|
||||||
|
color=KLIPPAIN_COLORS['red_pink'],
|
||||||
|
)
|
||||||
|
fig.text(
|
||||||
|
0.585,
|
||||||
|
0.175,
|
||||||
|
shaper_table_data['recommendations'][1],
|
||||||
|
fontsize=14,
|
||||||
|
color=KLIPPAIN_COLORS['red_pink'],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|||||||
Reference in New Issue
Block a user