Skip to content

Simple PyQt GUI that shows beautiful Mandelbrot and Julia fractals, allowing user to explore them interactively. And scripts for animation!

License

Notifications You must be signed in to change notification settings

AndreyTavleev/mandelbrot-julia-sets-viewer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

74 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Mandelbrot & Julia Sets Viewer

Just another one simple PyQt (PySide6) GUI that shows beautiful Mandelbrot and Julia fractals, allowing the user to explore them interactively. The user can zoom into different parts of the fractals, adjust calculation parameters, customise colours, and save the generated images.

Features:

  • Interactive visualisation of Mandelbrot and Julia sets
  • Support for arbitrary powers $k$ (from 2 to 8) in defining the sets
  • Zooming and panning for detailed exploration
  • Customisable calculation parameters
  • Various colourmaps, including user-defined ones
  • Shading options for enhanced visuals
  • Export images to common formats
  • Scripts for creating the zoom and rotation animations

Contents

Installation

This Application requires Pyside 6.5+ and Python 3.11+. The easiest way is to create the virtual environment and run the code through it:

python3 -m venv fractal
source fractal/bin/activate

Then update pip, install all the required packages, and run the code:

pip3 install -r requirements.txt
python3 Interface.py

Theory of Mandelbrot and Julia fractals

Both Mandelbrot and Julia sets are defined in the complex plane $\mathbb{C}: z = x + iy$ and are based on the iterative sequence:

$$z_{n+1} = z_n^k + c.$$

For the Mandelbrot set, the sequence starts with $z_0 = 0$ and $c = z$. For the Julia set, $z_0 = z$, and $c = x_c + iy_c$ is a constant chosen by the user. The most common exponent is $k=2$, but the user can choose any integer power from $2$ to $8$.

If, for a given value of $z$ (and $c$ in the case of the Julia set), the sequence does not diverge, then $z$ is considered to belong to the set. For a more detailed description, see Wikipedia and Wikipedia.

Strictly speaking, from a mathematical perspective, images of the Mandelbrot and Julia sets should be black-and-white β€” the given point either belongs to the set or it does not. To add colour, a common approach is used: points near the outer boundary of the set are coloured based on the number of iterations required to determine that the point does not belong to the set (i.e. when the divergence criterion $z_n^2>\rm horizon$ is met). The threshold value ${\rm horizon}\geq4$ can be set by the user. For a given number $z$ (and $c$ in the case of a Julia set), the sequence is iterated until the divergence criterion is met. The function then returns:

$${\rm iter} + 1 - \log_k \left(\frac{\ln(z_n^2)}{\ln({\rm horizon})}\right),$$

Where ${\rm iter}$ is the iteration number at which the divergence criterion is satisfied. If the criterion is never met, the function returns $0$. This method results in smooth colour transitions. The maximum number of iterations, $N$, is also a parameter and can be set by the user. The deeper the zoom into the set, the larger the value of $N$ required.

Setting the limits and exploring

The application allows the user to interactively explore different regions of the Mandelbrot and Julia sets by adjusting the limits of the complex plane.

Zooming and Navigation

  • Use mouse selection to zoom into a rectangular region of interest within the fractal display. Click the πŸ” button on the matplotlib toolbar under the image and drag over the fractal image to define the zoom area.
  • The new region will be recalculated and rendered based on the current or default parameters (horizon, $N$, power, $C$, see below).
  • Use the Zoom buttons to zoom-in or zoom-out twice.
  • The Matplotlib toolbar also includes the Pan/Move, 🏠 (return to the initial view), ⬅️, and ➑️ (navigate to the previous/next view) buttons for moving around the image.
  • Zooming deeper into the set reveals more intricate structures. As a result, a higher iteration limit $N$ may be required for finer detail. By default, this limit depends on the zoom level β€” the deeper the zoom, the larger the $N$ value.

Manual Limit Configuration

For precise control, you can set the complex plane limits manually:

  1. Click the Set new limits button to open the limit configuration dialogue.
  2. Enter the desired bounds:
    • Xmin, Xmax and Ymin, Ymax β€” the desired X- and Y-bounds, or
    • XCentre, YCentre, deltaX and deltaY β€” coordinates of the centre and the width of the X- and Y-axis.
  3. Confirm the values to apply them to the view.

The current X- and Y-limits, as well as the coordinates of the centre, are displayed above the Zoom buttons. Use the Reset limits button to restore the default view range. It varies depending on the set type and power.

Adjustable parameters

The GUI provides several options that the user can customise:

  • Set type β€” Choose between Mandelbrot and Julia sets.
  • Power β€” Degree of the polynomial $k$ ($2 \leq k \leq 8$). Mandelbrot sets shift when the power is changed, so use the Reset limits button to re-centre the set.
  • Horizon β€” Divergence threshold $\geq4$. Very large for Mandelbrot ($\sim 2\cdot 10^{50}$), but small for Julia ($\sim 4$).
  • $N$ β€” Iteration limit β€” The maximum number of iterations per point. The deeper you zoom into the set, the larger the value of $N$ required. This value can be:
    • Entered manually
    • Adjusted via the N-slider
    • Reset to default using the Reset N button. The default value of $N$ depends on the zoom level as $N=100\cdot(1 + \lg({\rm zoom}))$.

To generate an image with the desired Horizon and N, enter the values and click the Rebuild button. To restore the default values, click the Reset button.

  • $C$ β€” Complex constant for Julia set. This can be set in two ways:
    • By adjusting the C-sliders to modify either the real and imaginary parts of $C = x_c + i y_c$, or the modulus $\rho$ and argument $\varphi$: $C=\rho e^{i\varphi}$. The relevant option β€” ReC, ImC or $\rho$, $\varphi$ β€” is selected via the corresponding dropdown menu.
    • Clicking the set C button, which allows input via:
      • Real and imaginary parts, or
      • Modulus and argument.

The current value of $C$ is displayed above the C-sliders. To return to the default value $C = -0.8 - 0.156i$, click the Reset C button.

Colours and Shading

The application offers customisable colour schemes and shading effects to enhance the visualisation of the Mandelbrot and Julia sets:

Colourmaps

Choose from a wide range of matplotlib colour palettes via the dropdown menu. Each option displays a preview of the colour gradient.

  • User-defined colourmaps: By selecting the Set your own colourmap... option from the dropdown menu, you can create your own colourmap by placing colour points along the gradient. You can also save the created colourmap to a file and load previously saved colourmaps to edit or use them.

Colouring regimes

There are two colouring techniques available in the Regime dropdown menu:

  • Standard: Applies linear colour scaling, mapping the lowest data value to 0 and the highest to 1.
  • Sin: Transforms the data using the formula $\sin^2(\omega \cdot \text{data} + \Delta)$, where the frequency $\omega$ (default: $0.01$) and the offset $\Delta$ (default: $0.0$) can be set by the user. This allows for cyclic colour variation.

Shading

Click Set shading to apply hillshading effects. In the configuration dialogue adjust:

  • The light source’s azimuth and altitude. Angles are in degrees, with the azimuth measured clockwise from north and elevation up from the zero plane of the surface.
  • The vertical exaggeration for 3D-like depth. This is the amount to exaggerate the elevation values by when calculating illumination.

For details see the matplotlib documentation and tutorials. To revert to the flat colourmap display, click the Remove shading button.

Saving and loading

Save / Load dropdown menu allows you to save images, as well as to save and load metadata.

Generated images can be exported in multiple formats for high-quality output by choosing the Save image option or clicking the πŸ’Ύ icon on the matplotlib toolbar under the image:

  • Supported Formats: PNG, JPEG, TIFF, PDF, and EPS.
  • Customisation: Specify dimensions (in inches) to control resolution and file size. Enable Lock Aspect Ratio to maintain the current proportions when adjusting the width or height. Toggle With Axes to retain coordinate labels and ticks. In that case, you can also set the dots per inches (DPI) of the image, which will affect the size of the axes β€” see here for a discussion on DPI. The image renders at the specified resolution, preserving shading and colourmap preferences.
  • Antialiasing: You can also enable antialiasing by setting the supersampling antialiasing (SSAA) factor. If this factor is equal to one, no antialiasing is applied. Otherwise, the image is rendered at a higher resolution (scaled by this factor along each axis) and then downsampled by averaging the pixels to reduce aliasing. For more details, see Wikipedia. Note that antialiasing could affect the image colours.

Metadata refers to a JSON file that contains all the information about the generated fractal β€” set type, calculation parameters, axis limits, and colouring/shading options. By selecting the Save metadata option, you can save the current fractal for quick access in the future. To load a previously saved fractal, choose the Load metadata option.

Animations

Zooming

The script zoom_animation.py generates a smooth zoom animation of a fractal β€” either the Mandelbrot set or a Julia set. It supports many customisation options, which are described via the --help flag:

python3 zoom_animation.py --help
usage: zoom_animation.py [-h] [--metadata METADATA] [--x_centre_1 X_CENTRE_1]
                         [--y_centre_1 Y_CENTRE_1] [--delta_x_1 DELTA_X_1]
                         [--delta_y_1 DELTA_Y_1] [--x_centre_2 X_CENTRE_2]
                         [--y_centre_2 Y_CENTRE_2] [--delta_x_2 DELTA_X_2]
                         [--delta_y_2 DELTA_Y_2] [--x_c X_C] [--y_c Y_C]
                         [-m mandelbrot|julia|burning_ship|burning_ship_julia]
                         [-p {2,3,4,5,6,7,8}] [--n_regime dynamic|static]
                         [--n_i N_I] [--n_f N_F] [-H HORIZON] [-f FRAMES]
                         [-l LENGTH] [-hei HEIGHT] [-c COLOURMAP]
                         [--c_regime standard|sin] [-fr FREQ] [-of OFFSET] [-s]
                         [-az AZDEG] [-al ALTDEG] [-ve VERT_EXAG] [-t THREADS]
                         [-ss SUPERSAMPLING]
...description...

The primary input parameters are the coordinates of the centres of the initial and final fractals, along with the widths of the X- and Y-axes for both views. Alternatively, you may provide a previously saved metadata.json file to set the final fractal's coordinates and other calculation and colouring options. You can also use a previously saved colourmap.json file to set the custom colourmap.

Another important parameter is the maximum number of iterations, $N$, for the initial and final fractals. There are two modes available:

  • Static β€” $N$ remains constant across all animation frames. It can be specified using the --n_f flag. If metadata is provided, the number of iterations will be taken from there.
  • Dynamic β€” $N$ changes dynamically from n_i to n_f, following the $n = n_i\cdot(1 + \alpha\lg({\rm zoom}))$ formula, where $\alpha$ is determined from n_i (default: 100) and n_f. If metadata is provided, the n_f parameter will be taken from there.

Note: The aspect ratios of the initial and final frames should match. You can ensure this by adjusting the axis widths and the image's length and height accordingly. If the aspect ratios differ, the script will suggest possible corrections, but can still generate a video using the current aspect ratio.

Below is an example video created with the default values for all flags:

python3 zoom_animation.py

The video has been compressed for README:

video.mp4

Another example is created from this metadata, using the following flags:

python3 zoom_animation.py --metadata Metadata_11.json --length 1500

The video has been compressed for README:

output_reduce.mp4

Rotation

The script rotate_animation.py generates a smooth rotational animation of a Julia set, in which the angle (argument $\varphi$) of the complex parameter $C=\rho e^{\varphi}$ varies over time, tracing a circular path in the complex plane. The result is a visually striking transformation of the Julia set as it rotates through the parameter space. It supports many customisation options, which are described via the --help flag:

python3 rotate_animation.py --help
usage: rotate_animation.py [-h] [--metadata METADATA] [--xmin XMIN]
                           [--xmax XMAX] [--ymin YMIN] [--ymax YMAX]
                           [--rho RHO] [--phi_min PHI_MIN] [--phi_max PHI_MAX]
                           [-m julia|burning_ship_julia] [--n N]
                           [-p {2,3,4,5,6,7,8}] [-H HORIZON] [-f FRAMES]
                           [-l LENGTH] [-hei HEIGHT] [-c COLOURMAP]
                           [--c_regime standard|sin] [-fr FREQ] [-of OFFSET]
                           [-s] [-az AZDEG] [-al ALTDEG] [-ve VERT_EXAG]
                           [-t THREADS] [-ss SUPERSAMPLING]
...description...

The primary input parameters are the bounds of the X- and Y-axes, the modulus $\rho$ of the Julia set C-parameter, and the minimum and maximum values of the argument $\varphi$. Alternatively, you may provide a previously saved metadata.json file to set the fractal's coordinates and other calculation and colouring options. You can also use a previously saved colourmap.json file to set the custom colourmap.

Note: The aspect ratio of the axes and image size should match. You can ensure this by adjusting the axis widths and the image's length and height accordingly. If the aspect ratios differ, the script will suggest possible corrections, but can still generate a video using the current aspect ratio.

Below is an example video created using the following flag:

python3 rotate_animation.py --power 3 --xmin -1.5 --xmax 1.5 --ymin -1.5 --ymax 1.5

The video has been compressed for README:

video.mp4

Gallery

Overall, have fun! Some screenshots with corresponding metadata:

First: Second: Third: Sin colourisation results in beautifully cycling colours. The parameter $\omega$ controls how frequently the colours cycle, while the offset $\Delta$ shifts the colour gradient (Metadata): Fifth: Shading option (vert_exag=3.0) with custom colourmap (Metadata): Seventh: Sin colourisation and shading (vert_exag=100.0, Metadata):

About

Simple PyQt GUI that shows beautiful Mandelbrot and Julia fractals, allowing user to explore them interactively. And scripts for animation!

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages