The so-called Julia set is a wonderful pattern similar to the one below
Julia Collection
In particular, when c = an initial value of z, the set of z's that satisfy the convergence condition constitute the famous Mandelbrot set
In the above figure, the color indicates the rate of divergence of the point, which can be interpreted as the number of iterations at the beginning of the divergence. The code for its generation is also very simple:
# import numpy as np import time import as plt # Generate z-coordinate, axis is the starting position, nx, ny is the number of grid points in x- and y-directions def genZ(axis,nx,ny): x0,x1,y0,y1 = axis x = (x0,x1,nx) y = (y0,y1,ny) real, img = (x,y) z = real + img*1j return z # Get Julia set, n is the number of iterations, m is the judgment dispersion point, greater than 1 can be def getJulia(z,c,n,m=2): t = () c = np.zeros_like(z)+c out = abs(z) for i in range(n): absz = abs(z) z[absz>m]=0 # Set zero to the point where the divergence begins c[absz>m]=0 out[absz>m]=i # Record the rate of dispersion of the dispersion point z = z*z + c print("time:",()-t) return out if __name__ == "__main__": axis = ([-2,1,-1.5,1.5]) z0 = genZ(axis,500,500) mBrot = getJulia(z0,z0,50) (mBrot, cmap=, extent=axis) ().set_axis_off() ()
matplotlib binding events
In the following, we would like to realize that clicking on a point in the Mandelbrot set generates the corresponding Julia set.
In mpl, the event binding function mpl_connect is encapsulated in theCavnas classin which the call is formatted as
canvas.mpl_connect('str', func)
where func event function, the string is passed into the event function of the event identification, as listed below, look at the meaning of the word can be
'button_press_event' 'button_release_event' 'draw_event' 'key_press_event' 'key_release_event' 'motion_notify_event' 'pick_event' 'resize_event' 'scroll_event' 'figure_enter_event' 'figure_leave_event' 'axes_enter_event' 'axes_leave_event' 'close_event'
For simplicity, we can start by detecting the mouse click event 'button_press_event', for which we need to define an event function with a slight modification of the entry function above:
def test(evt): print() #xdata i.e. x-direction coordinates if __name__ == "__main__": axis = ([-2,1,-1.5,1.5]) z0 = genZ(axis,500,500) mBrot = getJulia(z0,z0,50) fig, ax = () .mpl_connect('button_press_event', test)# Call event functions (mBrot, cmap=, extent=axis) ().set_axis_off() ()
So clicking on the image that comes out of imshow() returns the corresponding x-coordinate.
python time: 0.47572827339172363 -0.8652597402597402 -0.7840909090909087 -0.18344155844155807 0.23051948051948123 0.8149350649350655
resizing
Then generating the Julia set only requires a single re-call togetJulia
This function is sufficient.
The fractal character of the Mandelbrot set means that the images we generate can be zoomed in infinitely, but the zoom tool that comes with mpl doesn't regenerate the data, so it's a spurious zoom. So we need to rebind the zoom operation, the idea is to record the coordinates at this point when the right button is clicked ('button_press_event'), and redraw the picture when the right button is released ('button_release_event') is put, in order to prevent conflict with the left button, so in the In order to prevent conflict with the left button, we add the left and right button judgment in the event function corresponding to the click.
The result is shown in Figure
In addition, the mouse wheel can be bound to achieve true scaling of the Mandelbrot set at that point, with the following code
import as plt import numpy as np from matplotlib import cm import matplotlib.backend_bases as mbb import time class MandelBrot(): def __init__(self,x0,x1,y0,y1,n): = ([x0,x1,y0,y1]) # Initial coordinates = ,, = n,n,n # of grid divisions in the x,y direction = 100 # of iterations self.n0 = 0 # of pre-iterations = genZ(,,) () def DrawMandelbrot(self): mBrot = getJulia(,,) , ax = () (mBrot, cmap=, extent=) ().set_axis_off() .mpl_disconnect(.key_press_handler_id) .mpl_connect('button_press_event', ) .mpl_connect('button_release_event', ) .mpl_connect('scroll_event', ) () def DrawJulia(self,c0): z = genZ([-2,2,-2,2],800,800) julia = getJulia(z,c0,) jFig,jAx = () () (julia, cmap=, extent=) ().set_axis_off() () .draw_idle() # Scroll wheel zoom def OnScroll(self,evt): x0,y0 = , if == "up": = (+[x0,x0,y0,y0])/2 elif == 'down': = 2*-[x0,x0,y0,y0] z = genZ(,,) mBrot = getJulia(z,z,) () (mBrot, cmap=, extent=) ().set_axis_off() mBrot[mBrot<1]==self.n0+ self.n0 = int((mBrot)) .draw_idle() pass def OnMouse(self, evt): = = .draw_idle() def OnRelease(self,evt): x0,y0,x1,y1 = ,,, if == : (x1+y1*1j) # If the release was a left click, then draw the Julia set and return the return #Right-click and drag to zoom in realistically on the Mandelbrot set = ([min(x0,x1),max(x0,x1), min(y0,y1),max(y0,y1)]) nxny = [[1,3]]-[[0,2]] , = (nxny/max(nxny)*).astype(int) z = genZ(,,) n = 100 #n is the number of iterations mBrot = getJulia(z,z,n) () (mBrot, cmap=, extent=) ().set_axis_off() mBrot[mBrot<1]==self.n0+n self.n0 = int((mBrot)) .draw_idle() def genZ(axis,nx,ny): x0,x1,y0,y1 = axis x = (x0,x1,nx) y = (y0,y1,ny) real, img = (x,y) z = real + img*1j return z def getJulia(z,c,n,n0=0,m=2): t = () c = np.zeros_like(z)+c out = abs(z) for _ in range(n0): z = z*z + c for i in range(n0,n0+n): absz = abs(z) z[absz>m]=0 c[absz>m]=0 out[absz>m]=i z = z*z + c print("time:",()-t) return out if __name__ == "__main__": x,y = 0,0 brot = MandelBrot(-2,1,-1.5,1.5,1000)
The above is python programming matplotlib interactive plotting Julia set sample analysis of the details, more information about matplotlib interactive plotting Julia set please pay attention to my other related articles!