Mandelbrot集迭代滑块失效求助:默认值以上调节无响应
Mandelbrot集迭代滑块异常问题修复
问题概述
课程项目需实现带自定义色图和max_iter滑块的Mandelbrot集展示,色图单选按钮功能正常,但迭代滑块存在以下异常:
- AI提供的修正代码仅在迭代次数低于默认值30时有效,调至100时视觉无实际变化
- 手动修改初始
max_iter为100后,滑块设为30的效果与正常30次迭代的结果完全不同,仅滑块设为100时效果符合预期
原代码(注释为波兰语,可忽略)
# sparametryzować liczbę iteracji import numpy as np import matplotlib.pyplot as plt from matplotlib.widgets import RadioButtons, Slider fig, ax = plt.subplots() plt.subplots_adjust(left=0.3) # Rozmiary i obszar width, height = 1500, 1500 x_min, x_max = -2, 0.5 y_min, y_max = -1.25, 1.25 max_iter = 30 # Siatka x = np.linspace(x_min, x_max, width) y = np.linspace(y_min, y_max, height) X, Y = np.meshgrid(x, y) C = X + 1j * Y # Mandelbrot z użyciem pętli Z = np.zeros(C.shape, dtype=complex) M = np.zeros(C.shape, dtype=int) axiter = plt.axes([0.25,0.05,0.65,0.03], facecolor="#777777") iter_slider = Slider(axiter, "Ilość iteracji", 1, 100, valinit = 30, track_color="#777777",) for k in range(max_iter): mask = np.abs(Z) <= 2.0 Z[mask] = Z[mask]**2 + C[mask] M[mask] = k + 1 # Wyświetlenie fraktalu img = ax.imshow(M, extent=(x_min, x_max, y_min, y_max), cmap='twilight', origin='lower') ax.axis('equal') ax.axis('off') # RadioButtons do zmiany cmap ax.set_title('Fraktal Mandelbrota', pad=10) rax = plt.axes([0.05, 0.4, 0.15, 0.15]) radio = RadioButtons(rax, ('twilight', 'Spectral', 'inferno', 'pink', 'viridis', 'berlin')) rax.set_title('Wybór mapy kolorów', pad=10) def update(label): sliter=iter_slider.val max_iter = sliter for k in range(max_iter): mask = np.abs(Z) <= 2.0 Z[mask] = Z[mask]**2 + C[mask] M[mask] = k + 1 ax.imshow(M, extent=(x_min, x_max, y_min, y_max), cmap='twilight', origin='lower') img.set_cmap(label) fig.canvas.draw_idle() radio.on_clicked(update) plt.show()
AI提供的修正代码(注释为波兰语,可忽略)
import numpy as np import matplotlib.pyplot as plt from matplotlib.widgets import RadioButtons, Slider fig, ax = plt.subplots() plt.subplots_adjust(left=0.3) # Rozmiary i obszar width, height = 1500, 1500 x_min, x_max = -2, 0.5 y_min, y_max = -1.25, 1.25 max_iter = 30 # Siatka x = np.linspace(x_min, x_max, width) y = np.linspace(y_min, y_max, height) X, Y = np.meshgrid(x, y) C = X + 1j * Y # Mandelbrot z użyciem pętli Z = np.zeros(C.shape, dtype=complex) M = np.zeros(C.shape, dtype=int) axiter = plt.axes([0.25,0.05,0.65,0.03], facecolor="#777777") iter_slider = Slider(axiter, "Ilość iteracji", 1, 100, valinit=30, track_color="#777777") for k in range(max_iter): mask = np.abs(Z) <= 2.0 Z[mask] = Z[mask]**2 + C[mask] M[mask] = k + 1 # Wyświetlenie fraktalu img = ax.imshow(M, extent=(x_min, x_max, y_min, y_max), cmap='twilight', origin='lower') ax.axis('equal') ax.axis('off') # RadioButtons do zmiany cmap ax.set_title('Fraktal Mandelbrota', pad=10) rax = plt.axes([0.05, 0.4, 0.15, 0.15]) radio = RadioButtons(rax, ('twilight', 'Spectral', 'inferno', 'pink', 'viridis', 'berlin')) rax.set_title('Wybór mapy kolorów', pad=10) def redraw(): max_iter = int(iter_slider.val) Z = np.zeros(C.shape, dtype=complex) M = np.zeros(C.shape, dtype=int) for k in range(max_iter): mask = np.abs(Z) <= 2.0 Z[mask] = Z[mask]**2 + C[mask] M[mask] = k + 1 img.set_data(M) img.set_cmap(radio.value_selected) fig.canvas.draw_idle() def update(label): redraw() def update_iter(val): redraw() radio.on_clicked(update) iter_slider.on_changed(update_iter) plt.show()
效果对比
- 手动设置100迭代效果:

- 滑块设置100迭代效果:

- 初始max_iter设为100时,滑块设置30迭代效果:

问题根源
异常的核心原因是颜色映射的范围未随迭代次数动态更新:
- matplotlib的
imshow默认会根据初始数据的极值自动设置颜色范围(vmin和vmax) - 当迭代次数变化时,修正代码仅更新了数据
M,但未调整颜色范围:- 初始
max_iter=30时,vmax被设为30,滑块调至100后,M的最大值为100,但所有大于30的值会被映射到同一种颜色,视觉上无变化 - 初始
max_iter=100时,vmax被设为100,滑块调至30后,M的最大值为30,颜色范围仍为0-100,导致颜色对比度极低,显示异常
- 初始
修复方案
在每次重绘时,手动更新颜色范围以匹配当前迭代次数的结果,只需修改redraw函数,添加img.set_clim(vmin=0, vmax=max_iter)即可:
修改后的完整代码
import numpy as np import matplotlib.pyplot as plt from matplotlib.widgets import RadioButtons, Slider fig, ax = plt.subplots() plt.subplots_adjust(left=0.3) # Rozmiary i obszar width, height = 1500, 1500 x_min, x_max = -2, 0.5 y_min, y_max = -1.25, 1.25 max_iter = 30 # Siatka x = np.linspace(x_min, x_max, width) y = np.linspace(y_min, y_max, height) X, Y = np.meshgrid(x, y) C = X + 1j * Y # Mandelbrot z użyciem pętli Z = np.zeros(C.shape, dtype=complex) M = np.zeros(C.shape, dtype=int) axiter = plt.axes([0.25,0.05,0.65,0.03], facecolor="#777777") iter_slider = Slider(axiter, "Ilość iteracji", 1, 100, valinit=30, track_color="#777777") for k in range(max_iter): mask = np.abs(Z) <= 2.0 Z[mask] = Z[mask]**2 + C[mask] M[mask] = k + 1 # Wyświetlenie fraktalu img = ax.imshow(M, extent=(x_min, x_max, y_min, y_max), cmap='twilight', origin='lower') ax.axis('equal') ax.axis('off') # RadioButtons do zmiany cmap ax.set_title('Fraktal Mandelbrota', pad=10) rax = plt.axes([0.05, 0.4, 0.15, 0.15]) radio = RadioButtons(rax, ('twilight', 'Spectral', 'inferno', 'pink', 'viridis', 'berlin')) rax.set_title('Wybór mapy kolorów', pad=10) def redraw(): max_iter = int(iter_slider.val) Z = np.zeros(C.shape, dtype=complex) M = np.zeros(C.shape, dtype=int) for k in range(max_iter): mask = np.abs(Z) <= 2.0 Z[mask] = Z[mask]**2 + C[mask] M[mask] = k + 1 img.set_data(M) img.set_cmap(radio.value_selected) # 动态更新颜色范围,匹配当前迭代次数 img.set_clim(vmin=0, vmax=max_iter) fig.canvas.draw_idle() def update(label): redraw() def update_iter(val): redraw() radio.on_clicked(update) iter_slider.on_changed(update_iter) plt.show()
内容的提问来源于stack exchange,提问作者Helewapo
相关产品推荐
相关产品推荐

