I'm currently coding a Mandelbrot set using matplotlib with a zoom function to infinitely zoom in on any section of it, however when I zoom in the new data that's calculated is off-center from the graph axes.
This screenshot shows the graph after one zoom in - the set isn't generated correctly for the axes. The graph should be symmetrical about y=0, but it isn't - it changes whenever I zoom. I can't think of what could be causing this - I can't see any issue in the code. How do i fix this?
Here's my code:
import numpy as np
import matplotlib.pyplot as plt
def mandelbrot_set(xmin, xmax, ymin, ymax, width, height, maxiter):
x = np.linspace(xmin, xmax, width).reshape((1, width))
y = np.linspace(ymin, ymax, height).reshape((height, 1))
c = x + y * 1j
z = c
fractal = np.zeros(z.shape, dtype=int)
for i in range(maxiter):
z = z**2 + c
mask = np.abs(z) > 2
fractal += mask
z[mask] = 2
return fractal
xmin, xmax, ymin, ymax = -2, 1, -1.5, 1.5
maxiter = 300
width, height = 500, 500
fractal = mandelbrot_set(xmin, xmax, ymin, ymax, width, height, maxiter)
fig, ax = plt.subplots(figsize=(10, 10))
im = ax.imshow(fractal, cmap='magma', extent=(xmin, xmax, ymin, ymax))
def update_plot(xmin, xmax, ymin, ymax):
fractal = mandelbrot_set(xmin, xmax, ymin, ymax, width, height, maxiter)
im.set_data(fractal)
im.set_extent((xmin, xmax, ymin, ymax))
fig.canvas.draw()
def on_scroll(event):
xmin, xmax = ax.get_xlim()
ymin, ymax = ax.get_ylim()
x, y = event.xdata, event.ydata
if event.button == 'up':
scale_factor = 0.5
else:
scale_factor = 2.0
xmin = x - (x - xmin)*scale_factor
xmax = x + (xmax - x)*scale_factor
ymin = y - (y - ymin)*scale_factor
ymax = y + (ymax - y)*scale_factor
print(f"xmin: {xmin}, xmax: {xmax}, ymin: {ymin}, ymax: {ymax}")
update_plot(xmin, xmax, ymin, ymax)
fig.canvas.mpl_connect('scroll_event', on_scroll)
plt.show()

Your issue is that
imshowby default plots withorigin='upper'(https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.imshow.html#matplotlib.axes.Axes.imshow) meaning Y axis is reversed, breaking your boundary computation downstream, useand it will solve your problems.
Also not sure if this was on purpose from your side, but this bondary update rules seem to make more sense?