1+ {
2+ "nbformat" : 4 ,
3+ "nbformat_minor" : 5 ,
4+ "metadata" : {
5+ "kernelspec" : {
6+ "display_name" : " Python 3" ,
7+ "language" : " python" ,
8+ "name" : " python3"
9+ },
10+ "language_info" : {
11+ "name" : " python" ,
12+ "version" : " 3.12.0"
13+ }
14+ },
15+ "cells" : [
16+ {
17+ "cell_type" : " markdown" ,
18+ "metadata" : {},
19+ "source" : [
20+ " # 3D Visualizations\n " ,
21+ " \n " ,
22+ " ggplotly provides geoms for creating interactive 3D plots powered by Plotly's WebGL renderer.\n " ,
23+ " \n " ,
24+ " ## 3D Scatter Plots\n " ,
25+ " \n " ,
26+ " ### Basic 3D Scatter"
27+ ]
28+ },
29+ {
30+ "cell_type" : " code" ,
31+ "execution_count" : null ,
32+ "metadata" : {},
33+ "outputs" : [],
34+ "source" : [
35+ " import numpy as np\n " ,
36+ " import pandas as pd\n " ,
37+ " from ggplotly import *\n " ,
38+ " \n " ,
39+ " df = pd.DataFrame({\n " ,
40+ " 'x': np.random.randn(200),\n " ,
41+ " 'y': np.random.randn(200),\n " ,
42+ " 'z': np.random.randn(200)\n " ,
43+ " })\n " ,
44+ " \n " ,
45+ " ggplot(df, aes(x='x', y='y', z='z')) + geom_point_3d()"
46+ ]
47+ },
48+ {
49+ "cell_type" : " markdown" ,
50+ "metadata" : {},
51+ "source" : [
52+ " ### Colored by Group"
53+ ]
54+ },
55+ {
56+ "cell_type" : " code" ,
57+ "execution_count" : null ,
58+ "metadata" : {},
59+ "outputs" : [],
60+ "source" : [
61+ " df = pd.DataFrame({\n " ,
62+ " 'x': np.random.randn(200),\n " ,
63+ " 'y': np.random.randn(200),\n " ,
64+ " 'z': np.random.randn(200),\n " ,
65+ " 'group': np.random.choice(['A', 'B', 'C'], 200)\n " ,
66+ " })\n " ,
67+ " \n " ,
68+ " ggplot(df, aes(x='x', y='y', z='z', color='group')) + geom_point_3d(size=6)"
69+ ]
70+ },
71+ {
72+ "cell_type" : " markdown" ,
73+ "metadata" : {},
74+ "source" : [
75+ " ### Colored by Continuous Variable"
76+ ]
77+ },
78+ {
79+ "cell_type" : " code" ,
80+ "execution_count" : null ,
81+ "metadata" : {},
82+ "outputs" : [],
83+ "source" : [
84+ " df = pd.DataFrame({\n " ,
85+ " 'x': np.random.randn(200),\n " ,
86+ " 'y': np.random.randn(200),\n " ,
87+ " 'z': np.random.randn(200),\n " ,
88+ " 'value': np.random.rand(200) * 100\n " ,
89+ " })\n " ,
90+ " \n " ,
91+ " (ggplot(df, aes(x='x', y='y', z='z', color='value'))\n " ,
92+ " + geom_point_3d(size=5)\n " ,
93+ " + scale_color_gradient(low='blue', high='red'))"
94+ ]
95+ },
96+ {
97+ "cell_type" : " markdown" ,
98+ "metadata" : {},
99+ "source" : [
100+ " ## 3D Surfaces\n " ,
101+ " \n " ,
102+ " ### Creating Surface Data\n " ,
103+ " \n " ,
104+ " Surfaces require gridded data. Here's a helper function:"
105+ ]
106+ },
107+ {
108+ "cell_type" : " code" ,
109+ "execution_count" : null ,
110+ "metadata" : {},
111+ "outputs" : [],
112+ "source" : [
113+ " def make_surface(func, x_range=(-5, 5), y_range=(-5, 5), resolution=50):\n " ,
114+ " \"\"\" Generate surface data from a function z = f(x, y).\"\"\"\n " ,
115+ " x = np.linspace(x_range[0], x_range[1], resolution)\n " ,
116+ " y = np.linspace(y_range[0], y_range[1], resolution)\n " ,
117+ " X, Y = np.meshgrid(x, y)\n " ,
118+ " Z = func(X, Y)\n " ,
119+ " return pd.DataFrame({\n " ,
120+ " 'x': X.flatten(),\n " ,
121+ " 'y': Y.flatten(),\n " ,
122+ " 'z': Z.flatten()\n " ,
123+ " })"
124+ ]
125+ },
126+ {
127+ "cell_type" : " markdown" ,
128+ "metadata" : {},
129+ "source" : [
130+ " ### Paraboloid"
131+ ]
132+ },
133+ {
134+ "cell_type" : " code" ,
135+ "execution_count" : null ,
136+ "metadata" : {},
137+ "outputs" : [],
138+ "source" : [
139+ " df = make_surface(lambda x, y: x**2 + y**2)\n " ,
140+ " ggplot(df, aes(x='x', y='y', z='z')) + geom_surface(colorscale='Viridis')"
141+ ]
142+ },
143+ {
144+ "cell_type" : " markdown" ,
145+ "metadata" : {},
146+ "source" : [
147+ " ### Saddle Surface (Hyperbolic Paraboloid)"
148+ ]
149+ },
150+ {
151+ "cell_type" : " code" ,
152+ "execution_count" : null ,
153+ "metadata" : {},
154+ "outputs" : [],
155+ "source" : [
156+ " df = make_surface(lambda x, y: x**2 - y**2)\n " ,
157+ " \n " ,
158+ " (ggplot(df, aes(x='x', y='y', z='z'))\n " ,
159+ " + geom_surface(colorscale='RdBu')\n " ,
160+ " + labs(title='Saddle Surface'))"
161+ ]
162+ },
163+ {
164+ "cell_type" : " markdown" ,
165+ "metadata" : {},
166+ "source" : [
167+ " ### Sinc Function (2D)"
168+ ]
169+ },
170+ {
171+ "cell_type" : " code" ,
172+ "execution_count" : null ,
173+ "metadata" : {},
174+ "outputs" : [],
175+ "source" : [
176+ " def sinc_2d(x, y):\n " ,
177+ " r = np.sqrt(x**2 + y**2)\n " ,
178+ " return np.where(r == 0, 1, np.sin(r) / r)\n " ,
179+ " \n " ,
180+ " df = make_surface(sinc_2d, x_range=(-10, 10), y_range=(-10, 10), resolution=80)\n " ,
181+ " \n " ,
182+ " (ggplot(df, aes(x='x', y='y', z='z'))\n " ,
183+ " + geom_surface(colorscale='Plasma')\n " ,
184+ " + labs(title='2D Sinc Function'))"
185+ ]
186+ },
187+ {
188+ "cell_type" : " markdown" ,
189+ "metadata" : {},
190+ "source" : [
191+ " ### Trigonometric Surface"
192+ ]
193+ },
194+ {
195+ "cell_type" : " code" ,
196+ "execution_count" : null ,
197+ "metadata" : {},
198+ "outputs" : [],
199+ "source" : [
200+ " df = make_surface(lambda x, y: np.sin(x) * np.cos(y))\n " ,
201+ " \n " ,
202+ " (ggplot(df, aes(x='x', y='y', z='z'))\n " ,
203+ " + geom_surface(colorscale='Viridis')\n " ,
204+ " + labs(title='sin(x) * cos(y)'))"
205+ ]
206+ },
207+ {
208+ "cell_type" : " markdown" ,
209+ "metadata" : {},
210+ "source" : [
211+ " ### Surface Colorscales\n " ,
212+ " \n " ,
213+ " Available colorscales for `geom_surface`:\n " ,
214+ " \n " ,
215+ " - **Sequential**: `Viridis`, `Plasma`, `Inferno`, `Magma`, `Cividis`, `Blues`, `Greens`, `Reds`, `YlOrRd`, `YlGnBu`\n " ,
216+ " - **Diverging**: `RdBu`, `RdYlBu`, `RdYlGn`, `BrBG`, `PiYG`, `PRGn`, `Spectral`\n " ,
217+ " - **Other**: `Jet`, `Hot`, `Electric`, `Blackbody`, `Earth`, `Picnic`, `Portland`\n " ,
218+ " \n " ,
219+ " ## Wireframe Plots\n " ,
220+ " \n " ,
221+ " Wireframes show the surface structure without solid fills:"
222+ ]
223+ },
224+ {
225+ "cell_type" : " code" ,
226+ "execution_count" : null ,
227+ "metadata" : {},
228+ "outputs" : [],
229+ "source" : [
230+ " df = make_surface(lambda x, y: np.sin(x) * np.cos(y), resolution=30)\n " ,
231+ " \n " ,
232+ " (ggplot(df, aes(x='x', y='y', z='z'))\n " ,
233+ " + geom_wireframe(color='steelblue', linewidth=1)\n " ,
234+ " + labs(title='Wireframe Plot'))"
235+ ]
236+ },
237+ {
238+ "cell_type" : " markdown" ,
239+ "metadata" : {},
240+ "source" : [
241+ " ### Wireframe Parameters\n " ,
242+ " \n " ,
243+ " | Parameter | Default | Description |\n " ,
244+ " |-----------|---------|-------------|\n " ,
245+ " | `color` | 'steelblue' | Line color |\n " ,
246+ " | `linewidth` | 1 | Line width |\n " ,
247+ " | `opacity` | 1.0 | Transparency (0-1) |\n " ,
248+ " \n " ,
249+ " ## Combining 3D Geoms\n " ,
250+ " \n " ,
251+ " You can layer 3D geoms:"
252+ ]
253+ },
254+ {
255+ "cell_type" : " code" ,
256+ "execution_count" : null ,
257+ "metadata" : {},
258+ "outputs" : [],
259+ "source" : [
260+ " # Surface with scatter points\n " ,
261+ " df_surface = make_surface(lambda x, y: np.sin(x) * np.cos(y))\n " ,
262+ " \n " ,
263+ " # Sample points on the surface\n " ,
264+ " sample_idx = np.random.choice(len(df_surface), 50, replace=False)\n " ,
265+ " df_points = df_surface.iloc[sample_idx].copy()\n " ,
266+ " df_points['z'] += 0.1 # Offset slightly above surface\n " ,
267+ " \n " ,
268+ " (ggplot(df_surface, aes(x='x', y='y', z='z'))\n " ,
269+ " + geom_surface(colorscale='Viridis', opacity=0.7)\n " ,
270+ " + geom_point_3d(data=df_points, color='red', size=5))"
271+ ]
272+ },
273+ {
274+ "cell_type" : " markdown" ,
275+ "metadata" : {},
276+ "source" : [
277+ " ## Mathematical Visualizations\n " ,
278+ " \n " ,
279+ " ### Gaussian (Bell Curve) in 3D"
280+ ]
281+ },
282+ {
283+ "cell_type" : " code" ,
284+ "execution_count" : null ,
285+ "metadata" : {},
286+ "outputs" : [],
287+ "source" : [
288+ " def gaussian_2d(x, y, sigma=1):\n " ,
289+ " return np.exp(-(x**2 + y**2) / (2 * sigma**2))\n " ,
290+ " \n " ,
291+ " df = make_surface(gaussian_2d, x_range=(-3, 3), y_range=(-3, 3), resolution=60)\n " ,
292+ " \n " ,
293+ " (ggplot(df, aes(x='x', y='y', z='z'))\n " ,
294+ " + geom_surface(colorscale='Viridis')\n " ,
295+ " + labs(title='2D Gaussian Distribution'))"
296+ ]
297+ },
298+ {
299+ "cell_type" : " markdown" ,
300+ "metadata" : {},
301+ "source" : [
302+ " ### Ripple Effect"
303+ ]
304+ },
305+ {
306+ "cell_type" : " code" ,
307+ "execution_count" : null ,
308+ "metadata" : {},
309+ "outputs" : [],
310+ "source" : [
311+ " def ripple(x, y):\n " ,
312+ " r = np.sqrt(x**2 + y**2)\n " ,
313+ " return np.sin(3 * r) * np.exp(-0.3 * r)\n " ,
314+ " \n " ,
315+ " df = make_surface(ripple, x_range=(-5, 5), y_range=(-5, 5), resolution=80)\n " ,
316+ " \n " ,
317+ " (ggplot(df, aes(x='x', y='y', z='z'))\n " ,
318+ " + geom_surface(colorscale='RdBu')\n " ,
319+ " + labs(title='Ripple Effect'))"
320+ ]
321+ },
322+ {
323+ "cell_type" : " markdown" ,
324+ "metadata" : {},
325+ "source" : [
326+ " ### Rosenbrock Function (Optimization Test)"
327+ ]
328+ },
329+ {
330+ "cell_type" : " code" ,
331+ "execution_count" : null ,
332+ "metadata" : {},
333+ "outputs" : [],
334+ "source" : [
335+ " def rosenbrock(x, y, a=1, b=100):\n " ,
336+ " return (a - x)**2 + b * (y - x**2)**2\n " ,
337+ " \n " ,
338+ " df = make_surface(rosenbrock, x_range=(-2, 2), y_range=(-1, 3), resolution=60)\n " ,
339+ " \n " ,
340+ " (ggplot(df, aes(x='x', y='y', z='z'))\n " ,
341+ " + geom_surface(colorscale='Hot')\n " ,
342+ " + labs(title='Rosenbrock Function'))"
343+ ]
344+ },
345+ {
346+ "cell_type" : " markdown" ,
347+ "metadata" : {},
348+ "source" : [
349+ " ## Interactivity\n " ,
350+ " \n " ,
351+ " All 3D plots support:\n " ,
352+ " \n " ,
353+ " - **Rotation**: Click and drag to rotate\n " ,
354+ " - **Zoom**: Scroll wheel or pinch\n " ,
355+ " - **Pan**: Shift + drag\n " ,
356+ " - **Reset**: Double-click\n " ,
357+ " \n " ,
358+ " The 3D camera position is automatically saved when you interact, so subsequent renders maintain your viewpoint."
359+ ]
360+ }
361+ ]
362+ }
0 commit comments