├── .codespellignore
├── .codespellrc
├── .github
├── ISSUE_TEMPLATE
│ ├── bug-report.md
│ ├── config.yml
│ └── feature-request.md
├── PULL_REQUEST_TEMPLATE.md
├── dependabot.yml
└── workflows
│ ├── auto-approve.yml
│ ├── doc.yml
│ ├── docker.yaml
│ ├── reviewdog.yml
│ └── update-pr-branch.yml
├── .gitignore
├── .pre-commit-config.yaml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── SECURITY.md
├── doc
├── .gitignore
├── Makefile
├── ironProt.vtk
├── make.bat
└── source
│ ├── .gitignore
│ ├── _static
│ ├── cards.css
│ ├── copybutton.css
│ ├── fontawesome
│ │ ├── LICENSE.txt
│ │ ├── css
│ │ │ └── all.css
│ │ └── webfonts
│ │ │ ├── fa-brands-400.eot
│ │ │ ├── fa-brands-400.svg
│ │ │ ├── fa-brands-400.ttf
│ │ │ ├── fa-brands-400.woff
│ │ │ ├── fa-brands-400.woff2
│ │ │ ├── fa-regular-400.eot
│ │ │ ├── fa-regular-400.svg
│ │ │ ├── fa-regular-400.ttf
│ │ │ ├── fa-regular-400.woff
│ │ │ ├── fa-regular-400.woff2
│ │ │ ├── fa-solid-900.eot
│ │ │ ├── fa-solid-900.svg
│ │ │ ├── fa-solid-900.ttf
│ │ │ ├── fa-solid-900.woff
│ │ │ └── fa-solid-900.woff2
│ ├── no_search_highlight.css
│ ├── pyvista_banner.png
│ ├── pyvista_banner_small.png
│ ├── pyvista_ipython_demo.mp4
│ ├── pyvista_jupyterlab_demo.mp4
│ ├── pyvista_logo.png
│ ├── pyvista_logo_sm.png
│ ├── pyvista_logo_sm_sq.png
│ └── table.css
│ ├── conf.py
│ ├── getting-started.rst
│ ├── images
│ ├── action
│ │ ├── AeroSandbox.png
│ │ ├── Duoprism_3-30.gif
│ │ ├── air_racing_optimization.png
│ │ ├── anvil_cirrus_plumes.png
│ │ ├── atmospheric_convection.jpeg
│ │ ├── boolean_marching_cubes.png
│ │ ├── coil_field_lines.png
│ │ ├── comet_fenicsx.png
│ │ ├── damavand_volcano.gif
│ │ ├── discretize.png
│ │ ├── drilldown.jpg
│ │ ├── felupe.png
│ │ ├── flem.png
│ │ ├── forge.png
│ │ ├── geemap.gif
│ │ ├── gemgis.png
│ │ ├── geovista_earth.png
│ │ ├── gmsh_model.png
│ │ ├── grad_descent_visualizer.gif
│ │ ├── griddip.gif
│ │ ├── nikolov1.gif
│ │ ├── nikolov2.gif
│ │ ├── nikolov3.gif
│ │ ├── omfvista.png
│ │ ├── open-foam.png
│ │ ├── optimization.gif
│ │ ├── orvisu.gif
│ │ ├── ptera_software.gif
│ │ ├── pvgeo.png
│ │ ├── pyelastica.gif
│ │ ├── pyfbs.webp
│ │ ├── pymeshfix.png
│ │ ├── stpyvista_intro_crop.gif
│ │ ├── sunkit-pyvista.png
│ │ ├── tetgen.png
│ │ ├── vessel_vio.png
│ │ └── visualpic.png
│ ├── gifs
│ │ ├── .gitignore
│ │ ├── box-clip.gif
│ │ ├── documentation.gif
│ │ ├── dynamic_flask.gif
│ │ ├── line-widget-streamlines.gif
│ │ ├── multiple-checkbox-widget.gif
│ │ ├── multiple-slider-widget.gif
│ │ ├── plane-clip.gif
│ │ ├── plane-glyph.gif
│ │ ├── plane-slice-continuous.gif
│ │ ├── plane-slice.gif
│ │ ├── scalar-bar-interactive.gif
│ │ ├── shrink-globe.gif
│ │ ├── single-checkbox-widget.gif
│ │ ├── slider-widget-resolution.gif
│ │ ├── slider-widget-threshold.gif
│ │ ├── sphere-widget-a.gif
│ │ ├── sphere-widget-b.gif
│ │ ├── sphere-widget-c.gif
│ │ └── spline-widget.gif
│ ├── jupyter.png
│ ├── trame-pyvista.png
│ └── user-generated
│ │ ├── .gitkeep
│ │ ├── femorph-qt.png
│ │ ├── qt_multiplot.png
│ │ └── qt_plotting_sphere.png
│ ├── index.rst
│ ├── locales
│ └── .gitkeep
│ ├── make_external_gallery.py
│ └── tutorial.rst
├── pyproject.toml
├── requirements.txt
├── start
└── tutorial
├── 00_intro
├── README.rst
└── a_basic.py
├── 00_jupyter
├── README.rst
└── jupyter.py
├── 01_basic
├── README.rst
├── a_lesson_basic.py
├── exercises
│ ├── README.rst
│ └── a_load_examples_exercise.py
├── ironProt.vtk
└── solutions
│ ├── P_shelf_pin.stl
│ ├── README.rst
│ └── a_load_examples_solution.py
├── 02_mesh
├── README.rst
├── a_lesson_mesh.py
├── exercises
│ ├── README.rst
│ ├── b_create-point-cloud.py
│ ├── c_create-uniform-grid.py
│ ├── d_create-tri-surface.py
│ └── e_read-file.py
├── scipy.vtk
└── solutions
│ ├── README.rst
│ ├── b_create-point-cloud.py
│ ├── c_create-uniform-grid.py
│ ├── d_create-tri-surface.py
│ └── e_read-file.py
├── 03_figures
├── README.rst
├── a_lesson_figures.py
├── b_shading.py
├── bonus
│ ├── README.rst
│ ├── d_pbr.py
│ ├── e_labels.py
│ └── g_orbit.py
├── c_geological-map.py
├── d_gif.py
├── exercises
│ ├── README.rst
│ ├── a_display_options.py
│ ├── b_lighting_mesh.py
│ └── c_edl.py
└── solutions
│ ├── README.rst
│ ├── a_display_options.py
│ ├── b_lighting_mesh.py
│ └── c_edl.py
├── 04_filters
├── README.rst
├── a_lesson_filters.py
├── bonus
│ ├── README.rst
│ └── f_sampling_functions_3d.py
├── exercises
│ ├── README.rst
│ ├── b_clipping.py
│ ├── c_compute-normals.py
│ ├── d_contouring.py
│ └── e_glyphs.py
└── solutions
│ ├── README.rst
│ ├── b_clipping.py
│ ├── c_compute-normals.py
│ ├── d_contouring.py
│ └── e_glyphs.py
├── 05_action
├── LICENSE
└── README.rst
├── 06_vtk
├── README.rst
├── a_1_transition_vtk.py
├── a_2_pyvista_vtk.py
├── b_create_vtk.py
├── c_vtk_algorithms.py
├── d_wasm.py
└── e_vtk_next.py
├── 07_sphinx
└── README.rst
├── 08_widgets
├── README.rst
├── a_box-widget.py
├── b_checkbox-widget.py
├── c_line-widget.py
├── d_multi-slider-widget.py
├── e_plane-widget.py
├── f_slider-bar-widget.py
├── g_sphere-widget.py
└── h_spline-widget.py
└── 09_trame
├── README.rst
├── a_getting_started.py
├── a_trame_simple.py
├── b_trame_actor_color.py
├── b_trame_vtk.py
├── c_trame_scalars.py
├── d_trame_scalar_range.py
├── e_trame_algorithm.py
└── f_trame_open_file.py
/.codespellignore:
--------------------------------------------------------------------------------
1 | flem
2 | FLEM
3 |
--------------------------------------------------------------------------------
/.codespellrc:
--------------------------------------------------------------------------------
1 | [codespell]
2 | skip = *.svg
3 | ignore-words = .codespellignore
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug-report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug Report
3 | about: Create a report to help us fix broken features
4 | title: ""
5 | labels: bug
6 | assignees: ""
7 | ---
8 |
9 | **Describe the bug, what's wrong, and what you expect:**
10 |
11 | A clear and concise description of what the bug is.
12 |
13 | A clear and concise description of what you expected to happen.
14 |
15 | ---
16 |
17 | **To Reproduce**
18 |
19 | Please include a code snippet to reproduce the bug in the block below:
20 |
21 | ```py
22 | # Insert code here
23 |
24 | ```
25 |
26 | **Screenshots**
27 | If applicable, add screenshots to help explain your problem.
28 |
29 | ---
30 |
31 | **System Information:**
32 | Please run the following code wherever you are experiencing the bug and paste the output below. This report helps us track down bugs and it is critical to addressing your bug:
33 |
34 | ```py
35 | # Get system info
36 | import pyvista as pv
37 | print(pv.Report())
38 | ```
39 |
40 | ```txt
41 | # Paste system info here
42 |
43 | ```
44 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | contact_links:
2 | - name: Questions and Discussions
3 | url: https://github.com/pyvista/pyvista-tutorial/discussions
4 | about: For general questions and discussions
5 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature-request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature Request
3 | about: Request that a feature be added to pyvista-tutorial
4 | title: ""
5 | labels: enhancement
6 | assignees: ""
7 | ---
8 |
9 | **Describe what feature you would like added.**
10 |
11 | A clear and concise description of what you would like added.
12 |
13 | If you are requesting a feature from PyVista document, please include links to the PyVista document, example, or class definition.
14 |
15 | Feel free to include pseudocode or screenshots of the requested outcome.
16 |
17 | ---
18 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### Overview
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | ### Details
10 |
11 | - < feature1 or bug1 description >
12 | - < feature2 or bug2 description >
13 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "pip"
4 | directory: "/"
5 | insecure-external-code-execution: allow
6 | schedule:
7 | interval: "monthly"
8 | open-pull-requests-limit: 100
9 | groups:
10 | trame:
11 | patterns:
12 | - "trame"
13 | - "trame-*"
14 | - package-ecosystem: "docker"
15 | directory: "/"
16 | schedule:
17 | interval: "monthly"
18 | open-pull-requests-limit: 100
19 | - package-ecosystem: "github-actions"
20 | directory: "/"
21 | schedule:
22 | interval: "daily"
23 | open-pull-requests-limit: 100
24 | labels:
25 | - "maintenance"
26 | - "dependencies"
27 |
--------------------------------------------------------------------------------
/.github/workflows/auto-approve.yml:
--------------------------------------------------------------------------------
1 | name: Approve PRs
2 | on:
3 | workflow_dispatch:
4 | issue_comment:
5 | types: [created]
6 |
7 | jobs:
8 | autoapprove:
9 | # This job only runs for pull request comments by approved users on creation
10 | name: PR comment
11 | if: github.event.issue.pull_request &&
12 | contains(github.event.comment.body, '@pyvista-bot LGTM') && (
13 | github.event.comment.user.login == 'banesullivan' ||
14 | github.event.comment.user.login == 'tkoyama010' ||
15 | github.event.comment.user.login == 'akaszynski'
16 | )
17 | permissions:
18 | pull-requests: write
19 | runs-on: ubuntu-latest
20 | steps:
21 | - uses: hmarr/auto-approve-action@v4
22 | with:
23 | review-message: ":white_check_mark: Approving this PR because [${{ github.event.comment.user.login }}](https://github.com/${{ github.event.comment.user.login }}) said so in [here](${{ github.event.comment.html_url }}) :shipit:"
24 | pull-request-number: ${{ github.event.issue.number }}
25 | github-token: ${{ secrets.GITHUB_TOKEN }}
26 |
--------------------------------------------------------------------------------
/.github/workflows/docker.yaml:
--------------------------------------------------------------------------------
1 | name: Build Docker Image
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | tags:
7 | - "*"
8 | branches:
9 | - main
10 | pull_request:
11 |
12 | env:
13 | REGISTRY: ghcr.io
14 | IMAGE_NAME: ${{ github.repository }}
15 |
16 | jobs:
17 | build-docker:
18 | permissions:
19 | packages: write
20 | pull-requests: read
21 | issues: read
22 | repository-projects: read
23 | runs-on: ubuntu-latest
24 | if:
25 | github.event_name == 'push' || github.event_name == 'workflow_dispatch' ||
26 | ( github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository )
27 | steps:
28 | - uses: actions/checkout@v4
29 | with:
30 | persist-credentials: false
31 | - name: Log into the Container registry
32 | uses: docker/login-action@v3
33 | with:
34 | registry: ${{ env.REGISTRY }}
35 | username: token
36 | password: ${{ secrets.GITHUB_TOKEN }}
37 | - name: Extract metadata for the Jupyter Docker image
38 | id: meta
39 | uses: docker/metadata-action@v5
40 | with:
41 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
42 | - name: Build and push the Jupyter Docker image
43 | uses: docker/build-push-action@v6
44 | with:
45 | context: .
46 | file: Dockerfile
47 | push: ${{ github.actor != 'dependabot[bot]' && github.actor != 'pre-commit-ci[bot]' }}
48 | tags: ${{ steps.meta.outputs.tags }}
49 | labels: ${{ steps.meta.outputs.labels }}
50 |
--------------------------------------------------------------------------------
/.github/workflows/reviewdog.yml:
--------------------------------------------------------------------------------
1 | name: reviewdog
2 | on: [pull_request]
3 | jobs:
4 | misspell:
5 | name: runner / misspell
6 | permissions:
7 | pull-requests: read
8 | issues: read
9 | repository-projects: read
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: Check out code.
13 | uses: actions/checkout@v4
14 | with:
15 | persist-credentials: false
16 | - name: misspell
17 | uses: reviewdog/action-misspell@v1
18 | with:
19 | github_token: ${{ secrets.github_token }}
20 | locale: "US"
21 | pattern: "*.md"
22 |
--------------------------------------------------------------------------------
/.github/workflows/update-pr-branch.yml:
--------------------------------------------------------------------------------
1 | name: PR update
2 |
3 | on:
4 | push:
5 | branches:
6 | - "main"
7 | jobs:
8 | autoupdate:
9 | permissions:
10 | pull-requests: write
11 | issues: read
12 | repository-projects: read
13 | runs-on: ubuntu-latest
14 | steps:
15 | - name: Automatically update PR
16 | uses: adRise/update-pr-branch@v0.10.1
17 | with:
18 | token: ${{ secrets.GITHUB_TOKEN }}
19 | base: "main"
20 | required_approval_count: 1
21 | require_passed_checks: false
22 | sort: "created"
23 | direction: "desc"
24 | require_auto_merge_enabled: true
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .venv
2 | **/*.DS_Store
3 | **/*.ipynb_checkpoints
4 |
5 | doc/source/images/auto-generated/*
6 | node_modules/
7 | .vscode/
8 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | repos:
2 | - repo: https://github.com/codespell-project/codespell
3 | rev: v2.4.1
4 | hooks:
5 | - id: codespell
6 | args: ["doc tutorial", "*.py *.rst *.md"]
7 |
8 | - repo: https://github.com/pre-commit/pre-commit-hooks
9 | rev: v5.0.0
10 | hooks:
11 | - id: check-merge-conflict
12 | - id: debug-statements
13 | - id: no-commit-to-branch
14 | args: [--branch, main]
15 | - id: requirements-txt-fixer
16 | - id: trailing-whitespace
17 | exclude: ^(doc/source/_static/.*)
18 | - id: mixed-line-ending
19 | - id: end-of-file-fixer
20 |
21 | - repo: https://github.com/python-jsonschema/check-jsonschema
22 | rev: 0.33.0
23 | hooks:
24 | - id: check-github-workflows
25 |
26 | - repo: https://github.com/rbubley/mirrors-prettier
27 | rev: v3.5.3
28 | hooks:
29 | - id: prettier
30 | types_or: [yaml, markdown, html, css, scss, javascript, json]
31 |
32 | - repo: https://github.com/astral-sh/ruff-pre-commit
33 | rev: v0.11.13
34 | hooks:
35 | - id: ruff
36 | args: [--fix, --show-fixes]
37 | - id: ruff-format
38 |
39 | - repo: https://github.com/ComPWA/taplo-pre-commit
40 | rev: v0.9.3
41 | hooks:
42 | - id: taplo-format
43 | # See options: https://taplo.tamasfe.dev/configuration/formatter-options.html
44 | args: [--option, "reorder_arrays=true", --option, "reorder_keys=true"]
45 |
46 | - repo: https://github.com/woodruffw/zizmor-pre-commit
47 | rev: v1.5.2
48 | hooks:
49 | - id: zizmor
50 |
51 | - repo: https://github.com/sphinx-contrib/sphinx-lint
52 | rev: v1.0.0
53 | hooks:
54 | - id: sphinx-lint
55 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our
7 | project and our community a harassment-free experience for everyone,
8 | regardless of age, body size, disability, ethnicity, sex
9 | characteristics, gender identity and expression, level of experience,
10 | education, socioeconomic status, nationality, personal appearance,
11 | race, religion, or sexual identity and orientation.
12 |
13 | Please reference the contributing guide at [pyvista/CODE_OF_CONDUCT.md](https://github.com/pyvista/pyvista/blob/master/CODE_OF_CONDUCT.md) for additional details.
14 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | We absolutely welcome contributions and we hope that this guide will
4 | facilitate an understanding of the PyVista code repository. It is
5 | important to note that the PyVista software package is maintained on a
6 | volunteer basis and thus we need to foster a community that can
7 | support user questions and develop new features to make this software
8 | a useful tool for all users.
9 |
10 | Please reference the contributing guide at [pyvista/CONTRIBUTING.rst](https://github.com/pyvista/pyvista/blob/master/CONTRIBUTING.rst) for contributing to this repository.
11 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG BASE_IMAGE_TAG=latest
2 | FROM ghcr.io/pyvista/pyvista:$BASE_IMAGE_TAG
3 |
4 | COPY . ${HOME}
5 | WORKDIR ${HOME}
6 | RUN pip install hypothesis lxml pyct rtree tqdm
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022-2025 The PyVista Developers
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | [Security Policy](https://github.com/pyvista/pyvista/blob/main/SECURITY.md)
2 |
--------------------------------------------------------------------------------
/doc/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 |
--------------------------------------------------------------------------------
/doc/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = source
9 | BUILDDIR = build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
22 | # remove the sphinx-gallery
23 | clean:
24 | rm -rf $(BUILDDIR)/*
25 | rm -rf source/tutorial/
26 | rm -rf source/images/auto-generated
27 |
28 | # Spin up a local http server to view the rendered documentation.
29 | # This is required for interactive examples to work.
30 | serve-html:
31 | python -m http.server 11000 --directory "$(BUILDDIR)"/html
32 |
--------------------------------------------------------------------------------
/doc/ironProt.vtk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/ironProt.vtk
--------------------------------------------------------------------------------
/doc/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 |
13 | %SPHINXBUILD% >NUL 2>NUL
14 | if errorlevel 9009 (
15 | echo.
16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
17 | echo.installed, then set the SPHINXBUILD environment variable to point
18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
19 | echo.may add the Sphinx directory to PATH.
20 | echo.
21 | echo.If you don't have Sphinx installed, grab it from
22 | echo.https://www.sphinx-doc.org/
23 | exit /b 1
24 | )
25 |
26 | if "%1" == "" goto help
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/doc/source/.gitignore:
--------------------------------------------------------------------------------
1 | tutorial/
2 | errors.txt
3 | __pycache__
4 | sg_execution_times.rst
5 |
--------------------------------------------------------------------------------
/doc/source/_static/cards.css:
--------------------------------------------------------------------------------
1 | .pyvista-card-title {
2 | color: #459db9;
3 | font-style: normal;
4 | font-weight: 500 !important;
5 | font-size: 20px;
6 | text-align: center;
7 | }
8 |
--------------------------------------------------------------------------------
/doc/source/_static/copybutton.css:
--------------------------------------------------------------------------------
1 | /* Copy buttons */
2 | a.copybtn {
3 | position: absolute;
4 | top: 2px;
5 | right: 2px;
6 | width: 1em;
7 | height: 1em;
8 | padding: 0.3em;
9 | opacity: 0.3;
10 | transition: opacity 0.5s;
11 | }
12 |
13 | div.highlight {
14 | position: relative;
15 | }
16 |
17 | .highlight:hover .copybtn {
18 | opacity: 1;
19 | }
20 |
21 | /**
22 | * A minimal CSS-only tooltip copied from:
23 | * https://codepen.io/mildrenben/pen/rVBrpK
24 | *
25 | * To use, write HTML like the following:
26 | *
27 | *
Short
28 | */
29 | .o-tooltip--left {
30 | position: relative;
31 | }
32 |
33 | .o-tooltip--left:after {
34 | opacity: 0;
35 | visibility: hidden;
36 | position: absolute;
37 | content: attr(data-tooltip);
38 | padding: 2px;
39 | top: 0;
40 | left: 0;
41 | background: grey;
42 | font-size: 1rem;
43 | color: white;
44 | white-space: nowrap;
45 | z-index: 2;
46 | border-radius: 2px;
47 | transform: translateX(-102%) translateY(0);
48 | transition:
49 | opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1),
50 | transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1);
51 | }
52 |
53 | .o-tooltip--left:hover:after {
54 | display: block;
55 | opacity: 1;
56 | visibility: visible;
57 | transform: translateX(-100%) translateY(0);
58 | transition:
59 | opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1),
60 | transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1);
61 | }
62 |
--------------------------------------------------------------------------------
/doc/source/_static/fontawesome/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Font Awesome Free License
2 | -------------------------
3 |
4 | Font Awesome Free is free, open source, and GPL friendly. You can use it for
5 | commercial projects, open source projects, or really almost whatever you want.
6 | Full Font Awesome Free license: https://fontawesome.com/license/free.
7 |
8 | # Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/)
9 | In the Font Awesome Free download, the CC BY 4.0 license applies to all icons
10 | packaged as SVG and JS file types.
11 |
12 | # Fonts: SIL OFL 1.1 License (https://scripts.sil.org/OFL)
13 | In the Font Awesome Free download, the SIL OFL license applies to all icons
14 | packaged as web and desktop font files.
15 |
16 | # Code: MIT License (https://opensource.org/licenses/MIT)
17 | In the Font Awesome Free download, the MIT license applies to all non-font and
18 | non-icon files.
19 |
20 | # Attribution
21 | Attribution is required by MIT, SIL OFL, and CC BY licenses. Downloaded Font
22 | Awesome Free files already contain embedded comments with sufficient
23 | attribution, so you shouldn't need to do anything additional when using these
24 | files normally.
25 |
26 | We've kept attribution comments terse, so we ask that you do not actively work
27 | to remove them from files, especially code. They're a great way for folks to
28 | learn about Font Awesome.
29 |
30 | # Brand Icons
31 | All brand icons are trademarks of their respective owners. The use of these
32 | trademarks does not indicate endorsement of the trademark holder by Font
33 | Awesome, nor vice versa. **Please do not use brand logos for any purpose except
34 | to represent the company, product, or service to which they refer.**
35 |
--------------------------------------------------------------------------------
/doc/source/_static/fontawesome/webfonts/fa-brands-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/fontawesome/webfonts/fa-brands-400.eot
--------------------------------------------------------------------------------
/doc/source/_static/fontawesome/webfonts/fa-brands-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/fontawesome/webfonts/fa-brands-400.ttf
--------------------------------------------------------------------------------
/doc/source/_static/fontawesome/webfonts/fa-brands-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/fontawesome/webfonts/fa-brands-400.woff
--------------------------------------------------------------------------------
/doc/source/_static/fontawesome/webfonts/fa-brands-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/fontawesome/webfonts/fa-brands-400.woff2
--------------------------------------------------------------------------------
/doc/source/_static/fontawesome/webfonts/fa-regular-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/fontawesome/webfonts/fa-regular-400.eot
--------------------------------------------------------------------------------
/doc/source/_static/fontawesome/webfonts/fa-regular-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/fontawesome/webfonts/fa-regular-400.ttf
--------------------------------------------------------------------------------
/doc/source/_static/fontawesome/webfonts/fa-regular-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/fontawesome/webfonts/fa-regular-400.woff
--------------------------------------------------------------------------------
/doc/source/_static/fontawesome/webfonts/fa-regular-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/fontawesome/webfonts/fa-regular-400.woff2
--------------------------------------------------------------------------------
/doc/source/_static/fontawesome/webfonts/fa-solid-900.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/fontawesome/webfonts/fa-solid-900.eot
--------------------------------------------------------------------------------
/doc/source/_static/fontawesome/webfonts/fa-solid-900.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/fontawesome/webfonts/fa-solid-900.ttf
--------------------------------------------------------------------------------
/doc/source/_static/fontawesome/webfonts/fa-solid-900.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/fontawesome/webfonts/fa-solid-900.woff
--------------------------------------------------------------------------------
/doc/source/_static/fontawesome/webfonts/fa-solid-900.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/fontawesome/webfonts/fa-solid-900.woff2
--------------------------------------------------------------------------------
/doc/source/_static/no_search_highlight.css:
--------------------------------------------------------------------------------
1 | /* No search term highlighting, see https://stackoverflow.com/a/48771802 */
2 | span.highlighted {
3 | background-color: transparent;
4 | }
5 |
--------------------------------------------------------------------------------
/doc/source/_static/pyvista_banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/pyvista_banner.png
--------------------------------------------------------------------------------
/doc/source/_static/pyvista_banner_small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/pyvista_banner_small.png
--------------------------------------------------------------------------------
/doc/source/_static/pyvista_ipython_demo.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/pyvista_ipython_demo.mp4
--------------------------------------------------------------------------------
/doc/source/_static/pyvista_jupyterlab_demo.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/pyvista_jupyterlab_demo.mp4
--------------------------------------------------------------------------------
/doc/source/_static/pyvista_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/pyvista_logo.png
--------------------------------------------------------------------------------
/doc/source/_static/pyvista_logo_sm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/pyvista_logo_sm.png
--------------------------------------------------------------------------------
/doc/source/_static/pyvista_logo_sm_sq.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/_static/pyvista_logo_sm_sq.png
--------------------------------------------------------------------------------
/doc/source/_static/table.css:
--------------------------------------------------------------------------------
1 | .rendered_html table {
2 | table-layout: auto;
3 | }
4 |
--------------------------------------------------------------------------------
/doc/source/getting-started.rst:
--------------------------------------------------------------------------------
1 | .. _getting_started:
2 |
3 | Getting Started
4 | ===============
5 |
6 | The only prerequisite for installing PyVista is Python itself. If you don't have
7 | Python yet and want the simplest way to get started, we recommend you use the
8 | `Anaconda Distribution`_.
9 |
10 | .. _Anaconda Distribution: https://www.anaconda.com/
11 |
12 | PyVista can be installed locally with conda or pip. If you'd
13 | prefer it, you can also run PyVista on the cloud using :ref:`colab` or
14 | :ref:`mybinder`. For more detailed instructions, see the installation
15 | guide below.
16 |
17 |
18 | Installation
19 | ------------
20 |
21 | PyVista can be installed on several environments, including, but not limited to:
22 |
23 | .. tab-set::
24 |
25 | .. tab-item:: pip
26 |
27 | .. code::
28 |
29 | pip install 'pyvista[all,trame]' jupyterlab
30 |
31 | .. tab-item:: conda
32 |
33 | .. code::
34 |
35 | conda install -c conda-forge pyvista jupyterlab trame trame-vuetify trame-vtk ipywidgets
36 |
37 |
38 |
39 |
40 | You can then plot in Jupyter with either a static or interactive backend:
41 |
42 | .. pyvista-plot::
43 |
44 | import pyvista as pv
45 | from pyvista import examples
46 |
47 | dataset = examples.download_lucy()
48 | dataset.plot(smooth_shading=True, color='white')
49 |
50 |
51 | .. _mybinder:
52 |
53 | MyBinder
54 | --------
55 | MyBinder, similar to Google Colab, allows you to run Jupyter notebooks on the
56 | cloud. Click on the link below to open up a MyBinder environment to run
57 | PyVista.
58 |
59 | |binder|
60 |
61 | .. |binder| image:: https://static.mybinder.org/badge_logo.svg
62 | :target: https://mybinder.org/v2/gh/pyvista/pyvista-tutorial/gh-pages?urlpath=lab/tree/notebooks
63 | :alt: Launch on Binder
64 |
65 |
66 | .. _colab:
67 |
68 | Google Colab
69 | ------------
70 | Google Colab is a moving target and many of the "cloud ready" JavaScript
71 | plotting environments that make PyVista so great to work with do not seem to be
72 | available on Google Colab. However, we still have a working PyVista example for
73 | `Google Colab `_ with static plotting.
74 |
75 | Visit the `PyVista on Colab `_ notebook to see PyVista in action. The minimum code to get PyVista running in a Colab environment is:
76 |
77 | .. code::
78 |
79 | !apt-get install -qq xvfb libgl1-mesa-glx
80 | !pip install pyvista -qq
81 |
82 | .. code:: python
83 |
84 | import pyvista
85 |
86 | pyvista.set_jupyter_backend('static')
87 | pyvista.global_theme.notebook = True
88 | pyvista.start_xvfb()
89 |
--------------------------------------------------------------------------------
/doc/source/images/action/AeroSandbox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/AeroSandbox.png
--------------------------------------------------------------------------------
/doc/source/images/action/Duoprism_3-30.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/Duoprism_3-30.gif
--------------------------------------------------------------------------------
/doc/source/images/action/air_racing_optimization.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/air_racing_optimization.png
--------------------------------------------------------------------------------
/doc/source/images/action/anvil_cirrus_plumes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/anvil_cirrus_plumes.png
--------------------------------------------------------------------------------
/doc/source/images/action/atmospheric_convection.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/atmospheric_convection.jpeg
--------------------------------------------------------------------------------
/doc/source/images/action/boolean_marching_cubes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/boolean_marching_cubes.png
--------------------------------------------------------------------------------
/doc/source/images/action/coil_field_lines.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/coil_field_lines.png
--------------------------------------------------------------------------------
/doc/source/images/action/comet_fenicsx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/comet_fenicsx.png
--------------------------------------------------------------------------------
/doc/source/images/action/damavand_volcano.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/damavand_volcano.gif
--------------------------------------------------------------------------------
/doc/source/images/action/discretize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/discretize.png
--------------------------------------------------------------------------------
/doc/source/images/action/drilldown.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/drilldown.jpg
--------------------------------------------------------------------------------
/doc/source/images/action/felupe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/felupe.png
--------------------------------------------------------------------------------
/doc/source/images/action/flem.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/flem.png
--------------------------------------------------------------------------------
/doc/source/images/action/forge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/forge.png
--------------------------------------------------------------------------------
/doc/source/images/action/geemap.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/geemap.gif
--------------------------------------------------------------------------------
/doc/source/images/action/gemgis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/gemgis.png
--------------------------------------------------------------------------------
/doc/source/images/action/geovista_earth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/geovista_earth.png
--------------------------------------------------------------------------------
/doc/source/images/action/gmsh_model.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/gmsh_model.png
--------------------------------------------------------------------------------
/doc/source/images/action/grad_descent_visualizer.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/grad_descent_visualizer.gif
--------------------------------------------------------------------------------
/doc/source/images/action/griddip.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/griddip.gif
--------------------------------------------------------------------------------
/doc/source/images/action/nikolov1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/nikolov1.gif
--------------------------------------------------------------------------------
/doc/source/images/action/nikolov2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/nikolov2.gif
--------------------------------------------------------------------------------
/doc/source/images/action/nikolov3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/nikolov3.gif
--------------------------------------------------------------------------------
/doc/source/images/action/omfvista.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/omfvista.png
--------------------------------------------------------------------------------
/doc/source/images/action/open-foam.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/open-foam.png
--------------------------------------------------------------------------------
/doc/source/images/action/optimization.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/optimization.gif
--------------------------------------------------------------------------------
/doc/source/images/action/orvisu.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/orvisu.gif
--------------------------------------------------------------------------------
/doc/source/images/action/ptera_software.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/ptera_software.gif
--------------------------------------------------------------------------------
/doc/source/images/action/pvgeo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/pvgeo.png
--------------------------------------------------------------------------------
/doc/source/images/action/pyelastica.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/pyelastica.gif
--------------------------------------------------------------------------------
/doc/source/images/action/pyfbs.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/pyfbs.webp
--------------------------------------------------------------------------------
/doc/source/images/action/pymeshfix.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/pymeshfix.png
--------------------------------------------------------------------------------
/doc/source/images/action/stpyvista_intro_crop.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/stpyvista_intro_crop.gif
--------------------------------------------------------------------------------
/doc/source/images/action/sunkit-pyvista.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/sunkit-pyvista.png
--------------------------------------------------------------------------------
/doc/source/images/action/tetgen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/tetgen.png
--------------------------------------------------------------------------------
/doc/source/images/action/vessel_vio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/vessel_vio.png
--------------------------------------------------------------------------------
/doc/source/images/action/visualpic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/action/visualpic.png
--------------------------------------------------------------------------------
/doc/source/images/gifs/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/.gitignore
--------------------------------------------------------------------------------
/doc/source/images/gifs/box-clip.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/box-clip.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/documentation.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/documentation.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/dynamic_flask.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/dynamic_flask.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/line-widget-streamlines.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/line-widget-streamlines.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/multiple-checkbox-widget.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/multiple-checkbox-widget.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/multiple-slider-widget.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/multiple-slider-widget.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/plane-clip.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/plane-clip.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/plane-glyph.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/plane-glyph.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/plane-slice-continuous.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/plane-slice-continuous.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/plane-slice.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/plane-slice.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/scalar-bar-interactive.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/scalar-bar-interactive.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/shrink-globe.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/shrink-globe.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/single-checkbox-widget.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/single-checkbox-widget.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/slider-widget-resolution.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/slider-widget-resolution.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/slider-widget-threshold.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/slider-widget-threshold.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/sphere-widget-a.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/sphere-widget-a.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/sphere-widget-b.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/sphere-widget-b.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/sphere-widget-c.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/sphere-widget-c.gif
--------------------------------------------------------------------------------
/doc/source/images/gifs/spline-widget.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/gifs/spline-widget.gif
--------------------------------------------------------------------------------
/doc/source/images/jupyter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/jupyter.png
--------------------------------------------------------------------------------
/doc/source/images/trame-pyvista.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/trame-pyvista.png
--------------------------------------------------------------------------------
/doc/source/images/user-generated/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/user-generated/.gitkeep
--------------------------------------------------------------------------------
/doc/source/images/user-generated/femorph-qt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/user-generated/femorph-qt.png
--------------------------------------------------------------------------------
/doc/source/images/user-generated/qt_multiplot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/user-generated/qt_multiplot.png
--------------------------------------------------------------------------------
/doc/source/images/user-generated/qt_plotting_sphere.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/images/user-generated/qt_plotting_sphere.png
--------------------------------------------------------------------------------
/doc/source/locales/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/doc/source/locales/.gitkeep
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | dynamic = ['version']
3 | name = "pyvista-tutorial"
4 | requires-python = '>=3.9'
5 |
6 | [project.optional-dependencies]
7 | all = ['docs']
8 | docs = [
9 | 'Sphinx==8.2.1',
10 | 'atsphinx-mini18n==0.4.1',
11 | 'cmocean==4.0.3',
12 | 'colorcet==3.1.0',
13 | 'geovista==0.5.3',
14 | 'imageio-ffmpeg==0.6.0',
15 | 'imageio>=2.5.0',
16 | 'ipygany==0.5.0',
17 | 'ipywidgets==8.1.7',
18 | 'jupyter_sphinx==0.5.3',
19 | 'jupyterlab==4.4.3',
20 | 'lxml==5.4.0',
21 | 'matplotlib==3.10.1',
22 | 'meshio==5.3.5',
23 | 'mypy-extensions==1.1.0',
24 | 'mypy==1.16.0',
25 | 'numpydoc==1.8.0',
26 | 'osmnx==2.0.3',
27 | 'pypandoc==1.15',
28 | 'pytest-sphinx==0.6.3',
29 | 'pyvista-xarray==0.1.7',
30 | 'pyvista[all]==0.45.2',
31 | 'scipy==1.15.2',
32 | 'sphinx-autobuild==2024.10.3',
33 | 'sphinx-book-theme==1.1.4',
34 | 'sphinx-copybutton==0.5.2',
35 | 'sphinx-gallery==0.19.0',
36 | 'sphinx-notfound-page==1.1.0',
37 | 'sphinx_design==0.6.1',
38 | 'sphinxcontrib-websupport==2.0.0',
39 | 'sphinxcontrib.asciinema==0.4.2',
40 | 'trame-client==3.9.0',
41 | 'trame-server==3.4.0',
42 | 'trame-vtk==2.8.15',
43 | 'trame-vuetify==3.0.1',
44 | 'trame==3.10.1',
45 | 'trimesh==4.6.10',
46 | 'typed-ast==1.5.5',
47 | 'typing_extensions==4.13.2',
48 | 'vtk-xref==0.1.0',
49 | 'vtk<9.5',
50 | ]
51 |
52 | [tool.ruff]
53 | exclude = ['.git', 'build', 'dist', 'doc/_build', 'doc/tutorial', 'pycache__']
54 | indent-width = 4
55 | line-length = 100
56 | lint.ignore = ["COM812", "D203", "D212", "E501", "ERA001", "ISC001"]
57 | lint.select = ["ALL"]
58 |
59 | [tool.ruff.lint.per-file-ignores]
60 | "doc/**" = ["ANN", "ARG", "D", "INP001"]
61 | "tutorial/**" = [
62 | "ANN",
63 | "ARG",
64 | "B015", # https://github.com/pyvista/pyvista/pull/6014
65 | "B018", # https://github.com/pyvista/pyvista/pull/6019
66 | "D101",
67 | "D102",
68 | "D103",
69 | "D107",
70 | "D205",
71 | "D400",
72 | "D401",
73 | "D415",
74 | "E402",
75 | "F704",
76 | "INP001",
77 | "NPY",
78 | "PLE1142",
79 | ]
80 |
81 | [tool.ruff.format]
82 | docstring-code-format = true
83 | quote-style = "preserve"
84 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | cmocean
2 | geovista
3 | imageio>=2.5.0
4 | imageio-ffmpeg
5 | ipywidgets<9.0.0
6 | jupyterlab<5.0.0
7 | matplotlib
8 | pyvista[all]
9 | sphinx
10 | tqdm
11 | trame>=2.5.0
12 | trame-client>=2.9.4
13 | trame-server>=2.11.4
14 | trame-vtk>=2.5.4
15 |
--------------------------------------------------------------------------------
/start:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | export PYVISTA_TRAME_SERVER_PROXY_PREFIX="$JUPYTERHUB_SERVICE_PREFIX/proxy/"
3 | exec "$@"
4 |
--------------------------------------------------------------------------------
/tutorial/00_intro/a_basic.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _ref_geometric_example:
3 |
4 | Create Basic Geometric Objects
5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 |
7 | This is the "Hello, world!" of PyVista.
8 | """
9 |
10 | import pyvista as pv
11 |
12 | ###############################################################################
13 | # This runs through several of the available geometric objects available in
14 | # VTK which PyVista provides simple convenience methods for generating.
15 | #
16 | # Let's run through creating a few geometric objects!
17 |
18 | cyl = pv.Cylinder()
19 | arrow = pv.Arrow()
20 | sphere = pv.Sphere()
21 | plane = pv.Plane()
22 | line = pv.Line()
23 | box = pv.Box()
24 | cone = pv.Cone()
25 | poly = pv.Polygon()
26 | disc = pv.Disc()
27 |
28 | ###############################################################################
29 | # Now let's plot them all in one window
30 |
31 | p = pv.Plotter(shape=(3, 3))
32 | # Top row
33 | p.subplot(0, 0)
34 | p.add_mesh(cyl, color="tan", show_edges=True)
35 | p.subplot(0, 1)
36 | p.add_mesh(arrow, color="tan", show_edges=True)
37 | p.subplot(0, 2)
38 | p.add_mesh(sphere, color="tan", show_edges=True)
39 | # Middle row
40 | p.subplot(1, 0)
41 | p.add_mesh(plane, color="tan", show_edges=True)
42 | p.subplot(1, 1)
43 | p.add_mesh(line, color="tan", line_width=3)
44 | p.subplot(1, 2)
45 | p.add_mesh(box, color="tan", show_edges=True)
46 | # Bottom row
47 | p.subplot(2, 0)
48 | p.add_mesh(cone, color="tan", show_edges=True)
49 | p.subplot(2, 1)
50 | p.add_mesh(poly, color="tan", show_edges=True)
51 | p.subplot(2, 2)
52 | p.add_mesh(disc, color="tan", show_edges=True)
53 | # Render all of them
54 | p.show()
55 | # Export this plotter as an interactive scene to a HTML file.
56 | # p.export_html("a_basic.html")
57 |
58 | ###############################################################################
59 | # .. raw:: html
60 | #
61 | #
62 | #
63 | #
64 | #
65 | #
66 |
--------------------------------------------------------------------------------
/tutorial/00_jupyter/jupyter.py:
--------------------------------------------------------------------------------
1 | """
2 | Test out PyVista's Jupyter Backend
3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 |
5 | Become familiar with PyVista Jupyter backend.
6 | """
7 |
8 | import pyvista as pv
9 |
10 | # Set/enable the backed
11 | pv.set_jupyter_backend("trame")
12 |
13 | ###############################################################################
14 |
15 | pl = pv.Plotter()
16 | pl.add_mesh(pv.ParametricKlein())
17 | pl.show()
18 |
19 |
20 | ###############################################################################
21 | # Client-side rendering only (in browser)
22 |
23 | pl = pv.Plotter()
24 | pl.add_mesh(pv.ParametricRandomHills().elevation())
25 | pl.show(jupyter_backend="client")
26 |
27 |
28 | ###############################################################################
29 | # Server-side rendering only
30 |
31 | pl = pv.Plotter()
32 | pl.add_volume(pv.Wavelet())
33 | pl.show(jupyter_backend="server")
34 |
35 | ###############################################################################
36 | # .. raw:: html
37 | #
38 | #
39 | #
40 | #
41 | #
42 | #
43 |
--------------------------------------------------------------------------------
/tutorial/01_basic/README.rst:
--------------------------------------------------------------------------------
1 | .. _basic:
2 |
3 | Basic usage
4 | ===========
5 |
6 | This section demonstrates how to use PyVista to reading and plotting 3D data
7 | using the `pyvista.examples`_ module and external files.
8 |
9 | .. tip::
10 |
11 | This section of the tutorial was adopted from the `Basic API Usage
12 | `_ chapter of the PyVista
13 | documentation.
14 |
15 | .. _pyvista.examples: https://docs.pyvista.org/api/examples/_autosummary/pyvista.examples.examples.html#
16 |
17 | Using Existing Data
18 | ~~~~~~~~~~~~~~~~~~~
19 | There are two main ways of getting data into PyVista: creating it yourself from
20 | scratch or loading the dataset from any one of the `compatible file formats
21 | `_. Since we're just starting
22 | out, let's load a file.
23 |
24 | If you have a dataset handy, like a surface model, point cloud, or VTK file,
25 | you can use that. If you don't have something immediately available, PyVista
26 | has a variety of files you can download in its `pyvista.examples.downloads
27 | `_
28 | module.
29 |
30 | Here's a very basic dataset you can download.
31 |
32 | .. pyvista-plot::
33 | :context:
34 | :include-source: False
35 |
36 | # Configure for trame
37 | import pyvista
38 | pyvista.set_plot_theme('document')
39 | pyvista.set_jupyter_backend('trame')
40 | pyvista.global_theme.axes.show = False
41 | pyvista.global_theme.smooth_shading = True
42 |
43 |
44 | .. pyvista-plot::
45 | :context:
46 |
47 | from pyvista import examples
48 | dataset = examples.download_saddle_surface()
49 | dataset
50 |
51 | |
52 |
53 | Note how this is a :class:`pyvista.PolyData`, which is effectively a surface
54 | dataset containing points, lines, and/or faces. We can immediately plot this with:
55 |
56 | .. pyvista-plot::
57 | :context:
58 |
59 | dataset.plot(color='tan')
60 |
61 | |
62 |
63 | This is a fairly basic plot. You can change how its plotted by adding
64 | parameters as ``show_edges=True`` or changing the color by setting ``color`` to
65 | a different value. All of this is described in PyVista's API documentation in
66 | :func:`pyvista.plot`, but for now let's take a look at another dataset. This
67 | one is a volumetric dataset.
68 |
69 | .. pyvista-plot::
70 | :context:
71 |
72 | dataset = examples.download_frog()
73 | dataset
74 |
75 | |
76 |
77 | This is a :class:`pyvista.ImageData`, which is a dataset containing a uniform
78 | set of points with consistent spacing. When we plot this dataset, we have the
79 | option of enabling volumetric plotting, which plots individual cells based on
80 | the content of the data associated with those cells.
81 |
82 | .. pyvista-plot::
83 | :context:
84 |
85 | dataset.plot(volume=True)
86 |
87 | .. note::
88 | One thing you might have noticed by now is that the plots here in the online
89 | tutorial may look slightly different than your plots depending on how you're plotting them
90 | on your computer. This depends on your ``jupyter_backend``, or if
91 | you're even using a jupyter notebook. As you're playing around with these
92 | examples, feel free to change settings like disabling (or enabling)
93 | ``notebook``, or using a different plotting backend for displaying within
94 | your notebook (if applicable).
95 |
96 |
97 | Read from a file
98 | ~~~~~~~~~~~~~~~~
99 | You can read datasets directly from a file if you have access to it locally on
100 | your computer. This can be one of the many file formats that VTK supports, and
101 | many more that it doesn't as PyVista can rely on libraries like `meshio
102 | `_.
103 |
104 | In the following example, we load VTK's iron protein dataset `ironProt.vtk
105 | `_ from a
106 | file using :func:`pyvista.read`.
107 |
108 | .. pyvista-plot::
109 | :context:
110 |
111 | import pyvista as pv
112 | dataset = pv.read('ironProt.vtk')
113 | dataset
114 |
115 | |
116 |
117 | This is again a :class:`pyvista.ImageData` and we can plot it volumetrically
118 | with:
119 |
120 | .. pyvista-plot::
121 | :context:
122 |
123 | dataset.plot(volume=True)
124 |
125 | |
126 |
127 | Lesson Material
128 | ===============
129 |
130 | This is the notebook rendering of this page where you can interactively follow
131 | along with this lesson.
132 |
--------------------------------------------------------------------------------
/tutorial/01_basic/a_lesson_basic.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _basic_lesson:
3 |
4 | Basic Usage Lesson
5 | ==================
6 |
7 | This section demonstrates how to use PyVista to read and plot 3D data
8 | using the `pyvista.examples.downloads
9 | `_
10 | module and external files.
11 | """
12 |
13 | import pyvista as pv
14 | from pyvista import examples
15 |
16 | # Set the default plot theme to the "document" theme.
17 | # pv.set_plot_theme('document')
18 |
19 |
20 | ###############################################################################
21 | # Using Existing Data
22 | # ~~~~~~~~~~~~~~~~~~~
23 | # There are two main ways of getting data into PyVista: creating it yourself from
24 | # scratch or loading the dataset from any one of the `compatible file formats
25 | # `_. Since we're just starting
26 | # out, let's load a file.
27 |
28 | # If you have a dataset handy, like a surface model, point cloud, or VTK file,
29 | # you can use that. If you don't have something immediately available, PyVista
30 | # has a variety of files you can download in its `pyvista.examples.downloads
31 | # `_
32 | #
33 |
34 |
35 | dataset = examples.download_saddle_surface()
36 | dataset
37 |
38 | ###############################################################################
39 | # Note how this is a :class:`pyvista.PolyData`, which is effectively a surface
40 | # dataset containing points, lines, and/or faces. We can immediately plot this with:
41 |
42 | dataset.plot()
43 |
44 | ###############################################################################
45 | # This is a fairly basic plot. You can change how its plotted by adding
46 | # parameters as ``show_edges=True`` or changing the color by setting ``color`` to
47 | # a different value. All of this is described in PyVista's API documentation in
48 | # :func:`pyvista.plot`, but for now let's take a look at another dataset. This
49 | # one is a volumetric dataset.
50 |
51 | dataset = examples.download_frog()
52 | dataset
53 |
54 | ###############################################################################
55 | # This is a :class:`pyvista.ImageData`, which is a dataset containing a uniform
56 | # set of points with consistent spacing. When we plot this dataset, we have the
57 | # option of enabling volumetric plotting, which plots individual cells based on
58 | # the content of the data associated with those cells.
59 |
60 | dataset.plot(volume=True)
61 |
62 |
63 | ###############################################################################
64 | # Read from a file
65 | # ~~~~~~~~~~~~~~~~
66 | # You can read datasets directly from a file if you have access to it on your
67 | # environment. This can be one of the many file formats that VTK supports, and
68 | # many more that it doesn't as PyVista can rely on libraries like `meshio
69 | # `_.
70 | #
71 | # In the following example, we load VTK's iron protein dataset `ironProt.vtk
72 | # `_ from a
73 | # file using :func:`pyvista.read`.
74 |
75 | dataset = pv.read("ironProt.vtk")
76 | dataset
77 |
78 | ###############################################################################
79 | # This is again a :class:`pyvista.ImageData` and we can plot it volumetrically
80 | # with:
81 |
82 | dataset.plot(volume=True)
83 |
84 | ###############################################################################
85 | # .. raw:: html
86 | #
87 | #
88 | #
89 | #
90 | #
91 | #
92 |
--------------------------------------------------------------------------------
/tutorial/01_basic/exercises/README.rst:
--------------------------------------------------------------------------------
1 | Exercises
2 | =========
3 |
--------------------------------------------------------------------------------
/tutorial/01_basic/exercises/a_load_examples_exercise.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _load_examples:
3 |
4 | Download and Plot Examples
5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~
6 |
7 | Download and plot example datasets.
8 |
9 | PyVista contains many downloadable datasets documented at
10 | `pyvista.examples.downloads
11 | `_. You can download these through Python and immediately plot them.
12 |
13 | This is an easy way to immediately get started with example datasets within
14 | PyVista without having to manually download and load them.
15 |
16 |
17 | """
18 |
19 | ###############################################################################
20 | # Import PyVista and the examples module
21 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
22 | import pyvista as pv
23 | from pyvista import examples
24 |
25 | ###############################################################################
26 | # Surface DataSet - Download
27 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~
28 | # Download a surface dataset of pine roots. Note how the dataset is
29 | # automatically loaded right into Python.
30 | dataset = examples.download_pine_roots()
31 | dataset
32 |
33 |
34 | ###############################################################################
35 | # Surface DataSet - Plot
36 | # ~~~~~~~~~~~~~~~~~~~~~~
37 | # Plot the pine roots using PyVista's default plotting settings.
38 | dataset.plot()
39 |
40 |
41 | ###############################################################################
42 | # Volume DataSet - Download
43 | # ~~~~~~~~~~~~~~~~~~~~~~~~~
44 | # Download the bolt dataset. This is an excellent dataset to visualize using
45 | # "volumetric" plotting.
46 |
47 | dataset = examples.download_bolt_nut()
48 | dataset
49 |
50 |
51 | ###############################################################################
52 | # Volume DataSet - Plot
53 | # ~~~~~~~~~~~~~~~~~~~~~
54 | # Here, we plot the dataset using a custom view direction using
55 | # :class:`pyvista.Plotter`.
56 |
57 | pl = pv.Plotter()
58 | _ = pl.add_volume(
59 | dataset,
60 | cmap="coolwarm",
61 | opacity="sigmoid_5",
62 | show_scalar_bar=False,
63 | )
64 | pl.camera_position = [(194.6, -141.8, 182.0), (34.5, 61.0, 32.5), (-0.229, 0.45, 0.86)]
65 | pl.show()
66 |
67 |
68 | ###############################################################################
69 | # Exercise #1 - Use PyVista Examples
70 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
71 | # Visualize one of PyVista's built in examples.
72 | #
73 | # If your IDE supports it, you should be able to type
74 | # ``dataset = examples.download_`` and press tab to see all the available
75 | # examples you can download.
76 |
77 |
78 | ###############################################################################
79 | # Exercise #2 - Download and View a File
80 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
81 | # Experiment on your own by downloading a dataset and reading it in with
82 | # :func:`pyvista.read`. You can use one of your own files or try downloading
83 | # one from the following sources:
84 | #
85 | # - `Sample VTK DataSets `_
86 | # - `Sample STL files `_
87 | # - `Thingiverse `_
88 |
89 | ###############################################################################
90 | # .. raw:: html
91 | #
92 | #
93 | #
94 | #
95 | #
96 | #
97 |
--------------------------------------------------------------------------------
/tutorial/01_basic/ironProt.vtk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/tutorial/01_basic/ironProt.vtk
--------------------------------------------------------------------------------
/tutorial/01_basic/solutions/P_shelf_pin.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/tutorial/01_basic/solutions/P_shelf_pin.stl
--------------------------------------------------------------------------------
/tutorial/01_basic/solutions/README.rst:
--------------------------------------------------------------------------------
1 | Solutions
2 | =========
3 |
4 | These are the solutions to the above examples.
5 |
--------------------------------------------------------------------------------
/tutorial/01_basic/solutions/a_load_examples_solution.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _load_examples_solution:
3 |
4 | Download and Plot Examples
5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~
6 |
7 | .. note::
8 | This is the solution to :ref:`load_examples`. If you haven't already tried to
9 | solve it on your own, you probably should try that first.
10 |
11 | Download and plot example datasets.
12 |
13 | PyVista contains many downloadable datasets documented at
14 | `pyvista.examples.downloads
15 | `_. You can download these through Python and then immediately plot them.
16 |
17 | This is an easy way to immediately get started with example datasets within
18 | PyVista without having to manually download and load them.
19 |
20 | """
21 |
22 | ###############################################################################
23 | # Import PyVista and the examples module
24 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 | import pyvista as pv
26 | from pyvista import examples
27 |
28 | ###############################################################################
29 | # Surface DataSet - Download
30 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~
31 | # Download a surface dataset of pine roots. Note how the dataset is
32 | # automatically loaded right into Python.
33 | dataset = examples.download_pine_roots()
34 | dataset
35 |
36 |
37 | ###############################################################################
38 | # Surface DataSet - Plot
39 | # ~~~~~~~~~~~~~~~~~~~~~~
40 | # Plot the pine roots using PyVista's default plotting settings.
41 | dataset.plot()
42 |
43 |
44 | ###############################################################################
45 | # Volume DataSet - Download
46 | # ~~~~~~~~~~~~~~~~~~~~~~~~~
47 | # Download the bolt dataset. This is an excellent dataset to visualize using
48 | # "volumetric" plotting.
49 |
50 | dataset = examples.download_bolt_nut()
51 | dataset
52 |
53 |
54 | ###############################################################################
55 | # Volume DataSet - Plot
56 | # ~~~~~~~~~~~~~~~~~~~~~
57 | # Here, we plot the dataset using a custom view direction using
58 | # :class:`pyvista.Plotter`.
59 |
60 | pl = pv.Plotter()
61 | _ = pl.add_volume(
62 | dataset,
63 | cmap="coolwarm",
64 | opacity="sigmoid_5",
65 | show_scalar_bar=False,
66 | )
67 | pl.camera_position = [(194.6, -141.8, 182.0), (34.5, 61.0, 32.5), (-0.229, 0.45, 0.86)]
68 | pl.show()
69 |
70 |
71 | ###############################################################################
72 | # Exercise #1 - Use PyVista Examples
73 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
74 | # Visualize one of PyVista's built in examples.
75 | #
76 | # If your IDE supports it, you should be able to type
77 | # ``dataset = examples.download_`` and press tab to see all the available
78 | # examples you can download.
79 |
80 | dataset = examples.download_gears()
81 | bodies = dataset.split_bodies()
82 | bodies.plot(
83 | cmap="jet",
84 | multi_colors=True,
85 | smooth_shading=True,
86 | split_sharp_edges=True,
87 | )
88 |
89 |
90 | ###############################################################################
91 | # Exercise #2 - Download and View a File
92 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
93 | # Experiment on your own by downloading a dataset and reading it in with
94 | # :class:`pyvista.read`. You can use one of your own files or try downloading
95 | # one from the following sources:
96 | #
97 | # - `Sample VTK DataSets `_
98 | # - `Sample STL files `_
99 | # - `Thingiverse `_
100 | #
101 | # **Solution**
102 | # Download the file ``'P_shelf_pin.stl'`` from
103 | # https://www.thingiverse.com/thing:5412753
104 |
105 | mesh = pv.read("P_shelf_pin.stl")
106 | mesh.plot()
107 |
108 | ###############################################################################
109 | # .. raw:: html
110 | #
111 | #
112 | #
113 | #
114 | #
115 | #
116 |
--------------------------------------------------------------------------------
/tutorial/02_mesh/exercises/README.rst:
--------------------------------------------------------------------------------
1 | Do it yourself
2 | ~~~~~~~~~~~~~~
3 |
--------------------------------------------------------------------------------
/tutorial/02_mesh/exercises/d_create-tri-surface.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _triangulated_surface_exercises:
3 |
4 | Create Triangulated Surface
5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 |
7 | Create a surface from a set of points through a Delaunay triangulation.
8 |
9 | .. note::
10 | We will use a filter from PyVista to perform our triangulation: `delaunay_2d `_.
11 | """
12 |
13 | import numpy as np
14 | import pyvista as pv
15 |
16 | ###############################################################################
17 | # Simple Triangulations
18 | # +++++++++++++++++++++
19 | #
20 | # First, create some points for the surface.
21 |
22 | # Define a simple Gaussian surface
23 | n = 20
24 | x = np.linspace(-200, 200, num=n) + np.random.uniform(-5, 5, size=n)
25 | y = np.linspace(-200, 200, num=n) + np.random.uniform(-5, 5, size=n)
26 | xx, yy = np.meshgrid(x, y)
27 | A, b = 100, 100
28 | zz = A * np.exp(-0.5 * ((xx / b) ** 2.0 + (yy / b) ** 2.0))
29 |
30 | # Get the points as a 2D NumPy array (N by 3)
31 | points = np.c_[xx.reshape(-1), yy.reshape(-1), zz.reshape(-1)]
32 | points[0:5, :]
33 |
34 | ###############################################################################
35 | # Now use those points to create a point cloud PyVista data object. This will
36 | # be encompassed in a :class:`pyvista.PolyData` object.
37 |
38 | # simply pass the numpy points to the PolyData constructor
39 | cloud = ...
40 | cloud.plot(point_size=15)
41 |
42 | ###############################################################################
43 | # Now that we have a PyVista data structure of the points, we can perform a
44 | # triangulation to turn those boring discrete points into a connected surface.
45 | # See :func:`pyvista.UnstructuredGridFilters.delaunay_2d`.
46 | help(cloud.delaunay_2d)
47 |
48 | ###############################################################################
49 | # Apply the ``delaunay_2d`` filter.
50 |
51 | surf = ...
52 |
53 | # And plot it with edges shown
54 | surf.plot(show_edges=True)
55 |
56 |
57 | ###############################################################################
58 | # Clean Edges & Triangulations
59 | # ++++++++++++++++++++++++++++
60 |
61 | # Create the points to triangulate
62 | x = np.arange(10, dtype=float)
63 | xx, yy, zz = np.meshgrid(x, x, [0])
64 | points = np.column_stack((xx.ravel(order="F"), yy.ravel(order="F"), zz.ravel(order="F")))
65 | # Perturb the points
66 | points[:, 0] += np.random.rand(len(points)) * 0.3
67 | points[:, 1] += np.random.rand(len(points)) * 0.3
68 |
69 | # Create the point cloud mesh to triangulate from the coordinates
70 | cloud = pv.PolyData(points)
71 | cloud
72 |
73 | ###############################################################################
74 | cloud.plot(cpos="xy")
75 |
76 | ###############################################################################
77 | # Run the triangulation on these points
78 | surf = cloud.delaunay_2d()
79 | surf.plot(cpos="xy", show_edges=True)
80 |
81 | ###############################################################################
82 | # Note that some of the outer edges are unconstrained and the triangulation
83 | # added unwanted triangles. We can mitigate that with the ``alpha`` parameter.
84 | surf = cloud.delaunay_2d(alpha=...)
85 | surf.plot(cpos="xy", show_edges=True)
86 |
87 | ###############################################################################
88 | # .. raw:: html
89 | #
90 | #
91 | #
92 | #
93 | #
94 | #
95 |
--------------------------------------------------------------------------------
/tutorial/02_mesh/exercises/e_read-file.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _read_file_exercise:
3 |
4 | Load and Plot from a File
5 | ~~~~~~~~~~~~~~~~~~~~~~~~~
6 |
7 | Read a dataset from a known file type.
8 |
9 | """
10 |
11 | ###############################################################################
12 | # We try to make loading a mesh as easy as possible - if your data is in one
13 | # of the many supported file formats, simply use :func:`pyvista.read` to
14 | # load your spatially referenced dataset into a PyVista mesh object.
15 | #
16 | # The following code block uses a built-in example file and displays an
17 | # airplane mesh.
18 |
19 | # sphinx_gallery_thumbnail_number = 5
20 | import pyvista as pv
21 | from pyvista import examples
22 |
23 | ###############################################################################
24 | help(pv.read)
25 |
26 | ###############################################################################
27 | # PyVista supports a wide variety of file formats. The supported file
28 | # extensions are listed in an internal function:
29 | help(pv.core.utilities.reader.get_reader)
30 |
31 |
32 | ###############################################################################
33 | # The following code block uses a built-in example
34 | # file, displays an airplane mesh and returns the camera's position:
35 |
36 | # Get a sample file
37 | filename = examples.planefile
38 | filename
39 |
40 | ###############################################################################
41 | # Note the above filename, it's a ``.ply`` file - one of the many supported
42 | # formats in PyVista.
43 | #
44 | # Use ``pv.read`` to load the file as a mesh:
45 |
46 | mesh = ...
47 | cpos = mesh.plot()
48 |
49 |
50 | ###############################################################################
51 | # The points from the mesh are directly accessible as a NumPy array:
52 |
53 | mesh.points
54 |
55 | ###############################################################################
56 | # The faces from the mesh are also directly accessible as a NumPy array:
57 |
58 | mesh.faces.reshape(-1, 4)[:, 1:] # triangular faces
59 |
60 |
61 | ###############################################################################
62 | # Loading other files types is just as easy! Simply pass your file path to the
63 | # :func:`pyvista.read` function and that's it!
64 | #
65 | # Here are a few other examples - simply replace ``examples.download_*`` in the
66 | # examples below with ``pyvista.read('path/to/you/file.ext')``
67 |
68 | ###############################################################################
69 | # Example STL file:
70 | mesh = examples.download_cad_model()
71 | cpos = [(107.0, 68.5, 204.0), (128.0, 86.5, 223.5), (0.45, 0.36, -0.8)]
72 | mesh.plot(cpos=cpos)
73 |
74 | ###############################################################################
75 | # Example OBJ file
76 | mesh = examples.download_doorman()
77 | mesh.plot(cpos="xy")
78 |
79 |
80 | ###############################################################################
81 | # Example BYU file
82 | mesh = examples.download_teapot()
83 | mesh.plot(cpos=[-1, 2, -5], show_edges=True)
84 |
85 |
86 | ###############################################################################
87 | # Example VTK file
88 | mesh = examples.download_bunny_coarse()
89 | cpos = [(0.2, 0.3, 0.9), (0, 0, 0), (0, 1, 0)]
90 | mesh.plot(cpos=cpos, show_edges=True, color=True)
91 |
92 |
93 | ###############################################################################
94 | # Exercise
95 | # ^^^^^^^^
96 | # Read a file yourself with :func:`pyvista.read`. If you have a supported file
97 | # format, use that! Otherwise, download this file:
98 | # https://github.com/pyvista/pyvista-tutorial/raw/main/tutorial/02_mesh/scipy.vtk
99 |
100 | # (your code here)
101 | # mesh = pv.read('path/to/file.vtk)
102 |
103 | ###############################################################################
104 | # .. raw:: html
105 | #
106 | #
107 | #
108 | #
109 | #
110 | #
111 |
--------------------------------------------------------------------------------
/tutorial/02_mesh/scipy.vtk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pyvista/pyvista-tutorial/b4166075a08f6212278067b6d6d051f4ee6d170d/tutorial/02_mesh/scipy.vtk
--------------------------------------------------------------------------------
/tutorial/02_mesh/solutions/README.rst:
--------------------------------------------------------------------------------
1 | Solutions
2 | ~~~~~~~~~
3 |
--------------------------------------------------------------------------------
/tutorial/02_mesh/solutions/d_create-tri-surface.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _triangulated_surface:
3 |
4 | Create Triangulated Surface
5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 |
7 | Create a surface from a set of points through a Delaunay triangulation.
8 |
9 | .. note::
10 | We will use a filter from PyVista to perform our triangulation: `delaunay_2d `_.
11 | """
12 |
13 | import numpy as np
14 | import pyvista as pv
15 |
16 | ###############################################################################
17 | # Simple Triangulations
18 | # +++++++++++++++++++++
19 | #
20 | # First, create some points for the surface.
21 |
22 | # Define a simple Gaussian surface
23 | n = 20
24 | x = np.linspace(-200, 200, num=n) + np.random.uniform(-5, 5, size=n)
25 | y = np.linspace(-200, 200, num=n) + np.random.uniform(-5, 5, size=n)
26 | xx, yy = np.meshgrid(x, y)
27 | A, b = 100, 100
28 | zz = A * np.exp(-0.5 * ((xx / b) ** 2.0 + (yy / b) ** 2.0))
29 |
30 | # Get the points as a 2D NumPy array (N by 3)
31 | points = np.c_[xx.reshape(-1), yy.reshape(-1), zz.reshape(-1)]
32 | points[0:5, :]
33 |
34 | ###############################################################################
35 | # Now use those points to create a point cloud PyVista data object. This will
36 | # be encompassed in a :class:`pyvista.PolyData` object.
37 |
38 | # simply pass the numpy points to the PolyData constructor
39 | cloud = pv.PolyData(points)
40 | cloud.plot(point_size=15)
41 |
42 | ###############################################################################
43 | # Now that we have a PyVista data structure of the points, we can perform a
44 | # triangulation to turn those boring discrete points into a connected surface.
45 | # See :func:`pyvista.UnstructuredGridFilters.delaunay_2d`.
46 | help(cloud.delaunay_2d)
47 |
48 | ###############################################################################
49 | # Apply the ``delaunay_2d`` filter.
50 |
51 | surf = cloud.delaunay_2d()
52 |
53 | # And plot it with edges shown
54 | surf.plot(show_edges=True)
55 |
56 |
57 | ###############################################################################
58 | # Clean Edges & Triangulations
59 | # ++++++++++++++++++++++++++++
60 |
61 | # Create the points to triangulate
62 | x = np.arange(10, dtype=float)
63 | xx, yy, zz = np.meshgrid(x, x, [0])
64 | points = np.column_stack((xx.ravel(order="F"), yy.ravel(order="F"), zz.ravel(order="F")))
65 | # Perturb the points
66 | points[:, 0] += np.random.rand(len(points)) * 0.3
67 | points[:, 1] += np.random.rand(len(points)) * 0.3
68 |
69 | # Create the point cloud mesh to triangulate from the coordinates
70 | cloud = pv.PolyData(points)
71 | cloud
72 |
73 | ###############################################################################
74 | cloud.plot(cpos="xy")
75 |
76 | ###############################################################################
77 | # Run the triangulation on these points
78 | surf = cloud.delaunay_2d()
79 | surf.plot(cpos="xy", show_edges=True)
80 |
81 | ###############################################################################
82 | # Note that some of the outer edges are unconstrained and the triangulation
83 | # added unwanted triangles. We can mitigate that with the ``alpha`` parameter.
84 | surf = cloud.delaunay_2d(alpha=1.0)
85 | surf.plot(cpos="xy", show_edges=True)
86 |
87 | ###############################################################################
88 | # .. raw:: html
89 | #
90 | #
91 | #
92 | #
93 | #
94 | #
95 |
--------------------------------------------------------------------------------
/tutorial/02_mesh/solutions/e_read-file.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _read_file_example:
3 |
4 | Load and Plot from a File
5 | ~~~~~~~~~~~~~~~~~~~~~~~~~
6 |
7 | Read a dataset from a known file type.
8 |
9 | """
10 |
11 | ###############################################################################
12 | # We try to make loading a mesh as easy as possible - if your data is in one
13 | # of the many supported file formats, simply use :func:`pyvista.read` to
14 | # load your spatially referenced dataset into a PyVista mesh object.
15 | #
16 | # The following code block uses a built-in example file and displays an
17 | # airplane mesh.
18 |
19 | # sphinx_gallery_thumbnail_number = 5
20 | import pyvista as pv
21 | from pyvista import examples
22 |
23 | ###############################################################################
24 | help(pv.read)
25 |
26 | ###############################################################################
27 | # PyVista supports a wide variety of file formats. The supported file
28 | # extensions are listed in an internal function:
29 | help(pv.core.utilities.reader.get_reader)
30 |
31 |
32 | ###############################################################################
33 | # The following code block uses a built-in example
34 | # file, displays an airplane mesh and returns the camera's position:
35 |
36 | # Get a sample file
37 | filename = examples.planefile
38 | filename
39 |
40 | ###############################################################################
41 | # Note the above filename, it's a ``.ply`` file - one of the many supported
42 | # formats in PyVista.
43 | #
44 | # Use ``pv.read`` to load the file as a mesh:
45 |
46 | mesh = pv.read(filename)
47 | cpos = mesh.plot()
48 |
49 |
50 | ###############################################################################
51 | # The points from the mesh are directly accessible as a NumPy array:
52 |
53 | mesh.points
54 |
55 | ###############################################################################
56 | # The faces from the mesh are also directly accessible as a NumPy array:
57 |
58 | mesh.faces.reshape(-1, 4)[:, 1:] # triangular faces
59 |
60 |
61 | ###############################################################################
62 | # Loading other files types is just as easy! Simply pass your file path to the
63 | # :func:`pyvista.read` function and that's it!
64 | #
65 | # Here are a few other examples - simply replace ``examples.download_*`` in the
66 | # examples below with ``pyvista.read('path/to/you/file.ext')``
67 |
68 | ###############################################################################
69 | # Example STL file:
70 | mesh = examples.download_cad_model()
71 | cpos = [(107.0, 68.5, 204.0), (128.0, 86.5, 223.5), (0.45, 0.36, -0.8)]
72 | mesh.plot(cpos=cpos)
73 |
74 | ###############################################################################
75 | # Example OBJ file
76 | mesh = examples.download_doorman()
77 | mesh.plot(cpos="xy")
78 |
79 |
80 | ###############################################################################
81 | # Example BYU file
82 | mesh = examples.download_teapot()
83 | mesh.plot(cpos=[-1, 2, -5], show_edges=True)
84 |
85 |
86 | ###############################################################################
87 | # Example VTK file
88 | mesh = examples.download_bunny_coarse()
89 | cpos = [(0.2, 0.3, 0.9), (0, 0, 0), (0, 1, 0)]
90 | mesh.plot(cpos=cpos, show_edges=True, color=True)
91 |
92 |
93 | ###############################################################################
94 | # Exercise
95 | # ^^^^^^^^
96 | # Read a file yourself with :func:`pyvista.read`. If you have a supported file
97 | # format, use that! Otherwise, download this file:
98 | # https://github.com/pyvista/pyvista-tutorial/raw/main/tutorial/02_mesh/scipy.vtk
99 |
100 | # (your code here)
101 | # mesh = pv.read('path/to/file.vtk)
102 |
103 | ###############################################################################
104 | # .. raw:: html
105 | #
106 | #
107 | #
108 | #
109 | #
110 | #
111 |
--------------------------------------------------------------------------------
/tutorial/03_figures/a_lesson_figures.py:
--------------------------------------------------------------------------------
1 | """
2 | Lesson Overview
3 | ~~~~~~~~~~~~~~~
4 | """
5 |
6 | import pyvista as pv
7 | from pyvista import examples
8 |
9 | mesh = pv.Wavelet()
10 |
11 | ###############################################################################
12 | # ``add_mesh``
13 | # ++++++++++++++
14 | #
15 | # When plotting, users must first create a :class:`pyvista.Plotter` instance (much like a Matplotlib figure). Then data are added to the plotter instance through the :func:`pyvista.Plotter.add_mesh` method. This workflow typically looks like:
16 |
17 | p = pv.Plotter()
18 | p.add_mesh(mesh)
19 | p.show()
20 |
21 | ###############################################################################
22 | # You can customize how that mesh is displayed through the parameters of the :func:`pyvista.Plotter.add_mesh` method. For example, we can change the colormap via the ``cmap`` argument:
23 |
24 | p = pv.Plotter()
25 | p.add_mesh(mesh, cmap="coolwarm")
26 | p.show()
27 |
28 | ###############################################################################
29 | # Or show the edges of the mesh with ``show_edges``:
30 |
31 | p = pv.Plotter()
32 | p.add_mesh(mesh, show_edges=True)
33 | p.show()
34 |
35 | ###############################################################################
36 | # Or adjust the opacity to be a scalar value or linear transfer function via the ``opacity`` argument:
37 |
38 | mesh = examples.download_st_helens().warp_by_scalar()
39 |
40 | p = pv.Plotter()
41 | p.add_mesh(mesh, cmap="terrain", opacity="linear")
42 | p.show()
43 |
44 | ###############################################################################
45 | # Take a look at all of the options for `add_mesh `_.
46 | #
47 | # The ``add_mesh`` method can be called over and over to add different data to the same ``Plotter`` scene. For example, we can create many different mesh objects and plot them together:
48 |
49 | kinds = [
50 | "tetrahedron",
51 | "cube",
52 | "octahedron",
53 | "dodecahedron",
54 | "icosahedron",
55 | ]
56 | centers = [
57 | (0, 1, 0),
58 | (0, 0, 0),
59 | (0, 2, 0),
60 | (-1, 0, 0),
61 | (-1, 2, 0),
62 | ]
63 |
64 | solids = [pv.PlatonicSolid(kind, radius=0.4, center=center) for kind, center in zip(kinds, centers)]
65 |
66 | p = pv.Plotter(window_size=[1000, 1000])
67 | for _ind, solid in enumerate(solids):
68 | p.add_mesh(solid, color="silver", specular=1.0, specular_power=10)
69 | p.view_vector((5.0, 2, 3))
70 | p.add_floor("-z", lighting=True, color="tan", pad=1.0)
71 | p.enable_shadows()
72 | p.show()
73 |
74 | ###############################################################################
75 | # Subplotting
76 | # +++++++++++
77 | #
78 | # Creating side-by-side comparisons of datasets is easy with PyVista's subplotting API. Get started by specifying the shape of the :class:`pyvista.Plotter` object then registering the active subplot by the :func:`pyvista.Plotter.subplot` method much like how you subplot with Matplotlib's API.
79 | p = pv.Plotter(shape=(1, 2))
80 |
81 | p.subplot(0, 0)
82 | p.add_mesh(pv.Sphere())
83 |
84 | p.subplot(0, 1)
85 | p.add_mesh(pv.Cube())
86 |
87 | p.show()
88 |
89 | ###############################################################################
90 | # Below is an example of side-by-side comparisons of the contours and slices of a single dataset.
91 | #
92 | # .. tip::
93 | #
94 | # You can link the cameras of both views with the :func:`pyvista.Plotter.link_views` method
95 | mesh = pv.Wavelet()
96 | cntr = mesh.contour()
97 | slices = mesh.slice_orthogonal()
98 |
99 | p = pv.Plotter(shape=(1, 2))
100 |
101 | p.add_mesh(cntr)
102 |
103 | p.subplot(0, 1)
104 | p.add_mesh(slices)
105 |
106 | p.link_views()
107 | p.view_isometric()
108 | p.show()
109 |
110 | ###############################################################################
111 | # Axes and Bounds
112 | # +++++++++++++++
113 | #
114 | # Axes can be added to the scene with :func:`pyvista.Plotter.show_axes`
115 |
116 |
117 | mesh = examples.load_random_hills()
118 |
119 | p = pv.Plotter()
120 | p.add_mesh(mesh)
121 | p.show_axes()
122 | p.show()
123 |
124 | ###############################################################################
125 | # And bounds similarly with :func:`pyvista.Plotter.show_bounds`
126 | #
127 | # .. tip::
128 | #
129 | # See `Plotting Bounds `_ for more details.
130 |
131 |
132 | p = pv.Plotter()
133 | p.add_mesh(mesh)
134 | p.show_axes()
135 | p.show_bounds()
136 | p.show()
137 |
138 | ###############################################################################
139 | # .. raw:: html
140 | #
141 | #
142 | #
143 | #
144 | #
145 | #
146 |
--------------------------------------------------------------------------------
/tutorial/03_figures/b_shading.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _shading_example:
3 |
4 | Types of Shading
5 | ~~~~~~~~~~~~~~~~
6 |
7 | Comparison of default, flat shading vs. smooth shading.
8 | """
9 |
10 | # sphinx_gallery_thumbnail_number = 4
11 | import pyvista as pv
12 | from pyvista import examples
13 |
14 | ###############################################################################
15 | # PyVista supports two types of shading: flat and smooth shading that uses
16 | # VTK's Phong shading algorithm.
17 | #
18 | # This is a plot with the default flat shading.
19 | mesh = examples.load_nut()
20 | mesh.plot()
21 |
22 |
23 | ###############################################################################
24 | # Here's the same sphere with smooth shading.
25 | mesh.plot(smooth_shading=True)
26 |
27 |
28 | ###############################################################################
29 | # Note how smooth shading makes edges that should be sharp look odd,
30 | # it's because the points of these normals are averaged between two
31 | # faces that have a sharp angle between them. You can avoid this by
32 | # enabling ``split_sharp_edges``.
33 | #
34 | # .. note::
35 | # You can configure the splitting angle with the optional
36 | # ``feature_angle`` keyword argument.
37 | mesh.plot(smooth_shading=True, split_sharp_edges=True)
38 |
39 |
40 | ###############################################################################
41 | # We can even plot the edges that will be split using
42 | # :func:`extract_feature_edges `.
43 |
44 | # extract the feature edges exceeding 30 degrees
45 | edges = mesh.extract_feature_edges(
46 | boundary_edges=False, non_manifold_edges=False, feature_angle=30, manifold_edges=False
47 | )
48 |
49 | # plot both the edges and the smoothed mesh
50 | pl = pv.Plotter()
51 | # pl.enable_anti_aliasing()
52 | pl.add_mesh(mesh, smooth_shading=True, split_sharp_edges=True)
53 | pl.add_mesh(edges, color="k", line_width=5)
54 | pl.show()
55 |
56 |
57 | ###############################################################################
58 | # The ``split_sharp_edges`` keyword argument is compatible with
59 | # physically based rendering as well.
60 |
61 | # plot both the edges and the smoothed mesh
62 | pl = pv.Plotter()
63 | # pl.enable_anti_aliasing()
64 | pl.add_mesh(mesh, color="w", split_sharp_edges=True, pbr=True, metallic=1.0, roughness=0.5)
65 | pl.show()
66 |
67 | ###############################################################################
68 | # .. raw:: html
69 | #
70 | #
71 | #
72 | #
73 | #
74 | #
75 |
--------------------------------------------------------------------------------
/tutorial/03_figures/bonus/README.rst:
--------------------------------------------------------------------------------
1 | Bonus Content
2 | ~~~~~~~~~~~~~
3 |
--------------------------------------------------------------------------------
/tutorial/03_figures/bonus/d_pbr.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _pbr_example:
3 |
4 | Physically Based Rendering
5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~
6 |
7 | VTK 9 introduced Physically Based Rendering (PBR) and we have exposed
8 | that functionality in PyVista. Read the `blog about PBR
9 | `_ for more details.
10 |
11 | PBR is only supported for :class:`pyvista.PolyData` and can be
12 | triggered via the ``pbr`` keyword argument of ``add_mesh``. Also use
13 | the ``metallic`` and ``roughness`` arguments for further control.
14 |
15 | Let's show off this functionality by rendering a high quality mesh of
16 | a statue as though it were metallic.
17 |
18 | """
19 |
20 | from itertools import product
21 |
22 | import pyvista as pv
23 | from pyvista import examples
24 |
25 | # Load the statue mesh
26 | mesh = examples.download_nefertiti()
27 | mesh.rotate_x(-90.0, inplace=True) # rotate to orient with the skybox
28 |
29 | # Download skybox
30 | cubemap = examples.download_sky_box_cube_map()
31 |
32 |
33 | ###############################################################################
34 | # Let's render the mesh with a base color of "linen" to give it a metal looking
35 | # finish.
36 | p = pv.Plotter()
37 | p.add_actor(cubemap.to_skybox())
38 | p.set_environment_texture(cubemap) # For reflecting the environment off the mesh
39 | p.add_mesh(mesh, color="linen", pbr=True, metallic=0.8, roughness=0.1, diffuse=1)
40 |
41 | # Define a nice camera perspective
42 | cpos = [(-313.40, 66.09, 1000.61), (0.0, 0.0, 0.0), (0.018, 0.99, -0.06)]
43 |
44 | p.show(cpos=cpos)
45 |
46 |
47 | ###############################################################################
48 | # Show the variation of the metallic and roughness parameters.
49 | #
50 | # Plot with metallic increasing from left to right and roughness
51 | # increasing from bottom to top.
52 |
53 | colors = ["red", "teal", "black", "orange", "silver"]
54 |
55 | p = pv.Plotter()
56 | p.set_environment_texture(cubemap)
57 |
58 | for i, j in product(range(5), range(6)):
59 | sphere = pv.Sphere(radius=0.5, center=(0.0, 4 - i, j))
60 | p.add_mesh(sphere, color=colors[i], pbr=True, metallic=i / 4, roughness=j / 5)
61 |
62 | p.view_vector((-1, 0, 0), (0, 1, 0))
63 | p.show()
64 |
65 |
66 | ###############################################################################
67 | # Combine custom lighting and physically based rendering.
68 |
69 | # download louis model
70 | mesh = examples.download_louis_louvre()
71 | mesh.rotate_z(140, inplace=True)
72 |
73 |
74 | plotter = pv.Plotter(lighting=None)
75 | plotter.set_background("black")
76 | plotter.add_mesh(mesh, color="linen", pbr=True, metallic=0.5, roughness=0.5, diffuse=1)
77 |
78 |
79 | # set up lighting
80 | light = pv.Light((-2, 2, 0), (0, 0, 0), "white")
81 | plotter.add_light(light)
82 |
83 | light = pv.Light((2, 0, 0), (0, 0, 0), (0.7, 0.0862, 0.0549))
84 | plotter.add_light(light)
85 |
86 | light = pv.Light((0, 0, 10), (0, 0, 0), "white")
87 | plotter.add_light(light)
88 |
89 |
90 | # plot with a good camera position
91 | plotter.camera_position = [(9.51, 13.92, 15.81), (-2.836, -0.93, 10.2), (-0.22, -0.18, 0.959)]
92 | cpos = plotter.show()
93 |
94 | ###############################################################################
95 | # .. raw:: html
96 | #
97 | #
98 | #
99 | #
100 | #
101 | #
102 |
--------------------------------------------------------------------------------
/tutorial/03_figures/bonus/e_labels.py:
--------------------------------------------------------------------------------
1 | """
2 | Label Points
3 | ~~~~~~~~~~~~
4 |
5 | Use string arrays in a point set to label points
6 | """
7 |
8 | # sphinx_gallery_thumbnail_number = 3
9 | import numpy as np
10 | import pyvista as pv
11 | from pyvista import examples
12 |
13 | ###############################################################################
14 | # The :func:`pyvista.Plotter.add_point_labels` method makes it easy to add
15 | # point labels to a scene.
16 | help(pv.Plotter.add_point_labels)
17 |
18 | ###############################################################################
19 | # Label Point Cloud
20 | # ++++++++++++++++++
21 | #
22 | # Let's make a random point cloud and label each point in 3D space
23 |
24 | # Make some random points
25 | poly = pv.PolyData(np.random.rand(10, 3))
26 |
27 | ###############################################################################
28 | # Add string labels to the point data - this associates a label with every
29 | # node:
30 |
31 | poly["My Labels"] = [f"Label {i}" for i in range(poly.n_points)]
32 | poly
33 |
34 | ###############################################################################
35 | # Now plot the points with labels using :func:`pyvista.Plotter.add_point_labels`
36 |
37 | # (your code here, answer below)
38 |
39 |
40 | ###############################################################################
41 | plotter = pv.Plotter()
42 | plotter.add_point_labels(poly, "My Labels", point_size=20, font_size=36)
43 | plotter.show()
44 |
45 |
46 | ###############################################################################
47 | # Label Node Locations
48 | # ++++++++++++++++++++
49 | #
50 | # This example will label the nodes of a mesh with their coordinate locations
51 |
52 | # Load example beam file
53 | grid = pv.UnstructuredGrid(examples.hexbeamfile)
54 |
55 |
56 | ###############################################################################
57 | # Create plotting class and add the unstructured grid
58 | plotter = pv.Plotter()
59 | plotter.add_mesh(grid, show_edges=True, color="tan")
60 |
61 | # Add labels to points on the yz plane (where x == 0)
62 | points = grid.points
63 | mask = points[:, 0] == 0
64 | plotter.add_point_labels(points[mask], points[mask].tolist(), point_size=20, font_size=36)
65 |
66 | plotter.camera_position = [(-1.5, 1.5, 3.0), (0.05, 0.6, 1.2), (0.2, 0.9, -0.25)]
67 |
68 | plotter.show()
69 |
70 |
71 | ###############################################################################
72 | # Label Scalar Values
73 | # +++++++++++++++++++
74 | #
75 | # This example will label each point with their scalar values
76 |
77 | mesh = examples.load_uniform().slice()
78 |
79 | ###############################################################################
80 | p = pv.Plotter()
81 |
82 | # Add the mesh:
83 | p.add_mesh(mesh, scalars="Spatial Point Data", show_edges=True)
84 | # Add the points with scalar labels:
85 | p.add_point_scalar_labels(mesh, "Spatial Point Data", point_size=20, font_size=36)
86 |
87 | # Use a nice camera position:
88 | p.camera_position = [(7, 4, 5), (4.4, 7.0, 7.2), (0.8, 0.5, 0.25)]
89 |
90 | p.show()
91 |
92 | ###############################################################################
93 | # .. raw:: html
94 | #
95 | #
96 | #
97 | #
98 | #
99 | #
100 |
--------------------------------------------------------------------------------
/tutorial/03_figures/bonus/g_orbit.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _orbiting_example:
3 |
4 | Orbiting
5 | ~~~~~~~~
6 |
7 | Orbit around a scene.
8 |
9 | .. note::
10 | The quality of the movie will be better when using
11 | ``p.open_movie('orbit.mp4')`` instead of
12 | ``p.open_gif('orbit.gif')``
13 |
14 | For orbiting to work you first have to show the scene and leave the plotter open
15 | with ``.show(auto_close=False)``. You may also have to set
16 | ``pv.Plotter(off_screen=True)``
17 |
18 | .. note::
19 | Use ``lighting=False`` to reduce the size of the color space to avoid
20 | "jittery" GIFs when showing the scalar bar.
21 |
22 | """
23 |
24 | # sphinx_gallery_thumbnail_number = 2
25 | import pyvista as pv
26 | from pyvista import examples
27 |
28 | mesh = examples.download_st_helens().warp_by_scalar()
29 |
30 | ###############################################################################
31 | # Orbit around the Mt. St Helens dataset.
32 |
33 | p = pv.Plotter()
34 | p.add_mesh(mesh, lighting=False)
35 | p.camera.zoom(1.5)
36 | p.show(auto_close=False)
37 | path = p.generate_orbital_path(n_points=36, shift=mesh.length)
38 | p.open_gif("orbit.gif")
39 | p.orbit_on_path(path, write_frames=True)
40 | p.close()
41 |
42 |
43 | ###############################################################################
44 |
45 | p = pv.Plotter()
46 | p.add_mesh(mesh, lighting=False)
47 | p.show_grid()
48 | p.show(auto_close=False)
49 | viewup = [0.5, 0.5, 1]
50 | path = p.generate_orbital_path(factor=2.0, shift=10000, viewup=viewup, n_points=36)
51 | p.open_gif("orbit.gif")
52 | p.orbit_on_path(path, write_frames=True, viewup=[0, 0, 1], step=0.05)
53 | p.close()
54 |
55 |
56 | ###############################################################################
57 |
58 | mesh = examples.download_dragon()
59 | viewup = [0, 1, 0]
60 |
61 | ###############################################################################
62 | p = pv.Plotter()
63 | p.add_mesh(mesh)
64 | p.show(auto_close=False)
65 | path = p.generate_orbital_path(factor=2.0, n_points=36, viewup=viewup, shift=0.2)
66 | p.open_gif("orbit.gif")
67 | p.orbit_on_path(path, write_frames=True, viewup=viewup, step=0.05)
68 | p.close()
69 |
70 | ###############################################################################
71 | # .. raw:: html
72 | #
73 | #
74 | #
75 | #
76 | #
77 | #
78 |
--------------------------------------------------------------------------------
/tutorial/03_figures/c_geological-map.py:
--------------------------------------------------------------------------------
1 | """
2 | Geological Map on Topography
3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 |
5 | Texture mapping for a GeoTIFF on a topography surface.
6 |
7 | To overlay an image/map from a GeoTIFF on to a topography surface, it's necessary to have texture coordinates ("texture mapping") matching the proper extends of the mesh/surface you'd like to drape the texture (GeoTIFF) on.
8 |
9 | We can do this by using the spatial reference of the GeoTIFF itself, as this allows you to preserve the entire mesh that the texture is being draped on without having to clip out the parts where you don't have imagery. In this example, we explicitly set the texture extents onto a topography surface where the texture/GeoTIFF has a much larger extent than the topography surface.
10 |
11 | Originally posted here: https://github.com/pyvista/pyvista-support/issues/14
12 | """
13 |
14 | # sphinx_gallery_thumbnail_number = 2
15 | import os
16 | import tempfile
17 |
18 | import numpy as np
19 | import pyvista as pv
20 | import requests
21 | from pyvista import examples
22 |
23 | ###############################################################################
24 | path = examples.download_file("topo_clean.vtk")
25 | topo = pv.read(path)
26 | topo
27 |
28 | ###############################################################################
29 | # Load the GeoTIFF/texture (this could take a minute to download)
30 | # https://dl.dropbox.com/s/bp9j3fl3wbi0fld/downsampled_Geologic_map_on_air_photo.tif?dl=0
31 | url = "https://dl.dropbox.com/s/bp9j3fl3wbi0fld/downsampled_Geologic_map_on_air_photo.tif?dl=0"
32 |
33 | response = requests.get(url) # noqa: S113
34 | filename = os.path.join(tempfile.gettempdir(), "downsampled_Geologic_map_on_air_photo.tif") # noqa: PTH118
35 | open(filename, "wb").write(response.content) # noqa: SIM115, PTH123
36 |
37 |
38 | ###############################################################################
39 | # In the block below, we can use the ``get_gcps`` function to get the
40 | # Ground Control Points of the raster, however this depends on GDAL. For this
41 | # tutorial, we are going to hard code the GCPs to avoid having users install
42 | # GDAL.
43 |
44 |
45 | def get_gcps(filename):
46 | """
47 | Helper function retrieves the Ground Control
48 | Points of a GeoTIFF. Note that this requires gdal.
49 | """
50 | import rasterio
51 |
52 | def get_point(gcp):
53 | return np.array([gcp.x, gcp.y, gcp.z])
54 |
55 | # Load a raster
56 | src = rasterio.open(filename)
57 | # Grab the Groung Control Points
58 | points = np.array([get_point(gcp) for gcp in src.gcps[0]])
59 | # Now Grab the three corners of their bounding box
60 | # -- This guarantees we grab the right points
61 | bounds = pv.PolyData(points).bounds
62 | origin = [bounds[0], bounds[2], bounds[4]] # BOTTOM LEFT CORNER
63 | point_u = [bounds[1], bounds[2], bounds[4]] # BOTTOM RIGHT CORNER
64 | point_v = [bounds[0], bounds[3], bounds[4]] # TOP LEFT CORNER
65 | return origin, point_u, point_v
66 |
67 |
68 | ###############################################################################
69 |
70 | # Fetch the GCPs
71 | # origin, point_u, point_v = get_gcps(filename)
72 |
73 | # Hard code GCPs
74 | origin = [310967.75148705335, 4238841.045453942, 0.0]
75 | point_u = [358682.9364281533, 4238841.045453942, 0.0]
76 | point_v = [310967.75148705335, 4276281.98755258, 0.0]
77 |
78 | ###############################################################################
79 |
80 | # Use the GCPs to map the texture coordinates onto the topography surface
81 | topo.texture_map_to_plane(origin, point_u, point_v, inplace=True)
82 |
83 | ###############################################################################
84 | # Show GCPs in relation to topo surface with texture coordinates displayed
85 | p = pv.Plotter()
86 | p.add_point_labels(
87 | np.array(
88 | [
89 | origin,
90 | point_u,
91 | point_v,
92 | ]
93 | ),
94 | ["Origin", "Point U", "Point V"],
95 | point_size=5,
96 | )
97 |
98 | p.add_mesh(topo)
99 | p.show(cpos="xy")
100 |
101 |
102 | ###############################################################################
103 | # Read the GeoTIFF as a ``Texture`` in PyVista:
104 | texture = pv.read_texture(filename)
105 |
106 | # Now plot the topo surface with the texture draped over it
107 | # And make window size large for a high-res screenshot
108 | p = pv.Plotter(window_size=np.array([1024, 768]) * 3)
109 | p.add_mesh(topo, texture=texture)
110 | p.camera_position = [
111 | (337461.4124956896, 4257141.430658634, 2738.4956020899253),
112 | (339000.40935731295, 4260394.940646875, 1724.0720826501868),
113 | (0.10526647627366331, 0.2502863297360612, 0.962432190920575),
114 | ]
115 | p.show()
116 |
117 | ###############################################################################
118 | # .. raw:: html
119 | #
120 | #
121 | #
122 | #
123 | #
124 | #
125 |
--------------------------------------------------------------------------------
/tutorial/03_figures/d_gif.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _gif_movie_example:
3 |
4 | Create a GIF Movie
5 | ~~~~~~~~~~~~~~~~~~
6 | Generate a moving gif from an active plotter.
7 |
8 | .. note::
9 | Use ``lighting=False`` to reduce the size of the color space to avoid
10 | "jittery" GIFs, especially for the scalar bar.
11 |
12 | """
13 |
14 | import numpy as np
15 | import pyvista as pv
16 |
17 | x = np.arange(-10, 10, 0.5)
18 | y = np.arange(-10, 10, 0.5)
19 | x, y = np.meshgrid(x, y)
20 | r = np.sqrt(x**2 + y**2)
21 | z = np.sin(r)
22 |
23 | # Create and structured surface
24 | grid = pv.StructuredGrid(x, y, z)
25 |
26 | # Create a plotter object and set the scalars to the Z height
27 | plotter = pv.Plotter(notebook=False, off_screen=True)
28 | plotter.add_mesh(
29 | grid,
30 | scalars=z.ravel(),
31 | lighting=False,
32 | show_edges=True,
33 | scalar_bar_args={"title": "Height"},
34 | clim=[-1, 1],
35 | )
36 |
37 | # Open a gif
38 | plotter.open_gif("wave.gif")
39 |
40 | pts = grid.points.copy()
41 |
42 | # Update Z and write a frame for each updated position
43 | nframe = 15
44 | for phase in np.linspace(0, 2 * np.pi, nframe + 1)[:nframe]:
45 | z = np.sin(r + phase)
46 | pts[:, -1] = z.ravel()
47 | plotter.update_coordinates(pts, render=False)
48 | plotter.update_scalars(z.ravel(), render=False)
49 |
50 | # Write a frame. This triggers a render.
51 | plotter.write_frame()
52 |
53 | # Closes and finalizes movie
54 | plotter.close()
55 |
56 | ###############################################################################
57 | # .. raw:: html
58 | #
59 | #
60 | #
61 | #
62 | #
63 | #
64 |
--------------------------------------------------------------------------------
/tutorial/03_figures/exercises/README.rst:
--------------------------------------------------------------------------------
1 | Do it yourself
2 | ~~~~~~~~~~~~~~
3 |
--------------------------------------------------------------------------------
/tutorial/03_figures/exercises/a_display_options.py:
--------------------------------------------------------------------------------
1 | """
2 | Display Options
3 | ~~~~~~~~~~~~~~~
4 |
5 | Take a look at the different display options offered by the ``add_mesh`` method.
6 | """
7 |
8 | import pyvista as pv
9 | from pyvista import examples
10 |
11 | mesh = examples.load_random_hills()
12 |
13 | p = pv.Plotter()
14 | p.add_mesh(mesh)
15 | p.show()
16 |
17 | ###############################################################################
18 | # Let's take a look at some different options for the ``add_mesh`` method to
19 | # alter how the above data are displayed.
20 | help(p.add_mesh)
21 |
22 | ###############################################################################
23 | # Plot that mesh with the edges of cells displayed
24 | p = pv.Plotter()
25 | p.add_mesh(mesh, ...)
26 | p.show()
27 |
28 | ###############################################################################
29 | # Plot that mesh with the colored edges and as a show the surface as a solid
30 | # color (use a named color!)
31 | p = pv.Plotter()
32 | p.add_mesh(mesh, ...)
33 | p.show()
34 |
35 | ###############################################################################
36 | # Display with a points representation style
37 | p = pv.Plotter()
38 | p.add_mesh(mesh, ...)
39 | p.show()
40 |
41 | ###############################################################################
42 | # And adjust the points display size
43 | p = pv.Plotter()
44 | p.add_mesh(mesh, ...)
45 | p.show()
46 |
47 | ###############################################################################
48 | # Change the color map and the color limits
49 | p = pv.Plotter()
50 | p.add_mesh(mesh, ...)
51 | p.show()
52 |
53 | ###############################################################################
54 | # Add some opacity
55 | p = pv.Plotter()
56 | p.add_mesh(mesh, ...)
57 | p.show()
58 |
59 | ###############################################################################
60 | # There you go! Those are a few of the most commonly used display options!
61 |
62 | ###############################################################################
63 | # .. raw:: html
64 | #
65 | #
66 | #
67 | #
68 | #
69 | #
70 |
--------------------------------------------------------------------------------
/tutorial/03_figures/exercises/b_lighting_mesh.py:
--------------------------------------------------------------------------------
1 | """
2 | Lighting Properties
3 | ~~~~~~~~~~~~~~~~~~~
4 |
5 | Control aspects of the rendered mesh's lighting such as Ambient, Diffuse,
6 | and Specular. These options only work if the ``lighting`` argument to
7 | ``add_mesh`` is ``True`` (it's ``True`` by default).
8 |
9 | You can turn off all lighting for the given mesh by passing ``lighting=False``
10 | to ``add_mesh``.
11 |
12 | See the ``add_mesh`` docs for lighting options:
13 | https://docs.pyvista.org/api/plotting/_autosummary/pyvista.Plotter.add_mesh.html
14 | """
15 |
16 | # sphinx_gallery_thumbnail_number = 4
17 | import pyvista as pv
18 | from pyvista import examples
19 |
20 | mesh = examples.download_st_helens().warp_by_scalar()
21 |
22 | cpos = [(575848.0, 5128459.0, 22289.0), (562835.0, 5114981.5, 2294.5), (-0.5, -0.5, 0.7)]
23 |
24 | ###############################################################################
25 | # First, let's take a look at the mesh with default lighting conditions
26 | mesh.plot(cpos=cpos, show_scalar_bar=False)
27 |
28 | ###############################################################################
29 | # What about with no lighting?
30 | mesh.plot(..., cpos=cpos, show_scalar_bar=False)
31 |
32 | ###############################################################################
33 | # Demonstration of the specular property
34 | #
35 | # Feel free to adjust the specular value in the ``s`` variable.
36 | p = pv.Plotter(shape=(1, 2), window_size=[1500, 500])
37 |
38 | p.subplot(0, 0)
39 | p.add_mesh(mesh, show_scalar_bar=False)
40 | p.add_text("No Specular")
41 |
42 | p.subplot(0, 1)
43 | specular = ...
44 | p.add_mesh(mesh, ..., show_scalar_bar=False)
45 | p.add_text(f"Specular of {specular}")
46 |
47 | p.link_views()
48 | p.view_isometric()
49 | p.show(cpos=cpos)
50 |
51 | ###############################################################################
52 | # Specular power (feel free to adjust)
53 | mesh.plot(..., cpos=cpos, show_scalar_bar=False)
54 |
55 | ###############################################################################
56 | # Demonstration of all diffuse, specular, and ambient in use together
57 | # (feel free to adjust)
58 | mesh.plot(..., cpos=cpos, show_scalar_bar=False)
59 |
60 | ###############################################################################
61 | # For detailed control over lighting conditions in general see the
62 | # `lighting examples `_
63 |
64 | ###############################################################################
65 | # .. raw:: html
66 | #
67 | #
68 | #
69 | #
70 | #
71 | #
72 |
--------------------------------------------------------------------------------
/tutorial/03_figures/exercises/c_edl.py:
--------------------------------------------------------------------------------
1 | """
2 | Eye Dome Lighting
3 | ~~~~~~~~~~~~~~~~~
4 |
5 | Eye-Dome Lighting (EDL) is a non-photorealistic, image-based shading technique
6 | designed to improve depth perception in scientific visualization images.
7 | To learn more, please see `this blog post`_.
8 |
9 | .. _this blog post: https://blog.kitware.com/eye-dome-lighting-a-non-photorealistic-shading-technique/
10 |
11 | """
12 |
13 | ###############################################################################
14 |
15 | # sphinx_gallery_thumbnail_number = 1
16 | import pyvista as pv
17 | from pyvista import examples
18 |
19 | ###############################################################################
20 | # Point Cloud
21 | # +++++++++++
22 | #
23 | # When plotting a simple point cloud, it can be difficult to perceive depth.
24 | # Take this Lidar point cloud for example:
25 |
26 | point_cloud = examples.download_lidar()
27 | point_cloud
28 |
29 | ###############################################################################
30 | # And now plot this point cloud as-is:
31 |
32 | # Plot a typical point cloud with no EDL
33 | p = pv.Plotter()
34 | p.add_mesh(point_cloud, color="tan", point_size=5)
35 | p.show()
36 |
37 |
38 | ###############################################################################
39 | # We can improve the depth mapping by enabling eye dome lighting on the
40 | # renderer with :func:`pyvista.Renderer.enable_eye_dome_lighting`.
41 | #
42 | # Try plotting that point cloud with Eye-Dome-Lighting yourself below:
43 |
44 | p = pv.Plotter()
45 | p.add_mesh(point_cloud, color="tan", point_size=5)
46 | # Turn on eye dome lighting here
47 | p.show()
48 |
49 |
50 | ###############################################################################
51 | # The eye dome lighting mode can also handle plotting scalar arrays. Try the
52 | # above block but by specifying a ``scalars`` array instead of ``color`` in
53 | # the ``add_mesh`` call.
54 |
55 | ###############################################################################
56 | # .. raw:: html
57 | #
58 | #
59 | #
60 | #
61 | #
62 | #
63 |
--------------------------------------------------------------------------------
/tutorial/03_figures/solutions/README.rst:
--------------------------------------------------------------------------------
1 | Solutions
2 | ~~~~~~~~~
3 |
--------------------------------------------------------------------------------
/tutorial/03_figures/solutions/a_display_options.py:
--------------------------------------------------------------------------------
1 | """
2 | Display Options
3 | ~~~~~~~~~~~~~~~
4 |
5 | Take a look at the different display options offered by the ``add_mesh`` method.
6 | """
7 |
8 | import pyvista as pv
9 | from pyvista import examples
10 |
11 | mesh = examples.load_random_hills()
12 |
13 | p = pv.Plotter()
14 | p.add_mesh(mesh)
15 | p.show()
16 |
17 | ###############################################################################
18 | # Let's take a look at some different options for the ``add_mesh`` method to
19 | # alter how the above data are displayed.
20 | #
21 | # See also https://docs.pyvista.org/api/plotting/_autosummary/pyvista.Plotter.add_mesh.html
22 | help(p.add_mesh)
23 |
24 | ###############################################################################
25 | # Plot that mesh with the edges of cells displayed
26 | p = pv.Plotter()
27 | p.add_mesh(mesh, show_edges=True)
28 | p.show()
29 |
30 | ###############################################################################
31 | # Plot that mesh with the colored edges and as a show the surface as a solid
32 | # color (use a named color!)
33 | p = pv.Plotter()
34 | p.add_mesh(mesh, color="magenta", show_edges=True, edge_color="blue")
35 | p.show()
36 |
37 | ###############################################################################
38 | # Display with a points representation style
39 | p = pv.Plotter()
40 | p.add_mesh(mesh, style="points")
41 | p.show()
42 |
43 | ###############################################################################
44 | # And adjust the points display size
45 | p = pv.Plotter()
46 | p.add_mesh(mesh, style="points", point_size=10, render_points_as_spheres=True)
47 | p.show()
48 |
49 | ###############################################################################
50 | # Change the color map and the color limits
51 | p = pv.Plotter()
52 | p.add_mesh(mesh, cmap="terrain", clim=[2, 5])
53 | p.show()
54 |
55 | ###############################################################################
56 | # Add some opacity
57 | p = pv.Plotter()
58 | p.add_mesh(mesh, cmap="terrain", clim=[2, 5], opacity="linear")
59 | p.show()
60 |
61 | ###############################################################################
62 | # There you go! Those are a few of the most commonly used display options!
63 |
64 | ###############################################################################
65 | # .. raw:: html
66 | #
67 | #
68 | #
69 | #
70 | #
71 | #
72 |
--------------------------------------------------------------------------------
/tutorial/03_figures/solutions/b_lighting_mesh.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _ref_lighting_properties_example:
3 |
4 | Lighting Properties
5 | ~~~~~~~~~~~~~~~~~~~
6 |
7 | Control aspects of the rendered mesh's lighting such as Ambient, Diffuse,
8 | and Specular. These options only work if the ``lighting`` argument to
9 | ``add_mesh`` is ``True`` (it's ``True`` by default).
10 |
11 | You can turn off all lighting for the given mesh by passing ``lighting=False``
12 | to ``add_mesh``.
13 |
14 | See the ``add_mesh`` docs for lighting options:
15 | https://docs.pyvista.org/api/plotting/_autosummary/pyvista.Plotter.add_mesh.html
16 | """
17 |
18 | # sphinx_gallery_thumbnail_number = 4
19 | import pyvista as pv
20 | from pyvista import examples
21 |
22 | mesh = examples.download_st_helens().warp_by_scalar()
23 |
24 | cpos = [(575848.0, 5128459.0, 22289.0), (562835.0, 5114981.5, 2294.5), (-0.5, -0.5, 0.7)]
25 |
26 | ###############################################################################
27 | # First, lets take a look at the mesh with default lighting conditions
28 | mesh.plot(cpos=cpos, show_scalar_bar=False)
29 |
30 | ###############################################################################
31 | # What about with no lighting?
32 | mesh.plot(lighting=False, cpos=cpos, show_scalar_bar=False)
33 |
34 | ###############################################################################
35 | # Demonstration of the specular property
36 | #
37 | # Feel free to adjust the specular value in the ``s`` variable.
38 | p = pv.Plotter(shape=(1, 2), window_size=[1500, 500])
39 |
40 | p.subplot(0, 0)
41 | p.add_mesh(mesh, show_scalar_bar=False)
42 | p.add_text("No Specular")
43 |
44 | p.subplot(0, 1)
45 | specular = 1.0
46 | p.add_mesh(mesh, specular=specular, show_scalar_bar=False)
47 | p.add_text(f"Specular of {specular}")
48 |
49 | p.link_views()
50 | p.view_isometric()
51 | p.show(cpos=cpos)
52 |
53 | ###############################################################################
54 | # Specular power (feel free to adjust)
55 | mesh.plot(specular=0.5, specular_power=15, cpos=cpos, show_scalar_bar=False)
56 |
57 | ###############################################################################
58 | # Demonstration of all diffuse, specular, and ambient in use together
59 | # (feel free to adjust)
60 | mesh.plot(diffuse=0.5, specular=0.5, ambient=0.5, cpos=cpos, show_scalar_bar=False)
61 |
62 | ###############################################################################
63 | # For detailed control over lighting conditions in general see the
64 | # `lighting examples `_
65 |
66 | ###############################################################################
67 | # .. raw:: html
68 | #
69 | #
70 | #
71 | #
72 | #
73 | #
74 |
--------------------------------------------------------------------------------
/tutorial/03_figures/solutions/c_edl.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _ref_edl:
3 |
4 | Eye Dome Lighting
5 | ~~~~~~~~~~~~~~~~~
6 |
7 | Eye-Dome Lighting (EDL) is a non-photorealistic, image-based shading technique
8 | designed to improve depth perception in scientific visualization images.
9 | To learn more, please see `this blog post`_.
10 |
11 | .. _this blog post: https://blog.kitware.com/eye-dome-lighting-a-non-photorealistic-shading-technique/
12 |
13 | """
14 |
15 | ###############################################################################
16 |
17 | # sphinx_gallery_thumbnail_number = 1
18 | import pyvista as pv
19 | from pyvista import examples
20 |
21 | ###############################################################################
22 | # Point Cloud
23 | # +++++++++++
24 | #
25 | # When plotting a simple point cloud, it can be difficult to perceive depth.
26 | # Take this Lidar point cloud for example:
27 |
28 | point_cloud = examples.download_lidar()
29 | point_cloud
30 |
31 | ###############################################################################
32 | # And now plot this point cloud as-is:
33 |
34 | # Plot a typical point cloud with no EDL
35 | p = pv.Plotter()
36 | p.add_mesh(point_cloud, color="tan", point_size=5)
37 | p.show()
38 |
39 |
40 | ###############################################################################
41 | # We can improve the depth mapping by enabling eye dome lighting on the
42 | # renderer with :func:`pyvista.Renderer.enable_eye_dome_lighting`.
43 | #
44 | # Try plotting that point cloud with Eye-Dome-Lighting yourself below:
45 |
46 | p = pv.Plotter()
47 | p.add_mesh(point_cloud, color="tan", point_size=5)
48 | p.enable_eye_dome_lighting() # Turn on eye dome lighting here
49 | p.show()
50 |
51 |
52 | ###############################################################################
53 | # The eye dome lighting mode can also handle plotting scalar arrays. Try the
54 | # above block but by specifying a ``scalars`` array instead of ``color`` in
55 | # the ``add_mesh`` call.
56 |
57 | p = pv.Plotter()
58 | p.add_mesh(point_cloud, scalars="Elevation", point_size=5)
59 | p.enable_eye_dome_lighting() # Turn on eye dome lighting here
60 | p.show()
61 |
62 | ###############################################################################
63 | # .. raw:: html
64 | #
65 | #
66 | #
67 | #
68 | #
69 | #
70 |
--------------------------------------------------------------------------------
/tutorial/04_filters/bonus/README.rst:
--------------------------------------------------------------------------------
1 | Bonus Content
2 | ~~~~~~~~~~~~~
3 |
--------------------------------------------------------------------------------
/tutorial/04_filters/bonus/f_sampling_functions_3d.py:
--------------------------------------------------------------------------------
1 | """
2 | Sample Function: Perlin Noise in 3D
3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 | Here we use :func:`pyvista.core.utilities.features.sample_function` to sample
5 | Perlin noise over a region to generate random terrain.
6 |
7 | Video games like Minecraft use Perlin noise to create terrain. Here,
8 | we create a voxelized mesh similar to a Minecraft "cave".
9 |
10 | """
11 |
12 | import pyvista as pv
13 |
14 | ###############################################################################
15 | # Generate Perlin Noise over a 3D StructuredGrid
16 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17 | # Feel free to change the values of ``freq`` to change the shape of
18 | # the "caves". For example, lowering the frequency will make the
19 | # caves larger and more expansive, while a higher frequency in any
20 | # direction will make the caves appear more "vein-like" and less open.
21 | #
22 | # Change the threshold to reduce or increase the percent of the
23 | # terrain that is open or closed
24 |
25 | freq = (1, 1, 1)
26 | noise = pv.perlin_noise(1, freq, (0, 0, 0))
27 | grid = pv.sample_function(noise, [0, 3.0, -0, 1.0, 0, 1.0], dim=(120, 40, 40))
28 | out = grid.threshold(0.02)
29 | out
30 |
31 | ###############################################################################
32 | # color limits without blue
33 | mn, mx = [out["scalars"].min(), out["scalars"].max()]
34 | clim = (mn, mx * 1.8)
35 |
36 | out.plot(
37 | cmap="gist_earth_r",
38 | background="white",
39 | show_scalar_bar=False,
40 | lighting=True,
41 | clim=clim,
42 | show_edges=False,
43 | )
44 |
45 | ###############################################################################
46 | # .. raw:: html
47 | #
48 | #
49 | #
50 | #
51 | #
52 | #
53 |
--------------------------------------------------------------------------------
/tutorial/04_filters/exercises/README.rst:
--------------------------------------------------------------------------------
1 | Do it yourself
2 | ~~~~~~~~~~~~~~
3 |
--------------------------------------------------------------------------------
/tutorial/04_filters/exercises/b_clipping.py:
--------------------------------------------------------------------------------
1 | """
2 | Clipping with Planes & Boxes
3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 |
5 | Clip/cut any dataset using using planes or boxes.
6 | """
7 |
8 | # sphinx_gallery_thumbnail_number = 2
9 | import pyvista as pv
10 | from pyvista import examples
11 |
12 | ###############################################################################
13 | # Clip with Plane
14 | # +++++++++++++++
15 | #
16 | # Clip any dataset by a user defined plane using the
17 | # :func:`pyvista.DataSetFilters.clip` filter
18 | dataset = examples.download_bunny_coarse()
19 | dataset
20 |
21 | ###############################################################################
22 | help(dataset.clip)
23 |
24 | ###############################################################################
25 | # Perform a clip with a Y axis normal
26 | clipped = ...
27 | clipped
28 |
29 | ###############################################################################
30 | # Plot the result.
31 | p = pv.Plotter()
32 | p.add_mesh(dataset, style="wireframe", color="blue", label="Input")
33 | p.add_mesh(clipped, label="Clipped")
34 | p.add_legend()
35 | p.camera_position = [(0.24, 0.32, 0.7), (0.02, 0.03, -0.02), (-0.12, 0.93, -0.34)]
36 | p.show()
37 |
38 |
39 | ###############################################################################
40 | # Clip with Bounds
41 | # ++++++++++++++++
42 | #
43 | # Clip any dataset by a set of XYZ bounds using the
44 | # :func:`pyvista.DataSetFilters.clip_box` filter.
45 | #
46 | # First, download an example dataset.
47 | dataset = examples.download_office()
48 |
49 | ###############################################################################
50 | help(dataset.clip_box)
51 |
52 | ###############################################################################
53 | # Clip the dataset with a bounding box defined by the values in ``bounds``
54 | # ``(xmin, xmax, ymin, ymax, zmin, zmax)``
55 | bounds = [2, 4.5, 2, 4.5, 1, 3]
56 | clipped = ...
57 | clipped
58 |
59 | ###############################################################################
60 | # Plot the original dataset and the clipped one.
61 | p = pv.Plotter()
62 | p.add_mesh(dataset, style="wireframe", color="blue", label="Input")
63 | p.add_mesh(clipped, label="Clipped")
64 | p.add_legend()
65 | p.show()
66 |
67 |
68 | ###############################################################################
69 | # Clip with Rotated Box
70 | # +++++++++++++++++++++
71 | #
72 | # Clip any dataset by an arbitrarily rotated solid box using the
73 | # :func:`pyvista.DataSetFilters.clip_box` filter.
74 | mesh = examples.load_airplane()
75 |
76 | # Use `pv.Box()` or `pv.Cube()` to create a region of interest
77 | roi = pv.Cube(center=(0.9e3, 0.2e3, mesh.center[2]), x_length=500, y_length=500, z_length=500)
78 | roi.rotate_z(33, inplace=True)
79 |
80 | p = pv.Plotter()
81 | p.add_mesh(roi, opacity=0.75, color="red")
82 | p.add_mesh(mesh, opacity=0.5)
83 | p.show()
84 |
85 | ###############################################################################
86 | # Run the box clipping algorithm with the defined box geometry.
87 | extracted = ...
88 |
89 | p = pv.Plotter(shape=(1, 2))
90 | p.add_mesh(roi, opacity=0.75, color="red")
91 | p.add_mesh(mesh)
92 | p.subplot(0, 1)
93 | p.add_mesh(extracted)
94 | p.add_mesh(roi, opacity=0.75, color="red")
95 | p.link_views()
96 | p.view_isometric()
97 | p.show()
98 |
99 | ###############################################################################
100 | # Crinkled Clipping
101 | # +++++++++++++++++
102 | # Crinkled clipping is useful if you don't want the clip filter to truly clip
103 | # cells on the boundary, but want to preserve the input cell structure and to
104 | # pass the entire cell on through the boundary.
105 | #
106 | # This option is available for :func:`pyvista.DataSetFilters.clip`,
107 | # :func:`pyvista.DataSetFilters.clip_box`, and
108 | # :func:`pyvista.DataSetFilters.clip_sruface`, but not available when clipping
109 | # by scalar in :func:`pyvista.DataSetFilters.clip_scalar`.
110 |
111 | # Input mesh
112 | mesh = pv.Wavelet()
113 |
114 | ###############################################################################
115 | # Define clipping plane
116 | normal = (1, 1, 1)
117 | plane = pv.Plane(i_size=30, j_size=30, direction=normal)
118 |
119 | ###############################################################################
120 | # Perform a standard clip
121 | clipped = mesh.clip(normal=normal)
122 |
123 | ###############################################################################
124 | # Perform a crinkled clip to compare
125 | crinkled = mesh.clip(..., normal=normal)
126 |
127 | ###############################################################################
128 | # Plot comparison
129 | p = pv.Plotter(shape=(1, 2))
130 | p.add_mesh(clipped, show_edges=True)
131 | p.add_mesh(plane.extract_feature_edges(), color="r")
132 | p.subplot(0, 1)
133 | p.add_mesh(crinkled, show_edges=True)
134 | p.add_mesh(plane.extract_feature_edges(), color="r")
135 | p.link_views()
136 | p.show()
137 |
138 | ###############################################################################
139 | # .. raw:: html
140 | #
141 | #
142 | #
143 | #
144 | #
145 | #
146 |
--------------------------------------------------------------------------------
/tutorial/04_filters/exercises/c_compute-normals.py:
--------------------------------------------------------------------------------
1 | """
2 | Computing Surface Normals
3 | ~~~~~~~~~~~~~~~~~~~~~~~~~
4 |
5 |
6 | Compute normals on a surface.
7 | """
8 |
9 | import numpy as np
10 |
11 | # sphinx_gallery_thumbnail_number = 2
12 | from pyvista import examples
13 |
14 | mesh = examples.download_topo_global()
15 | mesh.plot(cmap="gist_earth", show_scalar_bar=False)
16 |
17 | ###############################################################################
18 | # Now we have a surface dataset of the globe loaded - unfortunately, the
19 | # dataset shows the globe with a uniform radius which hides topographic relief.
20 | # Using :func:`pyvista.PolyData.compute_normals`, we can compute the normal
21 | # vectors on the globe at all points in the dataset, then use the values given
22 | # in the dataset to warp the surface in the normals direction to create some
23 | # exaggerated topographic relief.
24 |
25 | # Compute the normals in-place and use them to warp the globe
26 |
27 | ###############################################################################
28 | # Now use those normals to warp the surface
29 | warp = mesh.warp_by_scalar(factor=0.5e-5)
30 |
31 | ###############################################################################
32 | # And let's see it!
33 | warp.plot(cmap="gist_earth", show_scalar_bar=False)
34 |
35 |
36 | ###############################################################################
37 | # We could also use face or cell normals to extract all the faces of a mesh
38 | # facing a general direction. In the following snippet, we take a mesh, compute
39 | # the normals along its cell faces, and extract the faces that face upward.
40 |
41 | mesh = examples.download_nefertiti()
42 | # Compute normals
43 | mesh.compute_normals(...)
44 |
45 | # Get list of cell IDs that meet condition
46 | ids = np.arange(mesh.n_cells)[mesh["Normals"][...] > ...]
47 |
48 | # Extract those cells
49 | top = mesh.extract_cells(ids)
50 |
51 | cpos = [
52 | (-834.3184529757553, -918.4677714398535, 236.5468795300025),
53 | (11.03829376004883, -13.642289291587957, -35.91218884207208),
54 | (0.19212361465657216, 0.11401076390090074, 0.9747256344254143),
55 | ]
56 |
57 | top.plot(cpos=cpos, color=True)
58 |
59 | ###############################################################################
60 | # .. raw:: html
61 | #
62 | #
63 | #
64 | #
65 | #
66 | #
67 |
--------------------------------------------------------------------------------
/tutorial/04_filters/exercises/d_contouring.py:
--------------------------------------------------------------------------------
1 | """
2 | Contouring
3 | ~~~~~~~~~~
4 |
5 | Generate iso-lines or -surfaces for the scalars of a surface or volume.
6 |
7 | 3D meshes can have 2D iso-surfaces of a scalar field extracted and 2D surface
8 | meshes can have 1D iso-lines of a scalar field extracted.
9 | """
10 |
11 | import pyvista as pv
12 | from pyvista import examples
13 |
14 | ###############################################################################
15 | # Iso-Lines
16 | # +++++++++
17 | #
18 | # Let's extract 1D iso-lines of a scalar field from a 2D surface mesh.
19 | mesh = examples.load_random_hills()
20 |
21 | ###############################################################################
22 | help(mesh.contour)
23 |
24 | ###############################################################################
25 | contours = ...
26 |
27 | ###############################################################################
28 | p = pv.Plotter()
29 | p.add_mesh(mesh, opacity=0.85)
30 | p.add_mesh(contours, color="white", line_width=5)
31 | p.show()
32 |
33 |
34 | ###############################################################################
35 | # Iso-Surfaces
36 | # ++++++++++++
37 | #
38 | # Let's extract 2D iso-surfaces of a scalar field from a 3D mesh.
39 |
40 | mesh = examples.download_embryo()
41 | mesh
42 |
43 | ###############################################################################
44 | # For this example dataset, let's create 5 contour levels between the values
45 | # of 50 and 200
46 |
47 | contours = ...
48 |
49 | ###############################################################################
50 | p = pv.Plotter()
51 | p.add_mesh(mesh.outline(), color="k")
52 | p.add_mesh(contours, opacity=0.25, clim=[0, 200])
53 | p.camera_position = [
54 | (-130.99381142132086, 644.4868354828589, 163.80447435848686),
55 | (125.21748748157661, 123.94368717158413, 108.83283586619626),
56 | (0.2780372840777734, 0.03547871361794171, 0.9599148553609699),
57 | ]
58 | p.show()
59 |
60 | ###############################################################################
61 | # .. raw:: html
62 | #
63 | #
64 | #
65 | #
66 | #
67 | #
68 |
--------------------------------------------------------------------------------
/tutorial/04_filters/exercises/e_glyphs.py:
--------------------------------------------------------------------------------
1 | """
2 | Plotting Glyphs (Vectors or PolyData)
3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 |
5 | Use vectors in a dataset to plot and orient glyphs/geometric objects.
6 | """
7 |
8 | import numpy as np
9 | import pyvista as pv
10 | from pyvista import examples
11 |
12 | ###############################################################################
13 | # Example dataset with normals
14 | mesh = examples.load_random_hills()
15 |
16 | ###############################################################################
17 | # Glyphying can be done via the :func:`pyvista.DataSetFilters.glyph` filter
18 | help(mesh.glyph)
19 |
20 | ###############################################################################
21 | # Sometimes you might not want glyphs for every node in the input dataset. In
22 | # this case, you can choose to build glyphs for a subset of the input dataset
23 | # by using a merging tolerance. Here we specify a merging tolerance of five
24 | # percent which equates to five percent of the bounding box's length.
25 | #
26 | # create a subset of arrows using the glyph filter
27 | arrows = ...
28 |
29 |
30 | ###############################################################################
31 | p = pv.Plotter()
32 | p.add_mesh(arrows, color="black")
33 | p.add_mesh(mesh, scalars="Elevation", cmap="terrain", smooth_shading=True)
34 | p.show()
35 |
36 | ###############################################################################
37 | # A common approach is to load vectors directly to the mesh object and then
38 | # access the :attr:`pyvista.DataSet.arrows` property to produce glyphs.
39 |
40 | sphere = pv.Sphere(radius=3.14)
41 |
42 | # make cool swirly pattern
43 | vectors = np.vstack(
44 | (
45 | np.sin(sphere.points[:, 0]),
46 | np.cos(sphere.points[:, 1]),
47 | np.cos(sphere.points[:, 2]),
48 | )
49 | ).T
50 | vectors
51 |
52 |
53 | ###############################################################################
54 |
55 | # add and scale
56 | sphere["vectors"] = vectors * 0.3
57 | sphere.set_active_vectors("vectors")
58 |
59 | # plot just the arrows
60 | sphere.arrows.plot()
61 |
62 | ###############################################################################
63 | # Plot the arrows and the sphere.
64 | p = pv.Plotter()
65 | p.add_mesh(sphere.arrows, lighting=False, scalar_bar_args={"title": "Vector Magnitude"})
66 | p.add_mesh(sphere, color="grey", ambient=0.6, opacity=0.5, show_edges=False)
67 | p.show()
68 |
69 | ###############################################################################
70 | # .. raw:: html
71 | #
72 | #
73 | #
74 | #
75 | #
76 | #
77 |
--------------------------------------------------------------------------------
/tutorial/04_filters/solutions/README.rst:
--------------------------------------------------------------------------------
1 | Solutions
2 | ~~~~~~~~~
3 |
--------------------------------------------------------------------------------
/tutorial/04_filters/solutions/c_compute-normals.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _surface_normal_example:
3 |
4 | Computing Surface Normals
5 | ~~~~~~~~~~~~~~~~~~~~~~~~~
6 |
7 |
8 | Compute normals on a surface.
9 | """
10 |
11 | import numpy as np
12 |
13 | # sphinx_gallery_thumbnail_number = 2
14 | from pyvista import examples
15 |
16 | mesh = examples.download_topo_global()
17 | mesh.plot(cmap="gist_earth", show_scalar_bar=False)
18 |
19 | ###############################################################################
20 | # Now we have a surface dataset of the globe loaded - unfortunately, the
21 | # dataset shows the globe with a uniform radius which hides topographic relief.
22 | # Using :func:`pyvista.PolyData.compute_normals`, we can compute the normal
23 | # vectors on the globe at all points in the dataset, then use the values given
24 | # in the dataset to warp the surface in the normals direction to create some
25 | # exaggerated topographic relief.
26 |
27 | # Compute the normals in-place and use them to warp the globe
28 | mesh.compute_normals(inplace=True) # this activates the normals as well
29 |
30 | ###############################################################################
31 | # Now use those normals to warp the surface
32 | warp = mesh.warp_by_scalar(factor=0.5e-5)
33 |
34 | ###############################################################################
35 | # And let's see it!
36 | warp.plot(cmap="gist_earth", show_scalar_bar=False)
37 |
38 |
39 | ###############################################################################
40 | # We could also use face or cell normals to extract all the faces of a mesh
41 | # facing a general direction. In the following snippet, we take a mesh, compute
42 | # the normals along its cell faces, and extract the faces that face upward.
43 |
44 | mesh = examples.download_nefertiti()
45 | # Compute normals
46 | mesh.compute_normals(cell_normals=True, point_normals=False, inplace=True)
47 |
48 | # Get list of cell IDs that meet condition
49 | ids = np.arange(mesh.n_cells)[mesh["Normals"][:, 2] > 0.0]
50 |
51 | # Extract those cells
52 | top = mesh.extract_cells(ids)
53 |
54 | cpos = [
55 | (-834.3184529757553, -918.4677714398535, 236.5468795300025),
56 | (11.03829376004883, -13.642289291587957, -35.91218884207208),
57 | (0.19212361465657216, 0.11401076390090074, 0.9747256344254143),
58 | ]
59 |
60 | top.plot(cpos=cpos, color=True)
61 |
62 | ###############################################################################
63 | # .. raw:: html
64 | #
65 | #
66 | #
67 | #
68 | #
69 | #
70 |
--------------------------------------------------------------------------------
/tutorial/04_filters/solutions/d_contouring.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _contouring_example:
3 |
4 | Contouring
5 | ~~~~~~~~~~
6 |
7 | Generate iso-lines or -surfaces for the scalars of a surface or volume.
8 |
9 | 3D meshes can have 2D iso-surfaces of a scalar field extracted and 2D surface
10 | meshes can have 1D iso-lines of a scalar field extracted.
11 | """
12 |
13 | import numpy as np
14 | import pyvista as pv
15 | from pyvista import examples
16 |
17 | ###############################################################################
18 | # Iso-Lines
19 | # +++++++++
20 | #
21 | # Let's extract 1D iso-lines of a scalar field from a 2D surface mesh.
22 | mesh = examples.load_random_hills()
23 |
24 | ###############################################################################
25 | help(mesh.contour)
26 |
27 | ###############################################################################
28 | contours = mesh.contour()
29 |
30 | ###############################################################################
31 | p = pv.Plotter()
32 | p.add_mesh(mesh, opacity=0.85)
33 | p.add_mesh(contours, color="white", line_width=5)
34 | p.show()
35 |
36 |
37 | ###############################################################################
38 | # Iso-Surfaces
39 | # ++++++++++++
40 | #
41 | # Let's extract 2D iso-surfaces of a scalar field from a 3D mesh.
42 |
43 | mesh = examples.download_embryo()
44 | mesh
45 |
46 | ###############################################################################
47 | # For this example dataset, let's create 5 contour levels between the values
48 | # of 50 and 200
49 |
50 | contours = mesh.contour(np.linspace(50, 200, 5))
51 |
52 | ###############################################################################
53 | p = pv.Plotter()
54 | p.add_mesh(mesh.outline(), color="k")
55 | p.add_mesh(contours, opacity=0.25, clim=[0, 200])
56 | p.camera_position = [
57 | (-130.99381142132086, 644.4868354828589, 163.80447435848686),
58 | (125.21748748157661, 123.94368717158413, 108.83283586619626),
59 | (0.2780372840777734, 0.03547871361794171, 0.9599148553609699),
60 | ]
61 | p.show()
62 |
63 | ###############################################################################
64 | # .. raw:: html
65 | #
66 | #
67 | #
68 | #
69 | #
70 | #
71 |
--------------------------------------------------------------------------------
/tutorial/04_filters/solutions/e_glyphs.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _glyph_example:
3 |
4 | Plotting Glyphs (Vectors or PolyData)
5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 |
7 | Use vectors in a dataset to plot and orient glyphs/geometric objects.
8 | """
9 |
10 | import numpy as np
11 | import pyvista as pv
12 | from pyvista import examples
13 |
14 | ###############################################################################
15 | # Example dataset with normals
16 | mesh = examples.load_random_hills()
17 |
18 | ###############################################################################
19 | # Glyphying can be done via the :func:`pyvista.DataSetFilters.glyph` filter
20 | help(mesh.glyph)
21 |
22 | ###############################################################################
23 | # Sometimes you might not want glyphs for every node in the input dataset. In
24 | # this case, you can choose to build glyphs for a subset of the input dataset
25 | # by using a merging tolerance. Here we specify a merging tolerance of five
26 | # percent which equates to five percent of the bounding box's length.
27 | #
28 | # create a subset of arrows using the glyph filter
29 | arrows = mesh.glyph(scale="Normals", orient="Normals", tolerance=0.05)
30 |
31 |
32 | ###############################################################################
33 | p = pv.Plotter()
34 | p.add_mesh(arrows, color="black")
35 | p.add_mesh(mesh, scalars="Elevation", cmap="terrain", smooth_shading=True)
36 | p.show()
37 |
38 | ###############################################################################
39 | # A common approach is to load vectors directly to the mesh object and then
40 | # access the :attr:`pyvista.DataSet.arrows` property to produce glyphs.
41 |
42 | sphere = pv.Sphere(radius=3.14)
43 |
44 | # make cool swirly pattern
45 | vectors = np.vstack(
46 | (
47 | np.sin(sphere.points[:, 0]),
48 | np.cos(sphere.points[:, 1]),
49 | np.cos(sphere.points[:, 2]),
50 | )
51 | ).T
52 | vectors
53 |
54 |
55 | ###############################################################################
56 |
57 | # add and scale
58 | sphere["vectors"] = vectors * 0.3
59 | sphere.set_active_vectors("vectors")
60 |
61 | # plot just the arrows
62 | sphere.arrows.plot()
63 |
64 | ###############################################################################
65 | # Plot the arrows and the sphere.
66 | p = pv.Plotter()
67 | p.add_mesh(sphere.arrows, lighting=False, scalar_bar_args={"title": "Vector Magnitude"})
68 | p.add_mesh(sphere, color="grey", ambient=0.6, opacity=0.5, show_edges=False)
69 | p.show()
70 |
71 | ###############################################################################
72 | # .. raw:: html
73 | #
74 | #
75 | #
76 | #
77 | #
78 | #
79 |
--------------------------------------------------------------------------------
/tutorial/05_action/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2021-2023, Bill Little
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | 3. Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/tutorial/05_action/README.rst:
--------------------------------------------------------------------------------
1 | .. include:: ./external_gallery.txt
2 |
3 | Exercises
4 | ---------
5 |
6 | See `GeoVista tutorial `_ .
7 |
--------------------------------------------------------------------------------
/tutorial/06_vtk/a_2_pyvista_vtk.py:
--------------------------------------------------------------------------------
1 | """
2 | PyVista and VTK Together
3 | ~~~~~~~~~~~~~~~~~~~~~~~~
4 |
5 | PyVista is best known for is easy to use plotting API -- being familiar to most Python users already experienced with libraries like Matplotlib. Many people benefit from combining the power of VTK's Python bindings for their data pipelines and the flexibility and simplicity of PyVista for 3D rendering. The following section demonstrates this usage scenario.
6 |
7 | .. tip::
8 |
9 | In case it was not made clear in the :ref:`mesh` section, PyVista mesh classes are subclasses of their VTK counterparts - which means PyVista can be intermixed with VTK workflows.
10 |
11 | Nothing stops you from using VTK classes and then wrapping
12 | the output with PyVista for streamlined plotting. For example:
13 |
14 | """
15 |
16 | import pyvista as pv
17 | import vtk
18 | from pyvista import examples
19 |
20 | ###############################################################################
21 | # Create a circle using vtk
22 | polygonSource = vtk.vtkRegularPolygonSource() # noqa: N816
23 | polygonSource.GeneratePolygonOff()
24 | polygonSource.SetNumberOfSides(50)
25 | polygonSource.SetRadius(5.0)
26 | polygonSource.SetCenter(0.0, 0.0, 0.0)
27 | polygonSource.Update()
28 |
29 | ###############################################################################
30 | # wrap and plot using pyvista
31 | mesh = pv.wrap(polygonSource.GetOutput())
32 | mesh.plot(line_width=3, cpos="xy", color="k")
33 |
34 | ###############################################################################
35 | # In this manner, you can get the "best of both worlds" should you need
36 | # the flexibility of PyVista and the raw power of VTK.
37 | #
38 | # .. note::
39 | # You can use :func:`pyvista.Polygon` for a one line replacement of
40 | # the above VTK code.
41 |
42 | ###############################################################################
43 | # VTK Algorithms
44 | # ~~~~~~~~~~~~~~
45 | #
46 | # Perhaps there is a VTK algorithm that is not (yet) exposed in PyVista that you'd like to use. This is easy enough to work with since PyVista objects are VTK objects. We can pass our PyVista meshes to the VTK algorithm, then wrap the output for plotting, further filtering, or anything.
47 |
48 | mesh = examples.download_bunny_coarse()
49 |
50 | ###############################################################################
51 | # Initialize VTK algorithm
52 | splatter = vtk.vtkGaussianSplatter()
53 |
54 | ###############################################################################
55 | # Pass PyVista object as input to VTK
56 | splatter.SetInputData(mesh)
57 |
58 | ###############################################################################
59 | # Set parameters
60 | n = 200
61 | splatter.SetSampleDimensions(n, n, n)
62 | splatter.SetRadius(0.02)
63 | splatter.SetExponentFactor(-10)
64 | splatter.SetEccentricity(2)
65 | splatter.Update()
66 |
67 | ###############################################################################
68 | # Retrieve output and wrap with PyVista
69 | vol = pv.wrap(splatter.GetOutput())
70 |
71 | ###############################################################################
72 | # Use PyVista to produce contours
73 | cntrs = vol.contour([0.95 * splatter.GetRadius()])
74 |
75 | ###############################################################################
76 | # Use PyVista to plot
77 | p = pv.Plotter()
78 | p.add_mesh(mesh, style="wireframe")
79 | p.add_mesh(cntrs, color=True)
80 | p.show()
81 |
82 | ###############################################################################
83 | # .. note::
84 | #
85 | # The above example was adapted from VTK's `Embed Points Into Volume `_
86 |
87 | ###############################################################################
88 | # .. raw:: html
89 | #
90 | #
91 | #
92 | #
93 | #
94 | #
95 |
--------------------------------------------------------------------------------
/tutorial/06_vtk/b_create_vtk.py:
--------------------------------------------------------------------------------
1 | """
2 | Create VTK Objects
3 | ~~~~~~~~~~~~~~~~~~
4 |
5 | This exercise walks through the creation of a few different types of VTK datasets.
6 | """
7 |
8 | import numpy as np
9 | import pyvista as pv
10 | import vtk
11 |
12 | try:
13 | from vtkmodules.util.numpy_support import numpy_to_vtk
14 | except: # noqa: E722
15 | from vtk.util.numpy_support import numpy_to_vtk
16 |
17 | ###############################################################################
18 | # Create ``vtkImageData``
19 | # ^^^^^^^^^^^^^^^^^^^^^^^
20 | image = vtk.vtkImageData()
21 | image.SetDimensions(10, 10, 2)
22 | image.SetSpacing(1, 2, 5)
23 | image.SetOrigin(-0.5, -3, 0)
24 |
25 | ###############################################################################
26 | # Add point data
27 | values = np.arange(np.prod(image.GetDimensions()))
28 | # Convert numpy array to VTK array
29 | arr = numpy_to_vtk(values)
30 | arr.SetName("values") # CRITICAL
31 | image.GetPointData().SetScalars(arr)
32 | image
33 |
34 | ###############################################################################
35 | # Plot with PyVista for simplicity
36 | pv.plot(image, show_edges=True)
37 |
38 | ###############################################################################
39 | # Create ``vtkStructuredGrid``
40 | # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
41 |
42 | # Define structured points with NumPy
43 | x = np.arange(-10, 10, 0.25)
44 | y = np.arange(-10, 10, 0.25)
45 | x, y = np.meshgrid(x, y)
46 | r = np.sqrt(x**2 + y**2)
47 | z = np.sin(r)
48 |
49 | # Join the points
50 | values = np.c_[x.ravel(), y.ravel(), z.ravel()]
51 |
52 | coords = numpy_to_vtk(values)
53 |
54 | points = vtk.vtkPoints()
55 | points.SetData(coords)
56 |
57 | grid = vtk.vtkStructuredGrid()
58 | grid.SetDimensions(*z.shape, 1)
59 | grid.SetPoints(points)
60 | grid
61 |
62 | ###############################################################################
63 | # Add point data
64 | arr = numpy_to_vtk(z.ravel())
65 | arr.SetName("z") # CRITICAL
66 | grid.GetPointData().SetScalars(arr)
67 |
68 |
69 | ###############################################################################
70 | # Plot with PyVista for simplicity
71 | pv.plot(grid, show_edges=True)
72 |
73 | ###############################################################################
74 | # .. raw:: html
75 | #
76 | #
77 | #
78 | #
79 | #
80 | #
81 |
--------------------------------------------------------------------------------
/tutorial/06_vtk/c_vtk_algorithms.py:
--------------------------------------------------------------------------------
1 | """
2 | Using VTK Algorithms
3 | ~~~~~~~~~~~~~~~~~~~~
4 |
5 | In this exercise, you will use a VTK Algorithm directly to filter a PyVista mesh.
6 |
7 | VTK algorithms (filters) follow a standard flow for most cases:
8 |
9 | 1. Instantiate the algorithm
10 | 2. Set the input data object or connection: ``.SetInputDataObject(mesh)``
11 | 3. Adjust algorithm parameters with the setter methods, e.g., ``SetParameterName(value)``
12 | 4. Call ``.Update()`` to run the algorithm
13 | 5. Retrieve the output of the algorithm: ``output = alg.GetOutput()``
14 |
15 | Let's see if we can try a few VTK algorithms with that standard workflow.
16 | """
17 |
18 | import pyvista as pv
19 | import vtk
20 | from pyvista import examples
21 |
22 | ###############################################################################
23 | # Here is a sample mesh
24 | mesh = examples.load_random_hills()
25 | mesh
26 |
27 | ###############################################################################
28 | mesh.plot()
29 |
30 | ###############################################################################
31 | # Simple Filter
32 | # ^^^^^^^^^^^^^
33 | # Let's start out with a simple VTK filter: ``vtkOutlineFilter``
34 | help(vtk.vtkOutlineFilter)
35 |
36 | ###############################################################################
37 | # Try using this VTK filter yourself here:
38 | #
39 | # Remember that you will have to wrap the output of the algorithm with :func:`pyvista.wrap`
40 | alg = vtk.vtkOutlineFilter()
41 |
42 | # (your code here, answer below)
43 |
44 | outline = pv.wrap(alg.GetOutput())
45 | outline
46 |
47 | ###############################################################################
48 | alg.SetInputDataObject(mesh)
49 | alg.SetGenerateFaces(False) # noqa: FBT003
50 | alg.Update()
51 |
52 | outline = pv.wrap(alg.GetOutput())
53 | outline
54 |
55 | ###############################################################################
56 | # .. note::
57 | #
58 | # Note that the about filter can be replaced with a ``.outline()`` filter in PyVista
59 |
60 | ###############################################################################
61 | p = pv.Plotter()
62 | p.add_mesh(mesh)
63 | p.add_mesh(outline, color="k")
64 | p.show()
65 |
66 |
67 | ###############################################################################
68 | # Find your own filter
69 | # ^^^^^^^^^^^^^^^^^^^^
70 | #
71 | # Take a look at VTK's examples and documentation to find a filter you'd like
72 | # to apply to your mesh. The instructors will be around to help you implement.
73 | #
74 | # See https://kitware.github.io/vtk-examples/site/Python/
75 |
76 | ###############################################################################
77 | # .. raw:: html
78 | #
79 | #
80 | #
81 | #
82 | #
83 | #
84 |
--------------------------------------------------------------------------------
/tutorial/07_sphinx/README.rst:
--------------------------------------------------------------------------------
1 | .. _sphinx:
2 |
3 | PyVista and Sphinx
4 | ==================
5 |
6 | Leverage PyVista to make some awesome web documentation.
7 |
8 | .. tip::
9 |
10 | This section of the tutorial was adopted from `Plotting Themes
11 | `_ and `Sphinx PyVista
12 | Plot Directive `_
13 | chapter of the PyVista documentation.
14 |
15 | Generating 3D Plots in your Documentation
16 | -----------------------------------------
17 | PyVista allows you to generate images directly within Sphinx
18 | much like the `Matplotlib plot_directive
19 | `_. Rather
20 | than manually creating and adding plots after code sections, you can instead
21 | dynamically generate images and embed them directly within your
22 | documentation. This also works seamlessly with `sphinx-gallery
23 | `_, so you can create notebook examples just
24 | like the `Matplotlib Example Gallery
25 | `_.
26 |
27 | As an added side benefit, you can be sure that the documentation you generate
28 | matches your project API. If you include this within a `GitHub Workflow
29 | `_
30 |
31 | This section covers the following topics.
32 |
33 | - :ref:`static_plots`
34 |
35 | .. _static_plots:
36 |
37 | Static Plotting - Sphinx PyVista Plot Directive
38 | -----------------------------------------------
39 | You can generate static images of PyVista plots within sphinx using the
40 | ``pyvista-plot`` directive by adding the following to your ``conf.py``
41 | when building your documentation using Sphinx.
42 |
43 | .. code:: python
44 |
45 | extensions = [
46 | "sphinx.ext.napoleon",
47 | "pyvista.ext.plot_directive",
48 | ]
49 |
50 | You can then issue the plotting directive within your sphinx
51 | documentation files::
52 |
53 | .. pyvista-plot::
54 | :caption: A sphere
55 | :include-source: True
56 |
57 | >>> import pyvista
58 | >>> sphere = pyvista.Sphere()
59 | >>> out = sphere.plot()
60 |
61 | Which will be rendered as:
62 |
63 | .. pyvista-plot::
64 | :caption: This is a default sphere
65 | :include-source: True
66 |
67 | >>> import pyvista
68 | >>> sphere = pyvista.Sphere()
69 | >>> out = sphere.plot()
70 |
71 |
72 | Examples and Usage
73 | ~~~~~~~~~~~~~~~~~~
74 | There are two ways to use `trame `_ within
75 | Jupyter notebooks. You can use it on a plot by plot basis by setting the
76 | ``jupyter_backend`` in ``mesh.plot()``::
77 |
78 | .. pyvista-plot::
79 |
80 | import pyvista as pv
81 | from pyvista import examples
82 |
83 | # create a point cloud from lidar data and add height scalars
84 | dataset = examples.download_lidar()
85 | point_cloud = pv.PolyData(dataset.points[::100])
86 | point_cloud['height'] = point_cloud.points[:, 2]
87 | point_cloud.plot(window_size=[500, 500],
88 | cmap='jet',
89 | point_size=2,
90 | background='w')
91 |
92 | And here's the resulting output in Sphinx:
93 |
94 | .. pyvista-plot::
95 |
96 | import pyvista as pv
97 | from pyvista import examples
98 |
99 | # create a point cloud from lidar data and add height scalars
100 | dataset = examples.download_lidar()
101 | point_cloud = pv.PolyData(dataset.points[::100])
102 | point_cloud['height'] = point_cloud.points[:, 2]
103 | point_cloud.plot(window_size=[500, 500],
104 | cmap='jet',
105 | point_size=2,
106 | background='w')
107 |
108 | |
109 |
110 | And now just directly execute ``plot`` on any dataset::
111 |
112 | .. pyvista-plot::
113 |
114 | from pyvista import examples
115 | dataset = examples.download_dragon()
116 | dataset.plot(cpos="xy")
117 |
118 | Which looks like:
119 |
120 | .. pyvista-plot::
121 |
122 | from pyvista import examples
123 | dataset = examples.download_dragon()
124 | dataset.plot(cpos="xy")
125 |
126 |
127 | Exercises
128 | ---------
129 |
130 | Generate Sphinx documentation on your own using the
131 | `pyvista/pyvista-doc-example `_
132 | repository. Either clone the repository with::
133 |
134 | git clone https://github.com/pyvista/pyvista-doc-example
135 |
136 | Or just download the zip of the repository.
137 |
138 | .. button-link:: https://github.com/pyvista/pyvista-doc-example/archive/refs/heads/main.zip
139 | :color: primary
140 | :shadow:
141 |
142 | pyvista-doc-example-main.zip
143 |
144 |
145 | Build the documentation
146 | ~~~~~~~~~~~~~~~~~~~~~~~
147 |
148 | Once you've downloaded `pyvista/pyvista-doc-example
149 | `_, cd into the directory and
150 | install the documentation build requirements with::
151 |
152 | cd pyvista-doc-example
153 | pip install -r requirements_docs.txt
154 |
155 | Finally, build the documentation locally with::
156 |
157 | cd doc
158 | make html
159 |
160 | Or, if on Windows::
161 |
162 | cd doc
163 | make.bat
164 |
165 | You will then find the generated documentation within the ``doc/_build``
166 | directory. Open up ``index.html`` using your browser to see the documentation.
167 |
--------------------------------------------------------------------------------
/tutorial/08_widgets/README.rst:
--------------------------------------------------------------------------------
1 | .. _widgets:
2 |
3 | Widgets in PyVista
4 | ==================
5 |
6 | PyVista has several widgets that can be added to the rendering scene to control
7 | filters like clipping, slicing, and thresholding - specifically there are
8 | widgets to control the positions of boxes, planes, and lines or slider bars
9 | which can all be highly customized through the use of custom callback
10 | functions.
11 |
12 | Here we’ll take a look at the various widgets, some helper methods that
13 | leverage those widgets to do common tasks, and demonstrate how to leverage the
14 | widgets for user defined tasks and processing routines.
15 |
16 | .. tip::
17 |
18 | This section of the tutorial was adopted from the `widgets section
19 | `_
20 | of the PyVista example documentation.
21 |
22 |
23 | Widget Examples
24 | ---------------
25 |
26 | .. leave blank after this point for Sphinx-Gallery to populate examples
27 |
--------------------------------------------------------------------------------
/tutorial/08_widgets/a_box-widget.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _box_widget_example:
3 |
4 | Box Widget
5 | ~~~~~~~~~~
6 |
7 | The box widget can be enabled and disabled by the
8 | :func:`pyvista.Plotter.add_box_widget` and
9 | :func:`pyvista.Plotter.clear_box_widgets` methods respectively.
10 | When enabling the box widget, you must provide a custom callback function
11 | otherwise the box would appear and do nothing - the callback functions are
12 | what allow us to leverage the widget to perform a task like clipping/cropping.
13 |
14 | Considering that using a box to clip/crop a mesh is one of the most common use
15 | cases, we have included a helper method that will allow you to add a mesh to a
16 | scene with a box widget that controls its extent, the
17 | :func:`pyvista.Plotter.add_mesh_clip_box` method.
18 |
19 | .. image:: ../../images/gifs/box-clip.gif
20 | """
21 |
22 | import pyvista as pv
23 | from pyvista import examples
24 |
25 | mesh = examples.download_nefertiti()
26 |
27 | ###############################################################################
28 |
29 | p = pv.Plotter()
30 | p.add_mesh_clip_box(mesh, color="white")
31 | p.show(cpos=[-1, -1, 0.2])
32 |
33 |
34 | ###############################################################################
35 | # After interacting with the scene, the clipped mesh is available as:
36 | p.box_clipped_meshes
37 |
38 | ###############################################################################
39 | # .. raw:: html
40 | #
41 | #
42 | #
43 | #
44 | #
45 | #
46 |
--------------------------------------------------------------------------------
/tutorial/08_widgets/b_checkbox-widget.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _checkbox_widget_example:
3 |
4 | Checkbox Widget
5 | ~~~~~~~~~~~~~~~
6 |
7 | Use a checkbox to turn on/off the visibility of meshes in a scene.
8 |
9 | See :func:`pyvista.Plotter.add_checkbox_button_widget` for more details.
10 |
11 | """
12 |
13 | # sphinx_gallery_thumbnail_number = 2
14 | import pyvista as pv
15 |
16 | ###############################################################################
17 | # Single Checkbox
18 | # +++++++++++++++
19 |
20 | mesh = pv.Sphere()
21 |
22 | p = pv.Plotter()
23 | actor = p.add_mesh(mesh)
24 |
25 |
26 | def toggle_vis(flag) -> None:
27 | actor.SetVisibility(flag)
28 |
29 |
30 | p.add_checkbox_button_widget(toggle_vis, value=True)
31 | p.show()
32 |
33 | ##############################################################################
34 | # And here is a screen capture of a user interacting with this
35 | #
36 | # .. image:: ../../images/gifs/single-checkbox-widget.gif
37 |
38 | ###############################################################################
39 | # Multiple Checkboxes
40 | # +++++++++++++++++++
41 | #
42 | # In this example, we will add many meshes to a scene with unique colors and
43 | # create corresponding checkboxes for those meshes of the same color to toggle
44 | # their visibility in the scene.
45 |
46 | colors = [
47 | ["ff0000", "28e5da", "0000ff"],
48 | ["ffff00", "c8bebe", "f79292"],
49 | ["fffff0", "f18c1d", "23dcaa"],
50 | ["d785ec", "9d5b13", "e4e0b1"],
51 | ["894509", "af45f5", "fff000"],
52 | ]
53 |
54 |
55 | class SetVisibilityCallback:
56 | """Helper callback to keep a reference to the actor being modified."""
57 |
58 | def __init__(self, actor) -> None:
59 | self.actor = actor
60 |
61 | def __call__(self, state):
62 | self.actor.SetVisibility(state)
63 |
64 |
65 | ###############################################################################
66 |
67 | # Widget size
68 | size = 50
69 |
70 | p = pv.Plotter()
71 |
72 | Startpos = 12
73 | for i, lst in enumerate(colors):
74 | for j, color in enumerate(lst):
75 | actor = p.add_mesh(pv.Sphere(center=(i, j, 0)), color=color)
76 | # Make a separate callback for each widget
77 | callback = SetVisibilityCallback(actor)
78 | p.add_checkbox_button_widget(
79 | callback,
80 | value=True,
81 | position=(5.0, Startpos),
82 | size=size,
83 | border_size=1,
84 | color_on=color,
85 | color_off="grey",
86 | background_color="grey",
87 | )
88 | Startpos = Startpos + size + (size // 10)
89 |
90 | p.show()
91 |
92 | ##############################################################################
93 | # And here is a screen capture of a user interacting with this
94 | #
95 | # .. image:: ../../images/gifs/multiple-checkbox-widget.gif
96 |
97 | ###############################################################################
98 | # .. raw:: html
99 | #
100 | #
101 | #
102 | #
103 | #
104 | #
105 |
--------------------------------------------------------------------------------
/tutorial/08_widgets/c_line-widget.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _line_widget_example:
3 |
4 | Line Widget
5 | ~~~~~~~~~~~
6 |
7 | The line widget can be enabled and disabled by the
8 | :func:`pyvista.Plotter.add_line_widget` and
9 | :func:`pyvista.Plotter.clear_line_widgets` methods respectively.
10 | Unfortunately, PyVista does not have any helper methods to utilize this
11 | widget, so it is necessary to pass a custom callback method.
12 |
13 | One particularly fun example is to use the line widget to create a source for
14 | the :func:`pyvista.DataSetFilters.streamlines` filter. Again note the use of
15 | the ``name`` argument in ``add_mesh``.
16 | """
17 |
18 | import numpy as np
19 | import pyvista as pv
20 | from pyvista import examples
21 |
22 | pv.set_plot_theme("document")
23 |
24 | mesh = examples.download_kitchen()
25 | furniture = examples.download_kitchen(split=True)
26 |
27 | arr = np.linalg.norm(mesh["velocity"], axis=1)
28 | clim = [arr.min(), arr.max()]
29 |
30 | ###############################################################################
31 |
32 | p = pv.Plotter()
33 | p.add_mesh(furniture, name="furniture", color=True)
34 | p.add_mesh(mesh.outline(), color="black")
35 | p.add_axes()
36 |
37 |
38 | def simulate(pointa, pointb) -> None:
39 | streamlines = mesh.streamlines(
40 | n_points=10, max_steps=100, pointa=pointa, pointb=pointb, integration_direction="forward"
41 | )
42 | p.add_mesh(streamlines, name="streamlines", line_width=5, render_lines_as_tubes=True, clim=clim)
43 |
44 |
45 | p.add_line_widget(callback=simulate, use_vertices=True)
46 | p.show()
47 |
48 | ##############################################################################
49 | # And here is a screen capture of a user interacting with this
50 | #
51 | # .. image:: ../../images/gifs/line-widget-streamlines.gif
52 |
53 | ###############################################################################
54 | # .. raw:: html
55 | #
56 | #
57 | #
58 | #
59 | #
60 | #
61 |
--------------------------------------------------------------------------------
/tutorial/08_widgets/d_multi-slider-widget.py:
--------------------------------------------------------------------------------
1 | """
2 | Multiple Slider Widgets
3 | ~~~~~~~~~~~~~~~~~~~~~~~
4 |
5 | Use a class based callback to track multiple slider widgets for updating a
6 | single mesh.
7 |
8 | In this example we simply change a few parameters for the
9 | :func:`pyvista.Sphere` method, but this could easily be applied to any
10 | mesh-generating/altering code.
11 |
12 | """
13 |
14 | import pyvista as pv
15 |
16 |
17 | class MyCustomRoutine:
18 | def __init__(self, mesh) -> None:
19 | self.output = mesh # Expected PyVista mesh type
20 | # default parameters
21 | self.kwargs = {
22 | "radius": 0.5,
23 | "theta_resolution": 30,
24 | "phi_resolution": 30,
25 | }
26 |
27 | def __call__(self, param, value):
28 | self.kwargs[param] = value
29 | self.update()
30 |
31 | def update(self) -> None:
32 | # This is where you call your simulation
33 | result = pv.Sphere(**self.kwargs)
34 | self.output.copy_from(result)
35 |
36 |
37 | ###############################################################################
38 |
39 | starting_mesh = pv.Sphere()
40 | engine = MyCustomRoutine(starting_mesh)
41 |
42 | ###############################################################################
43 |
44 | p = pv.Plotter()
45 | p.add_mesh(starting_mesh, show_edges=True)
46 | p.add_slider_widget(
47 | callback=lambda value: engine("phi_resolution", int(value)),
48 | rng=[3, 60],
49 | value=30,
50 | title="Phi Resolution",
51 | pointa=(0.025, 0.1),
52 | pointb=(0.31, 0.1),
53 | style="modern",
54 | )
55 | p.add_slider_widget(
56 | callback=lambda value: engine("theta_resolution", int(value)),
57 | rng=[3, 60],
58 | value=30,
59 | title="Theta Resolution",
60 | pointa=(0.35, 0.1),
61 | pointb=(0.64, 0.1),
62 | style="modern",
63 | )
64 | p.add_slider_widget(
65 | callback=lambda value: engine("radius", value),
66 | rng=[0.1, 1.5],
67 | value=0.5,
68 | title="Radius",
69 | pointa=(0.67, 0.1),
70 | pointb=(0.98, 0.1),
71 | style="modern",
72 | )
73 | p.show()
74 |
75 | ##############################################################################
76 | # And here is a screen capture of a user interacting with this
77 | #
78 | # .. image:: ../../images/gifs/multiple-slider-widget.gif
79 |
80 | ###############################################################################
81 | # .. raw:: html
82 | #
83 | #
84 | #
85 | #
86 | #
87 | #
88 |
--------------------------------------------------------------------------------
/tutorial/08_widgets/e_plane-widget.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _plane_widget_example:
3 |
4 | Plane Widget
5 | ~~~~~~~~~~~~
6 |
7 | The plane widget can be enabled and disabled by the
8 | :func:`pyvista.Plotter.add_plane_widget` and
9 | :func:`pyvista.Plotter.clear_plane_widgets` methods respectively.
10 | As with all widgets, you must provide a custom callback method to utilize that
11 | plane. Considering that planes are most commonly used for clipping and slicing
12 | meshes, we have included two helper methods for doing those tasks!
13 |
14 | Let's use a plane to clip a mesh:
15 | """
16 |
17 | # sphinx_gallery_thumbnail_number = 2
18 | import pyvista as pv
19 | from pyvista import examples
20 |
21 | vol = examples.download_brain()
22 |
23 | p = pv.Plotter()
24 | p.add_mesh_clip_plane(vol)
25 | p.show()
26 |
27 | ###############################################################################
28 | # After interacting with the scene, the clipped mesh is available as:
29 | p.plane_clipped_meshes
30 |
31 | ###############################################################################
32 | # And here is a screen capture of a user interacting with this
33 | #
34 | # .. image:: ../../images/gifs/plane-clip.gif
35 |
36 | ###############################################################################
37 | # Or you could slice a mesh using the plane widget:
38 |
39 | p = pv.Plotter()
40 | p.add_mesh_slice(vol)
41 | p.show()
42 | ###############################################################################
43 | # After interacting with the scene, the slice is available as:
44 | p.plane_sliced_meshes
45 |
46 | ###############################################################################
47 | # And here is a screen capture of a user interacting with this
48 | #
49 | # .. image:: ../../images/gifs/plane-slice.gif
50 |
51 | ###############################################################################
52 | # Or you could leverage the plane widget for some custom task like glyphing a
53 | # vector field along that plane. Note that we have to pass a ``name`` when
54 | # calling ``add_mesh`` to ensure that there is only one set of glyphs plotted
55 | # at a time.
56 |
57 | import pyvista as pv
58 | from pyvista import examples
59 |
60 | mesh = examples.download_carotid()
61 |
62 | p = pv.Plotter()
63 | p.add_mesh(mesh.contour(8).extract_largest(), opacity=0.5)
64 |
65 |
66 | def my_plane_func(normal, origin) -> None:
67 | slc = mesh.slice(normal=normal, origin=origin)
68 | arrows = slc.glyph(orient="vectors", scale="scalars", factor=0.01)
69 | p.add_mesh(arrows, name="arrows")
70 |
71 |
72 | p.add_plane_widget(my_plane_func)
73 | p.show_grid()
74 | p.add_axes()
75 | p.show()
76 |
77 | ###############################################################################
78 | # And here is a screen capture of a user interacting with this
79 | #
80 | # .. image:: ../../images/gifs/plane-glyph.gif
81 |
82 |
83 | ###############################################################################
84 | # Further, a user can disable the arrow vector by setting the
85 | # ``normal_rotation`` argument to ``False``. For example, here we
86 | # programmatically set the normal vector on which we want to translate the
87 | # plane and we disable the arrow to prevent its rotation.
88 |
89 | p = pv.Plotter()
90 | p.add_mesh_slice(vol, normal=(1, 1, 1), normal_rotation=False)
91 | p.show()
92 |
93 | ###############################################################################
94 | # The vector is also forcibly disabled anytime the ``assign_to_axis`` argument
95 | # is set.
96 | p = pv.Plotter()
97 | p.add_mesh_slice(vol, assign_to_axis="z")
98 | p.show()
99 |
100 |
101 | ###############################################################################
102 | # Additionally, users can modify the interaction event that triggers the
103 | # callback functions handled by the different plane widget helpers through the
104 | # ``interaction_event`` keyword argument when available. For example,
105 | # we can have continuous slicing by using the ``InteractionEvent`` observer.
106 | import vtk
107 |
108 | p = pv.Plotter()
109 | p.add_mesh_slice(vol, assign_to_axis="z", interaction_event=vtk.vtkCommand.InteractionEvent)
110 | p.show()
111 |
112 | ###############################################################################
113 | # And here is a screen capture of a user interacting with this continuously via
114 | # the ``InteractionEvent`` observer:
115 | #
116 | # .. image:: ../../images/gifs/plane-slice-continuous.gif
117 |
118 | ###############################################################################
119 | # .. raw:: html
120 | #
121 | #
122 | #
123 | #
124 | #
125 | #
126 |
--------------------------------------------------------------------------------
/tutorial/08_widgets/f_slider-bar-widget.py:
--------------------------------------------------------------------------------
1 | """
2 | .. _slider_bar_widget_example:
3 |
4 | Slider Bar Widget
5 | ~~~~~~~~~~~~~~~~~
6 |
7 | The slider widget can be enabled and disabled by the
8 | :func:`pyvista.Plotter.add_slider_widget` and
9 | :func:`pyvista.Plotter.clear_slider_widgets` methods respectively.
10 | This is one of the most versatile widgets as it can control a value that can
11 | be used for just about anything.
12 | """
13 |
14 | # sphinx_gallery_thumbnail_number = 1
15 |
16 | ##############################################################################
17 | # One helper method we've added is the
18 | # :func:`pyvista.Plotter.add_mesh_threshold` method which leverages the
19 | # slider widget to control a thresholding value.
20 |
21 | import pyvista as pv
22 | from pyvista import examples
23 |
24 | mesh = examples.download_knee_full()
25 |
26 | p = pv.Plotter()
27 | p.add_mesh_threshold(mesh)
28 | p.show()
29 |
30 | ###############################################################################
31 | # After interacting with the scene, the threshold mesh is available as:
32 | p.threshold_meshes
33 |
34 | ##############################################################################
35 | # And here is a screen capture of a user interacting with this
36 | #
37 | # .. image:: ../../images/gifs/slider-widget-threshold.gif
38 |
39 | ###############################################################################
40 | # Custom Callback
41 | # +++++++++++++++
42 | #
43 | # Or you could leverage a custom callback function that takes a single value
44 | # from the slider as its argument to do something like control the resolution
45 | # of a mesh. Again note the use of the ``name`` argument in ``add_mesh``:
46 |
47 | p = pv.Plotter()
48 |
49 |
50 | def create_mesh(value) -> None:
51 | res = int(value)
52 | sphere = pv.Sphere(phi_resolution=res, theta_resolution=res)
53 | p.add_mesh(sphere, name="sphere", show_edges=True)
54 |
55 |
56 | p.add_slider_widget(create_mesh, [5, 100], title="Resolution")
57 | p.show()
58 |
59 | ##############################################################################
60 | # And here is a screen capture of a user interacting with this
61 | #
62 | # .. image:: ../../images/gifs/slider-widget-resolution.gif
63 |
64 | ###############################################################################
65 | # .. raw:: html
66 | #
67 | #
68 | #
69 | #
70 | #
71 | #
72 |
--------------------------------------------------------------------------------
/tutorial/08_widgets/g_sphere-widget.py:
--------------------------------------------------------------------------------
1 | """
2 | Sphere Widget
3 | ~~~~~~~~~~~~~
4 |
5 | The sphere widget can be enabled and disabled by the
6 | :func:`pyvista.Plotter.add_sphere_widget` and
7 | :func:`pyvista.Plotter.clear_sphere_widgets` methods respectively.
8 | This is a very versatile widget as it can control vertex location that can
9 | be used to control or update the location of just about anything.
10 |
11 | We don't have any convenient helper methods that utilize this widget out of
12 | the box, but we have added a lot of ways to use this widget so that you can
13 | easily add several widgets to a scene.
14 |
15 | Let's look at a few use cases that all update a surface mesh.
16 | """
17 |
18 | # sphinx_gallery_thumbnail_number = 3
19 |
20 | ##############################################################################
21 | # Example A
22 | # +++++++++
23 | #
24 | # Use a single sphere widget
25 |
26 | import numpy as np
27 | import pyvista as pv
28 |
29 | # Create a triangle surface
30 | surf = pv.PolyData()
31 | surf.points = np.array(
32 | [
33 | [-10, -10, -10],
34 | [10, 10, -10],
35 | [-10, 10, 0],
36 | ]
37 | )
38 | surf.faces = np.array([3, 0, 1, 2])
39 |
40 | p = pv.Plotter()
41 |
42 |
43 | def callback(point) -> None:
44 | surf.points[0] = point
45 |
46 |
47 | p.add_sphere_widget(callback)
48 | p.add_mesh(surf, color=True)
49 |
50 | p.show_grid()
51 | p.show()
52 |
53 | ##############################################################################
54 | # And here is a screen capture of a user interacting with this
55 | #
56 | # .. image:: ../../images/gifs/sphere-widget-a.gif
57 |
58 |
59 | ###############################################################################
60 | # Example B
61 | # +++++++++
62 | #
63 | # Use several sphere widgets at once
64 |
65 | import numpy as np
66 | import pyvista as pv
67 |
68 | # Create a triangle surface
69 | surf = pv.PolyData()
70 | surf.points = np.array(
71 | [
72 | [-10, -10, -10],
73 | [10, 10, -10],
74 | [-10, 10, 0],
75 | ]
76 | )
77 | surf.faces = np.array([3, 0, 1, 2])
78 |
79 |
80 | p = pv.Plotter()
81 |
82 |
83 | def callback(point, i) -> None:
84 | surf.points[i] = point
85 |
86 |
87 | p.add_sphere_widget(callback, center=surf.points)
88 | p.add_mesh(surf, color=True)
89 |
90 | p.show_grid()
91 | p.show()
92 |
93 | ##############################################################################
94 | # And here is a screen capture of a user interacting with this
95 | #
96 | # .. image:: ../../images/gifs/sphere-widget-b.gif
97 |
98 | ###############################################################################
99 | # Example C
100 | # +++++++++
101 | #
102 | # This one is the coolest - use four sphere widgets to update perturbations on
103 | # a surface and interpolate between them with some boundary conditions
104 |
105 | import numpy as np
106 | import pyvista as pv
107 | from scipy.interpolate import griddata
108 |
109 |
110 | def get_colors(n):
111 | """A helper function to get n colors."""
112 | from itertools import cycle
113 |
114 | import matplotlib as mpl
115 |
116 | cycler = mpl.rcParams["axes.prop_cycle"]
117 | colors = cycle(cycler)
118 | return [next(colors)["color"] for i in range(n)]
119 |
120 |
121 | # Create a grid to interpolate to
122 | xmin, xmax, ymin, ymax = 0, 100, 0, 100
123 | x = np.linspace(xmin, xmax, num=25)
124 | y = np.linspace(ymin, ymax, num=25)
125 | xx, yy, zz = np.meshgrid(x, y, [0])
126 |
127 | # Make sure boundary conditions exist
128 | boundaries = np.array([[xmin, ymin, 0], [xmin, ymax, 0], [xmax, ymin, 0], [xmax, ymax, 0]])
129 |
130 | # Create the PyVista mesh to hold this grid
131 | surf = pv.StructuredGrid(xx, yy, zz)
132 |
133 | # Create some initial perturbations
134 | # - this array will be updated inplace
135 | points = np.array([[33, 25, 45], [70, 80, 13], [51, 57, 10], [25, 69, 20]])
136 |
137 |
138 | # Create an interpolation function to update that surface mesh
139 | def update_surface(point, i) -> None:
140 | points[i] = point
141 | tp = np.vstack((points, boundaries))
142 | zz = griddata(tp[:, 0:2], tp[:, 2], (xx[:, :, 0], yy[:, :, 0]), method="cubic")
143 | surf.points[:, -1] = zz.ravel(order="F")
144 |
145 |
146 | # Get a list of unique colors for each widget
147 | colors = get_colors(len(points))
148 |
149 | ##############################################################################
150 |
151 | # Begin the plotting routine
152 | p = pv.Plotter()
153 |
154 | # Add the surface to the scene
155 | p.add_mesh(surf, color=True)
156 |
157 | # Add the widgets which will update the surface
158 | p.add_sphere_widget(update_surface, center=points, color=colors, radius=3)
159 | # Add axes grid
160 | p.show_grid()
161 |
162 | # Show it!
163 | p.show()
164 |
165 | ##############################################################################
166 | # And here is a screen capture of a user interacting with this
167 | #
168 | # .. image:: ../../images/gifs/sphere-widget-c.gif
169 |
170 | ###############################################################################
171 | # .. raw:: html
172 | #
173 | #
174 | #
175 | #
176 | #
177 | #
178 |
--------------------------------------------------------------------------------
/tutorial/08_widgets/h_spline-widget.py:
--------------------------------------------------------------------------------
1 | """
2 | Spline Widget
3 | ~~~~~~~~~~~~~
4 |
5 |
6 | A spline widget can be enabled and disabled by the
7 | :func:`pyvista.Plotter.add_spline_widget` and
8 | :func:`pyvista.Plotter.clear_spline_widgets` methods respectively.
9 | This widget allows users to interactively create a poly line (spline) through
10 | a scene and use that spline.
11 |
12 | A common task with splines is to slice a volumetric dataset using an irregular
13 | path. To do this, we have added a convenient helper method which leverages the
14 | :func:`pyvista.DataSetFilters.slice_along_line` filter named
15 | :func:`pyvista.Plotter.add_mesh_slice_spline`.
16 | """
17 |
18 | import numpy as np
19 | import pyvista as pv
20 |
21 | ##############################################################################
22 |
23 | mesh = pv.Wavelet()
24 |
25 | # initial spline to seed the example
26 | points = np.array(
27 | [
28 | [-8.64208925, -7.34294559, -9.13803458],
29 | [-8.25601497, -2.54814702, 0.93860914],
30 | [-0.30179377, -3.21555997, -4.19999019],
31 | [3.24099167, 2.05814768, 3.39041509],
32 | [4.39935227, 4.18804542, 8.96391132],
33 | ]
34 | )
35 |
36 | p = pv.Plotter()
37 | p.add_mesh(mesh.outline(), color="black")
38 | p.add_mesh_slice_spline(mesh, initial_points=points, n_handles=5)
39 | p.camera_position = [(30, -42, 30), (0.0, 0.0, 0.0), (-0.09, 0.53, 0.84)]
40 | p.show()
41 |
42 | ##############################################################################
43 | # And here is a screen capture of a user interacting with this
44 | #
45 | # .. image:: ../../images/gifs/spline-widget.gif
46 |
47 | ###############################################################################
48 | # .. raw:: html
49 | #
50 | #
51 | #
52 | #
53 | #
54 | #
55 |
--------------------------------------------------------------------------------
/tutorial/09_trame/README.rst:
--------------------------------------------------------------------------------
1 | .. _trame:
2 |
3 | Trame
4 | =====
5 |
6 | `Kitware's Trame `_ is an open-source platform for creating interactive and powerful visual analytics applications. Based on Python, and leveraging platforms such as VTK, ParaView, and Vega, it is possible to create web-based applications in minutes.
7 |
8 | .. raw:: html
9 |
10 |
11 |
12 |
13 | What is Trame?
14 | --------------
15 |
16 | Trame is a Python framework for building reactive web applications.
17 |
18 | * All the logic and UI definition can be done in plain Python
19 | * Runs on laptops, desktops, clusters, and the cloud while displaying everywhere (phone, tablet, laptop, workstation)
20 |
21 |
22 | .. tab-set::
23 |
24 | .. tab-item:: Documentation
25 |
26 | Learn more about Trame
27 |
28 | .. button-link:: https://kitware.github.io/trame/
29 | :color: primary
30 | :shadow:
31 |
32 | Trame Documentation
33 |
34 |
35 | .. tab-item:: Tutorial
36 |
37 | Gain hands on experience with Trame through the tutorial.
38 |
39 |
40 | .. button-link:: https://github.com/Kitware/trame-tutorial
41 | :color: primary
42 | :shadow:
43 |
44 | Trame Tutorial
45 |
46 |
47 | 3D visualization in web applications
48 | ------------------------------------
49 |
50 | PyVista and Trame work excellently together to provide a cutting-edge capabilities for 3D
51 | visualization in reactive web applications.
52 |
53 | 1. Trame provides a high-level framework for building reactive, stateful web applications
54 | 2. PyVista provides a high-level framework for 3D visualization, exposing VTK in a “Pythonic” manner
55 |
56 | High-level framework 1 + high-level framework 2 = a streamlined approach to making powerful web applications with 3D visualization front and center.
57 |
58 | The following code creates a simple Trame application with a PyVista plotter embedded in the UI.
59 | This code can be used as a base for building all of your Trame applications with PyVista as it
60 | contains all of the boilerplate code needed to get started.
61 |
62 |
63 | .. tab-set::
64 |
65 | .. tab-item:: Code
66 |
67 | .. code:: python
68 |
69 | import pyvista as pv
70 | from pyvista import examples
71 | from pyvista.trame.ui import plotter_ui
72 | from trame.app import get_server
73 | from trame.ui.vuetify3 import SinglePageLayout
74 |
75 | # Always set PyVista to plot off screen with Trame
76 | pv.OFF_SCREEN = True
77 |
78 | server = get_server()
79 | state, ctrl = server.state, server.controller
80 |
81 | mesh = examples.load_random_hills()
82 |
83 | pl = pv.Plotter()
84 | pl.add_mesh(mesh)
85 |
86 | with SinglePageLayout(server) as layout:
87 | with layout.content:
88 | # Use PyVista's Trame UI helper method
89 | # this will add UI controls
90 | view = plotter_ui(pl)
91 |
92 | server.start()
93 |
94 | .. tab-item:: Web App
95 |
96 | .. image:: ../../images/trame-pyvista.png
97 | :alt: A simple Trame application with PyVista
98 | :align: center
99 |
100 |
101 | .. note::
102 |
103 | PyVista's Jupyter backend is powered by Trame! If you've been using
104 | PyVista in Jupyter lately, you've been using Trame all along -- our
105 | Jupyter backend is a micro Trame application.
106 |
107 |
108 | Trame applications
109 | ~~~~~~~~~~~~~~~~~~
110 |
111 | Using an existing app
112 |
113 | .. code:: python
114 |
115 | from trame.app.demo import Cone
116 |
117 | app = Cone("demo")
118 | await app.ui.ready
119 | app.ui
120 |
121 |
122 | Try Pan3D: ``pip install pan3d``
123 |
124 | .. code:: python
125 |
126 | from pan3d import DatasetBuilder
127 |
128 | builder = DatasetBuilder(viewer=True)
129 |
130 | builder.import_config('example_sst_xarray.json')
131 |
132 | # Show viewer in cell output
133 | await builder.viewer.ready
134 | builder.viewer.ui
135 |
136 |
137 | Exercises
138 | ~~~~~~~~~
139 |
140 | Do not run these examples in Jupyter but rather as standalone scripts.
141 |
--------------------------------------------------------------------------------
/tutorial/09_trame/a_getting_started.py:
--------------------------------------------------------------------------------
1 | # Getting started with PyVista and Trame
2 | """
3 | Getting started
4 | ~~~~~~~~~~~~~~~
5 |
6 | Getting started with PyVista and Trame
7 |
8 | """
9 |
10 | import pyvista as pv
11 | from pyvista import examples
12 |
13 | ###############################################################################
14 | # PyVista's Jupyter backend is powered by **Trame**. So by default you are
15 | # using trame without knowing it.
16 | #
17 | # By default PyVista is serving you a micro trame application that let you
18 | # toggle between **Remote** and **Local** rendering along with some various
19 | # options to configure your visualization.
20 | #
21 | # **First try the Remote/Local rendering toggle and notice the differences**
22 | #
23 | # .. raw:: html
24 | #
25 | #
26 | # Look at the orientation axis between the 2 rendering modes.
27 | #
28 | #
29 | # One sends images generated on the server side while the other is sending geometry to vtk.js.
30 | dataset = examples.download_lucy()
31 | dataset.plot(smooth_shading=True, color="white")
32 |
33 | ###############################################################################
34 | # Building applications with PyVista and Trame
35 | #
36 | # Now, let's build a simple application that updates the mesh color with the click of a button.
37 |
38 | import random
39 |
40 | from pyvista.plotting.colors import hexcolors
41 | from pyvista.trame.ui import get_viewer
42 | from trame.ui.vuetify3 import SinglePageLayout
43 | from trame.widgets import vuetify3 as v3
44 |
45 | plotter = pv.Plotter()
46 | actor = plotter.add_mesh(dataset)
47 | viewer = get_viewer(plotter)
48 | view = None
49 |
50 |
51 | def change_color() -> None:
52 | actor.prop.color = random.choice(list(hexcolors.keys())) # noqa: S311
53 | view.update()
54 |
55 |
56 | # Create UI
57 | with SinglePageLayout(viewer.server) as layout:
58 | with layout.toolbar.clear() as tb:
59 | tb.density = "compact"
60 | tb.theme = "dark"
61 | viewer.ui_controls(mode="trame")
62 | v3.VBtn(icon="mdi-palette", click=change_color)
63 | with layout.content:
64 | view = viewer.ui(add_menu=False, mode="trame")
65 |
66 |
67 | # Show UI
68 | await layout.ready
69 | layout
70 |
--------------------------------------------------------------------------------
/tutorial/09_trame/a_trame_simple.py:
--------------------------------------------------------------------------------
1 | """
2 | Simple Trame App
3 | ~~~~~~~~~~~~~~~~
4 |
5 | A simple example of how to create a Trame app with a PyVista Plotter.
6 |
7 | This example contains the boilerplate code to use anytime you are creating a
8 | new Trame application with PyVista.
9 |
10 | """
11 |
12 | import pyvista as pv
13 | from pyvista import examples
14 | from pyvista.trame.ui import plotter_ui
15 | from trame.app import get_server
16 | from trame.ui.vuetify3 import SinglePageLayout
17 |
18 | pv.OFF_SCREEN = True
19 |
20 | server = get_server()
21 | state, ctrl = server.state, server.controller
22 |
23 | mesh = examples.load_random_hills()
24 |
25 | pl = pv.Plotter()
26 | pl.add_mesh(mesh)
27 |
28 | with SinglePageLayout(server) as layout, layout.content:
29 | view = plotter_ui(pl)
30 |
31 | # Show UI
32 | await layout.ready
33 | layout
34 | ###############################################################################
35 | # .. raw:: html
36 | #
37 | #
38 | #
39 | #
40 | #
41 | #
42 |
--------------------------------------------------------------------------------
/tutorial/09_trame/b_trame_actor_color.py:
--------------------------------------------------------------------------------
1 | """
2 | Control the Color of an Actor
3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 |
5 | Extending our simple example to have a dropdown menu to control the color of
6 | the actor.
7 |
8 | """
9 |
10 | import pyvista as pv
11 | from pyvista.plotting.colors import hexcolors
12 | from pyvista.trame.ui import plotter_ui
13 | from trame.app import get_server
14 | from trame.ui.vuetify3 import SinglePageLayout
15 | from trame.widgets import vuetify3
16 |
17 | pv.OFF_SCREEN = True
18 |
19 | server = get_server()
20 | state, ctrl = server.state, server.controller
21 |
22 | mesh = pv.Cone()
23 |
24 | pl = pv.Plotter()
25 | actor = pl.add_mesh(mesh, color="seagreen")
26 |
27 |
28 | @state.change("color")
29 | def color(color="seagreen", **kwargs) -> None:
30 | actor.prop.color = color
31 | ctrl.view_update()
32 |
33 |
34 | with SinglePageLayout(server) as layout:
35 | with layout.toolbar:
36 | vuetify3.VSpacer()
37 | vuetify3.VSelect(
38 | label="Color",
39 | v_model=("color", "seagreen"),
40 | items=("array_list", list(hexcolors.keys())),
41 | hide_details=True,
42 | density="compact",
43 | outlined=True,
44 | classes="pt-1 ml-2",
45 | style="max-width: 250px",
46 | )
47 |
48 | with (
49 | layout.content,
50 | vuetify3.VContainer(
51 | fluid=True,
52 | classes="pa-0 fill-height",
53 | ),
54 | ):
55 | # Use PyVista UI template for Plotters
56 | view = plotter_ui(pl, default_server_rendering=False)
57 | ctrl.view_update = view.update
58 |
59 | # Show UI
60 | await layout.ready
61 | layout
62 | ###############################################################################
63 | # .. raw:: html
64 | #
65 | #
66 | #
67 | #
68 | #
69 | #
70 |
--------------------------------------------------------------------------------
/tutorial/09_trame/b_trame_vtk.py:
--------------------------------------------------------------------------------
1 | """
2 | Using VTK/PyVista and Trame
3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 |
5 | In this application, we will connect a VTK filter with PyVista.
6 |
7 | It will use Trame to visualize the results and interactively control
8 | parameters of the VTK filter.
9 |
10 | """
11 |
12 | import pyvista as pv
13 | from pyvista import examples
14 | from trame.app import get_server
15 | from trame.ui.vuetify3 import VAppLayout
16 | from trame.widgets import vtk as vtk_widgets
17 | from trame.widgets import vuetify3 as v3
18 | from vtkmodules.vtkFiltersGeneral import vtkWarpScalar
19 |
20 | mesh = examples.load_random_hills()
21 | warp_by_scalar = vtkWarpScalar()
22 | warp_by_scalar.SetInputData(mesh)
23 | warp_by_scalar.SetScaleFactor(0.3)
24 |
25 | plotter = pv.Plotter()
26 | actor = plotter.add_mesh(warp_by_scalar)
27 | plotter.reset_camera()
28 |
29 | # Trame server setup
30 | server = get_server("trame_vtk_example")
31 | state, ctrl = server.state, server.controller
32 |
33 |
34 | @state.change("scale")
35 | def update_scale(scale, **kwargs) -> None:
36 | warp_by_scalar.SetScaleFactor(scale)
37 | ctrl.view_update()
38 |
39 |
40 | with VAppLayout(server, full_height=True) as layout: # noqa: SIM117
41 | with v3.VContainer(fluid=True, classes="fill-height"):
42 | with vtk_widgets.VtkRemoteView(plotter.render_window, interactive_ratio=1) as view:
43 | ctrl.view_update = view.update
44 | ctrl.view_reset_camera = view.reset_camera
45 |
46 | # Event binding
47 | v3.VBtn(
48 | icon="mdi-crop-free",
49 | click=ctrl.view_reset_camera,
50 | classes="position-absolute",
51 | style="left: 1rem; top: 1rem; z-index: 1",
52 | density="compact",
53 | )
54 |
55 | # State binding
56 | v3.VSlider(
57 | v_model=("scale", 0.3),
58 | min=0,
59 | max=0.5,
60 | step=0.01,
61 | density="compact",
62 | classes="position-absolute",
63 | style="right: 1rem; top: 1rem; width: 400px; z-index: 1",
64 | )
65 |
66 | # Make sure the app is running and ready
67 | await layout.ready
68 | # Show UI in result
69 | layout
70 |
--------------------------------------------------------------------------------
/tutorial/09_trame/c_trame_scalars.py:
--------------------------------------------------------------------------------
1 | """
2 | Control Scalar Array
3 | ~~~~~~~~~~~~~~~~~~~~
4 |
5 | Extending our simple example to have a dropdown menu to control which
6 | scalar array is used to color the mesh.
7 | """
8 |
9 | import pyvista as pv
10 | from pyvista import examples
11 | from pyvista.trame.ui import plotter_ui
12 | from trame.app import get_server
13 | from trame.ui.vuetify3 import SinglePageLayout
14 | from trame.widgets import vuetify3
15 |
16 | pv.OFF_SCREEN = True
17 |
18 | server = get_server()
19 | state, ctrl = server.state, server.controller
20 |
21 | mesh = examples.download_antarctica_velocity()
22 |
23 | pl = pv.Plotter()
24 | actor = pl.add_mesh(mesh)
25 | pl.view_xy()
26 |
27 |
28 | @state.change("scalars")
29 | def set_scalars(scalars=mesh.active_scalars_name, **kwargs) -> None:
30 | actor.mapper.array_name = scalars
31 | actor.mapper.scalar_range = mesh.get_data_range(scalars)
32 | ctrl.view_update()
33 |
34 |
35 | @state.change("log_scale")
36 | def set_log_scale(log_scale=False, **kwargs) -> None: # noqa: FBT002
37 | actor.mapper.lookup_table.log_scale = log_scale
38 | ctrl.view_update()
39 |
40 |
41 | with SinglePageLayout(server) as layout:
42 | with layout.toolbar:
43 | vuetify3.VSpacer()
44 | vuetify3.VCheckbox(
45 | label="Log Scale",
46 | v_model=("log_scale", False),
47 | hide_details=True,
48 | density="compact",
49 | outlined=True,
50 | )
51 | vuetify3.VSelect(
52 | label="Scalars",
53 | v_model=("scalars", mesh.active_scalars_name),
54 | items=("array_list", list(mesh.point_data.keys())),
55 | hide_details=True,
56 | density="compact",
57 | outlined=True,
58 | classes="pt-1 ml-2",
59 | style="max-width: 250px",
60 | )
61 |
62 | with (
63 | layout.content,
64 | vuetify3.VContainer(
65 | fluid=True,
66 | classes="pa-0 fill-height",
67 | ),
68 | ):
69 | # Use PyVista UI template for Plotters
70 | view = plotter_ui(pl)
71 | ctrl.view_update = view.update
72 |
73 | # Show UI
74 | await layout.ready
75 | layout
76 | ###############################################################################
77 | # .. raw:: html
78 | #
79 | #
80 | #
81 | #
82 | #
83 | #
84 |
--------------------------------------------------------------------------------
/tutorial/09_trame/d_trame_scalar_range.py:
--------------------------------------------------------------------------------
1 | """
2 | Control Scalar Range
3 | ~~~~~~~~~~~~~~~~~~~~
4 |
5 | Extending our simple example to control the color limits of the mapped scalars.
6 | """
7 |
8 | import pyvista as pv
9 | from pyvista.trame.ui import plotter_ui
10 | from trame.app import get_server
11 | from trame.ui.vuetify3 import SinglePageLayout
12 | from trame.widgets import vuetify3
13 |
14 | pv.OFF_SCREEN = True
15 |
16 | server = get_server()
17 | state, ctrl = server.state, server.controller
18 |
19 | mesh = pv.Wavelet()
20 |
21 | pl = pv.Plotter()
22 | actor = pl.add_mesh(mesh)
23 |
24 |
25 | @state.change("scalar_range")
26 | def set_scalar_range(scalar_range=mesh.get_data_range(), **kwargs) -> None: # noqa: B008
27 | actor.mapper.scalar_range = scalar_range
28 | ctrl.view_update()
29 |
30 |
31 | with SinglePageLayout(server) as layout:
32 | with layout.toolbar:
33 | vuetify3.VSpacer()
34 | vuetify3.VRangeSlider(
35 | thumb_size=16,
36 | thumb_label=True,
37 | label="Range",
38 | v_model=("scalar_range", [0, 300]),
39 | min=("0",),
40 | max=("500",),
41 | density="compact",
42 | hide_details=True,
43 | style="max-width: 400px",
44 | )
45 |
46 | with (
47 | layout.content,
48 | vuetify3.VContainer(
49 | fluid=True,
50 | classes="pa-0 fill-height",
51 | ),
52 | ):
53 | # Use PyVista UI template for Plotters
54 | view = plotter_ui(pl)
55 | ctrl.view_update = view.update
56 |
57 | # Show UI
58 | await layout.ready
59 | layout
60 | ###############################################################################
61 | # .. raw:: html
62 | #
63 | #
64 | #
65 | #
66 | #
67 | #
68 |
--------------------------------------------------------------------------------
/tutorial/09_trame/e_trame_algorithm.py:
--------------------------------------------------------------------------------
1 | """
2 | Using VTK, PyVista, and Trame
3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 |
5 | This example demonstrates how to use VTK, PyVista, and Trame together
6 | to show how the three libraries complement each other.
7 | """
8 |
9 | import pyvista as pv
10 | from pyvista.trame.ui import plotter_ui
11 | from trame.app import get_server
12 | from trame.ui.vuetify3 import SinglePageLayout
13 | from trame.widgets import vuetify3
14 | from vtkmodules.vtkFiltersSources import vtkConeSource
15 |
16 | pv.OFF_SCREEN = True
17 |
18 | server = get_server()
19 | state, ctrl = server.state, server.controller
20 |
21 | source = vtkConeSource()
22 |
23 | pl = pv.Plotter()
24 | pl.add_mesh(source, color="seagreen")
25 |
26 |
27 | @state.change("resolution")
28 | def update_contour(resolution, **kwargs) -> None:
29 | source.SetResolution(int(resolution))
30 | ctrl.view_update()
31 |
32 |
33 | with SinglePageLayout(server) as layout:
34 | with layout.toolbar:
35 | vuetify3.VSpacer()
36 | vuetify3.VSlider(
37 | v_model=("resolution", 15),
38 | min=5,
39 | max=30,
40 | hide_details=True,
41 | density="compact",
42 | style="max-width: 300px",
43 | change=ctrl.view_update,
44 | )
45 | vuetify3.VProgressLinear(
46 | indeterminate=True,
47 | absolute=True,
48 | bottom=True,
49 | active=("trame__busy",),
50 | )
51 |
52 | with (
53 | layout.content,
54 | vuetify3.VContainer(
55 | fluid=True,
56 | classes="pa-0 fill-height",
57 | ),
58 | ):
59 | # Use PyVista UI template for Plotters
60 | view = plotter_ui(pl)
61 | ctrl.view_update = view.update
62 |
63 | # Show UI
64 | await layout.ready
65 | layout
66 | ###############################################################################
67 | # .. raw:: html
68 | #
69 | #
70 | #
71 | #
72 | #
73 | #
74 |
--------------------------------------------------------------------------------
/tutorial/09_trame/f_trame_open_file.py:
--------------------------------------------------------------------------------
1 | """
2 | Open Mesh File
3 | ~~~~~~~~~~~~~~
4 |
5 | An example of opening a mesh file from the browser and viewing it with PyVista.
6 |
7 | """
8 |
9 | import tempfile
10 | from pathlib import Path
11 |
12 | import pyvista as pv
13 | from pyvista.trame.ui import plotter_ui
14 | from trame.app import get_server
15 | from trame.app.file_upload import ClientFile
16 | from trame.ui.vuetify3 import SinglePageLayout
17 | from trame.widgets import vuetify3
18 |
19 | pv.OFF_SCREEN = True
20 |
21 | server = get_server()
22 | state, ctrl = server.state, server.controller
23 |
24 | pl = pv.Plotter()
25 |
26 |
27 | @server.state.change("file_exchange")
28 | def handle(file_exchange, **kwargs) -> None:
29 | file = ClientFile(file_exchange)
30 |
31 | if file.content:
32 | print(file.info) # noqa: T201
33 | bytes = file.content # noqa: A001
34 | with tempfile.NamedTemporaryFile(suffix=file.name) as path:
35 | with Path(path.name).open("wb") as f:
36 | f.write(bytes)
37 | ds = pv.read(path.name)
38 | pl.add_mesh(ds, name=file.name)
39 | pl.reset_camera()
40 | else:
41 | pl.clear_actors()
42 | pl.reset_camera()
43 |
44 |
45 | with SinglePageLayout(server) as layout:
46 | with layout.toolbar:
47 | vuetify3.VSpacer()
48 | vuetify3.VFileInput(
49 | show_size=True,
50 | small_chips=True,
51 | truncate_length=25,
52 | v_model=("file_exchange", None),
53 | density="compact",
54 | hide_details=True,
55 | style="max-width: 300px;",
56 | )
57 | vuetify3.VProgressLinear(
58 | indeterminate=True, absolute=True, bottom=True, active=("trame__busy",)
59 | )
60 |
61 | with layout.content: # noqa: SIM117
62 | with vuetify3.VContainer(
63 | fluid=True, classes="pa-0 fill-height", style="position: relative;"
64 | ):
65 | view = plotter_ui(pl)
66 | ctrl.view_update = view.update
67 |
68 | # Show UI
69 | await layout.ready
70 | layout
71 | ###############################################################################
72 | # .. raw:: html
73 | #
74 | #
75 | #
76 | #
77 | #
78 | #
79 |
--------------------------------------------------------------------------------