From 539ed4203836631c2750ca086897402646dcf5be Mon Sep 17 00:00:00 2001 From: tkoyama010 Date: Tue, 6 Feb 2024 12:26:43 +0000 Subject: [PATCH] deploy: pyvista/pyvista@62dd86fc32450f71f0e96f667ef31d3c47774ad5 --- LICENSE | 2 +- examples/00-load/create-point-cloud.ipynb | 4 +- .../00-load/create-structured-surface.ipynb | 2 +- examples/00-load/create-tri-surface.ipynb | 4 +- examples/00-load/wrap-trimesh.ipynb | 2 +- examples/01-filter/extract-surface.ipynb | 2 +- examples/02-plot/composite-picking.ipynb | 2 +- examples/02-plot/labels.ipynb | 2 +- examples/02-plot/movie.ipynb | 2 +- examples/02-plot/points-gaussian-scale.ipynb | 126 ++++++++++++++++++ examples/02-plot/spherical.ipynb | 2 +- .../98-common/project-points-tessellate.ipynb | 2 +- examples/99-advanced/atomic-orbitals.ipynb | 2 +- examples/99-advanced/sphere_eversion.ipynb | 2 +- 14 files changed, 141 insertions(+), 15 deletions(-) create mode 100644 examples/02-plot/points-gaussian-scale.ipynb diff --git a/LICENSE b/LICENSE index b21162b..18c93f2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2023-2024, PyVista Developers +Copyright (c) 2023, PyVista Developers All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/examples/00-load/create-point-cloud.ipynb b/examples/00-load/create-point-cloud.ipynb index 4f79255..f085492 100644 --- a/examples/00-load/create-point-cloud.ipynb +++ b/examples/00-load/create-point-cloud.ipynb @@ -44,7 +44,7 @@ }, "outputs": [], "source": [ - "# Define some helpers - ignore these and use your own data.\ndef generate_points(subset=0.02):\n \"\"\"A helper to make a 3D NumPy array of points (n_points by 3)\"\"\"\n dataset = examples.download_lidar()\n ids = np.random.randint(low=0, high=dataset.n_points - 1, size=int(dataset.n_points * subset))\n return dataset.points[ids]\n\n\npoints = generate_points()\n# Print first 5 rows to prove its a numpy array (n_points by 3)\n# Columns are (X Y Z)\npoints[0:5, :]" + "# Define some helpers - ignore these and use your own data.\ndef generate_points(subset=0.02):\n \"\"\"A helper to make a 3D NumPy array of points (n_points by 3)\"\"\"\n dataset = examples.download_lidar()\n ids = np.random.default_rng().integers(\n low=0, high=dataset.n_points - 1, size=int(dataset.n_points * subset)\n )\n return dataset.points[ids]\n\n\npoints = generate_points()\n# Print first 5 rows to prove its a numpy array (n_points by 3)\n# Columns are (X Y Z)\npoints[0:5, :]" ] }, { @@ -152,7 +152,7 @@ }, "outputs": [], "source": [ - "# Create random XYZ points\npoints = np.random.rand(100, 3)\n# Make PolyData\npoint_cloud = pv.PolyData(points)\n\n\ndef compute_vectors(mesh):\n origin = mesh.center\n vectors = mesh.points - origin\n vectors = vectors / np.linalg.norm(vectors, axis=1)[:, None]\n return vectors\n\n\nvectors = compute_vectors(point_cloud)\nvectors[0:5, :]" + "# Create random XYZ points\npoints = np.random.default_rng().random((100, 3))\n# Make PolyData\npoint_cloud = pv.PolyData(points)\n\n\ndef compute_vectors(mesh):\n origin = mesh.center\n vectors = mesh.points - origin\n vectors = vectors / np.linalg.norm(vectors, axis=1)[:, None]\n return vectors\n\n\nvectors = compute_vectors(point_cloud)\nvectors[0:5, :]" ] }, { diff --git a/examples/00-load/create-structured-surface.ipynb b/examples/00-load/create-structured-surface.ipynb index 7b1a95f..838740c 100644 --- a/examples/00-load/create-structured-surface.ipynb +++ b/examples/00-load/create-structured-surface.ipynb @@ -109,7 +109,7 @@ }, "outputs": [], "source": [ - "def make_point_set():\n \"\"\"Ignore the contents of this function. Just know that it returns an\n n by 3 numpy array of structured coordinates.\"\"\"\n n, m = 29, 32\n x = np.linspace(-200, 200, num=n) + np.random.uniform(-5, 5, size=n)\n y = np.linspace(-200, 200, num=m) + np.random.uniform(-5, 5, size=m)\n xx, yy = np.meshgrid(x, y)\n A, b = 100, 100\n zz = A * np.exp(-0.5 * ((xx / b) ** 2.0 + (yy / b) ** 2.0))\n points = np.c_[xx.reshape(-1), yy.reshape(-1), zz.reshape(-1)]\n foo = pv.PolyData(points)\n foo.rotate_z(36.6, inplace=True)\n return foo.points\n\n\n# Get the points as a 2D NumPy array (N by 3)\npoints = make_point_set()\npoints[0:5, :]" + "def make_point_set():\n \"\"\"Ignore the contents of this function. Just know that it returns an\n n by 3 numpy array of structured coordinates.\"\"\"\n n, m = 29, 32\n x = np.linspace(-200, 200, num=n) + np.random.default_rng().uniform(-5, 5, size=n)\n y = np.linspace(-200, 200, num=m) + np.random.default_rng().uniform(-5, 5, size=m)\n xx, yy = np.meshgrid(x, y)\n A, b = 100, 100\n zz = A * np.exp(-0.5 * ((xx / b) ** 2.0 + (yy / b) ** 2.0))\n points = np.c_[xx.reshape(-1), yy.reshape(-1), zz.reshape(-1)]\n foo = pv.PolyData(points)\n foo.rotate_z(36.6, inplace=True)\n return foo.points\n\n\n# Get the points as a 2D NumPy array (N by 3)\npoints = make_point_set()\npoints[0:5, :]" ] }, { diff --git a/examples/00-load/create-tri-surface.ipynb b/examples/00-load/create-tri-surface.ipynb index 0655fdb..617ecd5 100644 --- a/examples/00-load/create-tri-surface.ipynb +++ b/examples/00-load/create-tri-surface.ipynb @@ -44,7 +44,7 @@ }, "outputs": [], "source": [ - "# Define a simple Gaussian surface\nn = 20\nx = np.linspace(-200, 200, num=n) + np.random.uniform(-5, 5, size=n)\ny = np.linspace(-200, 200, num=n) + np.random.uniform(-5, 5, size=n)\nxx, yy = np.meshgrid(x, y)\nA, b = 100, 100\nzz = A * np.exp(-0.5 * ((xx / b) ** 2.0 + (yy / b) ** 2.0))\n\n# Get the points as a 2D NumPy array (N by 3)\npoints = np.c_[xx.reshape(-1), yy.reshape(-1), zz.reshape(-1)]\npoints[0:5, :]" + "# Define a simple Gaussian surface\nn = 20\nx = np.linspace(-200, 200, num=n) + np.random.default_rng().uniform(-5, 5, size=n)\ny = np.linspace(-200, 200, num=n) + np.random.default_rng().uniform(-5, 5, size=n)\nxx, yy = np.meshgrid(x, y)\nA, b = 100, 100\nzz = A * np.exp(-0.5 * ((xx / b) ** 2.0 + (yy / b) ** 2.0))\n\n# Get the points as a 2D NumPy array (N by 3)\npoints = np.c_[xx.reshape(-1), yy.reshape(-1), zz.reshape(-1)]\npoints[0:5, :]" ] }, { @@ -98,7 +98,7 @@ }, "outputs": [], "source": [ - "x = np.arange(10, dtype=float)\nxx, yy, zz = np.meshgrid(x, x, [0])\npoints = np.column_stack((xx.ravel(order=\"F\"), yy.ravel(order=\"F\"), zz.ravel(order=\"F\")))\n# Perturb the points\npoints[:, 0] += np.random.rand(len(points)) * 0.3\npoints[:, 1] += np.random.rand(len(points)) * 0.3\n# Create the point cloud mesh to triangulate from the coordinates\ncloud = pv.PolyData(points)\ncloud" + "x = np.arange(10, dtype=float)\nxx, yy, zz = np.meshgrid(x, x, [0])\npoints = np.column_stack((xx.ravel(order=\"F\"), yy.ravel(order=\"F\"), zz.ravel(order=\"F\")))\n# Perturb the points\npoints[:, 0] += np.random.default_rng().random(len(points)) * 0.3\npoints[:, 1] += np.random.default_rng().random(len(points)) * 0.3\n# Create the point cloud mesh to triangulate from the coordinates\ncloud = pv.PolyData(points)\ncloud" ] }, { diff --git a/examples/00-load/wrap-trimesh.ipynb b/examples/00-load/wrap-trimesh.ipynb index 87f2d36..7f68634 100644 --- a/examples/00-load/wrap-trimesh.ipynb +++ b/examples/00-load/wrap-trimesh.ipynb @@ -44,7 +44,7 @@ }, "outputs": [], "source": [ - "import numpy as np\n\nimport pyvista as pv\n\npoints = np.random.random((30, 3))\ncloud = pv.wrap(points)\npv.plot(\n cloud,\n scalars=points[:, 2],\n render_points_as_spheres=True,\n point_size=50,\n opacity=points[:, 0],\n cpos='xz',\n)" + "import numpy as np\n\nimport pyvista as pv\n\npoints = np.random.default_rng().random((30, 3))\ncloud = pv.wrap(points)\npv.plot(\n cloud,\n scalars=points[:, 2],\n render_points_as_spheres=True,\n point_size=50,\n opacity=points[:, 0],\n cpos='xz',\n)" ] }, { diff --git a/examples/01-filter/extract-surface.ipynb b/examples/01-filter/extract-surface.ipynb index b77f197..7b94a00 100644 --- a/examples/01-filter/extract-surface.ipynb +++ b/examples/01-filter/extract-surface.ipynb @@ -44,7 +44,7 @@ }, "outputs": [], "source": [ - "lin_pts = np.array(\n [\n [-1, -1, -1], # point 0\n [1, -1, -1], # point 1\n [1, 1, -1], # point 2\n [-1, 1, -1], # point 3\n [-1, -1, 1], # point 4\n [1, -1, 1], # point 5\n [1, 1, 1], # point 6\n [-1, 1, 1], # point 7\n ],\n np.double,\n)\n\n# these are the \"midside\" points of a quad cell. See the definition of a\n# vtkQuadraticHexahedron at:\n# https://vtk.org/doc/nightly/html/classvtkQuadraticHexahedron.html\nquad_pts = np.array(\n [\n (lin_pts[1] + lin_pts[0]) / 2, # between point 0 and 1\n (lin_pts[1] + lin_pts[2]) / 2, # between point 1 and 2\n (lin_pts[2] + lin_pts[3]) / 2, # and so on...\n (lin_pts[3] + lin_pts[0]) / 2,\n (lin_pts[4] + lin_pts[5]) / 2,\n (lin_pts[5] + lin_pts[6]) / 2,\n (lin_pts[6] + lin_pts[7]) / 2,\n (lin_pts[7] + lin_pts[4]) / 2,\n (lin_pts[0] + lin_pts[4]) / 2,\n (lin_pts[1] + lin_pts[5]) / 2,\n (lin_pts[2] + lin_pts[6]) / 2,\n (lin_pts[3] + lin_pts[7]) / 2,\n ]\n)\n\n# introduce a minor variation to the location of the mid-side points\nquad_pts += np.random.random(quad_pts.shape) * 0.3\npts = np.vstack((lin_pts, quad_pts))\n\n# create the grid\ncells = np.hstack((20, np.arange(20))).astype(np.int64, copy=False)\ncelltypes = np.array([CellType.QUADRATIC_HEXAHEDRON])\ngrid = pv.UnstructuredGrid(cells, celltypes, pts)\n\n# finally, extract the surface and plot it\nsurf = grid.extract_surface()\nsurf.plot(show_scalar_bar=False)" + "lin_pts = np.array(\n [\n [-1, -1, -1], # point 0\n [1, -1, -1], # point 1\n [1, 1, -1], # point 2\n [-1, 1, -1], # point 3\n [-1, -1, 1], # point 4\n [1, -1, 1], # point 5\n [1, 1, 1], # point 6\n [-1, 1, 1], # point 7\n ],\n np.double,\n)\n\n# these are the \"midside\" points of a quad cell. See the definition of a\n# vtkQuadraticHexahedron at:\n# https://vtk.org/doc/nightly/html/classvtkQuadraticHexahedron.html\nquad_pts = np.array(\n [\n (lin_pts[1] + lin_pts[0]) / 2, # between point 0 and 1\n (lin_pts[1] + lin_pts[2]) / 2, # between point 1 and 2\n (lin_pts[2] + lin_pts[3]) / 2, # and so on...\n (lin_pts[3] + lin_pts[0]) / 2,\n (lin_pts[4] + lin_pts[5]) / 2,\n (lin_pts[5] + lin_pts[6]) / 2,\n (lin_pts[6] + lin_pts[7]) / 2,\n (lin_pts[7] + lin_pts[4]) / 2,\n (lin_pts[0] + lin_pts[4]) / 2,\n (lin_pts[1] + lin_pts[5]) / 2,\n (lin_pts[2] + lin_pts[6]) / 2,\n (lin_pts[3] + lin_pts[7]) / 2,\n ]\n)\n\n# introduce a minor variation to the location of the mid-side points\nquad_pts += np.random.default_rng().random(quad_pts.shape) * 0.3\npts = np.vstack((lin_pts, quad_pts))\n\n# create the grid\ncells = np.hstack((20, np.arange(20))).astype(np.int64, copy=False)\ncelltypes = np.array([CellType.QUADRATIC_HEXAHEDRON])\ngrid = pv.UnstructuredGrid(cells, celltypes, pts)\n\n# finally, extract the surface and plot it\nsurf = grid.extract_surface()\nsurf.plot(show_scalar_bar=False)" ] }, { diff --git a/examples/02-plot/composite-picking.ipynb b/examples/02-plot/composite-picking.ipynb index 0a95c34..93e89c0 100644 --- a/examples/02-plot/composite-picking.ipynb +++ b/examples/02-plot/composite-picking.ipynb @@ -44,7 +44,7 @@ }, "outputs": [], "source": [ - "def make_poly():\n \"\"\"Create a superellipsoid in a random location.\"\"\"\n poly = pv.ParametricSuperEllipsoid(\n n1=np.random.random(),\n n2=np.random.random() * 2,\n u_res=50,\n v_res=50,\n )\n poly.points += np.random.random(3) * 20\n return poly\n\n\n# Assemble the multiblock and plot it using the default plotting settings\nblocks = pv.MultiBlock([make_poly() for _ in range(100)])\nblocks.plot()" + "def make_poly():\n \"\"\"Create a superellipsoid in a random location.\"\"\"\n poly = pv.ParametricSuperEllipsoid(\n n1=np.random.default_rng().random(),\n n2=np.random.default_rng().random() * 2,\n u_res=50,\n v_res=50,\n )\n poly.points += np.random.default_rng().random(3) * 20\n return poly\n\n\n# Assemble the multiblock and plot it using the default plotting settings\nblocks = pv.MultiBlock([make_poly() for _ in range(100)])\nblocks.plot()" ] }, { diff --git a/examples/02-plot/labels.ipynb b/examples/02-plot/labels.ipynb index 9b43906..a90e7ce 100644 --- a/examples/02-plot/labels.ipynb +++ b/examples/02-plot/labels.ipynb @@ -44,7 +44,7 @@ }, "outputs": [], "source": [ - "# Make some random points\npoly = pv.PolyData(np.random.rand(10, 3))" + "# Make some random points\npoly = pv.PolyData(np.random.default_rng().random((10, 3)))" ] }, { diff --git a/examples/02-plot/movie.ipynb b/examples/02-plot/movie.ipynb index 83b8b99..a74899a 100644 --- a/examples/02-plot/movie.ipynb +++ b/examples/02-plot/movie.ipynb @@ -26,7 +26,7 @@ }, "outputs": [], "source": [ - "import numpy as np\n\nimport pyvista as pv\n\nfilename = \"sphere-shrinking.mp4\"\n\nmesh = pv.Sphere()\nmesh.cell_data[\"data\"] = np.random.random(mesh.n_cells)\n\nplotter = pv.Plotter()\n# Open a movie file\nplotter.open_movie(filename)\n\n# Add initial mesh\nplotter.add_mesh(mesh, scalars=\"data\", clim=[0, 1])\n# Add outline for shrinking reference\nplotter.add_mesh(mesh.outline_corners())\n\nplotter.show(auto_close=False) # only necessary for an off-screen movie\n\n# Run through each frame\nplotter.write_frame() # write initial data\n\n# Update scalars on each frame\nfor i in range(100):\n random_points = np.random.random(mesh.points.shape)\n mesh.points = random_points * 0.01 + mesh.points * 0.99\n mesh.points -= mesh.points.mean(0)\n mesh.cell_data[\"data\"] = np.random.random(mesh.n_cells)\n plotter.add_text(f\"Iteration: {i}\", name='time-label')\n plotter.write_frame() # Write this frame\n\n# Be sure to close the plotter when finished\nplotter.close()" + "import numpy as np\n\nimport pyvista as pv\n\nfilename = \"sphere-shrinking.mp4\"\n\nmesh = pv.Sphere()\nmesh.cell_data[\"data\"] = np.random.default_rng().random(mesh.n_cells)\n\nplotter = pv.Plotter()\n# Open a movie file\nplotter.open_movie(filename)\n\n# Add initial mesh\nplotter.add_mesh(mesh, scalars=\"data\", clim=[0, 1])\n# Add outline for shrinking reference\nplotter.add_mesh(mesh.outline_corners())\n\nplotter.show(auto_close=False) # only necessary for an off-screen movie\n\n# Run through each frame\nplotter.write_frame() # write initial data\n\n# Update scalars on each frame\nfor i in range(100):\n random_points = np.random.default_rng().random(mesh.points.shape)\n mesh.points = random_points * 0.01 + mesh.points * 0.99\n mesh.points -= mesh.points.mean(0)\n mesh.cell_data[\"data\"] = np.random.default_rng().random(mesh.n_cells)\n plotter.add_text(f\"Iteration: {i}\", name='time-label')\n plotter.write_frame() # Write this frame\n\n# Be sure to close the plotter when finished\nplotter.close()" ] } ], diff --git a/examples/02-plot/points-gaussian-scale.ipynb b/examples/02-plot/points-gaussian-scale.ipynb new file mode 100644 index 0000000..4b77136 --- /dev/null +++ b/examples/02-plot/points-gaussian-scale.ipynb @@ -0,0 +1,126 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Scaled Gaussian Points {#plot_spheres_example}\n======================\n\nThis example demonstrates how to plot spheres using the\n`'points_gaussian'` style and scale them by a dynamic radius.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import numpy as np\n\nimport pyvista as pv" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First, generate the sphere positions and radii randomly on the edge of a\ntorus.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "N_SPHERES = 10_000\ntheta = np.random.default_rng().uniform(0, 2 * np.pi, N_SPHERES)\nphi = np.random.default_rng().uniform(0, 2 * np.pi, N_SPHERES)\ntorus_radius = 1\ntube_radius = 0.3\nradius = torus_radius + tube_radius * np.cos(phi)\nrad = np.random.default_rng().random(N_SPHERES) * 0.01\n\npos = np.zeros((N_SPHERES, 3))\npos[:, 0] = radius * np.cos(theta)\npos[:, 1] = radius * np.sin(theta)\npos[:, 2] = tube_radius * np.sin(phi)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, create a PolyData object and add the sphere positions and radii as\ndata arrays.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "pdata = pv.PolyData(pos)\npdata['radius'] = rad" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, plot the spheres using the `points_gaussian` style and scale\nthem by radius.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "pl = pv.Plotter()\nactor = pl.add_mesh(\n pdata,\n style='points_gaussian',\n emissive=False,\n render_points_as_spheres=True,\n show_scalar_bar=False,\n)\nactor.mapper.scale_array = 'radius'\npl.camera.zoom(1.5)\npl.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Show the same plot with `emissive=True`.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "pl = pv.Plotter()\npl.background_color = 'k'\nactor = pl.add_mesh(\n pdata,\n style='points_gaussian',\n emissive=True,\n render_points_as_spheres=True,\n show_scalar_bar=False,\n)\nactor.mapper.scale_array = 'radius'\npl.camera.zoom(1.5)\npl.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.1" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/examples/02-plot/spherical.ipynb b/examples/02-plot/spherical.ipynb index 457b06e..79b694b 100644 --- a/examples/02-plot/spherical.ipynb +++ b/examples/02-plot/spherical.ipynb @@ -62,7 +62,7 @@ }, "outputs": [], "source": [ - "w_vec = np.random.rand(*u_vec.shape)\n\nwind_level = [RADIUS * 1.2]\n\n# Sequence of axis indices for transpose()\n# (1, 0) for 2D arrays\n# (2, 1, 0) for 3D arrays\ninv_axes = [*range(u_vec.ndim)[::-1]]\n\n# Transform vectors to cartesian coordinates\nvectors = np.stack(\n [\n i.transpose(inv_axes).swapaxes(-2, -1).ravel(\"C\")\n for i in pv.transform_vectors_sph_to_cart(\n x,\n y_polar,\n wind_level,\n u_vec.transpose(inv_axes),\n -v_vec.transpose(inv_axes), # Minus sign because y-vector in polar coords is required\n w_vec.transpose(inv_axes),\n )\n ],\n axis=1,\n)\n\n# Scale vectors to make them visible\nvectors *= RADIUS * 0.1\n\n# Create a grid for the vectors\ngrid_winds = pv.grid_from_sph_coords(x, y_polar, wind_level)\n\n# Add vectors to the grid\ngrid_winds.point_data[\"example\"] = vectors\n\n# Show the result\np = pv.Plotter()\np.add_mesh(pv.Sphere(radius=RADIUS))\np.add_mesh(grid_winds.glyph(orient=\"example\", scale=\"example\", tolerance=0.005))\np.show()" + "w_vec = np.random.default_rng().random(u_vec.shape)\n\nwind_level = [RADIUS * 1.2]\n\n# Sequence of axis indices for transpose()\n# (1, 0) for 2D arrays\n# (2, 1, 0) for 3D arrays\ninv_axes = [*range(u_vec.ndim)[::-1]]\n\n# Transform vectors to cartesian coordinates\nvectors = np.stack(\n [\n i.transpose(inv_axes).swapaxes(-2, -1).ravel(\"C\")\n for i in pv.transform_vectors_sph_to_cart(\n x,\n y_polar,\n wind_level,\n u_vec.transpose(inv_axes),\n -v_vec.transpose(inv_axes), # Minus sign because y-vector in polar coords is required\n w_vec.transpose(inv_axes),\n )\n ],\n axis=1,\n)\n\n# Scale vectors to make them visible\nvectors *= RADIUS * 0.1\n\n# Create a grid for the vectors\ngrid_winds = pv.grid_from_sph_coords(x, y_polar, wind_level)\n\n# Add vectors to the grid\ngrid_winds.point_data[\"example\"] = vectors\n\n# Show the result\np = pv.Plotter()\np.add_mesh(pv.Sphere(radius=RADIUS))\np.add_mesh(grid_winds.glyph(orient=\"example\", scale=\"example\", tolerance=0.005))\np.show()" ] }, { diff --git a/examples/98-common/project-points-tessellate.ipynb b/examples/98-common/project-points-tessellate.ipynb index 529b0bd..987cee3 100644 --- a/examples/98-common/project-points-tessellate.ipynb +++ b/examples/98-common/project-points-tessellate.ipynb @@ -44,7 +44,7 @@ }, "outputs": [], "source": [ - "num_points = 100\npoint_cloud = np.random.random((num_points, 3))\n\n# Define a plane\norigin = [0, 0, 0]\nnormal = [0, 0, 1]\nplane = pv.Plane(center=origin, direction=normal)\n\n\ndef project_points_to_plane(points, plane_origin, plane_normal):\n \"\"\"Project points to a plane.\"\"\"\n vec = points - plane_origin\n dist = np.dot(vec, plane_normal)\n return points - np.outer(dist, plane_normal)\n\n\nprojected_points = project_points_to_plane(point_cloud, origin, normal)\n\n# Create a polydata object with projected points\npolydata = pv.PolyData(projected_points)\n\n# Mesh using delaunay_2d and pyvista\nmesh = polydata.delaunay_2d()" + "num_points = 100\npoint_cloud = np.random.default_rng().random((num_points, 3))\n\n# Define a plane\norigin = [0, 0, 0]\nnormal = [0, 0, 1]\nplane = pv.Plane(center=origin, direction=normal)\n\n\ndef project_points_to_plane(points, plane_origin, plane_normal):\n \"\"\"Project points to a plane.\"\"\"\n vec = points - plane_origin\n dist = np.dot(vec, plane_normal)\n return points - np.outer(dist, plane_normal)\n\n\nprojected_points = project_points_to_plane(point_cloud, origin, normal)\n\n# Create a polydata object with projected points\npolydata = pv.PolyData(projected_points)\n\n# Mesh using delaunay_2d and pyvista\nmesh = polydata.delaunay_2d()" ] }, { diff --git a/examples/99-advanced/atomic-orbitals.ipynb b/examples/99-advanced/atomic-orbitals.ipynb index 0340666..787a350 100644 --- a/examples/99-advanced/atomic-orbitals.ipynb +++ b/examples/99-advanced/atomic-orbitals.ipynb @@ -159,7 +159,7 @@ }, "outputs": [], "source": [ - "# Generate the orbital and sample based on the square of the probability of an\n# electron being within a particular volume of space.\nhydro_orbital = examples.load_hydrogen_orbital(4, 2, 0, zoom_fac=0.5)\nprob = np.abs(hydro_orbital['real_wf']) ** 2\nprob /= prob.sum()\nindices = np.random.choice(hydro_orbital.n_points, 10000, p=prob)\n\n# add a small amount of noise to these coordinates to remove the \"grid like\"\n# structure present in the underlying ImageData\npoints = hydro_orbital.points[indices]\npoints += np.random.random(points.shape) - 0.5\n\n# Create a point cloud and add the phase as the active scalars\npoint_cloud = pv.PolyData(points)\npoint_cloud['phase'] = hydro_orbital['real_wf'][indices] < 0\n\n# Turn the point cloud into individual spheres. We do this so we can improve\n# the plot by enabling surface space ambient occlusion (SSAO)\ndplot = point_cloud.glyph(\n geom=pv.Sphere(theta_resolution=8, phi_resolution=8), scale=False, orient=False\n)\n\n# be sure to enable SSAO here. This makes the \"points\" that are deeper within\n# the density plot darker.\npl = pv.Plotter()\npl.add_mesh(\n dplot,\n smooth_shading=True,\n show_scalar_bar=False,\n cmap=['red', 'green'],\n ambient=0.2,\n)\npl.enable_ssao(radius=10)\npl.enable_anti_aliasing()\npl.camera.zoom(2)\npl.background_color = 'w'\npl.show()" + "# Generate the orbital and sample based on the square of the probability of an\n# electron being within a particular volume of space.\nhydro_orbital = examples.load_hydrogen_orbital(4, 2, 0, zoom_fac=0.5)\nprob = np.abs(hydro_orbital['real_wf']) ** 2\nprob /= prob.sum()\nindices = np.random.default_rng().choice(hydro_orbital.n_points, 10000, p=prob)\n\n# add a small amount of noise to these coordinates to remove the \"grid like\"\n# structure present in the underlying ImageData\npoints = hydro_orbital.points[indices]\npoints += np.random.default_rng().random(points.shape) - 0.5\n\n# Create a point cloud and add the phase as the active scalars\npoint_cloud = pv.PolyData(points)\npoint_cloud['phase'] = hydro_orbital['real_wf'][indices] < 0\n\n# Turn the point cloud into individual spheres. We do this so we can improve\n# the plot by enabling surface space ambient occlusion (SSAO)\ndplot = point_cloud.glyph(\n geom=pv.Sphere(theta_resolution=8, phi_resolution=8), scale=False, orient=False\n)\n\n# be sure to enable SSAO here. This makes the \"points\" that are deeper within\n# the density plot darker.\npl = pv.Plotter()\npl.add_mesh(\n dplot,\n smooth_shading=True,\n show_scalar_bar=False,\n cmap=['red', 'green'],\n ambient=0.2,\n)\npl.enable_ssao(radius=10)\npl.enable_anti_aliasing()\npl.camera.zoom(2)\npl.background_color = 'w'\npl.show()" ] }, { diff --git a/examples/99-advanced/sphere_eversion.ipynb b/examples/99-advanced/sphere_eversion.ipynb index 595a7a0..4676287 100644 --- a/examples/99-advanced/sphere_eversion.ipynb +++ b/examples/99-advanced/sphere_eversion.ipynb @@ -44,7 +44,7 @@ }, "outputs": [], "source": [ - "def sphere_to_cylinder(theta, phi):\n \"\"\"Map from spherical polar coordinates to cylindrical ones.\n\n Input theta goes from -pi/2 to pi/2, phi goes from -pi to pi.\n Output h goes from -infinity to infinity, phi goes from -phi to phi.\n\n \"\"\"\n h = w * np.sin(theta) / np.cos(theta) ** n\n # phi is unchanged\n return h, phi\n\n\ndef cylinder_to_wormhole(h, phi, t, p, q):\n \"\"\"Map from a cylinder to an open wormhole using Eq. (4).\n\n Input h goes from -infinity to infinity, phi goes from -phi to phi.\n Output is an (x, y, z) point embedded in 3d space.\n\n The parameters t, p, q vary during the eversion process.\n Start from |t| > 1 (fixed), p = 1 and q = 0. End at p = 0, qt = +-1.\n\n \"\"\"\n x = t * np.cos(phi) + p * np.sin((n - 1) * phi) - h * np.sin(phi)\n y = t * np.sin(phi) + p * np.cos((n - 1) * phi) + h * np.cos(phi)\n z = h * np.sin(n * phi) - t / n * np.cos(n * phi) - q * t * h\n return x, y, z\n\n\ndef close_wormhole(x0, y0, z0, eta, xi, alpha):\n \"\"\"Close the wormhole using Eqs. (7)-(8).\n\n Input is an (x0, y0, z0) point embedded in 3d space.\n Output is an (x2, y2, z2) == (x'', y'', z'') point embedded in 3d space.\n\n The parameters eta, xi, alpha vary during the eversion process.\n\n \"\"\"\n # Eq. (7): (x, y, z) -> (x', y', z')\n denominator = xi + eta * (x**2 + y**2)\n x1 = x0 / (denominator**kappa)\n y1 = y0 / (denominator**kappa)\n z1 = z0 / denominator\n\n gamma = 2 * np.sqrt(alpha * beta)\n # singular case, Eq (9):\n if np.isclose(gamma, 0):\n denominator = x1**2 + y1**2\n x2 = x1 / denominator\n y2 = y1 / denominator\n z2 = -z1\n return x2, y2, z2\n\n # Eq. (8): (x', y', z') -> (x'', y'', z'')\n exponential = np.exp(gamma * z1)\n numerator = alpha - beta * (x1**2 + y1**2)\n denominator = alpha + beta * (x1**2 + y1**2)\n x2 = x1 * exponential / denominator\n y2 = y1 * exponential / denominator\n z2 = numerator / denominator * exponential / gamma - (alpha - beta) / (alpha + beta) / gamma\n return x2, y2, z2\n\n\ndef unfold_sphere(theta, phi, t, q, eta, lamda):\n \"\"\"Unfold the sphere using Eqs. (12), (15), (10).\n\n Input is a (theta, phi) point in spherical coordinates.\n Output is an (x, y, z) point embedded in 3d space.\n\n The parameter lamda varies. Lamda = 1 is the final stage of the\n wormhole closing, and lamda = 0 is the recovered sphere.\n\n \"\"\"\n # apply Eqs. (12), (15)\n # fmt: off\n x = (\n t * (1 - lamda + lamda * np.cos(theta)**n) * np.cos(phi)\n - lamda * w * np.sin(theta) * np.sin(phi)\n )\n x /= np.cos(theta)**n\n y = (\n t * (1 - lamda + lamda * np.cos(theta)**n) * np.sin(phi)\n + lamda * w * np.sin(theta) * np.cos(phi)\n )\n y /= np.cos(theta) ** n\n z = (\n lamda * (\n (w * np.sin(theta) * (np.sin(n * phi) - q * t)) / np.cos(theta)**n\n - t / n * np.cos(n * phi)\n )\n - (1 - lamda) * eta**(1 + kappa) * t * abs(t)**(2 * kappa)\n * np.sin(theta) / np.cos(theta)**(2 * n) # noqa\n )\n # fmt: on\n\n # apply Eq. (10)\n denominator = x**2 + y**2\n x2 = x * eta**kappa / denominator ** (1 - kappa)\n y2 = y * eta**kappa / denominator ** (1 - kappa)\n z2 = -z / eta / denominator\n return x2, y2, z2" + "def sphere_to_cylinder(theta, phi):\n \"\"\"Map from spherical polar coordinates to cylindrical ones.\n\n Input theta goes from -pi/2 to pi/2, phi goes from -pi to pi.\n Output h goes from -infinity to infinity, phi goes from -phi to phi.\n\n \"\"\"\n h = w * np.sin(theta) / np.cos(theta) ** n\n # phi is unchanged\n return h, phi\n\n\ndef cylinder_to_wormhole(h, phi, t, p, q):\n \"\"\"Map from a cylinder to an open wormhole using Eq. (4).\n\n Input h goes from -infinity to infinity, phi goes from -phi to phi.\n Output is an (x, y, z) point embedded in 3d space.\n\n The parameters t, p, q vary during the eversion process.\n Start from |t| > 1 (fixed), p = 1 and q = 0. End at p = 0, qt = +-1.\n\n \"\"\"\n x = t * np.cos(phi) + p * np.sin((n - 1) * phi) - h * np.sin(phi)\n y = t * np.sin(phi) + p * np.cos((n - 1) * phi) + h * np.cos(phi)\n z = h * np.sin(n * phi) - t / n * np.cos(n * phi) - q * t * h\n return x, y, z\n\n\ndef close_wormhole(x0, y0, z0, eta, xi, alpha):\n \"\"\"Close the wormhole using Eqs. (7)-(8).\n\n Input is an (x0, y0, z0) point embedded in 3d space.\n Output is an (x2, y2, z2) == (x'', y'', z'') point embedded in 3d space.\n\n The parameters eta, xi, alpha vary during the eversion process.\n\n \"\"\"\n # Eq. (7): (x, y, z) -> (x', y', z')\n denominator = xi + eta * (x**2 + y**2)\n x1 = x0 / (denominator**kappa)\n y1 = y0 / (denominator**kappa)\n z1 = z0 / denominator\n\n gamma = 2 * np.sqrt(alpha * beta)\n # singular case, Eq (9):\n if np.isclose(gamma, 0):\n denominator = x1**2 + y1**2\n x2 = x1 / denominator\n y2 = y1 / denominator\n z2 = -z1\n return x2, y2, z2\n\n # Eq. (8): (x', y', z') -> (x'', y'', z'')\n exponential = np.exp(gamma * z1)\n numerator = alpha - beta * (x1**2 + y1**2)\n denominator = alpha + beta * (x1**2 + y1**2)\n x2 = x1 * exponential / denominator\n y2 = y1 * exponential / denominator\n z2 = numerator / denominator * exponential / gamma - (alpha - beta) / (alpha + beta) / gamma\n return x2, y2, z2\n\n\ndef unfold_sphere(theta, phi, t, q, eta, lamda):\n \"\"\"Unfold the sphere using Eqs. (12), (15), (10).\n\n Input is a (theta, phi) point in spherical coordinates.\n Output is an (x, y, z) point embedded in 3d space.\n\n The parameter lamda varies. Lamda = 1 is the final stage of the\n wormhole closing, and lamda = 0 is the recovered sphere.\n\n \"\"\"\n # apply Eqs. (12), (15)\n # fmt: off\n x = (\n t * (1 - lamda + lamda * np.cos(theta)**n) * np.cos(phi)\n - lamda * w * np.sin(theta) * np.sin(phi)\n )\n x /= np.cos(theta)**n\n y = (\n t * (1 - lamda + lamda * np.cos(theta)**n) * np.sin(phi)\n + lamda * w * np.sin(theta) * np.cos(phi)\n )\n y /= np.cos(theta) ** n\n z = (\n lamda * (\n (w * np.sin(theta) * (np.sin(n * phi) - q * t)) / np.cos(theta)**n\n - t / n * np.cos(n * phi)\n )\n - (1 - lamda) * eta**(1 + kappa) * t * abs(t)**(2 * kappa)\n * np.sin(theta) / np.cos(theta)**(2 * n) # noqa: E131\n )\n # fmt: on\n\n # apply Eq. (10)\n denominator = x**2 + y**2\n x2 = x * eta**kappa / denominator ** (1 - kappa)\n y2 = y * eta**kappa / denominator ** (1 - kappa)\n z2 = -z / eta / denominator\n return x2, y2, z2" ] }, {