summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrett Weiland <brett_weiland@gmail.com>2024-06-11 14:50:14 -0500
committerBrett Weiland <brett_weiland@gmail.com>2024-06-11 14:50:14 -0500
commitcb69732f68c0bd46c1574de16ce1aee6f38e439b (patch)
treedef1daaec81a0d4cd7b3d44b2c26b9535e07579c
restartingHEADmaster
-rw-r--r--.gitignore3
-rw-r--r--README1
-rw-r--r--animation/asdf.pngbin0 -> 1051370 bytes
-rwxr-xr-xanimation/gpu_migration.py146
-rw-r--r--animation/kernel.c30
-rw-r--r--animation/notes79
-rw-r--r--backup62
-rw-r--r--collective/.gpu_migration.py.swobin0 -> 20480 bytes
-rw-r--r--collective/.gpu_migration.py.swpbin0 -> 16384 bytes
-rw-r--r--collective/.kernel.c.swpbin0 -> 12288 bytes
-rwxr-xr-xcollective/gpu_migration.py165
-rw-r--r--collective/kernel.c116
l---------collective/mask.png1
-rw-r--r--collective/notes79
-rw-r--r--collective/out.pngbin0 -> 3981166 bytes
-rw-r--r--collective/out_grad.pngbin0 -> 3387948 bytes
-rw-r--r--collective/out_texture.pngbin0 -> 1907188 bytes
-rw-r--r--collective/texput.log21
-rw-r--r--cool_places6
-rw-r--r--field_tests/backup62
-rw-r--r--field_tests/basic_field_test.py168
-rwxr-xr-xfield_tests/field.py191
-rwxr-xr-xfield_tests/gpu_migration.py137
-rw-r--r--field_tests/kernel.c26
-rw-r--r--field_tests/makefile4
-rwxr-xr-xlinear_transform_test.py63
-rw-r--r--live_play/.gpu_migration.py.swobin0 -> 20480 bytes
-rw-r--r--live_play/.gpu_migration.py.swpbin0 -> 16384 bytes
-rw-r--r--live_play/.kernel.c.swpbin0 -> 12288 bytes
-rwxr-xr-xlive_play/gpu_migration.py154
-rw-r--r--live_play/kernel.c40
l---------live_play/mask.png1
-rw-r--r--live_play/notes79
-rw-r--r--mask_tests/;30
-rw-r--r--mask_tests/asdf.pngbin0 -> 1073534 bytes
-rw-r--r--mask_tests/kernel.c49
l---------mask_tests/mask.png1
-rwxr-xr-xmask_tests/mask.py153
-rw-r--r--mask_tests/mask.py.bak142
-rw-r--r--mask_tests/notes79
-rw-r--r--masks/clouds.pngbin0 -> 105871 bytes
-rw-r--r--masks/hi.pngbin0 -> 77000 bytes
-rw-r--r--masks/test_circle.pngbin0 -> 403275 bytes
-rw-r--r--masks/test_circle_linear_smooth.pngbin0 -> 443833 bytes
-rw-r--r--masks/test_circle_perceptual_smooth.pngbin0 -> 462280 bytes
-rw-r--r--masks/test_diagnol.pngbin0 -> 333665 bytes
-rw-r--r--masks/test_diagnol_linear_smooth.pngbin0 -> 586437 bytes
-rw-r--r--masks/test_diagnol_perceptual_smooth.pngbin0 -> 581351 bytes
-rw-r--r--masks/threedots.pngbin0 -> 182294 bytes
-rw-r--r--photos_incorrectly_named/cosine_gpu_double_2.pngbin0 -> 3992585 bytes
-rw-r--r--photos_incorrectly_named/cpu.pngbin0 -> 3968276 bytes
-rw-r--r--photos_incorrectly_named/ice_period_16.pngbin0 -> 1128935 bytes
-rw-r--r--photos_incorrectly_named/ice_period_16_shifted_.25.pngbin0 -> 1135767 bytes
-rw-r--r--photos_incorrectly_named/ice_period_16_shifted_.5.pngbin0 -> 1133084 bytes
-rw-r--r--photos_incorrectly_named/ice_period_noshift_x_1.pngbin0 -> 1125856 bytes
-rw-r--r--photos_incorrectly_named/linear_transform_sin_tan_arnolds_tongue_hotspot.pngbin0 -> 288187 bytes
-rw-r--r--polar/.gpu_migration.py.swobin0 -> 20480 bytes
-rw-r--r--polar/.gpu_migration.py.swpbin0 -> 16384 bytes
-rw-r--r--polar/.kernel.c.swpbin0 -> 12288 bytes
-rwxr-xr-xpolar/gpu_migration.py157
-rw-r--r--polar/kernel.c35
-rw-r--r--polar/notes79
-rw-r--r--polar/texput.log21
-rwxr-xr-xthorn_fractal.py55
64 files changed, 2435 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2bde90c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+#*.png
+*.mkv
+*.mp4
diff --git a/README b/README
new file mode 100644
index 0000000..c543a10
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+I will organize and collect this code all into one project some time!
diff --git a/animation/asdf.png b/animation/asdf.png
new file mode 100644
index 0000000..bbb1747
--- /dev/null
+++ b/animation/asdf.png
Binary files differ
diff --git a/animation/gpu_migration.py b/animation/gpu_migration.py
new file mode 100755
index 0000000..bbf718a
--- /dev/null
+++ b/animation/gpu_migration.py
@@ -0,0 +1,146 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.animation as animation
+import pyopencl as cl
+from alive_progress import alive_bar
+from matplotlib.backend_bases import MouseButton
+
+img_res_x = 1000
+img_res_y = 1000
+total_pixels = img_res_x * img_res_y # so we don't gotta compute it every time
+
+periods = 1
+square_x = 0
+square_y = 0
+
+x_min = (-periods * np.pi) + (square_x * np.pi)
+x_max = (periods * np.pi) + (square_x * np.pi)
+y_min = (-periods * np.pi) + (square_y * np.pi)
+y_max = (periods * np.pi) + (square_y * np.pi)
+
+escape = 10000
+iterations = 255*3
+c_x = 2 * np.pi
+c_y = 2 * np.pi
+
+animation_progres_save = "ani1_less.mp4"
+single_frame_save = "asdf.png"
+
+opencl_context = cl.create_some_context(interactive=False)
+opencl_queue = cl.CommandQueue(opencl_context)
+
+kernel_src_path = "./kernel.c"
+
+frames = 200
+rendered_frames = []
+
+image = np.empty([img_res_x, img_res_y], np.uint32)
+image_buffer = cl.Buffer(opencl_context, cl.mem_flags.WRITE_ONLY, image.nbytes)
+
+plt.style.use('dark_background')
+# fuck this shit
+fig = plt.figure(frameon=False)
+fig.set_size_inches(img_res_x/fig.dpi, img_res_y/fig.dpi)
+#fig.set_size_inches(width/height, 1, forward=False)
+
+
+ax = plt.Axes(fig, [0., 0., 1., 1.])
+#ax.set_axis_off()
+fig.add_axes(ax)
+
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+bruh = None
+
+def on_click(event):
+ global bruh
+ split_ratio = 1
+ if (event.button is MouseButton.MIDDLE) and (event.inaxes):
+ # there's probably a way to set global coordinates;
+ # I don't expect this to go anywhere so I don't really care
+ on_x = ((event.xdata / img_res_x) * abs(x_max - x_min)) + x_min
+ on_y = ((event.ydata / img_res_y) * abs(y_max - y_min)) + y_min
+
+ #I, uh, also don't know the best way to replicate the openCL code automaticly in python
+ #so ajust if nessesary
+ x_hops = []
+ y_hops = []
+ for i in range(iterations):
+ x_hops.append(((on_x - x_min) / abs(x_max - x_min)) * img_res_x)
+ y_hops.append(((on_y - y_min) / abs(y_max - y_min)) * img_res_y)
+ next_x = on_x/np.tan(on_y)
+ on_y = on_y/np.tan(on_x)
+ on_x = next_x
+ if on_x**2 + on_y**2 > escape:
+ break
+ print(y_hops[0])
+ print(on_y)
+ print("{} hops".format(len(x_hops)))
+ if bruh:
+ bruh.pop(0).remove()
+ bruh = ax.plot(x_hops, y_hops)
+ plt.draw()
+
+
+
+ print(on_x, on_y)
+
+
+print("compiling openCL kernel...")
+with open(kernel_src_path, 'r') as kernel_src:
+ compiled_kernel = cl.Program(opencl_context, kernel_src.read()).build()
+
+encoding_progress = alive_bar(frames, bar = 'filling', spinner = 'waves')
+
+def display_encoder_progress(current_frame: int, total_frames: int):
+ print("Encoding: frame {}/{}".format(current_frame, frames))
+
+
+mp_image = None
+
+print("Rendering {} frames...".format(frames))
+plt.show(block=False)
+if frames > 1:
+ with alive_bar(frames, bar = 'filling', spinner = 'waves') as bar_total:
+ for frame_i in range(0, frames):
+ compiled_kernel.render_frame(opencl_queue, image.shape, None, image_buffer,
+ np.double(abs(x_max - x_min) / img_res_x),
+ np.double(abs(y_max - y_min) / img_res_y),
+ np.double(x_min), np.double(y_min),
+ np.uint32(iterations), np.uint32(escape),
+ np.double(frame_i / frames))
+
+
+ cl.enqueue_copy(opencl_queue, image, image_buffer).wait()
+ rendered_frame = ax.imshow(image, norm="log", aspect="auto", cmap=cmap, animated="True", interpolation='none')
+ if frame_i == 0:
+ mp_image = rendered_frame
+ else:
+ pass
+ #mp_image.set_array(image)
+ rendered_frames.append([rendered_frame])
+ bar_total()
+ #fig.canvas.draw()
+ #fig.canvas.flush_events()
+ print("Encoding/Saving...")
+ ani = animation.ArtistAnimation(fig, rendered_frames, interval=30, blit=True)
+ ani.save(animation_progres_save, extra_args=['-preset', 'lossless'], progress_callback=display_encoder_progress, codec="h264_nvenc")
+else:
+ compiled_kernel.render_frame(opencl_queue, image.shape, None, image_buffer,
+ np.double(abs(x_max - x_min) / img_res_x),
+ np.double(abs(y_max - y_min) / img_res_y),
+ np.double(x_min), np.double(y_min),
+ np.uint32(iterations), np.uint32(escape),
+ np.double(1))
+ cl.enqueue_copy(opencl_queue, image, image_buffer).wait()
+ ax.imshow(image, norm="log", aspect="auto", cmap=cmap)
+ fig.savefig(single_frame_save)
+ plt.autoscale(False)
+ plt.connect('motion_notify_event', on_click)
+ plt.show()
+
+
diff --git a/animation/kernel.c b/animation/kernel.c
new file mode 100644
index 0000000..9c99b2b
--- /dev/null
+++ b/animation/kernel.c
@@ -0,0 +1,30 @@
+__kernel void basic_test() {
+ printf("this cores ID: (%lu, %lu)\n", get_global_id(0), get_global_id(1));
+}
+double cosecant_single(double a, double b) { return a / tan(b); }
+double secant_single(double a, double b) { return a / sin(b); }
+
+__kernel void render_frame(__global unsigned int *frame_output,
+ double x_step, double y_step,
+ double x_start, double y_start,
+ unsigned int iterations, unsigned int escape, double r) {
+ unsigned int iter;
+
+ double x_cart = (get_global_id(0) * x_step) + x_start;
+ double y_cart = (get_global_id(1) * y_step) + y_start;
+ size_t img_index = (get_global_id(1) * get_global_size(1)) + get_global_id(0);
+
+
+ double x = sqrt(pow(x_cart, 2) + pow(y_cart, 2));
+ double y = atan(y_cart / x_cart);
+ double next_x;
+
+ for(iter = 0; iter < iterations; iter++) {
+ next_x = (r * cosecant_single(x, y)) + ((1 - r) * secant_single(x, y));
+ y = (r * cosecant_single(y, x)) + ((1 - r) * secant_single(y, x));
+ x = next_x;
+ if((pow(x, 2) + pow(y, 2)) >= escape) break;
+ }
+
+ frame_output[img_index] = iter;
+}
diff --git a/animation/notes b/animation/notes
new file mode 100644
index 0000000..50249d7
--- /dev/null
+++ b/animation/notes
@@ -0,0 +1,79 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.animation as animation
+import pyopencl as cl
+from alive_progress import alive_bar
+
+img_res_x = 2000
+img_res_y = 2000
+total_pixels = img_res_x * img_res_y # so we don't gotta compute it every time
+
+periods = 1
+square_x = 0
+square_y = 0
+
+xmin = (-periods * np.pi) + (square_x * np.pi)
+xmax = (periods * np.pi) + (square_x * np.pi)
+ymin = (-periods * np.pi) + (square_y * np.pi)
+ymax = (periods * np.pi) + (square_y * np.pi)
+
+escape = 10000
+iterations = 255*3
+c_x = 2 * np.pi
+c_y = 2 * np.pi
+
+animation_progres_save = "./animations"
+frames = 120
+
+rendered_frames = []
+
+
+plt.style.use('dark_background')
+# fuck this shit
+fig = plt.figure(frameon=False)
+fig.set_size_inches(img_res_x/fig.dpi, img_res_y/fig.dpi)
+#fig.set_size_inches(width/height, 1, forward=False)
+
+ax = plt.Axes(fig, [0., 0., 1., 1.])
+ax.set_axis_off()
+fig.add_axes(ax)
+
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+opencl_context = cl.create_some_context()
+opencl_queue = cl.CommandQueue(opencl_context)
+
+
+#def render():
+# image = np.empty([img_res_y, img_res_x])
+# print("Rendering frames")
+# with alive_bar(frames, bar = 'filling', spinner = 'waves') as bar_total:
+# for frame in range(frames):
+# split_ratio = frame / frames
+# for pix_y, y in enumerate(np.linspace(ymin, ymax, img_res_y)):
+# for pix_x, x in enumerate(np.linspace(xmin, xmax, img_res_x)):
+# on_x = x
+# on_y = y
+# for i in range(iterations):
+# next_x = (split_ratio * (on_x/np.sin(on_y))) + ((1 - split_ratio) * on_x/np.tan(on_y))
+# on_y = (split_ratio * (on_y/np.sin(on_x))) + ((1 - split_ratio) * on_y/np.tan(on_x))
+# on_x = next_x
+# if on_x**2 + on_y**2 > escape:
+# break
+# image[pix_y][pix_x] = i
+# rendered_frame = ax.imshow(image, norm="log", aspect="auto", cmap=cmap, animated=False)
+# rendered_frames.append([rendered_frame])
+# bar_total()
+
+def display():
+ print(rendered_frames)
+ ani = animation.ArtistAnimation(fig, rendered_frames, interval=30, blit=True)
+ ani.save("test.mp4")
+ plt.show()
+
+render()
+display()
diff --git a/backup b/backup
new file mode 100644
index 0000000..2e60664
--- /dev/null
+++ b/backup
@@ -0,0 +1,62 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+from alive_progress import alive_bar
+
+img_res_x = 1000
+img_res_y = 1000
+total_pixels = img_res_x * img_res_y # so we don't gotta compute it every time
+
+periods = .25
+square_x = 1
+square_y = 1
+
+xmin = (-periods * np.pi) + (square_x * np.pi)
+xmax = (periods * np.pi) + (square_x * np.pi)
+ymin = (-periods * np.pi) + (square_y * np.pi)
+ymax = (periods * np.pi) + (square_y * np.pi)
+
+escape = 10000
+iterations = 255*3
+c_x = 2 * np.pi
+c_y = 2 * np.pi
+
+
+image = np.empty([img_res_y, img_res_x])
+
+with alive_bar(img_res_y, bar = 'filling', spinner = 'waves') as bar:
+ for pix_y, y in enumerate(np.linspace(ymin, ymax, img_res_y)):
+ for pix_x, x in enumerate(np.linspace(xmin, xmax, img_res_x)):
+ on_x = x
+ on_y = y
+ for i in range(iterations):
+ completed_ratio = (((pix_x * pix_y * 1)) / total_pixels)
+ next_x = (completed_ratio * (on_x/np.sin(on_y))) + ((1 - completed_ratio) * on_x/np.tan(on_y))
+ on_y = (completed_ratio * (on_y/np.sin(on_x))) + ((1 - completed_ratio) * on_y/np.tan(on_x))
+ on_x = next_x
+ if on_x**2 + on_y**2 > escape:
+ break
+ image[pix_y][pix_x] = i
+ bar()
+
+
+
+
+plt.style.use('dark_background')
+# fuck this shit
+fig = plt.figure(frameon=False)
+fig.set_size_inches(img_res_x/fig.dpi, img_res_y/fig.dpi)
+#fig.set_size_inches(width/height, 1, forward=False)
+
+ax = plt.Axes(fig, [0., 0., 1., 1.])
+ax.set_axis_off()
+fig.add_axes(ax)
+
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+ax.imshow(image, norm="log", aspect="auto", cmap=cmap)
+fig.savefig("linear_transform_sin_tan_arnolds_tongue_hotspot.png")
+plt.show()
diff --git a/collective/.gpu_migration.py.swo b/collective/.gpu_migration.py.swo
new file mode 100644
index 0000000..4806821
--- /dev/null
+++ b/collective/.gpu_migration.py.swo
Binary files differ
diff --git a/collective/.gpu_migration.py.swp b/collective/.gpu_migration.py.swp
new file mode 100644
index 0000000..bc46962
--- /dev/null
+++ b/collective/.gpu_migration.py.swp
Binary files differ
diff --git a/collective/.kernel.c.swp b/collective/.kernel.c.swp
new file mode 100644
index 0000000..7e1f62d
--- /dev/null
+++ b/collective/.kernel.c.swp
Binary files differ
diff --git a/collective/gpu_migration.py b/collective/gpu_migration.py
new file mode 100755
index 0000000..9536561
--- /dev/null
+++ b/collective/gpu_migration.py
@@ -0,0 +1,165 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.animation as animation
+import matplotlib.style as mplstyle
+import pyopencl as cl
+from alive_progress import alive_bar
+from matplotlib.backend_bases import MouseButton
+from PIL import Image
+
+# HELLO READER ------------------------------------------------------------------------
+# yes, I know this script is horrid, but it's more of a scratchpad to quickly test ideas
+# and not anything I'm ever going to show anyone else.
+
+img_res_x = 1000
+img_res_y = 1000
+total_pixels = img_res_x * img_res_y # so we don't gotta compute it every time
+
+periods = 1
+square_x = 0
+square_y = -2
+
+escape = 10000
+iterations = (255*3)
+c_x = 2 * np.pi
+c_y = 2 * np.pi
+
+animation_progres_save = "ani1_less.mp4"
+single_frame_save = "asdf.png"
+
+opencl_context = cl.create_some_context(interactive=False)
+opencl_queue = cl.CommandQueue(opencl_context)
+
+kernel_src_path = "./kernel.c"
+
+frames = 1
+rendered_frames = []
+
+image = np.empty([img_res_x, img_res_y], np.double)
+
+plt.style.use('dark_background')
+# fuck this shit
+fig = plt.figure(frameon=False)
+fig.set_size_inches(img_res_x/fig.dpi, img_res_y/fig.dpi)
+#fig.set_size_inches(width/height, 1, forward=False)
+
+
+ax = plt.Axes(fig, [0., 0., 1., 1.])
+
+manual_limits = [15.832664460420503,
+ 16.161782579162786,
+ 0.21263776938088172,
+ 0.2668613889327035]
+
+
+#ax.invert_yaxis()
+ax.set_xlim((-periods * np.pi) + (square_x * np.pi), (periods * np.pi) + (square_x * np.pi))
+ax.set_ylim((-periods * np.pi) + (square_y * np.pi), (periods * np.pi) + (square_y * np.pi))
+#ax.set_xlim(manual_limits[0], manual_limits[1])
+#ax.set_ylim(manual_limits[2], manual_limits[3])
+
+#ax.set_axis_off()
+fig.add_axes(ax)
+mplstyle.use('fast')
+
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+
+
+
+print("compiling openCL kernel...")
+with open(kernel_src_path, 'r') as kernel_src:
+ compiled_kernel = cl.Program(opencl_context, kernel_src.read()).build()
+
+encoding_progress = alive_bar(frames, bar = 'filling', spinner = 'waves')
+
+def display_encoder_progress(current_frame: int, total_frames: int):
+ print("Encoding: frame {}/{}".format(current_frame, frames))
+
+temp_render_hook = False
+mp_image = None
+
+def render(axes):
+ global temp_render_hook
+ global mp_image
+ if not temp_render_hook:
+ temp_render_hook = True
+ x_min = axes.get_xlim()[0]
+ x_max = axes.get_xlim()[1]
+ y_min = axes.get_ylim()[1]
+ y_max = axes.get_ylim()[0]
+ print(axes.get_ylim())
+ compiled_kernel.render_frame_curvature(opencl_queue, image.shape, None, image_buffer, mask_buffer,
+ np.double(abs(x_max - x_min) / img_res_x),
+ np.double(abs(y_max - y_min) / img_res_y),
+ np.double(x_min), np.double(y_min),
+ np.uint32(iterations), np.uint32(escape),
+ np.double(1))
+ cl.enqueue_copy(opencl_queue, image, image_buffer).wait()
+ print("kernel")
+ if mp_image == None:
+ mp_image = ax.imshow(image, norm="linear", aspect="auto", cmap=cmap, interpolation='none', extent=(x_min, x_max, y_min, y_max)) # TODO
+ else:
+ mp_image.set(extent=(x_min, x_max, y_min, y_max))
+ #ax.set_aspect('equal')
+ #mp_image.set_data(image)
+ mp_image.set_array(image)
+
+
+ fig.canvas.draw_idle()
+ fig.canvas.flush_events()
+ temp_render_hook = False
+
+#plt.ion()
+
+#open image
+mask_path = "mask.png"
+mask = np.asarray(Image.open(mask_path).convert("L").resize((img_res_x, img_res_y)), dtype=np.double)
+#mask = np.zeros((img_res_x, img_res_y), dtype=np.double)
+mask.setflags(write=1)
+mask /= np.max(mask) # normalize
+#print(mask.shape)
+#print(mask.dtype)
+#print(mask)
+#ax.imshow(mask, norm="linear")
+#plt.show()
+
+image_buffer = cl.Buffer(opencl_context, cl.mem_flags.WRITE_ONLY, image.nbytes)
+mask_buffer = cl.Buffer(opencl_context, cl.mem_flags.READ_ONLY, mask.nbytes)
+cl.enqueue_copy(opencl_queue, mask_buffer, mask).wait()
+#mask_buffer = cl.array.Array(opencl_context,mask.shape, dtype=np.uint8, data=mask)
+
+#move to render
+print("Rendering {} frames...".format(frames))
+if frames > 1:
+ x_min = ax.get_xlim()[0]
+ x_max = ax.get_xlim()[1]
+ y_min = ax.get_ylim()[1]
+ y_max = ax.get_ylim()[0]
+ with alive_bar(frames, bar = 'filling', spinner = 'waves') as bar_total:
+ for frame_i in range(0, frames):
+ compiled_kernel.render_frame_curvature(opencl_queue, image.shape, None, image_buffer, mask_buffer,
+ np.double(abs(x_max - x_min) / img_res_x),
+ np.double(abs(y_max - y_min) / img_res_y),
+ np.double(x_min), np.double(y_min),
+ np.uint32(iterations), np.uint32(escape),
+ np.double(frame_i/frames))
+
+
+ cl.enqueue_copy(opencl_queue, image, image_buffer).wait()
+ rendered_frame = ax.imshow(image, norm="linear", aspect="auto", cmap=cmap, animated="True")
+ rendered_frames.append([rendered_frame])
+ bar_total()
+ print("Encoding/Saving...")
+ ani = animation.ArtistAnimation(fig, rendered_frames, interval=30, blit=True)
+ ani.save(animation_progres_save, extra_args=['-preset', 'lossless'], progress_callback=display_encoder_progress, codec="h264_nvenc")
+else:
+ ax.callbacks.connect('ylim_changed', render)
+ ax.callbacks.connect('xlim_changed', render)
+ render(ax)
+ plt.savefig("out_texture.png")
+ plt.show(block=True)
diff --git a/collective/kernel.c b/collective/kernel.c
new file mode 100644
index 0000000..f3982a6
--- /dev/null
+++ b/collective/kernel.c
@@ -0,0 +1,116 @@
+//#include <math.h>
+#define PI 3.141592653589793115997963468544185161590576171875
+
+double cosecant_single(double a, double b) { return a / cos(b); }
+double secant_single(double a, double b) { return a / cos(b); }
+
+/**
+__kernel void render_frame_orbit_trap(__global double *frame_output, __global double *mask,
+ double x_step, double y_step,
+ double x_start, double y_start,
+ unsigned int iterations, unsigned int escape, double ratio) {
+
+ const vec2 point = (0, 0);
+
+ unsigned int result;
+ unsigned int iter;
+
+ double min_distance = DBL_MAX;
+
+ for(iter = 0; iter < iterations; iter++) {
+ double next_x;
+ double r = mask[img_index];
+ next_x = (r * cosecant_single(x, y)) + ((1 - r) * secant_single(x, y));
+ y = (r * cosecant_single(y, x)) + ((1 - r) * secant_single(y, x));
+ x = next_x;
+ if((pow(x, 2) + pow(y, 2)) >= escape) break;
+ }
+
+ frame_output[img_index] = total_curve / iter;
+
+}
+**/
+
+
+__kernel void render_frame_curvature(__global double *frame_output, __global double *mask,
+ double x_step, double y_step,
+ double x_start, double y_start,
+ unsigned int iterations, unsigned int escape, double ratio) {
+ unsigned int result;
+ unsigned int iter;
+
+ double x_cart = (get_global_id(0) * x_step) + x_start;
+ double y_cart = (get_global_id(1) * y_step) + y_start;
+ double x = sqrt(pow(x_cart, 2) + pow(y_cart, 2));
+ double y = atan(y_cart / x_cart);
+
+ //double x = (get_global_id(0) * x_step) + x_start;
+ //double y = (get_global_id(1) * y_step) + y_start;
+ size_t img_index = (get_global_id(1) * get_global_size(1)) + get_global_id(0);
+
+ double total_curve = 0;
+
+ //just found out vectors are a thing
+ double2 lp[3];
+
+ for(iter = 0; iter < iterations; iter++) {
+ double next_x;
+ double r = mask[img_index];
+ next_x = (r * secant_single(x, y)) + ((1 - r) * cosecant_single(x, y));
+ y = (r * secant_single(y, x)) + ((1 - r) * cosecant_single(y, x));
+ x = next_x;
+
+ if((pow(x, 2) + pow(y, 2)) >= escape) break;
+ lp[2] = lp[1];
+ lp[1] = lp[0];
+ lp[0] = (double2)(x, y); //why do I have to cast this? hope no accuracy lost
+
+ /**
+ if(img_index == 254234) {
+ printf("%u\n", ratio);
+ }
+ **/
+ if(iter >= 2) {
+ double curl = acos(dot((lp[0] - lp[1]), (lp[2] - lp[1])) / (distance(lp[0], lp[1]) * distance(lp[2], lp[1])));
+ total_curve = (total_curve + curl);
+ }
+ }
+ frame_output[img_index] = total_curve / iter;
+}
+
+
+__kernel void render_frame(__global double *frame_output, __global double *mask,
+ double x_step, double y_step,
+ double x_start, double y_start,
+ unsigned int iterations, unsigned int escape, double ratio) {
+ unsigned int result;
+ double x_cart = (get_global_id(0) * x_step) + x_start;
+ double y_cart = (get_global_id(1) * y_step) + y_start;
+ size_t img_index = (get_global_id(1) * get_global_size(1)) + get_global_id(0);
+
+ double x = sqrt(pow(x_cart, 2) + pow(y_cart, 2));
+ double y = atan(y_cart / x_cart);
+
+ //double x = (get_global_id(0) * x_step) + x_start;
+ //double y = (get_global_id(1) * y_step) + y_start;
+
+
+ unsigned int iter;
+
+ //vec2 pos;
+
+ for(iter = 0; iter < iterations; iter++) {
+ double next_x;
+ double r = ratio;
+ next_x = (r * cosecant_single(x, y)) + ((1 - r) * secant_single(x, y));
+ y = (r * cosecant_single(y, x)) + ((1 - r) * secant_single(y, x));
+ x = next_x;
+ //if(distance(pos) >= escape) break;
+ if((pow(x, 2) + pow(y, 2)) >= escape) break;
+ }
+
+
+ //TODO turn back to int whenever
+ frame_output[img_index] = (double)iter;
+ //frame_output[img_index] = mask[img_index] * 255;
+}
diff --git a/collective/mask.png b/collective/mask.png
new file mode 120000
index 0000000..afb5f75
--- /dev/null
+++ b/collective/mask.png
@@ -0,0 +1 @@
+../masks/clouds.png \ No newline at end of file
diff --git a/collective/notes b/collective/notes
new file mode 100644
index 0000000..50249d7
--- /dev/null
+++ b/collective/notes
@@ -0,0 +1,79 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.animation as animation
+import pyopencl as cl
+from alive_progress import alive_bar
+
+img_res_x = 2000
+img_res_y = 2000
+total_pixels = img_res_x * img_res_y # so we don't gotta compute it every time
+
+periods = 1
+square_x = 0
+square_y = 0
+
+xmin = (-periods * np.pi) + (square_x * np.pi)
+xmax = (periods * np.pi) + (square_x * np.pi)
+ymin = (-periods * np.pi) + (square_y * np.pi)
+ymax = (periods * np.pi) + (square_y * np.pi)
+
+escape = 10000
+iterations = 255*3
+c_x = 2 * np.pi
+c_y = 2 * np.pi
+
+animation_progres_save = "./animations"
+frames = 120
+
+rendered_frames = []
+
+
+plt.style.use('dark_background')
+# fuck this shit
+fig = plt.figure(frameon=False)
+fig.set_size_inches(img_res_x/fig.dpi, img_res_y/fig.dpi)
+#fig.set_size_inches(width/height, 1, forward=False)
+
+ax = plt.Axes(fig, [0., 0., 1., 1.])
+ax.set_axis_off()
+fig.add_axes(ax)
+
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+opencl_context = cl.create_some_context()
+opencl_queue = cl.CommandQueue(opencl_context)
+
+
+#def render():
+# image = np.empty([img_res_y, img_res_x])
+# print("Rendering frames")
+# with alive_bar(frames, bar = 'filling', spinner = 'waves') as bar_total:
+# for frame in range(frames):
+# split_ratio = frame / frames
+# for pix_y, y in enumerate(np.linspace(ymin, ymax, img_res_y)):
+# for pix_x, x in enumerate(np.linspace(xmin, xmax, img_res_x)):
+# on_x = x
+# on_y = y
+# for i in range(iterations):
+# next_x = (split_ratio * (on_x/np.sin(on_y))) + ((1 - split_ratio) * on_x/np.tan(on_y))
+# on_y = (split_ratio * (on_y/np.sin(on_x))) + ((1 - split_ratio) * on_y/np.tan(on_x))
+# on_x = next_x
+# if on_x**2 + on_y**2 > escape:
+# break
+# image[pix_y][pix_x] = i
+# rendered_frame = ax.imshow(image, norm="log", aspect="auto", cmap=cmap, animated=False)
+# rendered_frames.append([rendered_frame])
+# bar_total()
+
+def display():
+ print(rendered_frames)
+ ani = animation.ArtistAnimation(fig, rendered_frames, interval=30, blit=True)
+ ani.save("test.mp4")
+ plt.show()
+
+render()
+display()
diff --git a/collective/out.png b/collective/out.png
new file mode 100644
index 0000000..5011695
--- /dev/null
+++ b/collective/out.png
Binary files differ
diff --git a/collective/out_grad.png b/collective/out_grad.png
new file mode 100644
index 0000000..26fb1f1
--- /dev/null
+++ b/collective/out_grad.png
Binary files differ
diff --git a/collective/out_texture.png b/collective/out_texture.png
new file mode 100644
index 0000000..8031ab1
--- /dev/null
+++ b/collective/out_texture.png
Binary files differ
diff --git a/collective/texput.log b/collective/texput.log
new file mode 100644
index 0000000..d13b81a
--- /dev/null
+++ b/collective/texput.log
@@ -0,0 +1,21 @@
+This is pdfTeX, Version 3.141592653-2.6-1.40.26 (TeX Live 2024/Arch Linux) (preloaded format=pdflatex 2024.4.22) 28 APR 2024 21:33
+entering extended mode
+ restricted \write18 enabled.
+ %&-line parsing enabled.
+**
+
+! Emergency stop.
+<*>
+
+End of file on the terminal!
+
+
+Here is how much of TeX's memory you used:
+ 3 strings out of 476076
+ 113 string characters out of 5793775
+ 1925187 words of memory out of 5000000
+ 22212 multiletter control sequences out of 15000+600000
+ 558069 words of font info for 36 fonts, out of 8000000 for 9000
+ 14 hyphenation exceptions out of 8191
+ 0i,0n,0p,13b,6s stack positions out of 10000i,1000n,20000p,200000b,200000s
+! ==> Fatal error occurred, no output PDF file produced!
diff --git a/cool_places b/cool_places
new file mode 100644
index 0000000..6a9367d
--- /dev/null
+++ b/cool_places
@@ -0,0 +1,6 @@
+windows into space
+ 15.832664460420503
+ 16.161782579162786
+
+ 0.21263776938088172
+ 0.2668613889327035
diff --git a/field_tests/backup b/field_tests/backup
new file mode 100644
index 0000000..2e60664
--- /dev/null
+++ b/field_tests/backup
@@ -0,0 +1,62 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+from alive_progress import alive_bar
+
+img_res_x = 1000
+img_res_y = 1000
+total_pixels = img_res_x * img_res_y # so we don't gotta compute it every time
+
+periods = .25
+square_x = 1
+square_y = 1
+
+xmin = (-periods * np.pi) + (square_x * np.pi)
+xmax = (periods * np.pi) + (square_x * np.pi)
+ymin = (-periods * np.pi) + (square_y * np.pi)
+ymax = (periods * np.pi) + (square_y * np.pi)
+
+escape = 10000
+iterations = 255*3
+c_x = 2 * np.pi
+c_y = 2 * np.pi
+
+
+image = np.empty([img_res_y, img_res_x])
+
+with alive_bar(img_res_y, bar = 'filling', spinner = 'waves') as bar:
+ for pix_y, y in enumerate(np.linspace(ymin, ymax, img_res_y)):
+ for pix_x, x in enumerate(np.linspace(xmin, xmax, img_res_x)):
+ on_x = x
+ on_y = y
+ for i in range(iterations):
+ completed_ratio = (((pix_x * pix_y * 1)) / total_pixels)
+ next_x = (completed_ratio * (on_x/np.sin(on_y))) + ((1 - completed_ratio) * on_x/np.tan(on_y))
+ on_y = (completed_ratio * (on_y/np.sin(on_x))) + ((1 - completed_ratio) * on_y/np.tan(on_x))
+ on_x = next_x
+ if on_x**2 + on_y**2 > escape:
+ break
+ image[pix_y][pix_x] = i
+ bar()
+
+
+
+
+plt.style.use('dark_background')
+# fuck this shit
+fig = plt.figure(frameon=False)
+fig.set_size_inches(img_res_x/fig.dpi, img_res_y/fig.dpi)
+#fig.set_size_inches(width/height, 1, forward=False)
+
+ax = plt.Axes(fig, [0., 0., 1., 1.])
+ax.set_axis_off()
+fig.add_axes(ax)
+
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+ax.imshow(image, norm="log", aspect="auto", cmap=cmap)
+fig.savefig("linear_transform_sin_tan_arnolds_tongue_hotspot.png")
+plt.show()
diff --git a/field_tests/basic_field_test.py b/field_tests/basic_field_test.py
new file mode 100644
index 0000000..faf3c2c
--- /dev/null
+++ b/field_tests/basic_field_test.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+from alive_progress import alive_bar
+
+img_res_x = 100
+img_res_y = 100
+total_pixels = img_res_x * img_res_y # so we don't gotta compute it every time
+
+periods = 1
+square_x = 0
+square_y = 0
+
+#xmin = (-periods * np.pi) + (square_x * np.pi)
+#xmax = (periods * np.pi) + (square_x * np.pi)
+#ymin = (-periods * np.pi) + (square_y * np.pi)
+#ymax = (periods * np.pi) + (square_y * np.pi)
+
+xmin = -10
+xmax = 10
+ymin = -10
+ymax = 10
+
+escape = 10000
+iterations = 255*3
+c_x = 2 * np.pi
+c_y = 2 * np.pi
+
+
+image = np.empty([img_res_y, img_res_x])
+grid = np.meshgrid(np.linspace(ymin, ymax, img_res_y), np.linspace(xmin, xmax, img_res_x))
+print(grid[0].dtype)
+
+
+class point_charge():
+ def __init__(self, x, y, c, mod):
+ self.x = x
+ self.y = y
+ self.c = c
+ self.mod = mod
+ def get_field(self, to_x, to_y):
+ if(self.mod):
+ to_x = (to_x % self.mod)
+ to_y = (to_y % self.mod)
+ return (
+ ((self.c * (self.x - to_x)) / ((self.x - to_x)**2 + (self.y - to_y)**2)**1.5),
+ ((self.c * (self.y - to_y)) / ((self.x - to_x)**2 + (self.y - to_y)**2)**1.5))
+
+#will remove all the point charge code if it turns out to be good enough to be impliemnted into openCL
+#point_charges = [point_charge(-5, -5, 100), point_charge(-5, 5, -100), point_charge(5, 0, 100)]
+point_charges = [point_charge(5,5, 100, 10), point_charge(0,0,-100, 0)]
+
+
+plt.ion()
+ax = plt.gca()
+fig = plt.gcf()
+ax.set_autoscale_on(False)
+ax.set_xlim([xmin, xmax])
+ax.set_ylim([ymin, ymax])
+
+vector_arrows = None
+
+def show_field():
+ global vector_arrows
+ grid_f = np.zeros_like(grid)
+ for p in point_charges:
+ grid_f += p.get_field(grid[0], grid[1])
+ #plt.streamplot(grid[0], grid[1], grid_f[0], grid_f[1], density=5)
+ vector_arrows = plt.quiver(grid[0], grid[1], grid_f[0], grid_f[1])
+ plt.show(block=False)
+ plt.pause(.1)
+
+
+show_field()
+
+timestep = .1
+def test_sim():
+ particle_grid = np.meshgrid(np.linspace(ymin, ymax, 100), np.linspace(xmin, xmax, 100))
+ pos = particle_grid
+ acceleration = np.zeros_like(particle_grid)
+ velocity = np.zeros_like(particle_grid)
+ velocity = [np.ones_like(particle_grid[0]) * 1, np.ones_like(particle_grid[0]) * .5]
+ mass = 10
+ charge = 1
+ particle_plot = ax.plot(velocity[0], velocity[1], 'bo', animated=True)
+ #velocity += .1
+
+ background = fig.canvas.copy_from_bbox(ax.bbox)
+ ax.draw_artist(vector_arrows)
+ fig.canvas.blit(fig.bbox)
+
+ while True:
+ fig.canvas.restore_region(background)
+ field = np.zeros_like(particle_grid)
+ # TODO can make this quicker by skipping initilization
+ for p in point_charges:
+ field += p.get_field(pos[0], pos[1])
+ acceleration = ((charge * field) / mass) * timestep
+ #print(acceleration)
+ velocity += acceleration * timestep
+ pos += velocity * timestep
+
+ fig.canvas.restore_region(background)
+ particle_plot[0].set_data(pos[0],pos[1])
+ ax.draw_artist(particle_plot[0])
+ fig.canvas.blit(fig.bbox)
+ fig.canvas.flush_events()
+ plt.pause(1/60)
+
+ #fig.canvas.draw_idle()
+test_sim()
+
+exit(1)
+
+
+
+
+
+#with alive_bar(iterations, bar = 'filling', spinner = 'waves') as bar:
+# for i in range(iterations):
+# next_x = xx / np.sin(yy)
+# yy = yy / np.sin(xx)
+# xx = next_x
+# bar()
+#image = np.vstack([xx.ravel(), yy.ravel()])
+
+
+#meshgrid makes things slower as we can't test individual points for breaking to infinity
+fractal_test = False
+if fractal_test:
+ with alive_bar(img_res_y, bar = 'filling', spinner = 'waves') as bar:
+ for pix_y, y in enumerate(np.linspace(ymin, ymax, img_res_y)):
+ for pix_x, x in enumerate(np.linspace(xmin, xmax, img_res_x)):
+ on_x = x
+ on_y = y
+ for i in range(iterations):
+ completed_ratio = (((pix_x * pix_y * 1)) / total_pixels)
+ next_x = (completed_ratio * (on_x/np.sin(on_y))) + ((1 - completed_ratio) * on_x/np.tan(on_y))
+ on_y = (completed_ratio * (on_y/np.sin(on_x))) + ((1 - completed_ratio) * on_y/np.tan(on_x))
+ on_x = next_x
+ if on_x**2 + on_y**2 > escape:
+ break
+ image[pix_y][pix_x] = i
+ bar()
+else:
+ exit()
+
+
+exit(1)
+
+plt.style.use('dark_background')
+# fuck this shit
+fig = plt.figure(frameon=False)
+fig.set_size_inches(img_res_x/fig.dpi, img_res_y/fig.dpi)
+#fig.set_size_inches(width/height, 1, forward=False)
+
+ax = plt.Axes(fig, [0., 0., 1., 1.])
+ax.set_axis_off()
+fig.add_axes(ax)
+
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+ax.imshow(image, norm="log", aspect="auto", cmap=cmap)
+fig.savefig("linear_transform_sin_tan_arnolds_tongue_hotspot.png")
+plt.show()
diff --git a/field_tests/field.py b/field_tests/field.py
new file mode 100755
index 0000000..af2abbf
--- /dev/null
+++ b/field_tests/field.py
@@ -0,0 +1,191 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+from alive_progress import alive_bar
+
+img_res_x = 250
+img_res_y = 250
+total_pixels = img_res_x * img_res_y # so we don't gotta compute it every time
+
+periods = 1
+square_x = 0
+square_y = 0
+
+xmin = (-periods * np.pi) + (square_x * np.pi)
+xmax = (periods * np.pi) + (square_x * np.pi)
+ymin = (-periods * np.pi) + (square_y * np.pi)
+ymax = (periods * np.pi) + (square_y * np.pi)
+
+#xmin = -10
+#xmax = 10
+#ymin = -10
+#ymax = 10
+
+escape = 10000
+iterations = 255*3
+c_x = 2 * np.pi
+c_y = 2 * np.pi
+
+
+grid = np.meshgrid(np.linspace(ymin, ymax, 200), np.linspace(xmin, xmax, 200))
+#image = np.meshgrid(np.linspace(ymin, ymax, img_res_y), np.linspace(xmin, xmax, img_res_x))
+image = np.zeros([img_res_y, img_res_x], dtype=np.double)
+
+
+class point_charge():
+ def __init__(self, x, y, c, mod):
+ self.x = x
+ self.y = y
+ self.c = c
+ self.mod = mod
+ def get_field(self, to_x, to_y):
+ if(self.mod):
+ to_x = (to_x % self.mod)
+ to_y = (to_y % self.mod)
+ return np.array([
+ ((self.c * (self.x - to_x)) / ((self.x - to_x)**2 + (self.y - to_y)**2)**1.5),
+ ((self.c * (self.y - to_y)) / ((self.x - to_x)**2 + (self.y - to_y)**2)**1.5)])
+
+#will remove all the point charge code if it turns out to be good enough to be impliemnted into openCL
+#point_charges = [point_charge(-5, -5, 100), point_charge(-5, 5, -100), point_charge(5, 0, 100)]
+#point_charges = [point_charge(-1,-1, 100, 10), point_charge(1,1,-100, 0)]
+point_charges = []
+
+
+#plt.ion()
+ax = plt.gca()
+fig = plt.gcf()
+#ax.set_autoscale_on(False)
+#ax.set_xlim([xmin, xmax])
+#ax.set_ylim([ymin, ymax])
+
+vector_arrows = None
+
+def show_field():
+ global vector_arrows
+ grid_f = np.zeros_like(grid)
+ for p in point_charges:
+ grid_f += p.get_field(grid[0], grid[1])
+ #plt.streamplot(grid[0], grid[1], grid_f[0], grid_f[1], density=5)
+ vector_arrows = plt.quiver(grid[0], grid[1], grid_f[0], grid_f[1])
+ plt.show(block=False)
+ plt.pause(.1)
+
+
+#show_field()
+
+timestep = .1
+def test_sim():
+ particle_grid = np.meshgrid(np.linspace(ymin, ymax, 100), np.linspace(xmin, xmax, 100))
+ pos = particle_grid
+ acceleration = np.zeros_like(particle_grid)
+ velocity = np.zeros_like(particle_grid)
+ velocity = [np.ones_like(particle_grid[0]) * 1, np.ones_like(particle_grid[0]) * .5]
+ mass = 10
+ charge = 1
+ particle_plot = ax.plot(velocity[0], velocity[1], 'bo', animated=True)
+ #velocity += .1
+
+ background = fig.canvas.copy_from_bbox(ax.bbox)
+ ax.draw_artist(vector_arrows)
+ fig.canvas.blit(fig.bbox)
+
+ while True:
+ fig.canvas.restore_region(background)
+ field = np.zeros_like(particle_grid)
+ # TODO can make this quicker by skipping initilization
+ for p in point_charges:
+ field += p.get_field(pos[0], pos[1])
+ acceleration = ((charge * field) / mass) * timestep
+ #print(acceleration)
+ velocity += acceleration * timestep
+ pos += velocity * timestep
+
+ fig.canvas.restore_region(background)
+ particle_plot[0].set_data(pos[0],pos[1])
+ ax.draw_artist(particle_plot[0])
+ fig.canvas.blit(fig.bbox)
+ fig.canvas.flush_events()
+ plt.pause(1/60)
+
+ #fig.canvas.draw_idle()
+#test_sim()
+
+#exit(1)
+
+
+max_timesteps = 10
+
+def get_fractal_iter(img):
+ next_x = img[1][y][x] / np.sin(img[0][y][x])
+ img[0][y][x] = img[0][y][x] / np.sin(img[1][y][x])
+ img[1][y][x] = next_x
+ if (np.square(img[0][y][x]) + np.square(img[1][y][x])) >= escape:
+ z[y][x] = i
+
+
+#meshgrid makes things slower as we can't test individual points for breaking to infinity;
+#however, I will fix that later.
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+with alive_bar(img_res_y, bar = 'filling', spinner = 'waves') as bar:
+ for pix_y, y in enumerate(np.linspace(ymin, ymax, img_res_y)):
+ for pix_x, x in enumerate(np.linspace(xmin, xmax, img_res_x)):
+ on_x = x
+ on_y = y
+ for i in range(iterations):
+ completed_ratio = (((pix_x * pix_y * 1)) / total_pixels)
+ next_x = on_x/np.sin(on_y)
+ on_y = on_y/np.sin(on_x)
+ on_x = next_x
+
+
+ # do physics here - we could just use vectors but i keep rewriting things
+ timesteps = max_
+ acceleration = np.array([0, 0], dtype=np.double)
+ velocity = np.array([on_x, on_y], dtype=np.double) # maybe multiply by stuff
+ pos = np.array([0,0], dtype=np.double)
+ for t in range(timesteps):
+ for p in point_charges:
+ acceleration += p.get_field(on_x, on_y)
+ velocity += acceleration
+ pos += velocity * (timesteps)
+ on_x += pos[0]
+ on_y += pos[1]
+
+ if on_x**2 + on_y**2 > escape:
+ image[pix_x][pix_y] = i
+ break
+ bar()
+
+ax.imshow(image, norm="log", aspect="auto", cmap=cmap)
+plt.show()
+
+
+# yeah, I shouldn't have switched to a meshgrid, oh well
+#z = np.empty_like(image[0])
+exit(0)
+with alive_bar(img_res_x, bar = 'filling', spinner = 'waves') as bar:
+ for y in range(img_res_y):
+ for x in range(img_res_x):
+ for i in range(iterations):
+ if image[0][y][x] == np.NAN:
+ continue
+ next_x = image[1][y][x] / np.sin(image[0][y][x])
+ image[0][y][x] = image[0][y][x] / np.sin(image[1][y][x])
+ image[1][y][x] = next_x
+ if (np.square(image[0][y][x]) + np.square(image[1][y][x])) >= escape:
+ z[y][x] = i
+ image[0][y][x] = np.NAN
+ image[1][y][x] = np.NAN
+ break
+# #do physics here
+
+
+
+ bar()
+#image = np.clip(image, -escape, escape)
+
diff --git a/field_tests/gpu_migration.py b/field_tests/gpu_migration.py
new file mode 100755
index 0000000..718fe7d
--- /dev/null
+++ b/field_tests/gpu_migration.py
@@ -0,0 +1,137 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.animation as animation
+import pyopencl as cl
+from alive_progress import alive_bar
+from matplotlib.backend_bases import MouseButton
+
+img_res_x = 1000
+img_res_y = 1000
+total_pixels = img_res_x * img_res_y # so we don't gotta compute it every time
+
+periods = 1
+square_x = 0
+square_y = 0
+
+x_min = (-periods * np.pi) + (square_x * np.pi)
+x_max = (periods * np.pi) + (square_x * np.pi)
+y_min = (-periods * np.pi) + (square_y * np.pi)
+y_max = (periods * np.pi) + (square_y * np.pi)
+
+escape = 10000
+iterations = 255*3
+c_x = 2 * np.pi
+c_y = 2 * np.pi
+
+animation_progres_save = "ani1_less.mp4"
+single_frame_save = "asdf.png"
+
+opencl_context = cl.create_some_context(interactive=False)
+opencl_queue = cl.CommandQueue(opencl_context)
+
+kernel_src_path = "./kernel.c"
+
+frames = 1
+rendered_frames = []
+
+image = np.empty([img_res_x, img_res_y], np.uint32)
+image_buffer = cl.Buffer(opencl_context, cl.mem_flags.WRITE_ONLY, image.nbytes)
+
+plt.style.use('dark_background')
+# fuck this shit
+fig = plt.figure(frameon=False)
+fig.set_size_inches(img_res_x/fig.dpi, img_res_y/fig.dpi)
+#fig.set_size_inches(width/height, 1, forward=False)
+
+
+ax = plt.Axes(fig, [0., 0., 1., 1.])
+#ax.set_axis_off()
+fig.add_axes(ax)
+
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+bruh = None
+
+def on_click(event):
+ global bruh
+ split_ratio = 1
+ if (event.button is MouseButton.MIDDLE) and (event.inaxes):
+ # there's probably a way to set global coordinates;
+ # I don't expect this to go anywhere so I don't really care
+ on_x = ((event.xdata / img_res_x) * abs(x_max - x_min)) + x_min
+ on_y = ((event.ydata / img_res_y) * abs(y_max - y_min)) + y_min
+
+ #I, uh, also don't know the best way to replicate the openCL code automaticly in python
+ #so ajust if nessesary
+ x_hops = []
+ y_hops = []
+ for i in range(iterations):
+ x_hops.append(((on_x - x_min) / abs(x_max - x_min)) * img_res_x)
+ y_hops.append(((on_y - y_min) / abs(y_max - y_min)) * img_res_y)
+ next_x = on_x/np.tan(on_y)
+ on_y = on_y/np.tan(on_x)
+ on_x = next_x
+ if on_x**2 + on_y**2 > escape:
+ break
+ print(y_hops[0])
+ print(on_y)
+ print("{} hops".format(len(x_hops)))
+ if bruh:
+ bruh.pop(0).remove()
+ bruh = ax.plot(x_hops, y_hops)
+ plt.draw()
+
+
+
+ print(on_x, on_y)
+
+
+print("compiling openCL kernel...")
+with open(kernel_src_path, 'r') as kernel_src:
+ compiled_kernel = cl.Program(opencl_context, kernel_src.read()).build()
+
+encoding_progress = alive_bar(frames, bar = 'filling', spinner = 'waves')
+
+def display_encoder_progress(current_frame: int, total_frames: int):
+ print("Encoding: frame {}/{}".format(current_frame, frames))
+
+
+
+print("Rendering {} frames...".format(frames))
+if frames > 1:
+ with alive_bar(frames, bar = 'filling', spinner = 'waves') as bar_total:
+ for frame_i in range(0, frames):
+ compiled_kernel.render_frame(opencl_queue, image.shape, None, image_buffer,
+ np.double(abs(x_max - x_min) / img_res_x),
+ np.double(abs(y_max - y_min) / img_res_y),
+ np.double(x_min), np.double(y_min),
+ np.uint32(iterations), np.uint32(escape),
+ np.double(frame_i / frames))
+
+
+ cl.enqueue_copy(opencl_queue, image, image_buffer).wait()
+ rendered_frame = ax.imshow(image, norm="log", aspect="auto", cmap=cmap, animated="True")
+ rendered_frames.append([rendered_frame])
+ bar_total()
+ print("Encoding/Saving...")
+ ani = animation.ArtistAnimation(fig, rendered_frames, interval=30, blit=True)
+ ani.save(animation_progres_save, extra_args=['-preset', 'lossless'], progress_callback=display_encoder_progress, codec="h264_nvenc")
+else:
+ compiled_kernel.render_frame(opencl_queue, image.shape, None, image_buffer,
+ np.double(abs(x_max - x_min) / img_res_x),
+ np.double(abs(y_max - y_min) / img_res_y),
+ np.double(x_min), np.double(y_min),
+ np.uint32(iterations), np.uint32(escape),
+ np.double(1))
+ cl.enqueue_copy(opencl_queue, image, image_buffer).wait()
+ ax.imshow(image, norm="log", aspect="auto", cmap=cmap)
+ fig.savefig(single_frame_save)
+ plt.autoscale(False)
+ plt.connect('motion_notify_event', on_click)
+ plt.show()
+
+
diff --git a/field_tests/kernel.c b/field_tests/kernel.c
new file mode 100644
index 0000000..08b9137
--- /dev/null
+++ b/field_tests/kernel.c
@@ -0,0 +1,26 @@
+__kernel void basic_test() {
+ printf("this cores ID: (%lu, %lu)\n", get_global_id(0), get_global_id(1));
+}
+
+__kernel void render_frame(__global unsigned int *frame_output,
+ double x_step, double y_step,
+ double x_start, double y_start,
+ unsigned int iterations, unsigned int escape, double ratio) {
+ unsigned int result;
+ double on_x = (get_global_id(0) * x_step) + x_start;
+ double on_y = (get_global_id(1) * y_step) + y_start;
+ double next_x;
+ unsigned int iter;
+
+ orig_x = on_x;
+ orig_y = on_y;
+ for(iter = 0; iter < iterations; iter++) {
+ if(orig_x == 123 && orig_y == 5) printf("%d, %d\n", orig_x,orig_y);
+ next_x = on_x / sin(on_y);
+ on_y = on_y / sin(on_x);
+ on_x = next_x;
+ if((pow(on_x, 2) + pow(on_y, 2)) >= escape) break;
+ }
+
+ frame_output[(get_global_id(1) * get_global_size(1)) + get_global_id(0)] = iter;
+}
diff --git a/field_tests/makefile b/field_tests/makefile
new file mode 100644
index 0000000..539deb1
--- /dev/null
+++ b/field_tests/makefile
@@ -0,0 +1,4 @@
+make:
+ gcc -Wall -fpic -c field.c
+ gcc -Wall -shared -o field.so field.o
+ python3 field.py
diff --git a/linear_transform_test.py b/linear_transform_test.py
new file mode 100755
index 0000000..5a0afca
--- /dev/null
+++ b/linear_transform_test.py
@@ -0,0 +1,63 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+from alive_progress import alive_bar
+
+img_res_x = 500
+img_res_y = 500
+total_pixels = img_res_x * img_res_y # so we don't gotta compute it every time
+
+periods = .25
+square_x = 1
+square_y = 1
+
+xmin = (-periods * np.pi) + (square_x * np.pi)
+xmax = (periods * np.pi) + (square_x * np.pi)
+ymin = (-periods * np.pi) + (square_y * np.pi)
+ymax = (periods * np.pi) + (square_y * np.pi)
+
+escape = 10000
+iterations = 255*3
+c_x = 2 * np.pi
+c_y = 2 * np.pi
+
+
+image = np.empty([img_res_y, img_res_x])
+
+with alive_bar(img_res_y, bar = 'filling', spinner = 'waves') as bar:
+ for pix_y, y in enumerate(np.linspace(ymin, ymax, img_res_y)):
+ for pix_x, x in enumerate(np.linspace(xmin, xmax, img_res_x)):
+ on_x = x
+ on_y = y
+ for i in range(iterations):
+ completed_ratio = ((pix_y * img_res_y) + pix_x) / total_pixels
+ next_x = (completed_ratio * (on_x/np.sin(on_y))) + ((1 - completed_ratio) * on_x/np.tan(on_y))
+ on_y = (completed_ratio * (on_y/np.sin(on_x))) + ((1 - completed_ratio) * on_y/np.tan(on_x))
+ on_x = next_x
+ if on_x**2 + on_y**2 > escape:
+ break
+ print(completed_ratio)
+ image[pix_y][pix_x] = i
+ bar()
+
+
+
+
+plt.style.use('dark_background')
+# fuck this shit
+fig = plt.figure(frameon=False)
+fig.set_size_inches(img_res_x/fig.dpi, img_res_y/fig.dpi)
+#fig.set_size_inches(width/height, 1, forward=False)
+
+ax = plt.Axes(fig, [0., 0., 1., 1.])
+ax.set_axis_off()
+fig.add_axes(ax)
+
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+ax.imshow(image, norm="log", aspect="auto", cmap=cmap)
+fig.savefig("linear_transform_sin_tan_arnolds_tongue_hotspot.png")
+plt.show()
diff --git a/live_play/.gpu_migration.py.swo b/live_play/.gpu_migration.py.swo
new file mode 100644
index 0000000..4806821
--- /dev/null
+++ b/live_play/.gpu_migration.py.swo
Binary files differ
diff --git a/live_play/.gpu_migration.py.swp b/live_play/.gpu_migration.py.swp
new file mode 100644
index 0000000..29b75a7
--- /dev/null
+++ b/live_play/.gpu_migration.py.swp
Binary files differ
diff --git a/live_play/.kernel.c.swp b/live_play/.kernel.c.swp
new file mode 100644
index 0000000..6ab3a51
--- /dev/null
+++ b/live_play/.kernel.c.swp
Binary files differ
diff --git a/live_play/gpu_migration.py b/live_play/gpu_migration.py
new file mode 100755
index 0000000..4269bcc
--- /dev/null
+++ b/live_play/gpu_migration.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.animation as animation
+import matplotlib.style as mplstyle
+import pyopencl as cl
+from alive_progress import alive_bar
+from matplotlib.backend_bases import MouseButton
+from PIL import Image
+
+# HELLO READER ------------------------------------------------------------------------
+# yes, I know this script is horrid, but it's more of a scratchpad to quickly test ideas
+# and not anything I'm ever going to show anyone else.
+
+img_res_x = 1000
+img_res_y = 1000
+total_pixels = img_res_x * img_res_y # so we don't gotta compute it every time
+
+periods = 1
+square_x = 0
+square_y = -2
+
+escape = 10000
+iterations = (255*3)*2
+c_x = 2 * np.pi
+c_y = 2 * np.pi
+
+animation_progres_save = "ani1_less.mp4"
+single_frame_save = "asdf.png"
+
+opencl_context = cl.create_some_context(interactive=False)
+opencl_queue = cl.CommandQueue(opencl_context)
+
+kernel_src_path = "./kernel.c"
+
+frames = 1
+rendered_frames = []
+
+image = np.empty([img_res_x, img_res_y], np.uint32)
+
+plt.style.use('dark_background')
+# fuck this shit
+fig = plt.figure(frameon=False)
+fig.set_size_inches(img_res_x/fig.dpi, img_res_y/fig.dpi)
+#fig.set_size_inches(width/height, 1, forward=False)
+
+
+ax = plt.Axes(fig, [0., 0., 1., 1.])
+
+#ax.invert_yaxis()
+ax.set_xlim((-periods * np.pi) + (square_x * np.pi), (periods * np.pi) + (square_x * np.pi))
+ax.set_ylim((-periods * np.pi) + (square_y * np.pi), (periods * np.pi) + (square_y * np.pi))
+
+#ax.set_axis_off()
+fig.add_axes(ax)
+mplstyle.use('fast')
+
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+
+
+
+print("compiling openCL kernel...")
+with open(kernel_src_path, 'r') as kernel_src:
+ compiled_kernel = cl.Program(opencl_context, kernel_src.read()).build()
+
+encoding_progress = alive_bar(frames, bar = 'filling', spinner = 'waves')
+
+def display_encoder_progress(current_frame: int, total_frames: int):
+ print("Encoding: frame {}/{}".format(current_frame, frames))
+
+temp_render_hook = False
+mp_image = None
+
+def render(axes):
+ global temp_render_hook
+ global mp_image
+ if not temp_render_hook:
+ temp_render_hook = True
+ x_min = axes.get_xlim()[0]
+ x_max = axes.get_xlim()[1]
+ y_min = axes.get_ylim()[1]
+ y_max = axes.get_ylim()[0]
+ print(axes.get_ylim())
+ compiled_kernel.render_frame(opencl_queue, image.shape, None, image_buffer, mask_buffer,
+ np.double(abs(x_max - x_min) / img_res_x),
+ np.double(abs(y_max - y_min) / img_res_y),
+ np.double(x_min), np.double(y_min),
+ np.uint32(iterations), np.uint32(escape),
+ np.double(1))
+ cl.enqueue_copy(opencl_queue, image, image_buffer).wait()
+ print("kernel")
+ if mp_image == None:
+ mp_image = ax.imshow(image, norm="log", aspect="auto", cmap=cmap, interpolation='none', extent=(x_min, x_max, y_min, y_max)) # TODO
+ else:
+ mp_image.set(extent=(x_min, x_max, y_min, y_max))
+ #ax.set_aspect('equal')
+ #mp_image.set_data(image)
+ mp_image.set_array(image)
+
+
+ fig.canvas.draw_idle()
+ fig.canvas.flush_events()
+ temp_render_hook = False
+
+#plt.ion()
+
+#open image
+mask_path = "mask.png"
+mask = np.asarray(Image.open(mask_path).convert("L").resize((img_res_x, img_res_y)), dtype=np.double)
+#mask = np.zeros((1000, 1000), dtype=np.double)
+mask.setflags(write=1)
+mask /= np.max(mask) # normalize
+print(mask.shape)
+print(mask.dtype)
+print(mask)
+#ax.imshow(mask, norm="linear")
+#plt.show()
+
+image_buffer = cl.Buffer(opencl_context, cl.mem_flags.WRITE_ONLY, image.nbytes)
+mask_buffer = cl.Buffer(opencl_context, cl.mem_flags.READ_ONLY, mask.nbytes)
+cl.enqueue_copy(opencl_queue, mask_buffer, mask).wait()
+#mask_buffer = cl.array.Array(opencl_context,mask.shape, dtype=np.uint8, data=mask)
+
+#move to render
+print("Rendering {} frames...".format(frames))
+if frames > 1:
+ with alive_bar(frames, bar = 'filling', spinner = 'waves') as bar_total:
+ for frame_i in range(0, frames):
+ compiled_kernel.render_frame(opencl_queue, image.shape, None, image_buffer, mask,
+ np.double(abs(x_max - x_min) / img_res_x),
+ np.double(abs(y_max - y_min) / img_res_y),
+ np.double(x_min), np.double(y_min),
+ np.uint32(iterations), np.uint32(escape),
+ np.double(frame_i / frames))
+
+
+ cl.enqueue_copy(opencl_queue, image, image_buffer).wait()
+ rendered_frame = ax.imshow(image, norm="log", aspect="auto", cmap=cmap, animated="True")
+ rendered_frames.append([rendered_frame])
+ bar_total()
+ print("Encoding/Saving...")
+ ani = animation.ArtistAnimation(fig, rendered_frames, interval=30, blit=True)
+ ani.save(animation_progres_save, extra_args=['-preset', 'lossless'], progress_callback=display_encoder_progress, codec="h264_nvenc")
+else:
+ ax.callbacks.connect('ylim_changed', render)
+ ax.callbacks.connect('xlim_changed', render)
+ render(ax)
+ plt.show(block=True)
+
+
diff --git a/live_play/kernel.c b/live_play/kernel.c
new file mode 100644
index 0000000..e572a48
--- /dev/null
+++ b/live_play/kernel.c
@@ -0,0 +1,40 @@
+//#include <math.h>
+#define PI 3.141592653589793115997963468544185161590576171875
+
+double cosecant_single(double a, double b) { return a / sin(b); }
+double secant_single(double a, double b) {
+ //double killme = (double)floor(b / (PI / 2.0)) * (double)(PI / 2.0);
+ //return a / sin(killme);
+ //return a / sin((PI / 2.0));
+ //return a / sin(PI);
+ return a / sin(-PI);
+}
+
+
+__kernel void render_frame(__global unsigned int *frame_output, __global double *mask,
+ double x_step, double y_step,
+ double x_start, double y_start,
+ unsigned int iterations, unsigned int escape, double ratio) {
+ unsigned int result;
+ double x = (get_global_id(0) * x_step) + x_start;
+ double y = (get_global_id(1) * y_step) + y_start;
+ size_t img_index = (get_global_id(1) * get_global_size(1)) + get_global_id(0);
+
+ unsigned int iter;
+
+
+
+ for(iter = 0; iter < iterations; iter++) {
+ double next_x;
+ double r = mask[img_index];
+ next_x = (r * cosecant_single(x, y)) + ((1 - r) * secant_single(x, y));
+ y = (r * cosecant_single(y, x)) + ((1 - r) * secant_single(y, x));
+ x = next_x;
+ if((pow(x, 2) + pow(y, 2)) >= escape) break;
+ }
+
+
+
+ frame_output[img_index] = iter;
+ //frame_output[img_index] = mask[img_index] * 255;
+}
diff --git a/live_play/mask.png b/live_play/mask.png
new file mode 120000
index 0000000..5209b4e
--- /dev/null
+++ b/live_play/mask.png
@@ -0,0 +1 @@
+../masks/threedots.png \ No newline at end of file
diff --git a/live_play/notes b/live_play/notes
new file mode 100644
index 0000000..50249d7
--- /dev/null
+++ b/live_play/notes
@@ -0,0 +1,79 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.animation as animation
+import pyopencl as cl
+from alive_progress import alive_bar
+
+img_res_x = 2000
+img_res_y = 2000
+total_pixels = img_res_x * img_res_y # so we don't gotta compute it every time
+
+periods = 1
+square_x = 0
+square_y = 0
+
+xmin = (-periods * np.pi) + (square_x * np.pi)
+xmax = (periods * np.pi) + (square_x * np.pi)
+ymin = (-periods * np.pi) + (square_y * np.pi)
+ymax = (periods * np.pi) + (square_y * np.pi)
+
+escape = 10000
+iterations = 255*3
+c_x = 2 * np.pi
+c_y = 2 * np.pi
+
+animation_progres_save = "./animations"
+frames = 120
+
+rendered_frames = []
+
+
+plt.style.use('dark_background')
+# fuck this shit
+fig = plt.figure(frameon=False)
+fig.set_size_inches(img_res_x/fig.dpi, img_res_y/fig.dpi)
+#fig.set_size_inches(width/height, 1, forward=False)
+
+ax = plt.Axes(fig, [0., 0., 1., 1.])
+ax.set_axis_off()
+fig.add_axes(ax)
+
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+opencl_context = cl.create_some_context()
+opencl_queue = cl.CommandQueue(opencl_context)
+
+
+#def render():
+# image = np.empty([img_res_y, img_res_x])
+# print("Rendering frames")
+# with alive_bar(frames, bar = 'filling', spinner = 'waves') as bar_total:
+# for frame in range(frames):
+# split_ratio = frame / frames
+# for pix_y, y in enumerate(np.linspace(ymin, ymax, img_res_y)):
+# for pix_x, x in enumerate(np.linspace(xmin, xmax, img_res_x)):
+# on_x = x
+# on_y = y
+# for i in range(iterations):
+# next_x = (split_ratio * (on_x/np.sin(on_y))) + ((1 - split_ratio) * on_x/np.tan(on_y))
+# on_y = (split_ratio * (on_y/np.sin(on_x))) + ((1 - split_ratio) * on_y/np.tan(on_x))
+# on_x = next_x
+# if on_x**2 + on_y**2 > escape:
+# break
+# image[pix_y][pix_x] = i
+# rendered_frame = ax.imshow(image, norm="log", aspect="auto", cmap=cmap, animated=False)
+# rendered_frames.append([rendered_frame])
+# bar_total()
+
+def display():
+ print(rendered_frames)
+ ani = animation.ArtistAnimation(fig, rendered_frames, interval=30, blit=True)
+ ani.save("test.mp4")
+ plt.show()
+
+render()
+display()
diff --git a/mask_tests/; b/mask_tests/;
new file mode 100644
index 0000000..665c6ce
--- /dev/null
+++ b/mask_tests/;
@@ -0,0 +1,30 @@
+unsigned int secant_fractal(double x, double y, unsigned int escape, unsigned int iterations) {
+ for(unsigned int iter = 0; iter < iterations; iter++) {
+ double next_x;
+ next_x = x / cos(y);
+ y = y / cos(x);
+ x = next_x;
+ if((pow(x, 2) + pow(y, 2)) >= escape) return iter;
+ }
+}
+unsigned int cosecant_fractal(double x, double y, unsigned int escape, unsigned int iterations) {
+ for(unsigned int iter = 0; iter < iterations; iter++) {
+ double next_x;
+ next_x = x / sin(y);
+ y = y / sin(x);
+ x = next_x;
+ if((pow(x, 2) + pow(y, 2)) >= escape) return iter;
+ }
+}
+
+__kernel void render_frame(__global unsigned int *frame_output, //uint8_t *mask, //more bit depth is possible
+ double x_step, double y_step,
+ double x_start, double y_start,
+ unsigned int iterations, unsigned int escape, double ratio) {
+ unsigned int result;
+ double on_x = (get_global_id(0) * x_step) + x_start;
+ double on_y = (get_global_id(1) * y_step) + y_start;
+
+ frame_output[(get_global_id(1) * get_global_size(1)) + get_global_id(0)] =
+ secant_fractal(on_x, on_y, escape, iterations);
+}
diff --git a/mask_tests/asdf.png b/mask_tests/asdf.png
new file mode 100644
index 0000000..66d8a87
--- /dev/null
+++ b/mask_tests/asdf.png
Binary files differ
diff --git a/mask_tests/kernel.c b/mask_tests/kernel.c
new file mode 100644
index 0000000..669c382
--- /dev/null
+++ b/mask_tests/kernel.c
@@ -0,0 +1,49 @@
+unsigned int secant_fractal(double x, double y, unsigned int escape, unsigned int iterations) {
+ for(unsigned int iter = 0; iter < iterations; iter++) {
+ double next_x;
+ next_x = x / cos(y);
+ y = y / cos(x);
+ x = next_x;
+ if((pow(x, 2) + pow(y, 2)) >= escape) return iter;
+ }
+}
+unsigned int cosecant_fractal(double x, double y, unsigned int escape, unsigned int iterations) {
+ for(unsigned int iter = 0; iter < iterations; iter++) {
+ double next_x;
+ next_x = x / sin(y);
+ y = y / sin(x);
+ x = next_x;
+ if((pow(x, 2) + pow(y, 2)) >= escape) return iter;
+ }
+}
+
+double cosecant_single(double a, double b) { return a / sin(b); }
+double secant_single(double a, double b) { return a / tan(b); }
+
+
+__kernel void render_frame(__global unsigned int *frame_output, __global double *mask,
+ double x_step, double y_step,
+ double x_start, double y_start,
+ unsigned int iterations, unsigned int escape, double ratio) {
+ unsigned int result;
+ double x = (get_global_id(0) * x_step) + x_start;
+ double y = (get_global_id(1) * y_step) + y_start;
+ size_t img_index = (get_global_id(1) * get_global_size(1)) + get_global_id(0);
+
+ unsigned int iter;
+
+
+ for(iter = 0; iter < iterations; iter++) {
+ double next_x;
+ double r = mask[img_index];
+ next_x = (r * cosecant_single(x, y)) + ((1 - r) * secant_single(x, y));
+ y = (r * cosecant_single(y, x)) + ((1 - r) * secant_single(y, x));
+ x = next_x;
+ if((pow(x, 2) + pow(y, 2)) >= escape) break;
+ }
+
+
+
+ frame_output[img_index] = iter;
+ //frame_output[img_index] = mask[img_index] * 255;
+}
diff --git a/mask_tests/mask.png b/mask_tests/mask.png
new file mode 120000
index 0000000..5209b4e
--- /dev/null
+++ b/mask_tests/mask.png
@@ -0,0 +1 @@
+../masks/threedots.png \ No newline at end of file
diff --git a/mask_tests/mask.py b/mask_tests/mask.py
new file mode 100755
index 0000000..ee801d4
--- /dev/null
+++ b/mask_tests/mask.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.animation as animation
+import pyopencl as cl
+from alive_progress import alive_bar
+from matplotlib.backend_bases import MouseButton
+from PIL import Image
+
+img_res_x = 1000
+img_res_y = 1000
+total_pixels = img_res_x * img_res_y # so we don't gotta compute it every time
+
+periods = 1
+square_x = 0
+square_y = 0
+
+x_min = (-periods * np.pi) + (square_x * np.pi)
+x_max = (periods * np.pi) + (square_x * np.pi)
+y_min = (-periods * np.pi) + (square_y * np.pi)
+y_max = (periods * np.pi) + (square_y * np.pi)
+
+escape = 10000
+iterations = 255*3
+c_x = 2 * np.pi
+c_y = 2 * np.pi
+
+animation_progres_save = "ani1_less.mp4"
+single_frame_save = "asdf.png"
+
+opencl_context = cl.create_some_context(interactive=False)
+opencl_queue = cl.CommandQueue(opencl_context)
+
+kernel_src_path = "./kernel.c"
+
+frames = 1
+rendered_frames = []
+
+image = np.empty([img_res_x, img_res_y], np.uint32)
+
+plt.style.use('dark_background')
+# fuck this shit
+fig = plt.figure(frameon=False)
+fig.set_size_inches(img_res_x/fig.dpi, img_res_y/fig.dpi)
+#fig.set_size_inches(width/height, 1, forward=False)
+
+
+ax = plt.Axes(fig, [0., 0., 1., 1.])
+#ax.set_axis_off()
+fig.add_axes(ax)
+
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+mask_path = "mask.png"
+
+bruh = None
+
+def on_click(event):
+ global bruh
+ split_ratio = 1
+ if (event.button is MouseButton.MIDDLE) and (event.inaxes):
+ # there's probably a way to set global coordinates;
+ # I don't expect this to go anywhere so I don't really care
+ on_x = ((event.xdata / img_res_x) * abs(x_max - x_min)) + x_min
+ on_y = ((event.ydata / img_res_y) * abs(y_max - y_min)) + y_min
+
+ #I, uh, also don't know the best way to replicate the openCL code automaticly in python
+ #so ajust if nessesary
+ x_hops = []
+ y_hops = []
+ for i in range(iterations):
+ x_hops.append(((on_x - x_min) / abs(x_max - x_min)) * img_res_x)
+ y_hops.append(((on_y - y_min) / abs(y_max - y_min)) * img_res_y)
+ next_x = on_x/np.tan(on_y)
+ on_y = on_y/np.tan(on_x)
+ on_x = next_x
+ if on_x**2 + on_y**2 > escape:
+ break
+ print(y_hops[0])
+ print(on_y)
+ print("{} hops".format(len(x_hops)))
+ if bruh:
+ bruh.pop(0).remove()
+ bruh = ax.plot(x_hops, y_hops)
+ plt.draw()
+
+
+
+ print(on_x, on_y)
+
+
+print("compiling openCL kernel...")
+with open(kernel_src_path, 'r') as kernel_src:
+ compiled_kernel = cl.Program(opencl_context, kernel_src.read()).build()
+
+encoding_progress = alive_bar(frames, bar = 'filling', spinner = 'waves')
+
+def display_encoder_progress(current_frame: int, total_frames: int):
+ print("Encoding: frame {}/{}".format(current_frame, frames))
+
+#open image
+mask = np.asarray(Image.open(mask_path).convert("L"), dtype=np.double)
+mask.setflags(write=1)
+mask /= np.max(mask) # normalize
+print(mask.shape)
+print(mask.dtype)
+#ax.imshow(mask, norm="linear")
+#plt.show()
+
+image_buffer = cl.Buffer(opencl_context, cl.mem_flags.WRITE_ONLY, image.nbytes)
+mask_buffer = cl.Buffer(opencl_context, cl.mem_flags.READ_ONLY, mask.nbytes)
+cl.enqueue_copy(opencl_queue, mask_buffer, mask).wait()
+#mask_buffer = cl.array.Array(opencl_context,mask.shape, dtype=np.uint8, data=mask)
+
+
+
+
+# TODO clean this up
+print("Rendering {} frames...".format(frames))
+if frames > 1:
+ with alive_bar(frames, bar = 'filling', spinner = 'waves') as bar_total:
+ for frame_i in range(0, frames):
+ compiled_kernel.render_frame(opencl_queue, image.shape, None, image_buffer,
+ np.double(abs(x_max - x_min) / img_res_x),
+ np.double(abs(y_max - y_min) / img_res_y),
+ np.double(x_min), np.double(y_min),
+ np.uint32(iterations), np.uint32(escape),
+ np.double(frame_i / frames))
+
+
+ cl.enqueue_copy(opencl_queue, image, image_buffer).wait()
+ rendered_frame = ax.imshow(image, norm="log", aspect="auto", cmap=cmap, animated="True")
+ rendered_frames.append([rendered_frame])
+ bar_total()
+ print("Encoding/Saving...")
+ ani = animation.ArtistAnimation(fig, rendered_frames, interval=30, blit=True)
+ ani.save(animation_progres_save, extra_args=['-preset', 'lossless'], progress_callback=display_encoder_progress, codec="h264_nvenc")
+else:
+ compiled_kernel.render_frame(opencl_queue, image.shape, None, image_buffer, mask_buffer,
+ np.double(abs(x_max - x_min) / img_res_x),
+ np.double(abs(y_max - y_min) / img_res_y),
+ np.double(x_min), np.double(y_min),
+ np.uint32(iterations), np.uint32(escape),
+ np.double(1))
+ cl.enqueue_copy(opencl_queue, image, image_buffer).wait()
+ ax.imshow(image, norm="log", aspect="auto", cmap=cmap)
+ fig.savefig(single_frame_save)
+ plt.autoscale(False)
+ plt.connect('motion_notify_event', on_click)
+ plt.show()
diff --git a/mask_tests/mask.py.bak b/mask_tests/mask.py.bak
new file mode 100644
index 0000000..8fd3513
--- /dev/null
+++ b/mask_tests/mask.py.bak
@@ -0,0 +1,142 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.animation as animation
+import pyopencl as cl
+from alive_progress import alive_bar
+from matplotlib.backend_bases import MouseButton
+from PIL import Image
+
+img_res_x = 1000
+img_res_y = 1000
+total_pixels = img_res_x * img_res_y # so we don't gotta compute it every time
+
+periods = 1
+square_x = 0
+square_y = 0
+
+x_min = (-periods * np.pi) + (square_x * np.pi)
+x_max = (periods * np.pi) + (square_x * np.pi)
+y_min = (-periods * np.pi) + (square_y * np.pi)
+y_max = (periods * np.pi) + (square_y * np.pi)
+
+escape = 10000
+iterations = 255*3
+c_x = 2 * np.pi
+c_y = 2 * np.pi
+
+animation_progres_save = "ani1_less.mp4"
+single_frame_save = "asdf.png"
+
+opencl_context = cl.create_some_context(interactive=False)
+opencl_queue = cl.CommandQueue(opencl_context)
+
+kernel_src_path = "./kernel.c"
+
+frames = 1
+rendered_frames = []
+
+image = np.empty([img_res_x, img_res_y], np.uint32)
+image_buffer = cl.Buffer(opencl_context, cl.mem_flags.WRITE_ONLY, image.nbytes)
+
+plt.style.use('dark_background')
+# fuck this shit
+fig = plt.figure(frameon=False)
+fig.set_size_inches(img_res_x/fig.dpi, img_res_y/fig.dpi)
+#fig.set_size_inches(width/height, 1, forward=False)
+
+
+ax = plt.Axes(fig, [0., 0., 1., 1.])
+#ax.set_axis_off()
+fig.add_axes(ax)
+
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+mask_path = "mask.png"
+
+bruh = None
+
+def on_click(event):
+ global bruh
+ split_ratio = 1
+ if (event.button is MouseButton.MIDDLE) and (event.inaxes):
+ # there's probably a way to set global coordinates;
+ # I don't expect this to go anywhere so I don't really care
+ on_x = ((event.xdata / img_res_x) * abs(x_max - x_min)) + x_min
+ on_y = ((event.ydata / img_res_y) * abs(y_max - y_min)) + y_min
+
+ #I, uh, also don't know the best way to replicate the openCL code automaticly in python
+ #so ajust if nessesary
+ x_hops = []
+ y_hops = []
+ for i in range(iterations):
+ x_hops.append(((on_x - x_min) / abs(x_max - x_min)) * img_res_x)
+ y_hops.append(((on_y - y_min) / abs(y_max - y_min)) * img_res_y)
+ next_x = on_x/np.tan(on_y)
+ on_y = on_y/np.tan(on_x)
+ on_x = next_x
+ if on_x**2 + on_y**2 > escape:
+ break
+ print(y_hops[0])
+ print(on_y)
+ print("{} hops".format(len(x_hops)))
+ if bruh:
+ bruh.pop(0).remove()
+ bruh = ax.plot(x_hops, y_hops)
+ plt.draw()
+
+
+
+ print(on_x, on_y)
+
+
+print("compiling openCL kernel...")
+with open(kernel_src_path, 'r') as kernel_src:
+ compiled_kernel = cl.Program(opencl_context, kernel_src.read()).build()
+
+encoding_progress = alive_bar(frames, bar = 'filling', spinner = 'waves')
+
+def display_encoder_progress(current_frame: int, total_frames: int):
+ print("Encoding: frame {}/{}".format(current_frame, frames))
+
+with open G
+
+
+# TODO clean this up
+print("Rendering {} frames...".format(frames))
+if frames > 1:
+ with alive_bar(frames, bar = 'filling', spinner = 'waves') as bar_total:
+ for frame_i in range(0, frames):
+ compiled_kernel.render_frame(opencl_queue, image.shape, None, image_buffer,
+ np.double(abs(x_max - x_min) / img_res_x),
+ np.double(abs(y_max - y_min) / img_res_y),
+ np.double(x_min), np.double(y_min),
+ np.uint32(iterations), np.uint32(escape),
+ np.double(frame_i / frames))
+
+
+ cl.enqueue_copy(opencl_queue, image, image_buffer).wait()
+ rendered_frame = ax.imshow(image, norm="log", aspect="auto", cmap=cmap, animated="True")
+ rendered_frames.append([rendered_frame])
+ bar_total()
+ print("Encoding/Saving...")
+ ani = animation.ArtistAnimation(fig, rendered_frames, interval=30, blit=True)
+ ani.save(animation_progres_save, extra_args=['-preset', 'lossless'], progress_callback=display_encoder_progress, codec="h264_nvenc")
+else:
+ compiled_kernel.render_frame(opencl_queue, image.shape, None, image_buffer,
+ np.double(abs(x_max - x_min) / img_res_x),
+ np.double(abs(y_max - y_min) / img_res_y),
+ np.double(x_min), np.double(y_min),
+ np.uint32(iterations), np.uint32(escape),
+ np.double(1))
+ cl.enqueue_copy(opencl_queue, image, image_buffer).wait()
+ ax.imshow(image, norm="log", aspect="auto", cmap=cmap)
+ fig.savefig(single_frame_save)
+ plt.autoscale(False)
+ plt.connect('motion_notify_event', on_click)
+ plt.show()
+
+
diff --git a/mask_tests/notes b/mask_tests/notes
new file mode 100644
index 0000000..50249d7
--- /dev/null
+++ b/mask_tests/notes
@@ -0,0 +1,79 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.animation as animation
+import pyopencl as cl
+from alive_progress import alive_bar
+
+img_res_x = 2000
+img_res_y = 2000
+total_pixels = img_res_x * img_res_y # so we don't gotta compute it every time
+
+periods = 1
+square_x = 0
+square_y = 0
+
+xmin = (-periods * np.pi) + (square_x * np.pi)
+xmax = (periods * np.pi) + (square_x * np.pi)
+ymin = (-periods * np.pi) + (square_y * np.pi)
+ymax = (periods * np.pi) + (square_y * np.pi)
+
+escape = 10000
+iterations = 255*3
+c_x = 2 * np.pi
+c_y = 2 * np.pi
+
+animation_progres_save = "./animations"
+frames = 120
+
+rendered_frames = []
+
+
+plt.style.use('dark_background')
+# fuck this shit
+fig = plt.figure(frameon=False)
+fig.set_size_inches(img_res_x/fig.dpi, img_res_y/fig.dpi)
+#fig.set_size_inches(width/height, 1, forward=False)
+
+ax = plt.Axes(fig, [0., 0., 1., 1.])
+ax.set_axis_off()
+fig.add_axes(ax)
+
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+opencl_context = cl.create_some_context()
+opencl_queue = cl.CommandQueue(opencl_context)
+
+
+#def render():
+# image = np.empty([img_res_y, img_res_x])
+# print("Rendering frames")
+# with alive_bar(frames, bar = 'filling', spinner = 'waves') as bar_total:
+# for frame in range(frames):
+# split_ratio = frame / frames
+# for pix_y, y in enumerate(np.linspace(ymin, ymax, img_res_y)):
+# for pix_x, x in enumerate(np.linspace(xmin, xmax, img_res_x)):
+# on_x = x
+# on_y = y
+# for i in range(iterations):
+# next_x = (split_ratio * (on_x/np.sin(on_y))) + ((1 - split_ratio) * on_x/np.tan(on_y))
+# on_y = (split_ratio * (on_y/np.sin(on_x))) + ((1 - split_ratio) * on_y/np.tan(on_x))
+# on_x = next_x
+# if on_x**2 + on_y**2 > escape:
+# break
+# image[pix_y][pix_x] = i
+# rendered_frame = ax.imshow(image, norm="log", aspect="auto", cmap=cmap, animated=False)
+# rendered_frames.append([rendered_frame])
+# bar_total()
+
+def display():
+ print(rendered_frames)
+ ani = animation.ArtistAnimation(fig, rendered_frames, interval=30, blit=True)
+ ani.save("test.mp4")
+ plt.show()
+
+render()
+display()
diff --git a/masks/clouds.png b/masks/clouds.png
new file mode 100644
index 0000000..d57cade
--- /dev/null
+++ b/masks/clouds.png
Binary files differ
diff --git a/masks/hi.png b/masks/hi.png
new file mode 100644
index 0000000..f565075
--- /dev/null
+++ b/masks/hi.png
Binary files differ
diff --git a/masks/test_circle.png b/masks/test_circle.png
new file mode 100644
index 0000000..a52b528
--- /dev/null
+++ b/masks/test_circle.png
Binary files differ
diff --git a/masks/test_circle_linear_smooth.png b/masks/test_circle_linear_smooth.png
new file mode 100644
index 0000000..ba4687f
--- /dev/null
+++ b/masks/test_circle_linear_smooth.png
Binary files differ
diff --git a/masks/test_circle_perceptual_smooth.png b/masks/test_circle_perceptual_smooth.png
new file mode 100644
index 0000000..a26d2aa
--- /dev/null
+++ b/masks/test_circle_perceptual_smooth.png
Binary files differ
diff --git a/masks/test_diagnol.png b/masks/test_diagnol.png
new file mode 100644
index 0000000..270c160
--- /dev/null
+++ b/masks/test_diagnol.png
Binary files differ
diff --git a/masks/test_diagnol_linear_smooth.png b/masks/test_diagnol_linear_smooth.png
new file mode 100644
index 0000000..b9d929c
--- /dev/null
+++ b/masks/test_diagnol_linear_smooth.png
Binary files differ
diff --git a/masks/test_diagnol_perceptual_smooth.png b/masks/test_diagnol_perceptual_smooth.png
new file mode 100644
index 0000000..82aa4af
--- /dev/null
+++ b/masks/test_diagnol_perceptual_smooth.png
Binary files differ
diff --git a/masks/threedots.png b/masks/threedots.png
new file mode 100644
index 0000000..0d059f1
--- /dev/null
+++ b/masks/threedots.png
Binary files differ
diff --git a/photos_incorrectly_named/cosine_gpu_double_2.png b/photos_incorrectly_named/cosine_gpu_double_2.png
new file mode 100644
index 0000000..0d5ced0
--- /dev/null
+++ b/photos_incorrectly_named/cosine_gpu_double_2.png
Binary files differ
diff --git a/photos_incorrectly_named/cpu.png b/photos_incorrectly_named/cpu.png
new file mode 100644
index 0000000..ddea68c
--- /dev/null
+++ b/photos_incorrectly_named/cpu.png
Binary files differ
diff --git a/photos_incorrectly_named/ice_period_16.png b/photos_incorrectly_named/ice_period_16.png
new file mode 100644
index 0000000..7d7b208
--- /dev/null
+++ b/photos_incorrectly_named/ice_period_16.png
Binary files differ
diff --git a/photos_incorrectly_named/ice_period_16_shifted_.25.png b/photos_incorrectly_named/ice_period_16_shifted_.25.png
new file mode 100644
index 0000000..9943361
--- /dev/null
+++ b/photos_incorrectly_named/ice_period_16_shifted_.25.png
Binary files differ
diff --git a/photos_incorrectly_named/ice_period_16_shifted_.5.png b/photos_incorrectly_named/ice_period_16_shifted_.5.png
new file mode 100644
index 0000000..0bb2589
--- /dev/null
+++ b/photos_incorrectly_named/ice_period_16_shifted_.5.png
Binary files differ
diff --git a/photos_incorrectly_named/ice_period_noshift_x_1.png b/photos_incorrectly_named/ice_period_noshift_x_1.png
new file mode 100644
index 0000000..3be0525
--- /dev/null
+++ b/photos_incorrectly_named/ice_period_noshift_x_1.png
Binary files differ
diff --git a/photos_incorrectly_named/linear_transform_sin_tan_arnolds_tongue_hotspot.png b/photos_incorrectly_named/linear_transform_sin_tan_arnolds_tongue_hotspot.png
new file mode 100644
index 0000000..1e5b02d
--- /dev/null
+++ b/photos_incorrectly_named/linear_transform_sin_tan_arnolds_tongue_hotspot.png
Binary files differ
diff --git a/polar/.gpu_migration.py.swo b/polar/.gpu_migration.py.swo
new file mode 100644
index 0000000..4806821
--- /dev/null
+++ b/polar/.gpu_migration.py.swo
Binary files differ
diff --git a/polar/.gpu_migration.py.swp b/polar/.gpu_migration.py.swp
new file mode 100644
index 0000000..29b75a7
--- /dev/null
+++ b/polar/.gpu_migration.py.swp
Binary files differ
diff --git a/polar/.kernel.c.swp b/polar/.kernel.c.swp
new file mode 100644
index 0000000..6ab3a51
--- /dev/null
+++ b/polar/.kernel.c.swp
Binary files differ
diff --git a/polar/gpu_migration.py b/polar/gpu_migration.py
new file mode 100755
index 0000000..1a8af19
--- /dev/null
+++ b/polar/gpu_migration.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.animation as animation
+import matplotlib.style as mplstyle
+import pyopencl as cl
+from alive_progress import alive_bar
+from matplotlib.backend_bases import MouseButton
+from PIL import Image
+
+# HELLO READER ------------------------------------------------------------------------
+# yes, I know this script is horrid, but it's more of a scratchpad to quickly test ideas
+# and not anything I'm ever going to show anyone else.
+
+img_res_x = 10000
+img_res_y = 10000
+total_pixels = img_res_x * img_res_y # so we don't gotta compute it every time
+
+periods = 1
+square_x = 0
+square_y = -2
+
+escape = 10000
+iterations = (255*3)
+c_x = 2 * np.pi
+c_y = 2 * np.pi
+
+animation_progres_save = "ani1_less.mp4"
+single_frame_save = "asdf.png"
+
+opencl_context = cl.create_some_context(interactive=False)
+opencl_queue = cl.CommandQueue(opencl_context)
+
+kernel_src_path = "./kernel.c"
+
+frames = 1
+rendered_frames = []
+
+image = np.empty([img_res_x, img_res_y], np.uint32)
+
+plt.style.use('dark_background')
+# fuck this shit
+fig = plt.figure(frameon=False)
+fig.set_size_inches(img_res_x/fig.dpi, img_res_y/fig.dpi)
+#fig.set_size_inches(width/height, 1, forward=False)
+
+
+ax = plt.Axes(fig, [0., 0., 1., 1.])
+
+#ax.invert_yaxis()
+#ax.set_xlim((-periods * np.pi) + (square_x * np.pi), (periods * np.pi) + (square_x * np.pi))
+#ax.set_ylim((-periods * np.pi) + (square_y * np.pi), (periods * np.pi) + (square_y * np.pi))
+ax.set_xlim(-6.678564587410841, -4.837591292407222)
+ax.set_ylim(-1.0818908008385455, 0.9287284974589227)
+
+#ax.set_axis_off()
+fig.add_axes(ax)
+mplstyle.use('fast')
+
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+
+
+
+print("compiling openCL kernel...")
+with open(kernel_src_path, 'r') as kernel_src:
+ compiled_kernel = cl.Program(opencl_context, kernel_src.read()).build()
+
+encoding_progress = alive_bar(frames, bar = 'filling', spinner = 'waves')
+
+def display_encoder_progress(current_frame: int, total_frames: int):
+ print("Encoding: frame {}/{}".format(current_frame, frames))
+
+temp_render_hook = False
+mp_image = None
+
+def render(axes):
+ global temp_render_hook
+ global mp_image
+ if not temp_render_hook:
+ temp_render_hook = True
+ x_min = axes.get_xlim()[0]
+ x_max = axes.get_xlim()[1]
+ y_min = axes.get_ylim()[1]
+ y_max = axes.get_ylim()[0]
+ print(axes.get_ylim())
+ compiled_kernel.render_frame(opencl_queue, image.shape, None, image_buffer, mask_buffer,
+ np.double(abs(x_max - x_min) / img_res_x),
+ np.double(abs(y_max - y_min) / img_res_y),
+ np.double(x_min), np.double(y_min),
+ np.uint32(iterations), np.uint32(escape),
+ np.double(1))
+ cl.enqueue_copy(opencl_queue, image, image_buffer).wait()
+ print("kernel")
+ if mp_image == None:
+ mp_image = ax.imshow(image, norm="log", aspect="auto", cmap=cmap, interpolation='none', extent=(x_min, x_max, y_min, y_max)) # TODO
+ else:
+ mp_image.set(extent=(x_min, x_max, y_min, y_max))
+ #ax.set_aspect('equal')
+ #mp_image.set_data(image)
+ mp_image.set_array(image)
+
+
+ fig.canvas.draw_idle()
+ fig.canvas.flush_events()
+ temp_render_hook = False
+
+#plt.ion()
+
+#open image
+mask_path = "mask.png"
+mask = np.asarray(Image.open(mask_path).convert("L").resize((img_res_x, img_res_y)), dtype=np.double)
+#mask = np.zeros((img_res_x, img_res_y), dtype=np.double)
+mask.setflags(write=1)
+mask /= np.max(mask) # normalize
+print(mask.shape)
+print(mask.dtype)
+print(mask)
+#ax.imshow(mask, norm="linear")
+#plt.show()
+
+image_buffer = cl.Buffer(opencl_context, cl.mem_flags.WRITE_ONLY, image.nbytes)
+mask_buffer = cl.Buffer(opencl_context, cl.mem_flags.READ_ONLY, mask.nbytes)
+cl.enqueue_copy(opencl_queue, mask_buffer, mask).wait()
+#mask_buffer = cl.array.Array(opencl_context,mask.shape, dtype=np.uint8, data=mask)
+
+#move to render
+print("Rendering {} frames...".format(frames))
+if frames > 1:
+ with alive_bar(frames, bar = 'filling', spinner = 'waves') as bar_total:
+ for frame_i in range(0, frames):
+ compiled_kernel.render_frame(opencl_queue, image.shape, None, image_buffer, mask,
+ np.double(abs(x_max - x_min) / img_res_x),
+ np.double(abs(y_max - y_min) / img_res_y),
+ np.double(x_min), np.double(y_min),
+ np.uint32(iterations), np.uint32(escape),
+ np.double(frame_i / frames))
+
+
+ cl.enqueue_copy(opencl_queue, image, image_buffer).wait()
+ rendered_frame = ax.imshow(image, norm="linear", aspect="auto", cmap=cmap, animated="True")
+ rendered_frames.append([rendered_frame])
+ bar_total()
+ print("Encoding/Saving...")
+ ani = animation.ArtistAnimation(fig, rendered_frames, interval=30, blit=True)
+ ani.save(animation_progres_save, extra_args=['-preset', 'lossless'], progress_callback=display_encoder_progress, codec="h264_nvenc")
+else:
+ ax.callbacks.connect('ylim_changed', render)
+ ax.callbacks.connect('xlim_changed', render)
+ render(ax)
+ plt.savefig("out.png")
+ #plt.show(block=True)
+
+
diff --git a/polar/kernel.c b/polar/kernel.c
new file mode 100644
index 0000000..1369a7f
--- /dev/null
+++ b/polar/kernel.c
@@ -0,0 +1,35 @@
+//#include <math.h>
+#define PI 3.141592653589793115997963468544185161590576171875
+
+double cosecant_single(double a, double b) { return a / sin(b); }
+double secant_single(double a, double b) { return a / tan(b); }
+
+
+__kernel void render_frame(__global unsigned int *frame_output, __global double *mask,
+ double x_step, double y_step,
+ double x_start, double y_start,
+ unsigned int iterations, unsigned int escape, double ratio) {
+ unsigned int result;
+ double x_cart = (get_global_id(0) * x_step) + x_start;
+ double y_cart = (get_global_id(1) * y_step) + y_start;
+ size_t img_index = (get_global_id(1) * get_global_size(1)) + get_global_id(0);
+
+ double x = sqrt(pow(x_cart, 2) + pow(y_cart, 2));
+ double y = atan(y_cart / x_cart);
+
+ unsigned int iter;
+
+ for(iter = 0; iter < iterations; iter++) {
+ double next_x;
+ double r = mask[img_index];
+ next_x = (r * cosecant_single(x, y)) + ((1 - r) * secant_single(x, y));
+ y = (r * cosecant_single(y, x)) + ((1 - r) * secant_single(y, x));
+ x = next_x;
+ if((pow(x, 2) + pow(y, 2)) >= escape) break;
+ }
+
+
+
+ frame_output[img_index] = iter;
+ //frame_output[img_index] = mask[img_index] * 255;
+}
diff --git a/polar/notes b/polar/notes
new file mode 100644
index 0000000..50249d7
--- /dev/null
+++ b/polar/notes
@@ -0,0 +1,79 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.animation as animation
+import pyopencl as cl
+from alive_progress import alive_bar
+
+img_res_x = 2000
+img_res_y = 2000
+total_pixels = img_res_x * img_res_y # so we don't gotta compute it every time
+
+periods = 1
+square_x = 0
+square_y = 0
+
+xmin = (-periods * np.pi) + (square_x * np.pi)
+xmax = (periods * np.pi) + (square_x * np.pi)
+ymin = (-periods * np.pi) + (square_y * np.pi)
+ymax = (periods * np.pi) + (square_y * np.pi)
+
+escape = 10000
+iterations = 255*3
+c_x = 2 * np.pi
+c_y = 2 * np.pi
+
+animation_progres_save = "./animations"
+frames = 120
+
+rendered_frames = []
+
+
+plt.style.use('dark_background')
+# fuck this shit
+fig = plt.figure(frameon=False)
+fig.set_size_inches(img_res_x/fig.dpi, img_res_y/fig.dpi)
+#fig.set_size_inches(width/height, 1, forward=False)
+
+ax = plt.Axes(fig, [0., 0., 1., 1.])
+ax.set_axis_off()
+fig.add_axes(ax)
+
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+opencl_context = cl.create_some_context()
+opencl_queue = cl.CommandQueue(opencl_context)
+
+
+#def render():
+# image = np.empty([img_res_y, img_res_x])
+# print("Rendering frames")
+# with alive_bar(frames, bar = 'filling', spinner = 'waves') as bar_total:
+# for frame in range(frames):
+# split_ratio = frame / frames
+# for pix_y, y in enumerate(np.linspace(ymin, ymax, img_res_y)):
+# for pix_x, x in enumerate(np.linspace(xmin, xmax, img_res_x)):
+# on_x = x
+# on_y = y
+# for i in range(iterations):
+# next_x = (split_ratio * (on_x/np.sin(on_y))) + ((1 - split_ratio) * on_x/np.tan(on_y))
+# on_y = (split_ratio * (on_y/np.sin(on_x))) + ((1 - split_ratio) * on_y/np.tan(on_x))
+# on_x = next_x
+# if on_x**2 + on_y**2 > escape:
+# break
+# image[pix_y][pix_x] = i
+# rendered_frame = ax.imshow(image, norm="log", aspect="auto", cmap=cmap, animated=False)
+# rendered_frames.append([rendered_frame])
+# bar_total()
+
+def display():
+ print(rendered_frames)
+ ani = animation.ArtistAnimation(fig, rendered_frames, interval=30, blit=True)
+ ani.save("test.mp4")
+ plt.show()
+
+render()
+display()
diff --git a/polar/texput.log b/polar/texput.log
new file mode 100644
index 0000000..d13b81a
--- /dev/null
+++ b/polar/texput.log
@@ -0,0 +1,21 @@
+This is pdfTeX, Version 3.141592653-2.6-1.40.26 (TeX Live 2024/Arch Linux) (preloaded format=pdflatex 2024.4.22) 28 APR 2024 21:33
+entering extended mode
+ restricted \write18 enabled.
+ %&-line parsing enabled.
+**
+
+! Emergency stop.
+<*>
+
+End of file on the terminal!
+
+
+Here is how much of TeX's memory you used:
+ 3 strings out of 476076
+ 113 string characters out of 5793775
+ 1925187 words of memory out of 5000000
+ 22212 multiletter control sequences out of 15000+600000
+ 558069 words of font info for 36 fonts, out of 8000000 for 9000
+ 14 hyphenation exceptions out of 8191
+ 0i,0n,0p,13b,6s stack positions out of 10000i,1000n,20000p,200000b,200000s
+! ==> Fatal error occurred, no output PDF file produced!
diff --git a/thorn_fractal.py b/thorn_fractal.py
new file mode 100755
index 0000000..ed0e431
--- /dev/null
+++ b/thorn_fractal.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+
+img_res_x = 2000
+img_res_y = 2000
+
+xmin = -np.pi
+xmax = np.pi
+ymin = -np.pi
+ymax = np.pi
+
+escape = 10000
+iterations = 255
+c_x = 0
+c_y = 0
+
+
+image = np.empty([img_res_y, img_res_x], np.float32)
+
+for pix_y, y in enumerate(np.linspace(ymin, ymax, img_res_y)):
+ for pix_x, x in enumerate(np.linspace(xmin, xmax, img_res_x)):
+ on_x = x
+ on_y = y
+ for i in range(iterations):
+ next_x = (on_x/np.sin(on_y))
+ on_y = (on_y/np.sin(on_x))
+ on_x = next_x
+ if on_x**2 + on_y**2 > escape:
+ break
+ image[pix_y][pix_x] = i
+ #print(pix_y)
+
+
+
+
+plt.style.use('dark_background')
+# fuck this shit
+fig = plt.figure(frameon=False)
+fig.set_size_inches(img_res_x/fig.dpi, img_res_y/fig.dpi)
+#fig.set_size_inches(width/height, 1, forward=False)
+print(fig.dpi)
+
+ax = plt.Axes(fig, [0., 0., 1., 1.])
+ax.set_axis_off()
+fig.add_axes(ax)
+
+cmap = plt.cm.viridis
+cmap.set_bad((0,0,0))
+cmap.set_over((0,0,0))
+cmap.set_under((0,0,0))
+
+ax.imshow(image, norm="log", aspect="auto", cmap=cmap)
+fig.savefig("animation/cpu.png")
+#plt.show()