Skip to content

Commit 6752e2c

Browse files
DOC: Include examples (and example documentation) for sphinx-gallery
1 parent b98ba8e commit 6752e2c

35 files changed

Lines changed: 1249 additions & 471 deletions

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,4 @@ or `contact <https://www.predsci.com/portal/contact.php>`_ Predictive Science In
5959
`Predictive Science Inc. <https://predsci.com>`_ |
6060
`Repository <https://github.com/predsci/pyvisual>`_ |
6161
`Documentation <https://predsci.com/doc/pyvisual>`_ |
62-
`Distribution <https://pypi.org/project/pyvisual>`_
62+
`Distribution <https://pypi.org/project/psi-pyvisual>`_

docs/source/guide/index.rst

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
11
User Guide
22
==========
33

4-
To get started with **pyvisual**, please refer to the following sections:
4+
.. grid:: 3
5+
:gutter: 2
6+
:class-container: sd-mt-4
57

6-
.. toctree::
8+
.. grid-item-card:: Installation
9+
:link: installation
10+
:link-type: doc
11+
:text-align: center
12+
13+
Installation instructions, including recommended virtual environment setup
14+
and required/optional dependencies.
715

8-
installation
9-
overview
16+
.. grid-item-card:: Overview
17+
:link: overview
18+
:link-type: doc
19+
:text-align: center
1020

21+
Overview of the package structure, design principles, and core classes — with
22+
a focus on the :class:`~pyvisual.core.plot3d.Plot3d` class and its mixin components.
23+
24+
.. toctree::
25+
:hidden:
26+
:maxdepth: 2
1127

28+
installation
29+
overview

docs/source/guide/installation.rst

Lines changed: 97 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,112 @@
33
Installation
44
============
55

6+
.. attention::
7+
8+
We highly recommend using a virtual environment to manage your
9+
Python packages and avoid conflicts with other projects. For
10+
the best results, we recommend using ``conda`` – *via* Miniforge
11+
(preferred), Miniconda, or Anaconda – to create and manage
12+
your virtual environments.
13+
14+
To get started with **pyvisual**, you can install it directly from PyPI:
15+
16+
.. code-block:: bash
17+
18+
pip install psi-pyvisual
19+
620
Requirements
721
------------
822

923
**pyvisual** requires Python 3.10 or later and runs on Linux and macOS.
10-
The core dependencies — :mod:`numpy`, :mod:`pyvista`, :mod:`psi_io`,
11-
:mod:`sunpy`, and :mod:`astropy` — are installed automatically.
24+
25+
Core Dependencies
26+
^^^^^^^^^^^^^^^^^
27+
28+
The following packages are installed automatically:
29+
30+
.. list-table::
31+
:header-rows: 1
32+
:widths: 18 12 70
33+
34+
* - Package
35+
- Min. version
36+
- Role in **pyvisual**
37+
* - `NumPy <https://numpy.org/doc/stable/>`_
38+
- —
39+
- Array operations underpinning all coordinate transforms, mesh
40+
construction, and data manipulation throughout the library.
41+
* - `PyVista <https://docs.pyvista.org/>`_
42+
- —
43+
- 3-D rendering engine. **pyvisual** subclasses
44+
:class:`pyvista.Plotter` and uses PyVista mesh types
45+
(:class:`~pyvista.PolyData`, :class:`~pyvista.StructuredGrid`,
46+
:class:`~pyvista.RectilinearGrid`) as the primary data containers
47+
for all visualizations.
48+
* - `psi-io <https://predsci.com/doc/psi-io/guide/index.html>`_
49+
- 2.0.6
50+
- PSI library for reading HDF4/HDF5 model output files. Provides
51+
:func:`~psi_io.read_hdf_by_index` for loading subsets of coronal
52+
data arrays by index, and is required for all examples that use
53+
real PSI MAS model data.
54+
* - `SunPy <https://docs.sunpy.org/>`_
55+
- —
56+
- Solar physics toolkit used for coordinate frame transformations
57+
(e.g. Heliocentric Earth Ecliptic and Carrington frames) and
58+
spacecraft ephemeris calculations that drive the observer
59+
positioning utilities.
60+
* - `Astropy <https://docs.astropy.org/>`_
61+
- —
62+
- Astronomical units, time handling, and coordinate infrastructure
63+
underlying SunPy's frame system; used indirectly via SunPy for
64+
JPL Horizons queries and observer geometry.
65+
66+
Optional Dependencies
67+
^^^^^^^^^^^^^^^^^^^^^
68+
69+
Install these via extras (see `Standard Install`_ below):
70+
71+
.. list-table::
72+
:header-rows: 1
73+
:widths: 18 12 70
74+
75+
* - Package
76+
- Min. version
77+
- Role in **pyvisual**
78+
* - `pyhdf <https://pypi.org/project/pyhdf/>`_
79+
- 0.11.6
80+
- HDF4 file support. Required when PSI model data is stored in the
81+
legacy ``.hdf`` format rather than HDF5. Enabled by the
82+
``hdf4`` extra.
83+
* - `SciPy <https://docs.scipy.org/doc/scipy/>`_
84+
- —
85+
- Interpolation routines for regridding or resampling data onto
86+
non-native coordinate grids. Enabled by the ``interp`` extra
87+
(also pulled in by ``data``).
88+
* - `mapflpy <https://predsci.com/doc/mapflpy/>`_
89+
- 1.1.9
90+
- PSI library for tracing magnetic fieldlines on spherical grids.
91+
Provides :func:`~mapflpy.scripts.run_forward_tracing` and
92+
:func:`~mapflpy.scripts.run_fwdbwd_tracing`, which feed directly
93+
into :meth:`~pyvisual.core.mixins.StackMeshMixin.add_fieldlines`.
94+
Enabled by the ``tracing`` extra.
95+
* - `Pooch <https://www.fatiando.org/pooch/latest/>`_
96+
- —
97+
- Asset fetching and caching. Powers
98+
:func:`~pyvisual.utils.data.fetch_datasets`, which downloads
99+
sample PSI MAS model files to ``~/.cache/psi/`` on first use.
100+
Enabled by the ``data`` extra.
101+
* - `Matplotlib <https://matplotlib.org/stable/>`_
102+
- —
103+
- Colour maps and scalar-bar rendering used internally by PyVista.
104+
Pulled in automatically by the ``data`` extra.
12105

13106
Standard Install
14107
----------------
15108

16109
Install the latest release from PyPI::
17110

18-
pip install pyvisual
111+
pip install psi-pyvisual
19112

20113
To include support for reading HDF4 files (``pyhdf``), fieldline tracing
21114
(``mapflpy``), scipy-based interpolation, or the data-fetching utilities,
@@ -38,7 +131,7 @@ use the relevant extras:
38131

39132
Install one or more extras with::
40133

41-
pip install "pyvisual[hdf4,tracing]"
134+
pip install "psi-pyvisual[hdf4,tracing]"
42135

43136
Development Install
44137
-------------------

docs/source/guide/overview.rst

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ and maintained by `Predictive Science Inc. (PSI) <https://www.predsci.com/>`_ an
1010
is tightly coupled to the PSI data ecosystem — in particular
1111
`psi-io <https://predsci.com/doc/psi-io/guide/index.html>`_ (HDF4/HDF5 file I/O)
1212
and `mapflpy <https://predsci.com/doc/mapflpy/>`_ (magnetic fieldline tracing).
13-
Any rectilinear grid defined in spherical coordinates is compatible with the API,
14-
regardless of whether it originates from a PSI model.
13+
With that said, any rectilinear grid defined in spherical coordinates is compatible
14+
with the API.
1515

1616
.. attention::
1717

@@ -41,8 +41,24 @@ Cartesian frame (``'cartesian'``)
4141
Accepted aliases include ``'xyz'``, ``'cart'``, ``'rectilinear'``, and any
4242
permutation of the individual axis letters.
4343

44-
Conversion between the two frames is handled transparently — methods that accept a
45-
``frame`` argument convert to Cartesian before passing data to PyVista.
44+
.. note::
45+
46+
**pyvisual** is principally concerned with rendering rectilinear spherical grids,
47+
*viz.* those produced by PSI's MAS code; more specificially, this package is
48+
designed to facilitate the visualization of such datasets by converting these
49+
structured :math:`(r, \theta, \phi)` grids into the native Cartesian coordinate
50+
system used by PyVista and VTK for rendering.
51+
52+
The coordinate system of the :class:`~pyvista.Plotter` is always a Cartesian
53+
coordinate system in the Heliographic Carrington frame. Input data (however)
54+
is generally expected to be in the spherical frame, and the API provides utilities for
55+
converting between the two.
56+
57+
The spherical frame is used for all observer controls,
58+
reference geometry, and mesh construction; the Cartesian frame is used for all
59+
rendering and camera manipulation. The API abstracts away the details of converting
60+
between the two, but it is important to understand the distinction when working with
61+
the package.
4662

4763
The Plotter: ``Plot3d``
4864
-----------------------
@@ -97,7 +113,27 @@ Mesh Classes
97113
------------
98114

99115
Two mesh classes are provided for loading and manipulating model data before
100-
adding it to a plotter.
116+
adding it to a plotter. These classes can be instantiated from an HDF file
117+
path, from raw coordinate and data arrays, or from an existing PyVista dataset.
118+
119+
.. note::
120+
121+
When instantiating from an HDF filepath, the :mod:`psi-io` library is used
122+
to read the file and extract the coordinate and data arrays by index.
123+
As such, the file must be in a format compatible with :mod:`psi-io` (e.g. HDF4 with
124+
Fortran-order arrays, or HDF5 with the same structure).
125+
126+
*It is generally
127+
recommended to explicitly load the data arrays to ensure that the scales
128+
and data-values are properly interpreted, rather than relying on the mesh
129+
classes to infer them from the file.*
130+
131+
The motivation behind these classes is to provide a convenient container for solar
132+
physics model data that can make full use of the powerful PyVista/VTK
133+
`Filters <https://docs.pyvista.org/api/core/filters.html>`_ (along with a few
134+
additional "filters" provided by **pyvisual** in the
135+
:class:`~pyvisual.core.mesh3d.CartesianMeshFilters` and
136+
:class:`~pyvisual.core.mesh3d.SphericalMeshFilters` mixin classes).
101137

102138
:class:`~pyvisual.core.mesh3d.SphericalMesh`
103139
Wraps :class:`pyvista.RectilinearGrid` with a spherical-frame tag. Can be
@@ -111,6 +147,25 @@ adding it to a plotter.
111147
The Cartesian counterpart, wrapping :class:`pyvista.StructuredGrid`. It shares
112148
the same operator API as :class:`~pyvisual.core.mesh3d.SphericalMesh`.
113149

150+
.. note::
151+
152+
The general motivation behind the latter class (in contrast to the :class:`~pyvisual.core.mesh3d.SphericalMesh`
153+
class) is to facilitate the use of PyVista/VTK's
154+
`filters <https://docs.pyvista.org/api/core/filters>`_ on spherical grids that have
155+
been converted to Cartesian coordinates. This :func:`~pyvisual.utils.geometry.spherical_to_cartesian`
156+
transformation yeilds topological structured meshes that are, nevertheless, not composed
157+
of monotonically increasing coordinate arrays. Therefore, the grid's internal structure
158+
has to be stored explicitly *viz.* through a :class:`pyvista.StructuredGrid` rather than a
159+
:class:`pyvista.RectilinearGrid`.
160+
161+
.. warning::
162+
163+
The consequence of the above note is that the point arrays of this class are
164+
derived from a :func:`~numpy.meshgrid`-like Cartesian product of the input scales,
165+
and are not stored as the three separate 1-D arrays that are typical of rectilinear grids.
166+
As such, these grids can be substantially more memory-intensive than their
167+
:class:`~pyvisual.core.mesh3d.SphericalMesh` counterparts.
168+
114169
Both classes are available from the top-level package::
115170

116171
from pyvisual import SphericalMesh, CartesianMesh

docs/source/index.rst

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,51 @@ Because **pyvisual** renders through `PyVista <https://docs.pyvista.org/>`_ and
1717
it is strongly recommended to familiarise yourself with the PyVista documentation to
1818
get the most out of the package.
1919

20+
**pyvisual** is in active development. Although the existing API will remain unchanged,
21+
additional quality-of-life improvements are forthcoming. Please direct any comments,
22+
concerns, or issues to the Predictive Science Inc. research team via the distro `Issue Tracker
23+
<https://github.com/predsci/pyvisual/issues>`_ or
24+
`contact form <https://www.predsci.com/portal/contact.php>`_.
25+
26+
.. attention::
27+
28+
Please be aware that **pyvisual** is available through the Python Package Index (PyPI) as
29+
``psi-pyvisual``. Further installation instructions are available in the
30+
`User Guide <https://predsci.com/doc/pyvisual/guide/index.html>`_.
31+
32+
.. grid:: 3
33+
:gutter: 2
34+
:class-container: sd-mt-4
35+
36+
.. grid-item-card:: User Guide
37+
:link: guide/index
38+
:link-type: doc
39+
:text-align: center
40+
41+
Installation instructions, coordinate conventions, and an architectural
42+
overview of the :class:`~pyvisual.core.plot3d.Plot3d` class and its
43+
mixin components.
44+
45+
.. grid-item-card:: Examples
46+
:link: gallery/index
47+
:link-type: doc
48+
:text-align: center
49+
50+
Worked examples covering basic scenes, slicing, fieldlines, observer
51+
controls, and the mesh class API — organized by functional area.
52+
53+
.. grid-item-card:: API Reference
54+
:link: api/index
55+
:link-type: doc
56+
:text-align: center
57+
58+
Full API documentation for all public classes, methods, functions,
59+
and type aliases auto-generated from source docstrings.
60+
2061
.. toctree::
2162
:hidden:
63+
:maxdepth: 2
2264

23-
API <api/index>
2465
Guide <guide/index>
25-
Examples <gallery/index>
66+
Examples <gallery/index>
67+
API <api/index>
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
"""
2+
Loading and Plotting MHD Data
3+
==============================
4+
5+
This example introduces the two steps needed to go from a PSI data file to a
6+
rendered scene:
7+
8+
1. **Fetching a dataset** — :func:`~pyvisual.utils.data.fetch_datasets`
9+
downloads (or retrieves from cache) a version-pinned HDF5 file from the
10+
PSI asset server and returns its local path.
11+
2. **Reading the data** — :func:`~psi_io.read_hdf_by_index` loads the array
12+
values and the three coordinate grids :math:`(r, \\theta, \\phi)` from the
13+
file. Passing ``None`` for a dimension selects its full extent; passing an
14+
integer index fixes that dimension to a single grid point.
15+
16+
The dataset used here is the radial magnetic field :math:`B_r` from a
17+
Thermo 2 steady-state coronal simulation for Carrington Rotation 2282
18+
(CR 2282), covering the domain :math:`r \\in [1,\\,30]\\,R_\\odot`.
19+
"""
20+
21+
from psi_io import read_hdf_by_index
22+
from pyvisual import Plot3d
23+
from pyvisual.utils.data import fetch_datasets
24+
25+
# %%
26+
# Fetching a Dataset
27+
# ------------------
28+
#
29+
# :func:`~pyvisual.utils.data.fetch_datasets` accepts a *domain* identifier
30+
# (``'cor'`` for the coronal domain, ``'hel'`` for heliospheric) and a
31+
# *variable* name. It returns a :class:`~collections.namedtuple` whose fields
32+
# are named ``"{domain}_{variable}"``. The first call downloads the file to
33+
# the local cache; subsequent calls return the cached copy immediately without
34+
# hitting the network.
35+
36+
datasets = fetch_datasets("cor", "br")
37+
br_file = datasets.cor_br
38+
39+
# %%
40+
# Reading a 2-D Radial Slice
41+
# --------------------------
42+
#
43+
# :func:`~psi_io.read_hdf_by_index` reads the HDF5 file and returns
44+
# ``(data, r, t, p)`` — the scalar array followed by the three coordinate
45+
# vectors. Index arguments control which portion of the grid is loaded:
46+
#
47+
# - ``None`` — load the full extent of that dimension.
48+
# - An integer ``i`` — fix that dimension to the ``i``-th grid point
49+
# (1-based), collapsing it to a length-1 array.
50+
#
51+
# Here the colatitude is fixed at index 71 (the equatorial plane,
52+
# :math:`\theta_{71} \approx \pi/2`), while :math:`r` and :math:`\phi`
53+
# span their full extents. The result is a 2-D surface in the equatorial
54+
# plane colored by :math:`B_r`.
55+
56+
data, r, t, p = read_hdf_by_index(br_file, None, 71, None)
57+
58+
plotter = Plot3d()
59+
plotter.show_axes()
60+
plotter.add_sun()
61+
plotter.add_2d_slice(r, t, p, data, cmap='seismic', clim=(-1, 1),
62+
show_scalar_bar=True)
63+
plotter.show()
64+
65+
# %%
66+
# Scaling by :math:`r^2`
67+
# -----------------------
68+
#
69+
# The radial magnetic field falls off geometrically as :math:`1/r^2` with
70+
# distance. Multiplying by :math:`r^2` removes this trend and reveals the
71+
# longitudinal structure of open-field regions at all radii — a common
72+
# diagnostic in solar wind modeling. Because ``r`` is a plain NumPy array,
73+
# the scaling is a single element-wise operation before passing to the plotter.
74+
75+
plotter = Plot3d()
76+
plotter.show_axes()
77+
plotter.add_sun()
78+
plotter.add_2d_slice(r, t, p, data * r ** 2, cmap='seismic', clim=(-1, 1),
79+
show_scalar_bar=True)
80+
plotter.show()

0 commit comments

Comments
 (0)