diff --git a/README.md b/README.md index da29e14..f60e504 100644 --- a/README.md +++ b/README.md @@ -106,10 +106,9 @@ plt.savefig("example_images/lyapunov_ex.png") Image produced with this code: ```python -basis = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) -moves = pf.construct_moves(basis) -res = pf.randomwalk(moves, niter=5000000, width=4, height=3, depth=10, dpi=300) -pf.images.randomwalk_image(res, cmap=colormaps["gist_yarg"], gamma=1.0) +moves = pf.construct_moves((1, 0), (0, 1)) +res = pf.randomwalk(moves, niter=1000000, width=4, height=3, dpi=300) +pf.images.image(res, cmap=colormaps["gnuplot"], gamma=1.0) plt.savefig("example_images/randomwalk_ex.png") ``` @@ -140,13 +139,12 @@ plt.savefig("example_images/buddhabrot_ex.png") * Julia * Buddhabrot * Markus-Lyapunov -* 3D random walks +* 2D random walks ## Image Creation * Function `image` wrapping `matplotlib.pyplot.imshow` * Function `nebula_image` for Buddhabrot ["nebula"](https://en.wikipedia.org/wiki/Buddhabrot#Nuances) coloration * Function `markus_lyapunov_image` for [Markus-Lyapunov](https://doi.org/10.1016/0097-8493(89)90019-8) coloration -* Function `randomwalk_image` for coloring 3D random walks with depth * Function `save_animation` for animating a sequence of results ## More than Quadratic Polynomials diff --git a/example_images/randomwalk_ex.png b/example_images/randomwalk_ex.png index f42ff1f..b2c5820 100644 Binary files a/example_images/randomwalk_ex.png and b/example_images/randomwalk_ex.png differ diff --git a/examples.py b/examples.py index 74cd7c9..8dfac55 100644 --- a/examples.py +++ b/examples.py @@ -103,10 +103,8 @@ def lyapunov_example() -> None: def randomwalk_example() -> None: start_time = time.time() - basis = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) - moves = pf.construct_moves(basis) - res = pf.randomwalk(moves, niter=5000000, width=4, height=3, depth=10, dpi=300) - pf.images.randomwalk_image(res, cmap=colormaps["gist_yarg"], gamma=1.0) + res = pf.randomwalk(niter=1000000, width=4, height=3, dpi=300) + pf.images.image(res, cmap=colormaps["gnuplot"], gamma=1.0) plt.savefig("example_images/randomwalk_ex.png") print(f"calculation took {round((time.time() - start_time), 2)} seconds") diff --git a/pyfracgen/__init__.py b/pyfracgen/__init__.py index d947113..e209639 100644 --- a/pyfracgen/__init__.py +++ b/pyfracgen/__init__.py @@ -5,7 +5,7 @@ from .julia import julia from .lyapunov import lyapunov from .mandelbrot import mandelbrot -from .randomwalk import construct_moves, randomwalk +from .randomwalk import randomwalk __all__ = [ "buddhabrot", @@ -15,7 +15,6 @@ "lyapunov", "mandelbrot", "randomwalk", - "construct_moves", "Result", "Canvas", "funcs", diff --git a/pyfracgen/common.py b/pyfracgen/common.py index 7857708..f855fe5 100644 --- a/pyfracgen/common.py +++ b/pyfracgen/common.py @@ -9,7 +9,7 @@ import numpy as np -from pyfracgen.types import Bound, Lattice, Lattice3D +from pyfracgen.types import Bound, Lattice RESULT_DEFAULT_SAVE = Path("save.pickle") @@ -48,14 +48,6 @@ def paint(self, *args: Any, **kwargs: Any) -> None: raise NotImplementedError -class Canvas3D(Canvas): - def __init__(self, width: int, height: int, depth: int, dpi: int) -> None: - super().__init__(width, height, dpi) - self.lattice: Lattice3D = np.dstack( - [np.zeros(self.lattice.shape) for _ in range(depth)] - ) - - class CanvasBounded(Canvas): def __init__( self, width: int, height: int, dpi: int, xbound: Bound, ybound: Bound diff --git a/pyfracgen/images/images.py b/pyfracgen/images/images.py index c1aa36a..bc04217 100644 --- a/pyfracgen/images/images.py +++ b/pyfracgen/images/images.py @@ -96,31 +96,6 @@ def markus_lyapunov_image( return fig, ax0 -def randomwalk_image( - res: Result, - cmap: colors.Colormap = DEFAULT_COLORMAP, - ticks: bool = False, - gamma: float = 0.3, - alpha_scale: float = 1.0, -) -> tuple[Figure, Axes]: - fig, ax0 = plt.subplots(figsize=figaspect(res.image_array[:, :, 0]), dpi=res.dpi) - fig.subplots_adjust(0, 0, 1, 1) - max_ind = float(res.image_array.shape[-1] + 1) - for i in range(res.image_array.shape[-1]): - im = res.image_array[..., i] - im = np.ma.masked_where(im == 0, im) # type: ignore[no-untyped-call] - alpha = alpha_scale * (1 - (i + 1) / max_ind) - norm = colors.PowerNorm(gamma) - ax0.imshow( - im, origin="lower", alpha=alpha, cmap=cmap, norm=norm, interpolation=None - ) - if not ticks: - plt.axis(ticks) - fs = plt.gcf() - fs.set_size_inches(res.width_inches, res.height_inches) - return fig, ax0 - - def save_animation( series: Sequence[Result], cmap: colors.Colormap = DEFAULT_COLORMAP, diff --git a/pyfracgen/randomwalk.py b/pyfracgen/randomwalk.py index b01b8b4..f3b560d 100644 --- a/pyfracgen/randomwalk.py +++ b/pyfracgen/randomwalk.py @@ -5,50 +5,39 @@ from numpy import array from numpy.random import randint -from pyfracgen.common import Canvas3D, Result -from pyfracgen.types import Lattice3D, Moves3D - - -def construct_moves(basis: Moves3D) -> Moves3D: - basis = np.r_[basis, -1 * basis, [array([0, 0, 0])]] - nonnull = list( - filter(lambda x: np.any(x), (b0 + b1 for b0, b1 in itt.combinations(basis, 2))) - ) - moves: Moves3D = np.unique(nonnull, axis=0) - return moves +from pyfracgen.common import Result, Canvas +from pyfracgen.types import Moves, Lattice @jit(nopython=True) # type: ignore[misc] def _randomwalk_paint( - lattice: Lattice3D, - moves: Moves3D, + lattice: Lattice, + moves: Moves, niter: int, ) -> None: nmoves = len(moves) - h, w, d = lattice.shape - indices = array([h, w, d]) / 2.0 + h, w = lattice.shape + indices = array([h, w]) / 2.0 for iteration in range(niter): move = moves[randint(0, nmoves)] indices += move - iy, ix, iz = int(indices[0] % h), int(indices[1] % w), int(indices[2] % d) - lattice[iy, ix, iz] = iteration + iy, ix = int(indices[0] % h), int(indices[1] % w) + lattice[iy, ix] = iteration - lattice /= np.amax(lattice) +class RandomWalk(Canvas): + moves = np.array(list(itt.product([1, -1, 0], [1, -1, 0]))) -class RandomWalk(Canvas3D): - def paint(self, moves: Moves3D, niter: int) -> None: - _randomwalk_paint(self.lattice, moves, niter) + def paint(self, niter: int) -> None: + _randomwalk_paint(self.lattice, self.moves, niter) def randomwalk( - moves: Moves3D, niter: int, width: int = 5, height: int = 4, - depth: int = 1, dpi: int = 300, ) -> Result: - canvas = RandomWalk(width, height, depth, dpi) - canvas.paint(moves, niter) + canvas = RandomWalk(width, height, dpi) + canvas.paint(niter) return canvas.result diff --git a/pyfracgen/types.py b/pyfracgen/types.py index a9f52ea..e87c5dd 100644 --- a/pyfracgen/types.py +++ b/pyfracgen/types.py @@ -7,8 +7,7 @@ Depth = NewType("Depth", int) Lattice = NDArray[Shape["Height, Width"], Float64] -Lattice3D = NDArray[Shape["Height, Width, Depth"], Float64] -Moves3D = NDArray[Shape["*, 3"], Int64] +Moves = NDArray[Shape["*, 2"], Int64] Boxes = NDArray[Shape["*, 2"], Float64] ComplexSequence = NDArray[Shape["*"], Complex128]