Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
tkoyama010 committed Feb 6, 2024
1 parent 4248f74 commit 539ed42
Show file tree
Hide file tree
Showing 14 changed files with 141 additions and 15 deletions.
2 changes: 1 addition & 1 deletion 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
Expand Down
4 changes: 2 additions & 2 deletions examples/00-load/create-point-cloud.ipynb
Expand Up @@ -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, :]"
]
},
{
Expand Down Expand Up @@ -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, :]"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion examples/00-load/create-structured-surface.ipynb
Expand Up @@ -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, :]"
]
},
{
Expand Down
4 changes: 2 additions & 2 deletions examples/00-load/create-tri-surface.ipynb
Expand Up @@ -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, :]"
]
},
{
Expand Down Expand Up @@ -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"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion examples/00-load/wrap-trimesh.ipynb
Expand Up @@ -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)"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion examples/01-filter/extract-surface.ipynb
Expand Up @@ -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)"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion examples/02-plot/composite-picking.ipynb
Expand Up @@ -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()"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion examples/02-plot/labels.ipynb
Expand Up @@ -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)))"
]
},
{
Expand Down
2 changes: 1 addition & 1 deletion examples/02-plot/movie.ipynb
Expand Up @@ -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()"
]
}
],
Expand Down
126 changes: 126 additions & 0 deletions 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
}
2 changes: 1 addition & 1 deletion examples/02-plot/spherical.ipynb
Expand Up @@ -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()"
]
},
{
Expand Down

0 comments on commit 539ed42

Please sign in to comment.