DrGabrielLopez commited on
Commit
25c6e35
·
1 Parent(s): ff892bd
Files changed (1) hide show
  1. fractal_generator.py +82 -0
fractal_generator.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+
3
+ import matplotlib.pyplot as plt
4
+ import numpy as np
5
+ import os
6
+ from enum import Enum
7
+
8
+
9
+ class FractalType(Enum):
10
+ Julia = 1
11
+ Mandelbrot = 2
12
+
13
+
14
+ class FractalGenerator:
15
+ """ Creates a single fractal object and either returns it as as a numpy array, plot it or persists it as an pgn
16
+ image. The output of this class is used by FractalTrainingValidationSet to generate training/val sets
17
+ Args:
18
+ complex_function -- complex function to make a Julia fractal
19
+ n -- fractal size will ne n*n
20
+ xlim,ylim -- tuples with the plotting region on the complex plane
21
+ thr -- once a function grows larger that this number is considered to be divergent to infinity
22
+ max_iter -- number of compositions of the complex function with itself
23
+ type_ -- fractal type
24
+ fractal -- numpy array with the fractal
25
+ """
26
+
27
+ def __init__(self, n=256, xlim=(-2, 2), ylim=(-2, 2), thr=2, max_iter=10):
28
+ self.type_ = None
29
+ self.fractal = None
30
+ self.n = n
31
+ self.xlim = xlim
32
+ self.ylim = ylim
33
+ self.thr = thr
34
+ self.max_iter = max_iter
35
+
36
+ def create_julia(self, complex_function=lambda z: np.sin(z ** 4 + 1.41)):
37
+ """ Creates a fractal of the Julia family, the fractal is stored inside self.fractal """
38
+ fractal = np.zeros((self.n, self.n), dtype='complex')
39
+ x_space = np.linspace(self.xlim[0], self.xlim[1], self.n)
40
+ y_space = np.linspace(self.ylim[0], self.ylim[1], self.n)
41
+ for ix, x in enumerate(x_space):
42
+ for iy, y in enumerate(y_space):
43
+ for i in range(self.max_iter):
44
+ if i == 0: z = complex(x, y)
45
+ z = complex_function(z)
46
+ if np.abs(z) >= self.thr: z = self.thr; break
47
+ fractal[ix, iy] = z
48
+ self.fractal = np.abs(fractal)
49
+ self.type_ = FractalType.Julia
50
+ return self
51
+
52
+ def create_mandelbrot(self):
53
+ """ Creates a fractal of the Mandelbrot family, the fractal is stored inside self.fractal """
54
+ fractal = np.zeros((self.n, self.n), dtype='complex')
55
+ x_space = np.linspace(self.xlim[0], self.xlim[1], self.n)
56
+ y_space = np.linspace(self.ylim[0], self.ylim[1], self.n)
57
+ for ix, x in enumerate(x_space):
58
+ for iy, y in enumerate(y_space):
59
+ for i in range(self.max_iter):
60
+ if i == 0: z = 0
61
+ z = z ** 2 + complex(x, y)
62
+ if np.abs(z) >= self.thr: z = self.thr; break
63
+ fractal[ix, iy] = z
64
+ self.fractal = np.abs(fractal.transpose())
65
+ self.type_ = FractalType.Mandelbrot
66
+ return self
67
+
68
+ def plot(self, clim=None, **kwargs):
69
+ if self.fractal is None:
70
+ print('Nothing to plot. Generate a fractal first.')
71
+ return None
72
+ plt.matshow(self.fractal, **kwargs)
73
+ plt.gca().axes.get_xaxis().set_visible(False)
74
+ plt.gca().axes.get_yaxis().set_visible(False)
75
+ plt.clim(clim)
76
+ return plt.gcf()
77
+
78
+ def persist_plot(self, filename, container, clim=None, **kwargs):
79
+ if not os.path.isdir(container): os.mkdir(container)
80
+ self.plot(clim=clim, **kwargs)
81
+ plt.savefig(str(Path(container) / filename), png='png', dpi=None)
82
+ plt.close(plt.gcf())