Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit556feda

Browse files
authored
Merge pull requestpyscript#26 from anaconda/mattpap/numpy_canvas_example
Add a visualization with NumPy and canvas
2 parentsa612b64 +6919093 commit556feda

File tree

4 files changed

+267
-0
lines changed

4 files changed

+267
-0
lines changed

‎pyscriptjs/examples/fractals.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
importnumpyasnp
2+
3+
defmandelbrot(width:int,height:int,*,
4+
x:float=-0.5,y:float=0,zoom:int=1,max_iterations:int=100)->np.array:
5+
"""
6+
From https://www.learnpythonwithrune.org/numpy-compute-mandelbrot-set-by-vectorization/.
7+
"""
8+
# To make navigation easier we calculate these values
9+
x_width,y_height=1.5,1.5*height/width
10+
x_from,x_to=x-x_width/zoom,x+x_width/zoom
11+
y_from,y_to=y-y_height/zoom,y+y_height/zoom
12+
13+
# Here the actual algorithm starts
14+
x=np.linspace(x_from,x_to,width).reshape((1,width))
15+
y=np.linspace(y_from,y_to,height).reshape((height,1))
16+
c=x+1j*y
17+
18+
# Initialize z to all zero
19+
z=np.zeros(c.shape,dtype=np.complex128)
20+
21+
# To keep track in which iteration the point diverged
22+
div_time=np.zeros(z.shape,dtype=int)
23+
24+
# To keep track on which points did not converge so far
25+
m=np.full(c.shape,True,dtype=bool)
26+
foriinrange(max_iterations):
27+
z[m]=z[m]**2+c[m]
28+
diverged=np.greater(np.abs(z),2,out=np.full(c.shape,False),where=m)# Find diverging
29+
div_time[diverged]=i# set the value of the diverged iteration number
30+
m[np.abs(z)>2]=False# to remember which have diverged
31+
32+
returndiv_time
33+
34+
defjulia(width:int,height:int,*,
35+
c:complex=-0.4+0.6j,x:float=0,y:float=0,zoom:int=1,max_iterations:int=100)->np.array:
36+
"""
37+
From https://www.learnpythonwithrune.org/numpy-calculate-the-julia-set-with-vectorization/.
38+
"""
39+
# To make navigation easier we calculate these values
40+
x_width,y_height=1.5,1.5*height/width
41+
x_from,x_to=x-x_width/zoom,x+x_width/zoom
42+
y_from,y_to=y-y_height/zoom,y+y_height/zoom
43+
44+
# Here the actual algorithm starts
45+
x=np.linspace(x_from,x_to,width).reshape((1,width))
46+
y=np.linspace(y_from,y_to,height).reshape((height,1))
47+
z=x+1j*y
48+
49+
# Initialize z to all zero
50+
c=np.full(z.shape,c)
51+
52+
# To keep track in which iteration the point diverged
53+
div_time=np.zeros(z.shape,dtype=int)
54+
55+
# To keep track on which points did not converge so far
56+
m=np.full(c.shape,True,dtype=bool)
57+
foriinrange(max_iterations):
58+
z[m]=z[m]**2+c[m]
59+
m[np.abs(z)>2]=False
60+
div_time[m]=i
61+
62+
returndiv_time

‎pyscriptjs/examples/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ <h2 class="text-2xl font-bold text-blue-600"><a href="./panel.html" target=”_b
4545
<h2class="text-2xl font-bold text-blue-600"><ahref="./d3.html"target=”_blank”>Simple d3 visualization</a></h2>
4646
<p>Minimal d3 demo demonstrating how to create a visualization</p>
4747

48+
<h2class="text-2xl font-bold text-blue-600"><ahref="./numpy_canvas_fractals.html"target=”_blank”>Fractals with NumPy and canvas</a></h2>
49+
<p>Visualization of Mandelbrot and Julia sets with NumPy and HTML5 canvas</p>
4850

4951
<h2class="text-2xl font-bold text-blue-600"><ahref="./repl.html"target=”_blank”>REPL</a></h2>
5052
<p>A Python REPL (Read Eval Print Loop).</p>
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
<html>
2+
<head>
3+
<title>Visualization of Mandelbrot and Julia sets with NumPy and HTML5 canvas</title>
4+
<metacharset="utf-8">
5+
6+
<linkrel="stylesheet"href="../build/pyscript.css"/>
7+
<scriptdefersrc="../build/pyscript.js"></script>
8+
9+
<style>
10+
.loading {
11+
display: inline-block;
12+
width:50px;
13+
height:50px;
14+
border:3px solidrgba(255,255,255,0.3);
15+
border-radius:50%;
16+
border-top-color: black;
17+
animation: spin1s ease-in-out infinite;
18+
}
19+
20+
@keyframes spin {
21+
to {
22+
transform:rotate(360deg);
23+
}
24+
}
25+
</style>
26+
27+
</head>
28+
<body>
29+
<b>
30+
</b>
31+
<divstyle="display: flex; flex-direction: row; gap: 1em">
32+
<div>
33+
<divstyle="text-align: center">Mandelbrot set</div>
34+
<divid="mandelbrot"style="width: 600px; height: 600px">
35+
<divclass="loading"></div>
36+
</div>
37+
</div>
38+
<div>
39+
<divstyle="text-align: center">Julia set</div>
40+
<divid="julia"style="width: 600px; height: 600px">
41+
<divclass="loading"></div>
42+
</div>
43+
</div>
44+
</div>
45+
46+
<py-env>
47+
- numpy
48+
- paths:
49+
- /palettes.py
50+
- /fractals.py
51+
</py-env>
52+
53+
<py-script>
54+
from pyodide import to_js
55+
56+
import numpy as np
57+
58+
from palettes import Magma256
59+
from fractals import mandelbrot, julia
60+
61+
from js import (
62+
console,
63+
document,
64+
devicePixelRatio,
65+
ImageData,
66+
Uint8ClampedArray,
67+
CanvasRenderingContext2D as Context2d,
68+
)
69+
70+
def create_canvas(width: int, height: int, target: str) -> Context2d:
71+
pixel_ratio = devicePixelRatio
72+
73+
canvas = document.createElement("canvas")
74+
ctx = canvas.getContext("2d")
75+
76+
canvas.style.width = f"{width}px"
77+
canvas.style.height = f"{height}px"
78+
79+
canvas.width = width*pixel_ratio
80+
canvas.height = height*pixel_ratio
81+
82+
ctx.scale(pixel_ratio, pixel_ratio)
83+
ctx.translate(0.5, 0.5)
84+
85+
ctx.clearRect(0, 0, width, height)
86+
87+
el = document.querySelector(target)
88+
el.replaceChildren(canvas)
89+
90+
return ctx
91+
92+
def color_map(array: np.array, palette: np.array) -> np.array:
93+
size, _ = palette.shape
94+
index = (array/array.max()*(size - 1)).round().astype("uint8")
95+
96+
width, height = array.shape
97+
image = np.full((width, height, 4), 0xff, dtype=np.uint8)
98+
image[:, :, :3] = palette[index]
99+
100+
return image
101+
102+
def draw_image(ctx: Context2d, image: np.array) -> None:
103+
data = Uint8ClampedArray.new(to_js(image.tobytes()))
104+
width, height, _ = image.shape
105+
image_data = ImageData.new(data, width, height)
106+
ctx.putImageData(image_data, 0, 0)
107+
108+
def draw_mandelbrot(width: int, height: int) -> None:
109+
ctx = create_canvas(width, height, "#mandelbrot")
110+
111+
console.log("Computing Mandelbrot set ...")
112+
console.time("mandelbrot")
113+
array = mandelbrot(width, height)
114+
console.timeEnd("mandelbrot")
115+
116+
image = color_map(array, Magma256)
117+
draw_image(ctx, image)
118+
119+
def draw_julia(width: int, height: int) -> None:
120+
ctx = create_canvas(width, height, "#julia")
121+
122+
console.log("Computing Julia set ...")
123+
console.time("julia")
124+
array = julia(width, height)
125+
console.timeEnd("julia")
126+
127+
image = color_map(array, Magma256)
128+
draw_image(ctx, image)
129+
130+
draw_mandelbrot(600, 600)
131+
draw_julia(600, 600)
132+
</py-script>
133+
134+
</body>
135+
</html>

‎pyscriptjs/examples/palettes.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
importnumpyasnp
2+
3+
Magma256=np.array([
4+
[0x00,0x00,0x03], [0x00,0x00,0x04], [0x00,0x00,0x06], [0x01,0x00,0x07],
5+
[0x01,0x01,0x09], [0x01,0x01,0x0b], [0x02,0x02,0x0d], [0x02,0x02,0x0f],
6+
[0x03,0x03,0x11], [0x04,0x03,0x13], [0x04,0x04,0x15], [0x05,0x04,0x17],
7+
[0x06,0x05,0x19], [0x07,0x05,0x1b], [0x08,0x06,0x1d], [0x09,0x07,0x1f],
8+
[0x0a,0x07,0x22], [0x0b,0x08,0x24], [0x0c,0x09,0x26], [0x0d,0x0a,0x28],
9+
[0x0e,0x0a,0x2a], [0x0f,0x0b,0x2c], [0x10,0x0c,0x2f], [0x11,0x0c,0x31],
10+
[0x12,0x0d,0x33], [0x14,0x0d,0x35], [0x15,0x0e,0x38], [0x16,0x0e,0x3a],
11+
[0x17,0x0f,0x3c], [0x18,0x0f,0x3f], [0x1a,0x10,0x41], [0x1b,0x10,0x44],
12+
[0x1c,0x10,0x46], [0x1e,0x10,0x49], [0x1f,0x11,0x4b], [0x20,0x11,0x4d],
13+
[0x22,0x11,0x50], [0x23,0x11,0x52], [0x25,0x11,0x55], [0x26,0x11,0x57],
14+
[0x28,0x11,0x59], [0x2a,0x11,0x5c], [0x2b,0x11,0x5e], [0x2d,0x10,0x60],
15+
[0x2f,0x10,0x62], [0x30,0x10,0x65], [0x32,0x10,0x67], [0x34,0x10,0x68],
16+
[0x35,0x0f,0x6a], [0x37,0x0f,0x6c], [0x39,0x0f,0x6e], [0x3b,0x0f,0x6f],
17+
[0x3c,0x0f,0x71], [0x3e,0x0f,0x72], [0x40,0x0f,0x73], [0x42,0x0f,0x74],
18+
[0x43,0x0f,0x75], [0x45,0x0f,0x76], [0x47,0x0f,0x77], [0x48,0x10,0x78],
19+
[0x4a,0x10,0x79], [0x4b,0x10,0x79], [0x4d,0x11,0x7a], [0x4f,0x11,0x7b],
20+
[0x50,0x12,0x7b], [0x52,0x12,0x7c], [0x53,0x13,0x7c], [0x55,0x13,0x7d],
21+
[0x57,0x14,0x7d], [0x58,0x15,0x7e], [0x5a,0x15,0x7e], [0x5b,0x16,0x7e],
22+
[0x5d,0x17,0x7e], [0x5e,0x17,0x7f], [0x60,0x18,0x7f], [0x61,0x18,0x7f],
23+
[0x63,0x19,0x7f], [0x65,0x1a,0x80], [0x66,0x1a,0x80], [0x68,0x1b,0x80],
24+
[0x69,0x1c,0x80], [0x6b,0x1c,0x80], [0x6c,0x1d,0x80], [0x6e,0x1e,0x81],
25+
[0x6f,0x1e,0x81], [0x71,0x1f,0x81], [0x73,0x1f,0x81], [0x74,0x20,0x81],
26+
[0x76,0x21,0x81], [0x77,0x21,0x81], [0x79,0x22,0x81], [0x7a,0x22,0x81],
27+
[0x7c,0x23,0x81], [0x7e,0x24,0x81], [0x7f,0x24,0x81], [0x81,0x25,0x81],
28+
[0x82,0x25,0x81], [0x84,0x26,0x81], [0x85,0x26,0x81], [0x87,0x27,0x81],
29+
[0x89,0x28,0x81], [0x8a,0x28,0x81], [0x8c,0x29,0x80], [0x8d,0x29,0x80],
30+
[0x8f,0x2a,0x80], [0x91,0x2a,0x80], [0x92,0x2b,0x80], [0x94,0x2b,0x80],
31+
[0x95,0x2c,0x80], [0x97,0x2c,0x7f], [0x99,0x2d,0x7f], [0x9a,0x2d,0x7f],
32+
[0x9c,0x2e,0x7f], [0x9e,0x2e,0x7e], [0x9f,0x2f,0x7e], [0xa1,0x2f,0x7e],
33+
[0xa3,0x30,0x7e], [0xa4,0x30,0x7d], [0xa6,0x31,0x7d], [0xa7,0x31,0x7d],
34+
[0xa9,0x32,0x7c], [0xab,0x33,0x7c], [0xac,0x33,0x7b], [0xae,0x34,0x7b],
35+
[0xb0,0x34,0x7b], [0xb1,0x35,0x7a], [0xb3,0x35,0x7a], [0xb5,0x36,0x79],
36+
[0xb6,0x36,0x79], [0xb8,0x37,0x78], [0xb9,0x37,0x78], [0xbb,0x38,0x77],
37+
[0xbd,0x39,0x77], [0xbe,0x39,0x76], [0xc0,0x3a,0x75], [0xc2,0x3a,0x75],
38+
[0xc3,0x3b,0x74], [0xc5,0x3c,0x74], [0xc6,0x3c,0x73], [0xc8,0x3d,0x72],
39+
[0xca,0x3e,0x72], [0xcb,0x3e,0x71], [0xcd,0x3f,0x70], [0xce,0x40,0x70],
40+
[0xd0,0x41,0x6f], [0xd1,0x42,0x6e], [0xd3,0x42,0x6d], [0xd4,0x43,0x6d],
41+
[0xd6,0x44,0x6c], [0xd7,0x45,0x6b], [0xd9,0x46,0x6a], [0xda,0x47,0x69],
42+
[0xdc,0x48,0x69], [0xdd,0x49,0x68], [0xde,0x4a,0x67], [0xe0,0x4b,0x66],
43+
[0xe1,0x4c,0x66], [0xe2,0x4d,0x65], [0xe4,0x4e,0x64], [0xe5,0x50,0x63],
44+
[0xe6,0x51,0x62], [0xe7,0x52,0x62], [0xe8,0x54,0x61], [0xea,0x55,0x60],
45+
[0xeb,0x56,0x60], [0xec,0x58,0x5f], [0xed,0x59,0x5f], [0xee,0x5b,0x5e],
46+
[0xee,0x5d,0x5d], [0xef,0x5e,0x5d], [0xf0,0x60,0x5d], [0xf1,0x61,0x5c],
47+
[0xf2,0x63,0x5c], [0xf3,0x65,0x5c], [0xf3,0x67,0x5b], [0xf4,0x68,0x5b],
48+
[0xf5,0x6a,0x5b], [0xf5,0x6c,0x5b], [0xf6,0x6e,0x5b], [0xf6,0x70,0x5b],
49+
[0xf7,0x71,0x5b], [0xf7,0x73,0x5c], [0xf8,0x75,0x5c], [0xf8,0x77,0x5c],
50+
[0xf9,0x79,0x5c], [0xf9,0x7b,0x5d], [0xf9,0x7d,0x5d], [0xfa,0x7f,0x5e],
51+
[0xfa,0x80,0x5e], [0xfa,0x82,0x5f], [0xfb,0x84,0x60], [0xfb,0x86,0x60],
52+
[0xfb,0x88,0x61], [0xfb,0x8a,0x62], [0xfc,0x8c,0x63], [0xfc,0x8e,0x63],
53+
[0xfc,0x90,0x64], [0xfc,0x92,0x65], [0xfc,0x93,0x66], [0xfd,0x95,0x67],
54+
[0xfd,0x97,0x68], [0xfd,0x99,0x69], [0xfd,0x9b,0x6a], [0xfd,0x9d,0x6b],
55+
[0xfd,0x9f,0x6c], [0xfd,0xa1,0x6e], [0xfd,0xa2,0x6f], [0xfd,0xa4,0x70],
56+
[0xfe,0xa6,0x71], [0xfe,0xa8,0x73], [0xfe,0xaa,0x74], [0xfe,0xac,0x75],
57+
[0xfe,0xae,0x76], [0xfe,0xaf,0x78], [0xfe,0xb1,0x79], [0xfe,0xb3,0x7b],
58+
[0xfe,0xb5,0x7c], [0xfe,0xb7,0x7d], [0xfe,0xb9,0x7f], [0xfe,0xbb,0x80],
59+
[0xfe,0xbc,0x82], [0xfe,0xbe,0x83], [0xfe,0xc0,0x85], [0xfe,0xc2,0x86],
60+
[0xfe,0xc4,0x88], [0xfe,0xc6,0x89], [0xfe,0xc7,0x8b], [0xfe,0xc9,0x8d],
61+
[0xfe,0xcb,0x8e], [0xfd,0xcd,0x90], [0xfd,0xcf,0x92], [0xfd,0xd1,0x93],
62+
[0xfd,0xd2,0x95], [0xfd,0xd4,0x97], [0xfd,0xd6,0x98], [0xfd,0xd8,0x9a],
63+
[0xfd,0xda,0x9c], [0xfd,0xdc,0x9d], [0xfd,0xdd,0x9f], [0xfd,0xdf,0xa1],
64+
[0xfd,0xe1,0xa3], [0xfc,0xe3,0xa5], [0xfc,0xe5,0xa6], [0xfc,0xe6,0xa8],
65+
[0xfc,0xe8,0xaa], [0xfc,0xea,0xac], [0xfc,0xec,0xae], [0xfc,0xee,0xb0],
66+
[0xfc,0xf0,0xb1], [0xfc,0xf1,0xb3], [0xfc,0xf3,0xb5], [0xfc,0xf5,0xb7],
67+
[0xfb,0xf7,0xb9], [0xfb,0xf9,0xbb], [0xfb,0xfa,0xbd], [0xfb,0xfc,0xbf],
68+
],dtype="uint8")

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp