diff --git a/.buildinfo b/.buildinfo new file mode 100644 index 0000000..1f0ac3d --- /dev/null +++ b/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 3c29c526d69f6ad9f45ce2532034e3fe +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/.nojekll b/.nojekyll similarity index 100% rename from .nojekll rename to .nojekyll diff --git a/_downloads/07fcc19ba03226cd3d83d4e40ec44385/auto_examples_python.zip b/_downloads/07fcc19ba03226cd3d83d4e40ec44385/auto_examples_python.zip new file mode 100644 index 0000000..7038bca Binary files /dev/null and b/_downloads/07fcc19ba03226cd3d83d4e40ec44385/auto_examples_python.zip differ diff --git a/_downloads/326f1e4f381185b5da31cfd0fc7fb40e/latlon_to_healpix.py b/_downloads/326f1e4f381185b5da31cfd0fc7fb40e/latlon_to_healpix.py new file mode 100644 index 0000000..fa66776 --- /dev/null +++ b/_downloads/326f1e4f381185b5da31cfd0fc7fb40e/latlon_to_healpix.py @@ -0,0 +1,66 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +HealPIX regridding +------------------ + +In this notebook, I demonstrate bilinear regridding onto healpy grids in O(10) +ms. this is a 3 order of magnitude speed-up compared to what Dale has reported. + +Now, lets define a healpix grid with indexing in the XY convention. we convert +to NEST indexing in order to use the `healpy.pix2ang` to get the lat lon +coordinates. This operation is near instant. + +""" +# %% + +import matplotlib.pyplot as plt +import numpy as np +import torch + +import earth2grid + +# level is the resolution +level = 6 +hpx = earth2grid.healpix.Grid(level=level, pixel_order=earth2grid.healpix.XY()) +src = earth2grid.latlon.equiangular_lat_lon_grid(32, 64) +regrid = earth2grid.get_regridder(src, hpx) + + +z = np.cos(np.deg2rad(src.lat)) * np.cos(np.deg2rad(src.lon)) + + +z_torch = torch.as_tensor(z) +z_hpx = regrid(z_torch) + +fig, (a, b) = plt.subplots(2, 1) +a.pcolormesh(src.lon, src.lat, z) +a.set_title("Lat Lon Grid") + +b.scatter(hpx.lon, hpx.lat, c=z_hpx, s=0.1) +b.set_title("Healpix") + +# %% one tile +nside = 2**level +reshaped = z_hpx.reshape(12, nside, nside) +lat_r = hpx.lat.reshape(12, nside, nside) +lon_r = hpx.lon.reshape(12, nside, nside) + +tile = 11 +fig, axs = plt.subplots(3, 4, sharex=True, sharey=True) +axs = axs.ravel() + +for tile in range(12): + axs[tile].pcolormesh(lon_r[tile], lat_r[tile], reshaped[tile]) diff --git a/_downloads/6f1e7a639e0699d6164445b55e6c116d/auto_examples_jupyter.zip b/_downloads/6f1e7a639e0699d6164445b55e6c116d/auto_examples_jupyter.zip new file mode 100644 index 0000000..8afce95 Binary files /dev/null and b/_downloads/6f1e7a639e0699d6164445b55e6c116d/auto_examples_jupyter.zip differ diff --git a/_downloads/9b0d4977029b26f04ef1efed15239f54/hpx2grid.py b/_downloads/9b0d4977029b26f04ef1efed15239f54/hpx2grid.py new file mode 100644 index 0000000..42655a2 --- /dev/null +++ b/_downloads/9b0d4977029b26f04ef1efed15239f54/hpx2grid.py @@ -0,0 +1,46 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +HealPIX Image visualization +--------------------------- + +HealPIX maps can be viewed as a 2D image rotated by 45 deg. This is useful for +quick visualization with image viewers without distorting the native pixels of +the image. +""" + +import matplotlib.pyplot as plt +import numpy as np +import torch + +# %% +from matplotlib.colors import Normalize +from PIL import Image + +from earth2grid.healpix import Grid + +grid = Grid(level=8) +lat = torch.tensor(grid.lat) +lat_img = grid.to_image(lat) + +# Use Image to save at full resolution +normalizer = Normalize(vmin=np.nanmin(lat_img), vmax=np.nanmax(lat_img)) +array = normalizer(lat_img) +array = plt.cm.viridis(array) +array = (256 * array).astype("uint8") +# set transparency for nans +array[..., -1] = np.where(np.isnan(lat_img), 0, 255) +image = Image.fromarray(array) +image.save("hpx_grid.png") diff --git a/_downloads/a0fb23b6404ea0f060e2ee086a2a1fd2/pyvista_grids.py b/_downloads/a0fb23b6404ea0f060e2ee086a2a1fd2/pyvista_grids.py new file mode 100644 index 0000000..ce36d59 --- /dev/null +++ b/_downloads/a0fb23b6404ea0f060e2ee086a2a1fd2/pyvista_grids.py @@ -0,0 +1,60 @@ +# SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +Plot grids with PyVista +----------------------- + +""" +import pyvista as pv + +# %% +import earth2grid + + +def label(mesh, plotter, text): + """ + Add a label above a mesh in a PyVista plot. + + Parameters: + - mesh: The mesh to label. + - plotter: A PyVista plotter instance. + - text: The label text. + - color: The color of the text label. Default is 'white'. + """ + # Calculate the center of the mesh and the top Z-coordinate plus an offset + center = mesh.center + label_pos = [center[0], center[1], mesh.bounds[5] + 0.5] # Offset to place label above the mesh + + # Add the label using point labels for precise 3D positioning + plotter.add_point_labels( + [label_pos], [text], point_size=0, render_points_as_spheres=False, shape_opacity=0, font_size=20 + ) + + +grid = earth2grid.healpix.Grid(level=4) +hpx = grid.to_pyvista() +latlon = earth2grid.latlon.equiangular_lat_lon_grid(32, 64, includes_south_pole=False).to_pyvista() + + +pl = pv.Plotter() +mesh = hpx.translate([0, 2.5, 0]) +pl.add_mesh(mesh, show_edges=True) +label(mesh, pl, "HealPix") + +pl.add_mesh(latlon, show_edges=True) +label(latlon, pl, "Equiangular Lat/Lon") + +pl.camera.position = (5, 0, 5) +pl.show() diff --git a/_downloads/bc5f3d8ff2e85ce704e6bc194c4a1825/pyvista_grids.ipynb b/_downloads/bc5f3d8ff2e85ce704e6bc194c4a1825/pyvista_grids.ipynb new file mode 100644 index 0000000..360dc32 --- /dev/null +++ b/_downloads/bc5f3d8ff2e85ce704e6bc194c4a1825/pyvista_grids.ipynb @@ -0,0 +1,54 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# Plot grids with PyVista\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import pyvista as pv" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import earth2grid\n\n\ndef label(mesh, plotter, text):\n \"\"\"\n Add a label above a mesh in a PyVista plot.\n\n Parameters:\n - mesh: The mesh to label.\n - plotter: A PyVista plotter instance.\n - text: The label text.\n - color: The color of the text label. Default is 'white'.\n \"\"\"\n # Calculate the center of the mesh and the top Z-coordinate plus an offset\n center = mesh.center\n label_pos = [center[0], center[1], mesh.bounds[5] + 0.5] # Offset to place label above the mesh\n\n # Add the label using point labels for precise 3D positioning\n plotter.add_point_labels(\n [label_pos], [text], point_size=0, render_points_as_spheres=False, shape_opacity=0, font_size=20\n )\n\n\ngrid = earth2grid.healpix.Grid(level=4)\nhpx = grid.to_pyvista()\nlatlon = earth2grid.latlon.equiangular_lat_lon_grid(32, 64, includes_south_pole=False).to_pyvista()\n\n\npl = pv.Plotter()\nmesh = hpx.translate([0, 2.5, 0])\npl.add_mesh(mesh, show_edges=True)\nlabel(mesh, pl, \"HealPix\")\n\npl.add_mesh(latlon, show_edges=True)\nlabel(latlon, pl, \"Equiangular Lat/Lon\")\n\npl.camera.position = (5, 0, 5)\npl.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.3" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/_downloads/ceda851f459aa1125447c51ea42b0e9e/hpx2grid.ipynb b/_downloads/ceda851f459aa1125447c51ea42b0e9e/hpx2grid.ipynb new file mode 100644 index 0000000..32ab7c5 --- /dev/null +++ b/_downloads/ceda851f459aa1125447c51ea42b0e9e/hpx2grid.ipynb @@ -0,0 +1,54 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# HealPIX Image visualization\n\nHealPIX maps can be viewed as a 2D image rotated by 45 deg. This is useful for\nquick visualization with image viewers without distorting the native pixels of\nthe image.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\nimport numpy as np\nimport torch" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from matplotlib.colors import Normalize\nfrom PIL import Image\n\nfrom earth2grid.healpix import Grid\n\ngrid = Grid(level=8)\nlat = torch.tensor(grid.lat)\nlat_img = grid.to_image(lat)\n\n# Use Image to save at full resolution\nnormalizer = Normalize(vmin=np.nanmin(lat_img), vmax=np.nanmax(lat_img))\narray = normalizer(lat_img)\narray = plt.cm.viridis(array)\narray = (256 * array).astype(\"uint8\")\n# set transparency for nans\narray[..., -1] = np.where(np.isnan(lat_img), 0, 255)\nimage = Image.fromarray(array)\nimage.save(\"hpx_grid.png\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.3" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/_downloads/f6888b7c20ca92b13107eb2bef6349b7/latlon_to_healpix.ipynb b/_downloads/f6888b7c20ca92b13107eb2bef6349b7/latlon_to_healpix.ipynb new file mode 100644 index 0000000..e0891de --- /dev/null +++ b/_downloads/f6888b7c20ca92b13107eb2bef6349b7/latlon_to_healpix.ipynb @@ -0,0 +1,54 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n# HealPIX regridding\n\nIn this notebook, I demonstrate bilinear regridding onto healpy grids in O(10)\nms. this is a 3 order of magnitude speed-up compared to what Dale has reported.\n\nNow, lets define a healpix grid with indexing in the XY convention. we convert\nto NEST indexing in order to use the `healpy.pix2ang` to get the lat lon\ncoordinates. This operation is near instant.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\nimport numpy as np\nimport torch\n\nimport earth2grid\n\n# level is the resolution\nlevel = 6\nhpx = earth2grid.healpix.Grid(level=level, pixel_order=earth2grid.healpix.XY())\nsrc = earth2grid.latlon.equiangular_lat_lon_grid(32, 64)\nregrid = earth2grid.get_regridder(src, hpx)\n\n\nz = np.cos(np.deg2rad(src.lat)) * np.cos(np.deg2rad(src.lon))\n\n\nz_torch = torch.as_tensor(z)\nz_hpx = regrid(z_torch)\n\nfig, (a, b) = plt.subplots(2, 1)\na.pcolormesh(src.lon, src.lat, z)\na.set_title(\"Lat Lon Grid\")\n\nb.scatter(hpx.lon, hpx.lat, c=z_hpx, s=0.1)\nb.set_title(\"Healpix\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "nside = 2**level\nreshaped = z_hpx.reshape(12, nside, nside)\nlat_r = hpx.lat.reshape(12, nside, nside)\nlon_r = hpx.lon.reshape(12, nside, nside)\n\ntile = 11\nfig, axs = plt.subplots(3, 4, sharex=True, sharey=True)\naxs = axs.ravel()\n\nfor tile in range(12):\n axs[tile].pcolormesh(lon_r[tile], lat_r[tile], reshaped[tile])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.3" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/_images/sphx_glr_hpx2grid_001.png b/_images/sphx_glr_hpx2grid_001.png new file mode 100644 index 0000000..1803023 Binary files /dev/null and b/_images/sphx_glr_hpx2grid_001.png differ diff --git a/_images/sphx_glr_hpx2grid_thumb.png b/_images/sphx_glr_hpx2grid_thumb.png new file mode 100644 index 0000000..2ecf3a5 Binary files /dev/null and b/_images/sphx_glr_hpx2grid_thumb.png differ diff --git a/_images/sphx_glr_latlon_to_healpix_001.png b/_images/sphx_glr_latlon_to_healpix_001.png new file mode 100644 index 0000000..3004ce9 Binary files /dev/null and b/_images/sphx_glr_latlon_to_healpix_001.png differ diff --git a/_images/sphx_glr_latlon_to_healpix_002.png b/_images/sphx_glr_latlon_to_healpix_002.png new file mode 100644 index 0000000..b4adbea Binary files /dev/null and b/_images/sphx_glr_latlon_to_healpix_002.png differ diff --git a/_images/sphx_glr_latlon_to_healpix_thumb.png b/_images/sphx_glr_latlon_to_healpix_thumb.png new file mode 100644 index 0000000..e59a353 Binary files /dev/null and b/_images/sphx_glr_latlon_to_healpix_thumb.png differ diff --git a/_images/sphx_glr_pyvista_grids_001.png b/_images/sphx_glr_pyvista_grids_001.png new file mode 100644 index 0000000..be30f35 Binary files /dev/null and b/_images/sphx_glr_pyvista_grids_001.png differ diff --git a/_images/sphx_glr_pyvista_grids_thumb.png b/_images/sphx_glr_pyvista_grids_thumb.png new file mode 100644 index 0000000..7eb80e5 Binary files /dev/null and b/_images/sphx_glr_pyvista_grids_thumb.png differ diff --git a/_sources/api.rst.txt b/_sources/api.rst.txt new file mode 100644 index 0000000..a272fc2 --- /dev/null +++ b/_sources/api.rst.txt @@ -0,0 +1,25 @@ +API +=== + +Grids +----- + +.. autoclass:: earth2grid.healpix.Grid + :members: + :show-inheritance: + +.. autoclass:: earth2grid.latlon.LatLonGrid + :members: + :show-inheritance: + +.. autofunction:: earth2grid.latlon.equiangular_lat_lon_grid + +Regridding +---------- + +.. autofunction:: earth2grid.get_regridder + +Other utilities +--------------- + +.. autofunction:: earth2grid.healpix.pad diff --git a/_sources/auto_examples/hpx2grid.rst.txt b/_sources/auto_examples/hpx2grid.rst.txt new file mode 100644 index 0000000..a4f8029 --- /dev/null +++ b/_sources/auto_examples/hpx2grid.rst.txt @@ -0,0 +1,109 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "auto_examples/hpx2grid.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + :ref:`Go to the end ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_auto_examples_hpx2grid.py: + + +HealPIX Image visualization +--------------------------- + +HealPIX maps can be viewed as a 2D image rotated by 45 deg. This is useful for +quick visualization with image viewers without distorting the native pixels of +the image. + +.. GENERATED FROM PYTHON SOURCE LINES 23-28 + +.. code-block:: Python + + + import matplotlib.pyplot as plt + import numpy as np + import torch + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 29-47 + +.. code-block:: Python + + from matplotlib.colors import Normalize + from PIL import Image + + from earth2grid.healpix import Grid + + grid = Grid(level=8) + lat = torch.tensor(grid.lat) + lat_img = grid.to_image(lat) + + # Use Image to save at full resolution + normalizer = Normalize(vmin=np.nanmin(lat_img), vmax=np.nanmax(lat_img)) + array = normalizer(lat_img) + array = plt.cm.viridis(array) + array = (256 * array).astype("uint8") + # set transparency for nans + array[..., -1] = np.where(np.isnan(lat_img), 0, 255) + image = Image.fromarray(array) + image.save("hpx_grid.png") + + + +.. image-sg:: /auto_examples/images/sphx_glr_hpx2grid_001.png + :alt: hpx2grid + :srcset: /auto_examples/images/sphx_glr_hpx2grid_001.png + :class: sphx-glr-single-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + Warning, cannot find healpixpad module + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** (0 minutes 1.719 seconds) + + +.. _sphx_glr_download_auto_examples_hpx2grid.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: hpx2grid.ipynb ` + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: hpx2grid.py ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/_sources/auto_examples/index.rst.txt b/_sources/auto_examples/index.rst.txt new file mode 100644 index 0000000..b01511c --- /dev/null +++ b/_sources/auto_examples/index.rst.txt @@ -0,0 +1,98 @@ +:orphan: + +Examples +======== + +The examples are below + +The examples in misc/ are not included in the Sphinx Gallery. + + + +.. raw:: html + +
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /auto_examples/images/thumb/sphx_glr_hpx2grid_thumb.png + :alt: + + :ref:`sphx_glr_auto_examples_hpx2grid.py` + +.. raw:: html + +
HealPIX Image visualization
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /auto_examples/images/thumb/sphx_glr_latlon_to_healpix_thumb.png + :alt: + + :ref:`sphx_glr_auto_examples_latlon_to_healpix.py` + +.. raw:: html + +
HealPIX regridding
+
+ + +.. raw:: html + +
+ +.. only:: html + + .. image:: /auto_examples/images/thumb/sphx_glr_pyvista_grids_thumb.png + :alt: + + :ref:`sphx_glr_auto_examples_pyvista_grids.py` + +.. raw:: html + +
Plot grids with PyVista
+
+ + +.. raw:: html + +
+ + +.. toctree:: + :hidden: + + /auto_examples/hpx2grid + /auto_examples/latlon_to_healpix + /auto_examples/pyvista_grids + + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-gallery + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download all examples in Python source code: auto_examples_python.zip ` + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download all examples in Jupyter notebooks: auto_examples_jupyter.zip ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/_sources/auto_examples/latlon_to_healpix.rst.txt b/_sources/auto_examples/latlon_to_healpix.rst.txt new file mode 100644 index 0000000..f1e63b1 --- /dev/null +++ b/_sources/auto_examples/latlon_to_healpix.rst.txt @@ -0,0 +1,139 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "auto_examples/latlon_to_healpix.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + :ref:`Go to the end ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_auto_examples_latlon_to_healpix.py: + + +HealPIX regridding +------------------ + +In this notebook, I demonstrate bilinear regridding onto healpy grids in O(10) +ms. this is a 3 order of magnitude speed-up compared to what Dale has reported. + +Now, lets define a healpix grid with indexing in the XY convention. we convert +to NEST indexing in order to use the `healpy.pix2ang` to get the lat lon +coordinates. This operation is near instant. + +.. GENERATED FROM PYTHON SOURCE LINES 28-55 + +.. code-block:: Python + + + import matplotlib.pyplot as plt + import numpy as np + import torch + + import earth2grid + + # level is the resolution + level = 6 + hpx = earth2grid.healpix.Grid(level=level, pixel_order=earth2grid.healpix.XY()) + src = earth2grid.latlon.equiangular_lat_lon_grid(32, 64) + regrid = earth2grid.get_regridder(src, hpx) + + + z = np.cos(np.deg2rad(src.lat)) * np.cos(np.deg2rad(src.lon)) + + + z_torch = torch.as_tensor(z) + z_hpx = regrid(z_torch) + + fig, (a, b) = plt.subplots(2, 1) + a.pcolormesh(src.lon, src.lat, z) + a.set_title("Lat Lon Grid") + + b.scatter(hpx.lon, hpx.lat, c=z_hpx, s=0.1) + b.set_title("Healpix") + + + + +.. image-sg:: /auto_examples/images/sphx_glr_latlon_to_healpix_001.png + :alt: Lat Lon Grid, Healpix + :srcset: /auto_examples/images/sphx_glr_latlon_to_healpix_001.png + :class: sphx-glr-single-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + + Text(0.5, 1.0, 'Healpix') + + + +.. GENERATED FROM PYTHON SOURCE LINES 56-67 + +.. code-block:: Python + + nside = 2**level + reshaped = z_hpx.reshape(12, nside, nside) + lat_r = hpx.lat.reshape(12, nside, nside) + lon_r = hpx.lon.reshape(12, nside, nside) + + tile = 11 + fig, axs = plt.subplots(3, 4, sharex=True, sharey=True) + axs = axs.ravel() + + for tile in range(12): + axs[tile].pcolormesh(lon_r[tile], lat_r[tile], reshaped[tile]) + + + +.. image-sg:: /auto_examples/images/sphx_glr_latlon_to_healpix_002.png + :alt: latlon to healpix + :srcset: /auto_examples/images/sphx_glr_latlon_to_healpix_002.png + :class: sphx-glr-single-img + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + /Users/nbrenowitz/workspace/nvidia/earth2grid/examples/sphinx_gallery/latlon_to_healpix.py:66: UserWarning: The input coordinates to pcolormesh are interpreted as cell centers, but are not monotonically increasing or decreasing. This may lead to incorrectly calculated cell edges, in which case, please supply explicit cell edges to pcolormesh. + axs[tile].pcolormesh(lon_r[tile], lat_r[tile], reshaped[tile]) + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** (0 minutes 0.666 seconds) + + +.. _sphx_glr_download_auto_examples_latlon_to_healpix.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: latlon_to_healpix.ipynb ` + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: latlon_to_healpix.py ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/_sources/auto_examples/pyvista_grids.rst.txt b/_sources/auto_examples/pyvista_grids.rst.txt new file mode 100644 index 0000000..5cb2ccf --- /dev/null +++ b/_sources/auto_examples/pyvista_grids.rst.txt @@ -0,0 +1,133 @@ + +.. DO NOT EDIT. +.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. +.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: +.. "auto_examples/pyvista_grids.py" +.. LINE NUMBERS ARE GIVEN BELOW. + +.. only:: html + + .. note:: + :class: sphx-glr-download-link-note + + :ref:`Go to the end ` + to download the full example code + +.. rst-class:: sphx-glr-example-title + +.. _sphx_glr_auto_examples_pyvista_grids.py: + + +Plot grids with PyVista +----------------------- + +.. GENERATED FROM PYTHON SOURCE LINES 20-22 + +.. code-block:: Python + + import pyvista as pv + + + + + + + + +.. GENERATED FROM PYTHON SOURCE LINES 23-61 + +.. code-block:: Python + + import earth2grid + + + def label(mesh, plotter, text): + """ + Add a label above a mesh in a PyVista plot. + + Parameters: + - mesh: The mesh to label. + - plotter: A PyVista plotter instance. + - text: The label text. + - color: The color of the text label. Default is 'white'. + """ + # Calculate the center of the mesh and the top Z-coordinate plus an offset + center = mesh.center + label_pos = [center[0], center[1], mesh.bounds[5] + 0.5] # Offset to place label above the mesh + + # Add the label using point labels for precise 3D positioning + plotter.add_point_labels( + [label_pos], [text], point_size=0, render_points_as_spheres=False, shape_opacity=0, font_size=20 + ) + + + grid = earth2grid.healpix.Grid(level=4) + hpx = grid.to_pyvista() + latlon = earth2grid.latlon.equiangular_lat_lon_grid(32, 64, includes_south_pole=False).to_pyvista() + + + pl = pv.Plotter() + mesh = hpx.translate([0, 2.5, 0]) + pl.add_mesh(mesh, show_edges=True) + label(mesh, pl, "HealPix") + + pl.add_mesh(latlon, show_edges=True) + label(latlon, pl, "Equiangular Lat/Lon") + + pl.camera.position = (5, 0, 5) + pl.show() + + + + +.. image-sg:: /auto_examples/images/sphx_glr_pyvista_grids_001.png + :alt: pyvista grids + :srcset: /auto_examples/images/sphx_glr_pyvista_grids_001.png + :class: sphx-glr-single-img + + + + +.. rst-class:: sphx-glr-script-out + + .. code-block:: none + + [ -2.8125 2.8125 8.4375 14.0625 19.6875 25.3125 30.9375 36.5625 + 42.1875 47.8125 53.4375 59.0625 64.6875 70.3125 75.9375 81.5625 + 87.1875 92.8125 98.4375 104.0625 109.6875 115.3125 120.9375 126.5625 + 132.1875 137.8125 143.4375 149.0625 154.6875 160.3125 165.9375 171.5625 + 177.1875 182.8125 188.4375 194.0625 199.6875 205.3125 210.9375 216.5625 + 222.1875 227.8125 233.4375 239.0625 244.6875 250.3125 255.9375 261.5625 + 267.1875 272.8125 278.4375 284.0625 289.6875 295.3125 300.9375 306.5625 + 312.1875 317.8125 323.4375 329.0625 334.6875 340.3125 345.9375 351.5625 + 357.1875] + + + + + +.. rst-class:: sphx-glr-timing + + **Total running time of the script:** (0 minutes 0.294 seconds) + + +.. _sphx_glr_download_auto_examples_pyvista_grids.py: + +.. only:: html + + .. container:: sphx-glr-footer sphx-glr-footer-example + + .. container:: sphx-glr-download sphx-glr-download-jupyter + + :download:`Download Jupyter notebook: pyvista_grids.ipynb ` + + .. container:: sphx-glr-download sphx-glr-download-python + + :download:`Download Python source code: pyvista_grids.py ` + + +.. only:: html + + .. rst-class:: sphx-glr-signature + + `Gallery generated by Sphinx-Gallery `_ diff --git a/_sources/auto_examples/sg_execution_times.rst.txt b/_sources/auto_examples/sg_execution_times.rst.txt new file mode 100644 index 0000000..95960fc --- /dev/null +++ b/_sources/auto_examples/sg_execution_times.rst.txt @@ -0,0 +1,43 @@ + +:orphan: + +.. _sphx_glr_auto_examples_sg_execution_times: + + +Computation times +================= +**00:02.679** total execution time for 3 files **from auto_examples**: + +.. container:: + + .. raw:: html + + + + + + + + .. list-table:: + :header-rows: 1 + :class: table table-striped sg-datatable + + * - Example + - Time + - Mem (MB) + * - :ref:`sphx_glr_auto_examples_hpx2grid.py` (``hpx2grid.py``) + - 00:01.719 + - 0.0 + * - :ref:`sphx_glr_auto_examples_latlon_to_healpix.py` (``latlon_to_healpix.py``) + - 00:00.666 + - 0.0 + * - :ref:`sphx_glr_auto_examples_pyvista_grids.py` (``pyvista_grids.py``) + - 00:00.294 + - 0.0 diff --git a/_sources/changelog.md.txt b/_sources/changelog.md.txt new file mode 100644 index 0000000..a3343c9 --- /dev/null +++ b/_sources/changelog.md.txt @@ -0,0 +1,5 @@ +# Changelog + +## v2024.5.2 + +- First publicly available release diff --git a/_sources/contributing.md.txt b/_sources/contributing.md.txt new file mode 100644 index 0000000..b72f172 --- /dev/null +++ b/_sources/contributing.md.txt @@ -0,0 +1,76 @@ +# Contributing + +Contributions are welcome, and they are greatly appreciated! Every little bit +helps, and credit will always be given. + +## Developer Certificate of Origin + +``` +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` + +## Getting started + +1. Install the pre-commit hooks: `pre-commit install` +1. Checkout a feature branch `git checkout -b +1. When writing code, group changes logically into commits. Messy commits are + usually a result of excessive multitasking. If you work on one thing at a + time, then your commits will be cleaner. + 1. Name each commit "[imperative verb] [subject]" (e.g. "add earth2grid.some_modules"). Make sure it fits onto one line. + 1. Please provide context in the commit message. Start by explaining the + previous state of the code and why this needed changing. Focus on motivating + rather than explaining the changeset. + 1. run the test suite: `make unittest` + 1. run the docs: `make docs` +1. push the code to the repo `git push -u origin your-branch-name` and open an MR +1. ask for one reviewer. + +## Tips + + +## Deploying + +A reminder for the maintainers on how to deploy. +Make sure all your changes are committed (including an entry in CHANGELOG.md). +Then run: + +``` +$ poetry run bump2version patch # possible: major / minor / patch +$ git push +$ git push --tags +``` + +GitHub Actions will then deploy to PyPI if tests pass. diff --git a/_sources/index.rst.txt b/_sources/index.rst.txt new file mode 100644 index 0000000..a76e3e9 --- /dev/null +++ b/_sources/index.rst.txt @@ -0,0 +1,28 @@ +.. Earth2-Grid documentation master file, created by + sphinx-quickstart on Wed Feb 7 08:46:40 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to Earth2-Grid's documentation! +======================================= + +.. toctree:: + :maxdepth: 1 + :caption: Contents: + + installation.md + usage.md + api + changelog.md + contributing.md + auto_examples/index + + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/_sources/installation.md.txt b/_sources/installation.md.txt new file mode 100644 index 0000000..d1eda9d --- /dev/null +++ b/_sources/installation.md.txt @@ -0,0 +1,43 @@ +# Installation + +## Stable release + +To install Earth2 Grid Utilities, run this command in your +terminal: + +``` console +$ pip install earth2-grid +``` + +This is the preferred method to install Earth2 Grid Utilities, as it will always install the most recent stable release. + +If you don't have [pip][] installed, this [Python installation guide][] +can guide you through the process. + +## From source + +The source for Earth2 Grid Utilities can be downloaded from +the [Github repo][]. + +You can either clone the public repository: + +``` console +$ git clone git://github.com/waynerv/earth2-grid +``` + +Or download the [tarball][]: + +``` console +$ curl -OJL https://github.com/waynerv/earth2-grid/tarball/master +``` + +Once you have a copy of the source, you can install it with: + +``` console +$ pip install . +``` + + [pip]: https://pip.pypa.io + [Python installation guide]: http://docs.python-guide.org/en/latest/starting/installation/ + [Github repo]: https://github.com/%7B%7B%20cookiecutter.github_username%20%7D%7D/%7B%7B%20cookiecutter.project_slug%20%7D%7D + [tarball]: https://github.com/%7B%7B%20cookiecutter.github_username%20%7D%7D/%7B%7B%20cookiecutter.project_slug%20%7D%7D/tarball/master diff --git a/_sources/sg_execution_times.rst.txt b/_sources/sg_execution_times.rst.txt new file mode 100644 index 0000000..585cb62 --- /dev/null +++ b/_sources/sg_execution_times.rst.txt @@ -0,0 +1,43 @@ + +:orphan: + +.. _sphx_glr_sg_execution_times: + + +Computation times +================= +**00:02.679** total execution time for 3 files **from all galleries**: + +.. container:: + + .. raw:: html + + + + + + + + .. list-table:: + :header-rows: 1 + :class: table table-striped sg-datatable + + * - Example + - Time + - Mem (MB) + * - :ref:`sphx_glr_auto_examples_hpx2grid.py` (``../examples/sphinx_gallery/hpx2grid.py``) + - 00:01.719 + - 0.0 + * - :ref:`sphx_glr_auto_examples_latlon_to_healpix.py` (``../examples/sphinx_gallery/latlon_to_healpix.py``) + - 00:00.666 + - 0.0 + * - :ref:`sphx_glr_auto_examples_pyvista_grids.py` (``../examples/sphinx_gallery/pyvista_grids.py``) + - 00:00.294 + - 0.0 diff --git a/_sources/usage.md.txt b/_sources/usage.md.txt new file mode 100644 index 0000000..27b3493 --- /dev/null +++ b/_sources/usage.md.txt @@ -0,0 +1,18 @@ +# Usage + +To use Earth2 Grid Utilities in a project + +``` +import earth2grid +# level is the resolution +level = 6 +hpx = earth2grid.healpix.Grid(level=level, pixel_order=earth2grid.healpix.PixelOrder.XY) +src = earth2grid.latlon.equiangular_lat_lon_grid(32, 64) +z_torch = torch.as_tensor(z) +z_torch = torch.as_tensor(z) +regrid = earth2grid.get_regridder(src, hpx) +z_hpx = regrid(z_torch) +z_hpx.shape +nside = 2**level +reshaped = z_hpx.reshape(12, nside, nside) +``` diff --git a/_static/alabaster.css b/_static/alabaster.css new file mode 100644 index 0000000..517d0b2 --- /dev/null +++ b/_static/alabaster.css @@ -0,0 +1,703 @@ +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: Georgia, serif; + font-size: 17px; + background-color: #fff; + color: #000; + margin: 0; + padding: 0; +} + + +div.document { + width: 940px; + margin: 30px auto 0 auto; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 220px; +} + +div.sphinxsidebar { + width: 220px; + font-size: 14px; + line-height: 1.5; +} + +hr { + border: 1px solid #B1B4B6; +} + +div.body { + background-color: #fff; + color: #3E4349; + padding: 0 30px 0 30px; +} + +div.body > .section { + text-align: left; +} + +div.footer { + width: 940px; + margin: 20px auto 30px auto; + font-size: 14px; + color: #888; + text-align: right; +} + +div.footer a { + color: #888; +} + +p.caption { + font-family: inherit; + font-size: inherit; +} + + +div.relations { + display: none; +} + + +div.sphinxsidebar a { + color: #444; + text-decoration: none; + border-bottom: 1px dotted #999; +} + +div.sphinxsidebar a:hover { + border-bottom: 1px solid #999; +} + +div.sphinxsidebarwrapper { + padding: 18px 10px; +} + +div.sphinxsidebarwrapper p.logo { + padding: 0; + margin: -10px 0 0 0px; + text-align: center; +} + +div.sphinxsidebarwrapper h1.logo { + margin-top: -10px; + text-align: center; + margin-bottom: 5px; + text-align: left; +} + +div.sphinxsidebarwrapper h1.logo-name { + margin-top: 0px; +} + +div.sphinxsidebarwrapper p.blurb { + margin-top: 0; + font-style: normal; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: Georgia, serif; + color: #444; + font-size: 24px; + font-weight: normal; + margin: 0 0 5px 0; + padding: 0; +} + +div.sphinxsidebar h4 { + font-size: 20px; +} + +div.sphinxsidebar h3 a { + color: #444; +} + +div.sphinxsidebar p.logo a, +div.sphinxsidebar h3 a, +div.sphinxsidebar p.logo a:hover, +div.sphinxsidebar h3 a:hover { + border: none; +} + +div.sphinxsidebar p { + color: #555; + margin: 10px 0; +} + +div.sphinxsidebar ul { + margin: 10px 0; + padding: 0; + color: #000; +} + +div.sphinxsidebar ul li.toctree-l1 > a { + font-size: 120%; +} + +div.sphinxsidebar ul li.toctree-l2 > a { + font-size: 110%; +} + +div.sphinxsidebar input { + border: 1px solid #CCC; + font-family: Georgia, serif; + font-size: 1em; +} + +div.sphinxsidebar hr { + border: none; + height: 1px; + color: #AAA; + background: #AAA; + + text-align: left; + margin-left: 0; + width: 50%; +} + +div.sphinxsidebar .badge { + border-bottom: none; +} + +div.sphinxsidebar .badge:hover { + border-bottom: none; +} + +/* To address an issue with donation coming after search */ +div.sphinxsidebar h3.donation { + margin-top: 10px; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #004B6B; + text-decoration: underline; +} + +a:hover { + color: #6D4100; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: Georgia, serif; + font-weight: normal; + margin: 30px 0px 10px 0px; + padding: 0; +} + +div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } +div.body h2 { font-size: 180%; } +div.body h3 { font-size: 150%; } +div.body h4 { font-size: 130%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #DDD; + padding: 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + color: #444; + background: #EAEAEA; +} + +div.body p, div.body dd, div.body li { + line-height: 1.4em; +} + +div.admonition { + margin: 20px 0px; + padding: 10px 30px; + background-color: #EEE; + border: 1px solid #CCC; +} + +div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fafafa; +} + +div.admonition p.admonition-title { + font-family: Georgia, serif; + font-weight: normal; + font-size: 24px; + margin: 0 0 10px 0; + padding: 0; + line-height: 1; +} + +div.admonition p.last { + margin-bottom: 0; +} + +div.highlight { + background-color: #fff; +} + +dt:target, .highlight { + background: #FAF3E8; +} + +div.warning { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.danger { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.error { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.caution { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.attention { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.important { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.note { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.tip { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.hint { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.seealso { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.topic { + background-color: #EEE; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre, tt, code { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; + font-size: 0.9em; +} + +.hll { + background-color: #FFC; + margin: 0 -12px; + padding: 0 12px; + display: block; +} + +img.screenshot { +} + +tt.descname, tt.descclassname, code.descname, code.descclassname { + font-size: 0.95em; +} + +tt.descname, code.descname { + padding-right: 0.08em; +} + +img.screenshot { + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils { + border: 1px solid #888; + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils td, table.docutils th { + border: 1px solid #888; + padding: 0.25em 0.7em; +} + +table.field-list, table.footnote { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.footnote { + margin: 15px 0; + width: 100%; + border: 1px solid #EEE; + background: #FDFDFD; + font-size: 0.9em; +} + +table.footnote + table.footnote { + margin-top: -15px; + border-top: none; +} + +table.field-list th { + padding: 0 0.8em 0 0; +} + +table.field-list td { + padding: 0; +} + +table.field-list p { + margin-bottom: 0.8em; +} + +/* Cloned from + * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 + */ +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +table.footnote td.label { + width: .1px; + padding: 0.3em 0 0.3em 0.5em; +} + +table.footnote td { + padding: 0.3em 0.5em; +} + +dl { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding: 0; +} + +dl dd { + margin-left: 30px; +} + +blockquote { + margin: 0 0 0 30px; + padding: 0; +} + +ul, ol { + /* Matches the 30px from the narrow-screen "li > ul" selector below */ + margin: 10px 0 10px 30px; + padding: 0; +} + +pre { + background: #EEE; + padding: 7px 30px; + margin: 15px 0px; + line-height: 1.3em; +} + +div.viewcode-block:target { + background: #ffd; +} + +dl pre, blockquote pre, li pre { + margin-left: 0; + padding-left: 30px; +} + +tt, code { + background-color: #ecf0f3; + color: #222; + /* padding: 1px 2px; */ +} + +tt.xref, code.xref, a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fff; +} + +a.reference { + text-decoration: none; + border-bottom: 1px dotted #004B6B; +} + +/* Don't put an underline on images */ +a.image-reference, a.image-reference:hover { + border-bottom: none; +} + +a.reference:hover { + border-bottom: 1px solid #6D4100; +} + +a.footnote-reference { + text-decoration: none; + font-size: 0.7em; + vertical-align: top; + border-bottom: 1px dotted #004B6B; +} + +a.footnote-reference:hover { + border-bottom: 1px solid #6D4100; +} + +a:hover tt, a:hover code { + background: #EEE; +} + + +@media screen and (max-width: 870px) { + + div.sphinxsidebar { + display: none; + } + + div.document { + width: 100%; + + } + + div.documentwrapper { + margin-left: 0; + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + } + + div.bodywrapper { + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + margin-left: 0; + } + + ul { + margin-left: 0; + } + + li > ul { + /* Matches the 30px from the "ul, ol" selector above */ + margin-left: 30px; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .bodywrapper { + margin: 0; + } + + .footer { + width: auto; + } + + .github { + display: none; + } + + + +} + + + +@media screen and (max-width: 875px) { + + body { + margin: 0; + padding: 20px 30px; + } + + div.documentwrapper { + float: none; + background: #fff; + } + + div.sphinxsidebar { + display: block; + float: none; + width: 102.5%; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: #FFF; + } + + div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, + div.sphinxsidebar h3 a { + color: #fff; + } + + div.sphinxsidebar a { + color: #AAA; + } + + div.sphinxsidebar p.logo { + display: none; + } + + div.document { + width: 100%; + margin: 0; + } + + div.footer { + display: none; + } + + div.bodywrapper { + margin: 0; + } + + div.body { + min-height: 0; + padding: 0; + } + + .rtd_doc_footer { + display: none; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .footer { + width: auto; + } + + .github { + display: none; + } +} + + +/* misc. */ + +.revsys-inline { + display: none!important; +} + +/* Make nested-list/multi-paragraph items look better in Releases changelog + * pages. Without this, docutils' magical list fuckery causes inconsistent + * formatting between different release sub-lists. + */ +div#changelog > div.section > ul > li > p:only-child { + margin-bottom: 0; +} + +/* Hide fugly table cell borders in ..bibliography:: directive output */ +table.docutils.citation, table.docutils.citation td, table.docutils.citation th { + border: none; + /* Below needed in some edge cases; if not applied, bottom shadows appear */ + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + + +/* relbar */ + +.related { + line-height: 30px; + width: 100%; + font-size: 0.9rem; +} + +.related.top { + border-bottom: 1px solid #EEE; + margin-bottom: 20px; +} + +.related.bottom { + border-top: 1px solid #EEE; +} + +.related ul { + padding: 0; + margin: 0; + list-style: none; +} + +.related li { + display: inline; +} + +nav#rellinks { + float: right; +} + +nav#rellinks li+li:before { + content: "|"; +} + +nav#breadcrumbs li+li:before { + content: "\00BB"; +} + +/* Hide certain items when printing */ +@media print { + div.related { + display: none; + } +} \ No newline at end of file diff --git a/_static/basic.css b/_static/basic.css new file mode 100644 index 0000000..7577acb --- /dev/null +++ b/_static/basic.css @@ -0,0 +1,903 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/_static/binder_badge_logo.svg b/_static/binder_badge_logo.svg new file mode 100644 index 0000000..327f6b6 --- /dev/null +++ b/_static/binder_badge_logo.svg @@ -0,0 +1 @@ + launchlaunchbinderbinder \ No newline at end of file diff --git a/_static/broken_example.png b/_static/broken_example.png new file mode 100644 index 0000000..4fea24e Binary files /dev/null and b/_static/broken_example.png differ diff --git a/_static/custom.css b/_static/custom.css new file mode 100644 index 0000000..2a924f1 --- /dev/null +++ b/_static/custom.css @@ -0,0 +1 @@ +/* This file intentionally left blank. */ diff --git a/_static/doctools.js b/_static/doctools.js new file mode 100644 index 0000000..d06a71d --- /dev/null +++ b/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/_static/documentation_options.js b/_static/documentation_options.js new file mode 100644 index 0000000..b57ae3b --- /dev/null +++ b/_static/documentation_options.js @@ -0,0 +1,14 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/_static/file.png b/_static/file.png new file mode 100644 index 0000000..a858a41 Binary files /dev/null and b/_static/file.png differ diff --git a/_static/jupyterlite_badge_logo.svg b/_static/jupyterlite_badge_logo.svg new file mode 100644 index 0000000..5de36d7 --- /dev/null +++ b/_static/jupyterlite_badge_logo.svg @@ -0,0 +1,3 @@ + + +launchlaunchlitelite \ No newline at end of file diff --git a/_static/language_data.js b/_static/language_data.js new file mode 100644 index 0000000..250f566 --- /dev/null +++ b/_static/language_data.js @@ -0,0 +1,199 @@ +/* + * language_data.js + * ~~~~~~~~~~~~~~~~ + * + * This script contains the language-specific data used by searchtools.js, + * namely the list of stopwords, stemmer, scorer and splitter. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; + + +/* Non-minified version is copied as a separate JS file, is available */ + +/** + * Porter Stemmer + */ +var Stemmer = function() { + + var step2list = { + ational: 'ate', + tional: 'tion', + enci: 'ence', + anci: 'ance', + izer: 'ize', + bli: 'ble', + alli: 'al', + entli: 'ent', + eli: 'e', + ousli: 'ous', + ization: 'ize', + ation: 'ate', + ator: 'ate', + alism: 'al', + iveness: 'ive', + fulness: 'ful', + ousness: 'ous', + aliti: 'al', + iviti: 'ive', + biliti: 'ble', + logi: 'log' + }; + + var step3list = { + icate: 'ic', + ative: '', + alize: 'al', + iciti: 'ic', + ical: 'ic', + ful: '', + ness: '' + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + diff --git a/_static/minus.png b/_static/minus.png new file mode 100644 index 0000000..d96755f Binary files /dev/null and b/_static/minus.png differ diff --git a/_static/no_image.png b/_static/no_image.png new file mode 100644 index 0000000..8c2d48d Binary files /dev/null and b/_static/no_image.png differ diff --git a/_static/plus.png b/_static/plus.png new file mode 100644 index 0000000..7107cec Binary files /dev/null and b/_static/plus.png differ diff --git a/_static/pygments.css b/_static/pygments.css new file mode 100644 index 0000000..57c7df3 --- /dev/null +++ b/_static/pygments.css @@ -0,0 +1,84 @@ +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f8f8f8; } +.highlight .c { color: #8f5902; font-style: italic } /* Comment */ +.highlight .err { color: #a40000; border: 1px solid #ef2929 } /* Error */ +.highlight .g { color: #000000 } /* Generic */ +.highlight .k { color: #004461; font-weight: bold } /* Keyword */ +.highlight .l { color: #000000 } /* Literal */ +.highlight .n { color: #000000 } /* Name */ +.highlight .o { color: #582800 } /* Operator */ +.highlight .x { color: #000000 } /* Other */ +.highlight .p { color: #000000; font-weight: bold } /* Punctuation */ +.highlight .ch { color: #8f5902; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #8f5902; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #8f5902 } /* Comment.Preproc */ +.highlight .cpf { color: #8f5902; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #8f5902; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #8f5902; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #a40000 } /* Generic.Deleted */ +.highlight .ge { color: #000000; font-style: italic } /* Generic.Emph */ +.highlight .ges { color: #000000 } /* Generic.EmphStrong */ +.highlight .gr { color: #ef2929 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #888888 } /* Generic.Output */ +.highlight .gp { color: #745334 } /* Generic.Prompt */ +.highlight .gs { color: #000000; font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #a40000; font-weight: bold } /* Generic.Traceback */ +.highlight .kc { color: #004461; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #004461; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #004461; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #004461; font-weight: bold } /* Keyword.Pseudo */ +.highlight .kr { color: #004461; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #004461; font-weight: bold } /* Keyword.Type */ +.highlight .ld { color: #000000 } /* Literal.Date */ +.highlight .m { color: #990000 } /* Literal.Number */ +.highlight .s { color: #4e9a06 } /* Literal.String */ +.highlight .na { color: #c4a000 } /* Name.Attribute */ +.highlight .nb { color: #004461 } /* Name.Builtin */ +.highlight .nc { color: #000000 } /* Name.Class */ +.highlight .no { color: #000000 } /* Name.Constant */ +.highlight .nd { color: #888888 } /* Name.Decorator */ +.highlight .ni { color: #ce5c00 } /* Name.Entity */ +.highlight .ne { color: #cc0000; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #000000 } /* Name.Function */ +.highlight .nl { color: #f57900 } /* Name.Label */ +.highlight .nn { color: #000000 } /* Name.Namespace */ +.highlight .nx { color: #000000 } /* Name.Other */ +.highlight .py { color: #000000 } /* Name.Property */ +.highlight .nt { color: #004461; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #000000 } /* Name.Variable */ +.highlight .ow { color: #004461; font-weight: bold } /* Operator.Word */ +.highlight .pm { color: #000000; font-weight: bold } /* Punctuation.Marker */ +.highlight .w { color: #f8f8f8; text-decoration: underline } /* Text.Whitespace */ +.highlight .mb { color: #990000 } /* Literal.Number.Bin */ +.highlight .mf { color: #990000 } /* Literal.Number.Float */ +.highlight .mh { color: #990000 } /* Literal.Number.Hex */ +.highlight .mi { color: #990000 } /* Literal.Number.Integer */ +.highlight .mo { color: #990000 } /* Literal.Number.Oct */ +.highlight .sa { color: #4e9a06 } /* Literal.String.Affix */ +.highlight .sb { color: #4e9a06 } /* Literal.String.Backtick */ +.highlight .sc { color: #4e9a06 } /* Literal.String.Char */ +.highlight .dl { color: #4e9a06 } /* Literal.String.Delimiter */ +.highlight .sd { color: #8f5902; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4e9a06 } /* Literal.String.Double */ +.highlight .se { color: #4e9a06 } /* Literal.String.Escape */ +.highlight .sh { color: #4e9a06 } /* Literal.String.Heredoc */ +.highlight .si { color: #4e9a06 } /* Literal.String.Interpol */ +.highlight .sx { color: #4e9a06 } /* Literal.String.Other */ +.highlight .sr { color: #4e9a06 } /* Literal.String.Regex */ +.highlight .s1 { color: #4e9a06 } /* Literal.String.Single */ +.highlight .ss { color: #4e9a06 } /* Literal.String.Symbol */ +.highlight .bp { color: #3465a4 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #000000 } /* Name.Function.Magic */ +.highlight .vc { color: #000000 } /* Name.Variable.Class */ +.highlight .vg { color: #000000 } /* Name.Variable.Global */ +.highlight .vi { color: #000000 } /* Name.Variable.Instance */ +.highlight .vm { color: #000000 } /* Name.Variable.Magic */ +.highlight .il { color: #990000 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/_static/searchtools.js b/_static/searchtools.js new file mode 100644 index 0000000..97d56a7 --- /dev/null +++ b/_static/searchtools.js @@ -0,0 +1,566 @@ +/* + * searchtools.js + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for the full-text search. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _displayItem = (item, searchTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + + const [docName, title, anchor, descr, score, _filename] = item; + + let listItem = document.createElement("li"); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = docUrlRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = docUrlRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) + listItem.appendChild(document.createElement("span")).innerHTML = + " (" + descr + ")"; + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms) + ); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." + ); + else + Search.status.innerText = _( + `Search finished, found ${resultCount} page(s) matching the search query.` + ); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms), + 5 + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter(term => term) // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() }); + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent !== undefined) return docContent.textContent; + console.warn( + "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template." + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + /** + * execute search (requires search index to be loaded) + */ + query: (query) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords array is from language_data.js + if ( + stopwords.indexOf(queryTermLower) !== -1 || + queryTerm.match(/^\d+$/) + ) + return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js + localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + // array of [docname, title, anchor, descr, score, filename] + let results = []; + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) { + for (const [file, id] of foundTitles) { + let score = Math.round(100 * queryLower.length / title.length) + results.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { + for (const [file, id] of foundEntries) { + let score = Math.round(100 * queryLower.length / entry.length) + results.push([ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // lookup as object + objectTerms.forEach((term) => + results.push(...Search.performObjectSearch(term, objectTerms)) + ); + + // lookup as search terms in fulltext + results.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item))); + + // now sort the results by score (in opposite order of appearance, since the + // display function below uses pop() to retrieve items) and then + // alphabetically + results.sort((a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; + }); + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + results = results.reverse(); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4] + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => + objectSearchCallback(prefix, array) + ) + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + const arr = [ + { files: terms[word], score: Scorer.term }, + { files: titleTerms[word], score: Scorer.title }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord) && !terms[word]) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord) && !titleTerms[word]) + arr.push({ files: titleTerms[word], score: Scorer.partialTitle }); + }); + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, {}); + scoreMap.get(file)[word] = record.score; + }); + }); + + // create the mapping + files.forEach((file) => { + if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1) + fileMap.get(file).push(word); + else fileMap.set(file, [word]); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2 + ).length; + if ( + wordList.length !== searchTerms.size && + wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file || + titleTerms[term] === file || + (terms[term] || []).includes(file) || + (titleTerms[term] || []).includes(file) + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords) => { + const text = Search.htmlToText(htmlText); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/_static/sg_gallery-binder.css b/_static/sg_gallery-binder.css new file mode 100644 index 0000000..420005d --- /dev/null +++ b/_static/sg_gallery-binder.css @@ -0,0 +1,11 @@ +/* CSS for binder integration */ + +div.binder-badge { + margin: 1em auto; + vertical-align: middle; +} + +div.lite-badge { + margin: 1em auto; + vertical-align: middle; +} diff --git a/_static/sg_gallery-dataframe.css b/_static/sg_gallery-dataframe.css new file mode 100644 index 0000000..fac74c4 --- /dev/null +++ b/_static/sg_gallery-dataframe.css @@ -0,0 +1,47 @@ +/* Pandas dataframe css */ +/* Taken from: https://github.com/spatialaudio/nbsphinx/blob/fb3ba670fc1ba5f54d4c487573dbc1b4ecf7e9ff/src/nbsphinx.py#L587-L619 */ +html[data-theme="light"] { + --sg-text-color: #000; + --sg-tr-odd-color: #f5f5f5; + --sg-tr-hover-color: rgba(66, 165, 245, 0.2); +} +html[data-theme="dark"] { + --sg-text-color: #fff; + --sg-tr-odd-color: #373737; + --sg-tr-hover-color: rgba(30, 81, 122, 0.2); +} + +table.dataframe { + border: none !important; + border-collapse: collapse; + border-spacing: 0; + border-color: transparent; + color: var(--sg-text-color); + font-size: 12px; + table-layout: fixed; + width: auto; +} +table.dataframe thead { + border-bottom: 1px solid var(--sg-text-color); + vertical-align: bottom; +} +table.dataframe tr, +table.dataframe th, +table.dataframe td { + text-align: right; + vertical-align: middle; + padding: 0.5em 0.5em; + line-height: normal; + white-space: normal; + max-width: none; + border: none; +} +table.dataframe th { + font-weight: bold; +} +table.dataframe tbody tr:nth-child(odd) { + background: var(--sg-tr-odd-color); +} +table.dataframe tbody tr:hover { + background: var(--sg-tr-hover-color); +} diff --git a/_static/sg_gallery-rendered-html.css b/_static/sg_gallery-rendered-html.css new file mode 100644 index 0000000..93dc2ff --- /dev/null +++ b/_static/sg_gallery-rendered-html.css @@ -0,0 +1,224 @@ +/* Adapted from notebook/static/style/style.min.css */ +html[data-theme="light"] { + --sg-text-color: #000; + --sg-background-color: #ffffff; + --sg-code-background-color: #eff0f1; + --sg-tr-hover-color: rgba(66, 165, 245, 0.2); + --sg-tr-odd-color: #f5f5f5; +} +html[data-theme="dark"] { + --sg-text-color: #fff; + --sg-background-color: #121212; + --sg-code-background-color: #2f2f30; + --sg-tr-hover-color: rgba(66, 165, 245, 0.2); + --sg-tr-odd-color: #1f1f1f; +} + +.rendered_html { + color: var(--sg-text-color); + /* any extras will just be numbers: */ +} +.rendered_html em { + font-style: italic; +} +.rendered_html strong { + font-weight: bold; +} +.rendered_html u { + text-decoration: underline; +} +.rendered_html :link { + text-decoration: underline; +} +.rendered_html :visited { + text-decoration: underline; +} +.rendered_html h1 { + font-size: 185.7%; + margin: 1.08em 0 0 0; + font-weight: bold; + line-height: 1.0; +} +.rendered_html h2 { + font-size: 157.1%; + margin: 1.27em 0 0 0; + font-weight: bold; + line-height: 1.0; +} +.rendered_html h3 { + font-size: 128.6%; + margin: 1.55em 0 0 0; + font-weight: bold; + line-height: 1.0; +} +.rendered_html h4 { + font-size: 100%; + margin: 2em 0 0 0; + font-weight: bold; + line-height: 1.0; +} +.rendered_html h5 { + font-size: 100%; + margin: 2em 0 0 0; + font-weight: bold; + line-height: 1.0; + font-style: italic; +} +.rendered_html h6 { + font-size: 100%; + margin: 2em 0 0 0; + font-weight: bold; + line-height: 1.0; + font-style: italic; +} +.rendered_html h1:first-child { + margin-top: 0.538em; +} +.rendered_html h2:first-child { + margin-top: 0.636em; +} +.rendered_html h3:first-child { + margin-top: 0.777em; +} +.rendered_html h4:first-child { + margin-top: 1em; +} +.rendered_html h5:first-child { + margin-top: 1em; +} +.rendered_html h6:first-child { + margin-top: 1em; +} +.rendered_html ul:not(.list-inline), +.rendered_html ol:not(.list-inline) { + padding-left: 2em; +} +.rendered_html ul { + list-style: disc; +} +.rendered_html ul ul { + list-style: square; + margin-top: 0; +} +.rendered_html ul ul ul { + list-style: circle; +} +.rendered_html ol { + list-style: decimal; +} +.rendered_html ol ol { + list-style: upper-alpha; + margin-top: 0; +} +.rendered_html ol ol ol { + list-style: lower-alpha; +} +.rendered_html ol ol ol ol { + list-style: lower-roman; +} +.rendered_html ol ol ol ol ol { + list-style: decimal; +} +.rendered_html * + ul { + margin-top: 1em; +} +.rendered_html * + ol { + margin-top: 1em; +} +.rendered_html hr { + color: var(--sg-text-color); + background-color: var(--sg-text-color); +} +.rendered_html pre { + margin: 1em 2em; + padding: 0px; + background-color: var(--sg-background-color); +} +.rendered_html code { + background-color: var(--sg-code-background-color); +} +.rendered_html p code { + padding: 1px 5px; +} +.rendered_html pre code { + background-color: var(--sg-background-color); +} +.rendered_html pre, +.rendered_html code { + border: 0; + color: var(--sg-text-color); + font-size: 100%; +} +.rendered_html blockquote { + margin: 1em 2em; +} +.rendered_html table { + margin-left: auto; + margin-right: auto; + border: none; + border-collapse: collapse; + border-spacing: 0; + color: var(--sg-text-color); + font-size: 12px; + table-layout: fixed; +} +.rendered_html thead { + border-bottom: 1px solid var(--sg-text-color); + vertical-align: bottom; +} +.rendered_html tr, +.rendered_html th, +.rendered_html td { + text-align: right; + vertical-align: middle; + padding: 0.5em 0.5em; + line-height: normal; + white-space: normal; + max-width: none; + border: none; +} +.rendered_html th { + font-weight: bold; +} +.rendered_html tbody tr:nth-child(odd) { + background: var(--sg-tr-odd-color); +} +.rendered_html tbody tr:hover { + color: var(--sg-text-color); + background: var(--sg-tr-hover-color); +} +.rendered_html * + table { + margin-top: 1em; +} +.rendered_html p { + text-align: left; +} +.rendered_html * + p { + margin-top: 1em; +} +.rendered_html img { + display: block; + margin-left: auto; + margin-right: auto; +} +.rendered_html * + img { + margin-top: 1em; +} +.rendered_html img, +.rendered_html svg { + max-width: 100%; + height: auto; +} +.rendered_html img.unconfined, +.rendered_html svg.unconfined { + max-width: none; +} +.rendered_html .alert { + margin-bottom: initial; +} +.rendered_html * + .alert { + margin-top: 1em; +} +[dir="rtl"] .rendered_html p { + text-align: right; +} diff --git a/_static/sg_gallery.css b/_static/sg_gallery.css new file mode 100644 index 0000000..7222783 --- /dev/null +++ b/_static/sg_gallery.css @@ -0,0 +1,342 @@ +/* +Sphinx-Gallery has compatible CSS to fix default sphinx themes +Tested for Sphinx 1.3.1 for all themes: default, alabaster, sphinxdoc, +scrolls, agogo, traditional, nature, haiku, pyramid +Tested for Read the Docs theme 0.1.7 */ + +/* Define light colors */ +:root, html[data-theme="light"], body[data-theme="light"]{ + --sg-tooltip-foreground: black; + --sg-tooltip-background: rgba(250, 250, 250, 0.9); + --sg-tooltip-border: #ccc transparent; + --sg-thumb-box-shadow-color: #6c757d40; + --sg-thumb-hover-border: #0069d9; + --sg-script-out: #888; + --sg-script-pre: #fafae2; + --sg-pytb-foreground: #000; + --sg-pytb-background: #ffe4e4; + --sg-pytb-border-color: #f66; + --sg-download-a-background-color: #ffc; + --sg-download-a-background-image: linear-gradient(to bottom, #ffc, #d5d57e); + --sg-download-a-border-color: 1px solid #c2c22d; + --sg-download-a-color: #000; + --sg-download-a-hover-background-color: #d5d57e; + --sg-download-a-hover-box-shadow-1: rgba(255, 255, 255, 0.1); + --sg-download-a-hover-box-shadow-2: rgba(0, 0, 0, 0.25); +} +@media(prefers-color-scheme: light) { + :root[data-theme="auto"], html[data-theme="auto"], body[data-theme="auto"] { + --sg-tooltip-foreground: black; + --sg-tooltip-background: rgba(250, 250, 250, 0.9); + --sg-tooltip-border: #ccc transparent; + --sg-thumb-box-shadow-color: #6c757d40; + --sg-thumb-hover-border: #0069d9; + --sg-script-out: #888; + --sg-script-pre: #fafae2; + --sg-pytb-foreground: #000; + --sg-pytb-background: #ffe4e4; + --sg-pytb-border-color: #f66; + --sg-download-a-background-color: #ffc; + --sg-download-a-background-image: linear-gradient(to bottom, #ffc, #d5d57e); + --sg-download-a-border-color: 1px solid #c2c22d; + --sg-download-a-color: #000; + --sg-download-a-hover-background-color: #d5d57e; + --sg-download-a-hover-box-shadow-1: rgba(255, 255, 255, 0.1); + --sg-download-a-hover-box-shadow-2: rgba(0, 0, 0, 0.25); + } +} + +html[data-theme="dark"], body[data-theme="dark"] { + --sg-tooltip-foreground: white; + --sg-tooltip-background: rgba(10, 10, 10, 0.9); + --sg-tooltip-border: #333 transparent; + --sg-thumb-box-shadow-color: #79848d40; + --sg-thumb-hover-border: #003975; + --sg-script-out: rgb(179, 179, 179); + --sg-script-pre: #2e2e22; + --sg-pytb-foreground: #fff; + --sg-pytb-background: #1b1717; + --sg-pytb-border-color: #622; + --sg-download-a-background-color: #443; + --sg-download-a-background-image: linear-gradient(to bottom, #443, #221); + --sg-download-a-border-color: 1px solid #3a3a0d; + --sg-download-a-color: #fff; + --sg-download-a-hover-background-color: #616135; + --sg-download-a-hover-box-shadow-1: rgba(0, 0, 0, 0.1); + --sg-download-a-hover-box-shadow-2: rgba(255, 255, 255, 0.25); +} +@media(prefers-color-scheme: dark){ + html[data-theme="auto"], body[data-theme="auto"] { + --sg-tooltip-foreground: white; + --sg-tooltip-background: rgba(10, 10, 10, 0.9); + --sg-tooltip-border: #333 transparent; + --sg-thumb-box-shadow-color: #79848d40; + --sg-thumb-hover-border: #003975; + --sg-script-out: rgb(179, 179, 179); + --sg-script-pre: #2e2e22; + --sg-pytb-foreground: #fff; + --sg-pytb-background: #1b1717; + --sg-pytb-border-color: #622; + --sg-download-a-background-color: #443; + --sg-download-a-background-image: linear-gradient(to bottom, #443, #221); + --sg-download-a-border-color: 1px solid #3a3a0d; + --sg-download-a-color: #fff; + --sg-download-a-hover-background-color: #616135; + --sg-download-a-hover-box-shadow-1: rgba(0, 0, 0, 0.1); + --sg-download-a-hover-box-shadow-2: rgba(255, 255, 255, 0.25); + } +} + +.sphx-glr-thumbnails { + width: 100%; + margin: 0px 0px 20px 0px; + + /* align thumbnails on a grid */ + justify-content: space-between; + display: grid; + /* each grid column should be at least 160px (this will determine + the actual number of columns) and then take as much of the + remaining width as possible */ + grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); + gap: 15px; +} +.sphx-glr-thumbnails .toctree-wrapper { + /* hide empty toctree divs added to the DOM + by sphinx even though the toctree is hidden + (they would fill grid places with empty divs) */ + display: none; +} +.sphx-glr-thumbcontainer { + background: transparent; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; + box-shadow: 0 0 10px var(--sg-thumb-box-shadow-color); + + /* useful to absolutely position link in div */ + position: relative; + + /* thumbnail width should include padding and borders + and take all available space */ + box-sizing: border-box; + width: 100%; + padding: 10px; + border: 1px solid transparent; + + /* align content in thumbnail */ + display: flex; + flex-direction: column; + align-items: center; + gap: 7px; +} +.sphx-glr-thumbcontainer p { + position: absolute; + top: 0; + left: 0; +} +.sphx-glr-thumbcontainer p, +.sphx-glr-thumbcontainer p a { + /* link should cover the whole thumbnail div */ + width: 100%; + height: 100%; +} +.sphx-glr-thumbcontainer p a span { + /* text within link should be masked + (we are just interested in the href) */ + display: none; +} +.sphx-glr-thumbcontainer:hover { + border: 1px solid; + border-color: var(--sg-thumb-hover-border); + cursor: pointer; +} +.sphx-glr-thumbcontainer a.internal { + bottom: 0; + display: block; + left: 0; + box-sizing: border-box; + padding: 150px 10px 0; + position: absolute; + right: 0; + top: 0; +} +/* Next one is to avoid Sphinx traditional theme to cover all the +thumbnail with its default link Background color */ +.sphx-glr-thumbcontainer a.internal:hover { + background-color: transparent; +} + +.sphx-glr-thumbcontainer p { + margin: 0 0 0.1em 0; +} +.sphx-glr-thumbcontainer .figure { + margin: 10px; + width: 160px; +} +.sphx-glr-thumbcontainer img { + display: inline; + max-height: 112px; + max-width: 160px; +} +.sphx-glr-thumbcontainer[tooltip]:hover:after { + background: var(--sg-tooltip-background); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + color: var(--sg-tooltip-foreground); + content: attr(tooltip); + padding: 10px; + z-index: 98; + width: 100%; + height: 100%; + position: absolute; + pointer-events: none; + top: 0; + box-sizing: border-box; + overflow: hidden; + backdrop-filter: blur(3px); +} + +.sphx-glr-script-out { + color: var(--sg-script-out); + display: flex; + gap: 0.5em; +} +.sphx-glr-script-out::before { + content: "Out:"; + /* These numbers come from the pre style in the pydata sphinx theme. This + * turns out to match perfectly on the rtd theme, but be a bit too low for + * the pydata sphinx theme. As I could not find a dimension to use that was + * scaled the same way, I just picked one option that worked pretty close for + * both. */ + line-height: 1.4; + padding-top: 10px; +} +.sphx-glr-script-out .highlight { + background-color: transparent; + /* These options make the div expand... */ + flex-grow: 1; + /* ... but also keep it from overflowing its flex container. */ + overflow: auto; +} +.sphx-glr-script-out .highlight pre { + background-color: var(--sg-script-pre); + border: 0; + max-height: 30em; + overflow: auto; + padding-left: 1ex; + /* This margin is necessary in the pydata sphinx theme because pre has a box + * shadow which would be clipped by the overflow:auto in the parent div + * above. */ + margin: 2px; + word-break: break-word; +} +.sphx-glr-script-out + p { + margin-top: 1.8em; +} +blockquote.sphx-glr-script-out { + margin-left: 0pt; +} +.sphx-glr-script-out.highlight-pytb .highlight pre { + color: var(--sg-pytb-foreground); + background-color: var(--sg-pytb-background); + border: 1px solid var(--sg-pytb-border-color); + margin-top: 10px; + padding: 7px; +} + +div.sphx-glr-footer { + text-align: center; +} + +div.sphx-glr-download { + margin: 1em auto; + vertical-align: middle; +} + +div.sphx-glr-download a { + background-color: var(--sg-download-a-background-color); + background-image: var(--sg-download-a-background-image); + border-radius: 4px; + border: 1px solid var(--sg-download-a-border-color); + color: var(--sg-download-a-color); + display: inline-block; + font-weight: bold; + padding: 1ex; + text-align: center; +} + +div.sphx-glr-download code.download { + display: inline-block; + white-space: normal; + word-break: normal; + overflow-wrap: break-word; + /* border and background are given by the enclosing 'a' */ + border: none; + background: none; +} + +div.sphx-glr-download a:hover { + box-shadow: inset 0 1px 0 var(--sg-download-a-hover-box-shadow-1), 0 1px 5px var(--sg-download-a-hover-box-shadow-2); + text-decoration: none; + background-image: none; + background-color: var(--sg-download-a-hover-background-color); +} + +.sphx-glr-example-title:target::before { + display: block; + content: ""; + margin-top: -50px; + height: 50px; + visibility: hidden; +} + +ul.sphx-glr-horizontal { + list-style: none; + padding: 0; +} +ul.sphx-glr-horizontal li { + display: inline; +} +ul.sphx-glr-horizontal img { + height: auto !important; +} + +.sphx-glr-single-img { + margin: auto; + display: block; + max-width: 100%; +} + +.sphx-glr-multi-img { + max-width: 42%; + height: auto; +} + +div.sphx-glr-animation { + margin: auto; + display: block; + max-width: 100%; +} +div.sphx-glr-animation .animation { + display: block; +} + +p.sphx-glr-signature a.reference.external { + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; + padding: 3px; + font-size: 75%; + text-align: right; + margin-left: auto; + display: table; +} + +.sphx-glr-clear { + clear: both; +} + +a.sphx-glr-backref-instance { + text-decoration: none; +} diff --git a/_static/sphinx_highlight.js b/_static/sphinx_highlight.js new file mode 100644 index 0000000..aae669d --- /dev/null +++ b/_static/sphinx_highlight.js @@ -0,0 +1,144 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + parent.insertBefore( + span, + parent.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms") + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + + // get individual terms from highlight string + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(SphinxHighlight.highlightSearchWords); +_ready(SphinxHighlight.initEscapeListener); diff --git a/api.html b/api.html new file mode 100644 index 0000000..a2bb72d --- /dev/null +++ b/api.html @@ -0,0 +1,222 @@ + + + + + + + + + API — Earth2-Grid documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

API

+
+

Grids

+
+
+class earth2grid.healpix.Grid(level: int, pixel_order: PixelOrder | XY = PixelOrder.RING)
+

Bases: Grid

+

A Healpix Grid

+
+
Attrs:

level: 2^level = nside +pixel_order: the ordering convection of the data

+
+
+
+
+get_bilinear_regridder_to(lat: ndarray, lon: ndarray)
+

Get regridder to the specified lat and lon points

+
+ +
+
+reorder(order: PixelOrder | XY, x: Tensor) Tensor
+

Rorder the pixels of x to have order

+
+ +
+
+to_image(x: Tensor, fill_value=nan) Tensor
+

Use the 45 degree rotated grid pixelation +i points to SE, j point to NE

+
+ +
+ +
+
+class earth2grid.latlon.LatLonGrid(lat: list[float], lon: list[float])
+

Bases: Grid

+
+
+get_bilinear_regridder_to(lat: ndarray, lon: ndarray)
+

Get regridder to the specified lat and lon points

+
+ +
+ +
+
+earth2grid.latlon.equiangular_lat_lon_grid(nlat: int, nlon: int, includes_south_pole: bool = True) LatLonGrid
+

Return a regular lat-lon grid

+

Lat is ordered from 90 to -90. Includes -90 and only if if includes_south_pole is True. +Lon is ordered from 0 to 360. includes 0, but not 360.

+
+
Parameters:
+
    +
  • nlat – number of latitude points

  • +
  • nlon – number of longtidue points

  • +
  • includes_south_pole – if true the final nlat includes the south pole

  • +
+
+
+
+ +
+
+

Regridding

+
+
+earth2grid.get_regridder(src: Grid, dest: Grid) Module
+

Get a regridder from src to dest

+
+ +
+
+

Other utilities

+
+
+earth2grid.healpix.pad(x: Tensor, padding: int) Tensor
+

Pad each face consistently with its according neighbors in the HEALPix

+
+
Parameters:
+
    +
  • x – The input tensor of shape [N, F, H, W]

  • +
  • padding – the amount of padding

  • +
+
+
Returns:
+

The padded tensor with shape [N, F, H+2*padding, W+2*padding]

+
+
+

Examples

+

Ths example show to pad data described by a Grid object.

+
>>> grid = Grid(level=4, pixel_order=PixelOrder.RING)
+>>> lon = torch.from_numpy(grid.lon)
+>>> faces = grid.reorder(HEALPIX_PAD_XY, lon)
+>>> faces = faces.view(1, 12, grid._nside(), grid._nside())
+>>> faces.shape
+torch.Size([1, 12, 16, 16])
+>>> padded = pad(faces, padding=1)
+>>> padded.shape
+torch.Size([1, 12, 18, 18])
+
+
+
+ +
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/auto_examples/hpx2grid.html b/auto_examples/hpx2grid.html new file mode 100644 index 0000000..14a7a3b --- /dev/null +++ b/auto_examples/hpx2grid.html @@ -0,0 +1,165 @@ + + + + + + + + + HealPIX Image visualization — Earth2-Grid documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + +
+

HealPIX Image visualization

+

HealPIX maps can be viewed as a 2D image rotated by 45 deg. This is useful for +quick visualization with image viewers without distorting the native pixels of +the image.

+
import matplotlib.pyplot as plt
+import numpy as np
+import torch
+
+
+
from matplotlib.colors import Normalize
+from PIL import Image
+
+from earth2grid.healpix import Grid
+
+grid = Grid(level=8)
+lat = torch.tensor(grid.lat)
+lat_img = grid.to_image(lat)
+
+# Use Image to save at full resolution
+normalizer = Normalize(vmin=np.nanmin(lat_img), vmax=np.nanmax(lat_img))
+array = normalizer(lat_img)
+array = plt.cm.viridis(array)
+array = (256 * array).astype("uint8")
+# set transparency for nans
+array[..., -1] = np.where(np.isnan(lat_img), 0, 255)
+image = Image.fromarray(array)
+image.save("hpx_grid.png")
+
+
+hpx2grid
Warning, cannot find healpixpad module
+
+
+

Total running time of the script: (0 minutes 1.719 seconds)

+ +

Gallery generated by Sphinx-Gallery

+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/auto_examples/index.html b/auto_examples/index.html new file mode 100644 index 0000000..aa7a0e5 --- /dev/null +++ b/auto_examples/index.html @@ -0,0 +1,139 @@ + + + + + + + + + Examples — Earth2-Grid documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Examples

+

The examples are below

+

The examples in misc/ are not included in the Sphinx Gallery.

+
+

HealPIX Image visualization

+
HealPIX Image visualization
+
+

HealPIX regridding

+
HealPIX regridding
+
+

Plot grids with PyVista

+
Plot grids with PyVista
+
+
+ +

Gallery generated by Sphinx-Gallery

+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/auto_examples/latlon_to_healpix.html b/auto_examples/latlon_to_healpix.html new file mode 100644 index 0000000..089197c --- /dev/null +++ b/auto_examples/latlon_to_healpix.html @@ -0,0 +1,186 @@ + + + + + + + + + HealPIX regridding — Earth2-Grid documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + +
+

HealPIX regridding

+

In this notebook, I demonstrate bilinear regridding onto healpy grids in O(10) +ms. this is a 3 order of magnitude speed-up compared to what Dale has reported.

+

Now, lets define a healpix grid with indexing in the XY convention. we convert +to NEST indexing in order to use the healpy.pix2ang to get the lat lon +coordinates. This operation is near instant.

+
import matplotlib.pyplot as plt
+import numpy as np
+import torch
+
+import earth2grid
+
+# level is the resolution
+level = 6
+hpx = earth2grid.healpix.Grid(level=level, pixel_order=earth2grid.healpix.XY())
+src = earth2grid.latlon.equiangular_lat_lon_grid(32, 64)
+regrid = earth2grid.get_regridder(src, hpx)
+
+
+z = np.cos(np.deg2rad(src.lat)) * np.cos(np.deg2rad(src.lon))
+
+
+z_torch = torch.as_tensor(z)
+z_hpx = regrid(z_torch)
+
+fig, (a, b) = plt.subplots(2, 1)
+a.pcolormesh(src.lon, src.lat, z)
+a.set_title("Lat Lon Grid")
+
+b.scatter(hpx.lon, hpx.lat, c=z_hpx, s=0.1)
+b.set_title("Healpix")
+
+
+Lat Lon Grid, Healpix
Text(0.5, 1.0, 'Healpix')
+
+
+
nside = 2**level
+reshaped = z_hpx.reshape(12, nside, nside)
+lat_r = hpx.lat.reshape(12, nside, nside)
+lon_r = hpx.lon.reshape(12, nside, nside)
+
+tile = 11
+fig, axs = plt.subplots(3, 4, sharex=True, sharey=True)
+axs = axs.ravel()
+
+for tile in range(12):
+    axs[tile].pcolormesh(lon_r[tile], lat_r[tile], reshaped[tile])
+
+
+latlon to healpix
/Users/nbrenowitz/workspace/nvidia/earth2grid/examples/sphinx_gallery/latlon_to_healpix.py:66: UserWarning: The input coordinates to pcolormesh are interpreted as cell centers, but are not monotonically increasing or decreasing. This may lead to incorrectly calculated cell edges, in which case, please supply explicit cell edges to pcolormesh.
+  axs[tile].pcolormesh(lon_r[tile], lat_r[tile], reshaped[tile])
+
+
+

Total running time of the script: (0 minutes 0.666 seconds)

+ +

Gallery generated by Sphinx-Gallery

+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/auto_examples/pyvista_grids.html b/auto_examples/pyvista_grids.html new file mode 100644 index 0000000..59661c0 --- /dev/null +++ b/auto_examples/pyvista_grids.html @@ -0,0 +1,186 @@ + + + + + + + + + Plot grids with PyVista — Earth2-Grid documentation + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + +
+

Plot grids with PyVista

+
import pyvista as pv
+
+
+
import earth2grid
+
+
+def label(mesh, plotter, text):
+    """
+    Add a label above a mesh in a PyVista plot.
+
+    Parameters:
+    - mesh: The mesh to label.
+    - plotter: A PyVista plotter instance.
+    - text: The label text.
+    - color: The color of the text label. Default is 'white'.
+    """
+    # Calculate the center of the mesh and the top Z-coordinate plus an offset
+    center = mesh.center
+    label_pos = [center[0], center[1], mesh.bounds[5] + 0.5]  # Offset to place label above the mesh
+
+    # Add the label using point labels for precise 3D positioning
+    plotter.add_point_labels(
+        [label_pos], [text], point_size=0, render_points_as_spheres=False, shape_opacity=0, font_size=20
+    )
+
+
+grid = earth2grid.healpix.Grid(level=4)
+hpx = grid.to_pyvista()
+latlon = earth2grid.latlon.equiangular_lat_lon_grid(32, 64, includes_south_pole=False).to_pyvista()
+
+
+pl = pv.Plotter()
+mesh = hpx.translate([0, 2.5, 0])
+pl.add_mesh(mesh, show_edges=True)
+label(mesh, pl, "HealPix")
+
+pl.add_mesh(latlon, show_edges=True)
+label(latlon, pl, "Equiangular Lat/Lon")
+
+pl.camera.position = (5, 0, 5)
+pl.show()
+
+
+pyvista grids
[ -2.8125   2.8125   8.4375  14.0625  19.6875  25.3125  30.9375  36.5625
+  42.1875  47.8125  53.4375  59.0625  64.6875  70.3125  75.9375  81.5625
+  87.1875  92.8125  98.4375 104.0625 109.6875 115.3125 120.9375 126.5625
+ 132.1875 137.8125 143.4375 149.0625 154.6875 160.3125 165.9375 171.5625
+ 177.1875 182.8125 188.4375 194.0625 199.6875 205.3125 210.9375 216.5625
+ 222.1875 227.8125 233.4375 239.0625 244.6875 250.3125 255.9375 261.5625
+ 267.1875 272.8125 278.4375 284.0625 289.6875 295.3125 300.9375 306.5625
+ 312.1875 317.8125 323.4375 329.0625 334.6875 340.3125 345.9375 351.5625
+ 357.1875]
+
+
+

Total running time of the script: (0 minutes 0.294 seconds)

+ +

Gallery generated by Sphinx-Gallery

+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/auto_examples/sg_execution_times.html b/auto_examples/sg_execution_times.html new file mode 100644 index 0000000..9a07a5f --- /dev/null +++ b/auto_examples/sg_execution_times.html @@ -0,0 +1,149 @@ + + + + + + + + + Computation times — Earth2-Grid documentation + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Computation times

+

00:02.679 total execution time for 3 files from auto_examples:

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +

Example

Time

Mem (MB)

HealPIX Image visualization (hpx2grid.py)

00:01.719

0.0

HealPIX regridding (latlon_to_healpix.py)

00:00.666

0.0

Plot grids with PyVista (pyvista_grids.py)

00:00.294

0.0

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/changelog.html b/changelog.html new file mode 100644 index 0000000..3e15b76 --- /dev/null +++ b/changelog.html @@ -0,0 +1,123 @@ + + + + + + + + + Changelog — Earth2-Grid documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Changelog

+
+

v2024.5.2

+
    +
  • First publicly available release

  • +
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/contributing.html b/contributing.html new file mode 100644 index 0000000..0b0e767 --- /dev/null +++ b/contributing.html @@ -0,0 +1,194 @@ + + + + + + + + + Contributing — Earth2-Grid documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Contributing

+

Contributions are welcome, and they are greatly appreciated! Every little bit +helps, and credit will always be given.

+
+

Developer Certificate of Origin

+
Developer Certificate of Origin
+Version 1.1
+
+Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+
+
+Developer's Certificate of Origin 1.1
+
+By making a contribution to this project, I certify that:
+
+(a) The contribution was created in whole or in part by me and I
+    have the right to submit it under the open source license
+    indicated in the file; or
+
+(b) The contribution is based upon previous work that, to the best
+    of my knowledge, is covered under an appropriate open source
+    license and I have the right under that license to submit that
+    work with modifications, whether created in whole or in part
+    by me, under the same open source license (unless I am
+    permitted to submit under a different license), as indicated
+    in the file; or
+
+(c) The contribution was provided directly to me by some other
+    person who certified (a), (b) or (c) and I have not modified
+    it.
+
+(d) I understand and agree that this project and the contribution
+    are public and that a record of the contribution (including all
+    personal information I submit with it, including my sign-off) is
+    maintained indefinitely and may be redistributed consistent with
+    this project or the open source license(s) involved.
+
+
+
+
+

Getting started

+
    +
  1. Install the pre-commit hooks: pre-commit install

  2. +
  3. Checkout a feature branch `git checkout -b

  4. +
  5. When writing code, group changes logically into commits. Messy commits are +usually a result of excessive multitasking. If you work on one thing at a +time, then your commits will be cleaner.

    +
      +
    1. Name each commit “[imperative verb] [subject]” (e.g. “add earth2grid.some_modules”). Make sure it fits onto one line.

    2. +
    3. Please provide context in the commit message. Start by explaining the +previous state of the code and why this needed changing. Focus on motivating +rather than explaining the changeset.

    4. +
    5. run the test suite: make unittest

    6. +
    7. run the docs: make docs

    8. +
    +
  6. +
  7. push the code to the repo git push -u origin your-branch-name and open an MR

  8. +
  9. ask for one reviewer.

  10. +
+
+
+

Tips

+
+
+

Deploying

+

A reminder for the maintainers on how to deploy. +Make sure all your changes are committed (including an entry in CHANGELOG.md). +Then run:

+
$ poetry run bump2version patch # possible: major / minor / patch
+$ git push
+$ git push --tags
+
+
+

GitHub Actions will then deploy to PyPI if tests pass.

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/genindex.html b/genindex.html new file mode 100644 index 0000000..063bbef --- /dev/null +++ b/genindex.html @@ -0,0 +1,176 @@ + + + + + + + + Index — Earth2-Grid documentation + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..e3685a5 --- /dev/null +++ b/index.html @@ -0,0 +1,134 @@ + + + + + + + + + Welcome to Earth2-Grid’s documentation! — Earth2-Grid documentation + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Welcome to Earth2-Grid’s documentation!

+ +
+
+

Indices and tables

+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/installation.html b/installation.html new file mode 100644 index 0000000..3ac3f4f --- /dev/null +++ b/installation.html @@ -0,0 +1,145 @@ + + + + + + + + + Installation — Earth2-Grid documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Installation

+
+

Stable release

+

To install Earth2 Grid Utilities, run this command in your +terminal:

+
$ pip install earth2-grid
+
+
+

This is the preferred method to install Earth2 Grid Utilities, as it will always install the most recent stable release.

+

If you don’t have pip installed, this Python installation guide +can guide you through the process.

+
+
+

From source

+

The source for Earth2 Grid Utilities can be downloaded from +the Github repo.

+

You can either clone the public repository:

+
$ git clone git://github.com/waynerv/earth2-grid
+
+
+

Or download the tarball:

+
$ curl -OJL https://github.com/waynerv/earth2-grid/tarball/master
+
+
+

Once you have a copy of the source, you can install it with:

+
$ pip install .
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/objects.inv b/objects.inv new file mode 100644 index 0000000..df79dba Binary files /dev/null and b/objects.inv differ diff --git a/search.html b/search.html new file mode 100644 index 0000000..9300897 --- /dev/null +++ b/search.html @@ -0,0 +1,131 @@ + + + + + + + + Search — Earth2-Grid documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Search

+ + + + +

+ Searching for multiple words only shows matches that contain + all words. +

+ + +
+ + + +
+ + + +
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/searchindex.js b/searchindex.js new file mode 100644 index 0000000..89fbf65 --- /dev/null +++ b/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"docnames": ["api", "auto_examples/hpx2grid", "auto_examples/index", "auto_examples/latlon_to_healpix", "auto_examples/pyvista_grids", "auto_examples/sg_execution_times", "changelog", "contributing", "index", "installation", "sg_execution_times", "usage"], "filenames": ["api.rst", "auto_examples/hpx2grid.rst", "auto_examples/index.rst", "auto_examples/latlon_to_healpix.rst", "auto_examples/pyvista_grids.rst", "auto_examples/sg_execution_times.rst", "changelog.md", "contributing.md", "index.rst", "installation.md", "sg_execution_times.rst", "usage.md"], "titles": ["API", "HealPIX Image visualization", "Examples", "HealPIX regridding", "Plot grids with PyVista", "Computation times", "Changelog", "Contributing", "Welcome to Earth2-Grid\u2019s documentation!", "Installation", "Computation times", "Usage"], "terms": {"class": 0, "earth2grid": [0, 1, 3, 4, 7, 11], "healpix": [0, 2, 4, 5, 10, 11], "level": [0, 1, 3, 4, 11], "int": 0, "pixel_ord": [0, 3, 11], "pixelord": [0, 11], "xy": [0, 3, 11], "ring": 0, "base": [0, 7], "A": [0, 4, 7], "attr": 0, "2": [0, 3, 4, 11], "nside": [0, 3, 11], "order": [0, 3], "convect": 0, "data": 0, "get_bilinear_regridder_to": 0, "lat": [0, 1, 3, 4], "ndarrai": 0, "lon": [0, 3, 4], "get": [0, 3], "regridd": 0, "specifi": 0, "point": [0, 4], "reorder": 0, "x": 0, "tensor": [0, 1], "rorder": 0, "pixel": [0, 1], "have": [0, 7, 9], "to_imag": [0, 1], "fill_valu": 0, "nan": [0, 1], "us": [0, 1, 3, 4, 11], "45": [0, 1], "degre": 0, "rotat": [0, 1], "i": [0, 1, 3, 4, 7, 9, 11], "se": 0, "j": 0, "ne": 0, "latlon": [0, 3, 4, 11], "latlongrid": 0, "list": 0, "float": 0, "equiangular_lat_lon_grid": [0, 3, 4, 11], "nlat": 0, "nlon": 0, "includes_south_pol": [0, 4], "bool": 0, "true": [0, 3, 4], "return": 0, "regular": 0, "from": [0, 1, 5, 10], "90": 0, "includ": [0, 2, 7], "onli": 0, "0": [0, 1, 3, 4, 5, 10], "360": 0, "paramet": [0, 4], "number": 0, "latitud": 0, "longtidu": 0, "final": 0, "south": 0, "pole": 0, "get_regridd": [0, 3, 11], "src": [0, 3, 11], "dest": 0, "modul": [0, 1, 8], "pad": 0, "each": [0, 7], "face": 0, "consist": [0, 7], "its": [0, 7], "accord": 0, "neighbor": 0, "The": [0, 2, 3, 4, 7, 9], "input": [0, 3], "shape": [0, 11], "n": 0, "f": 0, "h": 0, "w": 0, "amount": 0, "exampl": [0, 1, 3, 4, 5, 8, 10], "th": 0, "show": [0, 4], "describ": 0, "object": 0, "4": [0, 3, 4], "torch": [0, 1, 3, 11], "from_numpi": 0, "healpix_pad_xi": 0, "view": [0, 1], "1": [0, 1, 3, 4, 7], "12": [0, 3, 11], "_nside": 0, "size": 0, "16": 0, "18": 0, "go": [1, 3, 4], "end": [1, 3, 4], "download": [1, 2, 3, 4, 9], "full": [1, 3, 4], "code": [1, 2, 3, 4, 7], "map": 1, "can": [1, 9], "2d": 1, "deg": 1, "thi": [1, 3, 7, 9], "quick": 1, "viewer": 1, "without": 1, "distort": 1, "nativ": 1, "import": [1, 3, 4, 11], "matplotlib": [1, 3], "pyplot": [1, 3], "plt": [1, 3], "numpi": [1, 3], "np": [1, 3], "color": [1, 4], "normal": 1, "pil": 1, "grid": [1, 2, 3, 5, 9, 10, 11], "8": [1, 4], "lat_img": 1, "save": 1, "resolut": [1, 3, 11], "vmin": 1, "nanmin": 1, "vmax": 1, "nanmax": 1, "arrai": 1, "cm": 1, "viridi": 1, "256": 1, "astyp": 1, "uint8": 1, "set": 1, "transpar": 1, "where": 1, "isnan": 1, "255": [1, 4], "fromarrai": 1, "hpx_grid": 1, "png": 1, "warn": 1, "cannot": 1, "find": 1, "healpixpad": 1, "total": [1, 3, 4, 5, 10], "run": [1, 3, 4, 7, 9], "time": [1, 3, 4, 7], "script": [1, 3, 4], "minut": [1, 3, 4], "719": [1, 5, 10], "second": [1, 3, 4], "jupyt": [1, 2, 3, 4], "notebook": [1, 2, 3, 4], "hpx2grid": [1, 5, 10], "ipynb": [1, 3, 4], "python": [1, 2, 3, 4, 9], "sourc": [1, 2, 3, 4, 7], "py": [1, 3, 4, 5, 10], "galleri": [1, 2, 3, 4, 10], "gener": [1, 2, 3, 4], "sphinx": [1, 2, 3, 4], "ar": [2, 3, 7], "below": 2, "misc": 2, "imag": [2, 5, 10], "visual": [2, 5, 10], "regrid": [2, 5, 10, 11], "plot": [2, 5, 10], "pyvista": [2, 5, 10], "all": [2, 7, 10], "auto_examples_python": 2, "zip": 2, "auto_examples_jupyt": 2, "In": 3, "demonstr": 3, "bilinear": 3, "onto": [3, 7], "healpi": 3, "o": 3, "10": 3, "m": 3, "3": [3, 5, 10], "magnitud": 3, "speed": 3, "up": 3, "compar": 3, "what": 3, "dale": 3, "ha": 3, "report": 3, "now": 3, "let": 3, "defin": 3, "index": [3, 8], "convent": 3, "we": 3, "convert": 3, "nest": 3, "pix2ang": 3, "coordin": [3, 4], "oper": 3, "instant": 3, "6": [3, 11], "hpx": [3, 4, 11], "32": [3, 4, 11], "64": [3, 4, 11], "z": [3, 4, 11], "co": 3, "deg2rad": 3, "z_torch": [3, 11], "as_tensor": [3, 11], "z_hpx": [3, 11], "fig": 3, "b": [3, 7], "subplot": 3, "pcolormesh": 3, "set_titl": 3, "scatter": 3, "c": [3, 7], "": [3, 7], "text": [3, 4], "5": [3, 4], "reshap": [3, 11], "lat_r": 3, "lon_r": 3, "tile": 3, "11": 3, "ax": 3, "sharex": 3, "sharei": 3, "ravel": 3, "rang": 3, "user": 3, "nbrenowitz": 3, "workspac": 3, "nvidia": 3, "sphinx_galleri": [3, 10], "latlon_to_healpix": [3, 5, 10], "66": 3, "userwarn": 3, "interpret": 3, "cell": 3, "center": [3, 4], "monoton": 3, "increas": 3, "decreas": 3, "mai": [3, 7], "lead": 3, "incorrectli": 3, "calcul": [3, 4], "edg": 3, "which": 3, "case": 3, "pleas": [3, 7], "suppli": 3, "explicit": 3, "666": [3, 5, 10], "pv": 4, "def": 4, "label": 4, "mesh": 4, "plotter": 4, "add": [4, 7], "abov": 4, "instanc": 4, "default": 4, "white": 4, "top": 4, "plu": 4, "an": [4, 7], "offset": 4, "label_po": 4, "bound": 4, "place": 4, "precis": 4, "3d": 4, "posit": 4, "add_point_label": 4, "point_siz": 4, "render_points_as_spher": 4, "fals": 4, "shape_opac": 4, "font_siz": 4, "20": 4, "to_pyvista": 4, "pl": 4, "translat": 4, "add_mesh": 4, "show_edg": 4, "equiangular": 4, "camera": 4, "8125": 4, "4375": 4, "14": 4, "0625": 4, "19": 4, "6875": 4, "25": 4, "3125": 4, "30": 4, "9375": 4, "36": 4, "5625": 4, "42": 4, "1875": 4, "47": 4, "53": 4, "59": 4, "70": 4, "75": 4, "81": 4, "87": 4, "92": 4, "98": 4, "104": 4, "109": 4, "115": 4, "120": 4, "126": 4, "132": 4, "137": 4, "143": 4, "149": 4, "154": 4, "160": 4, "165": 4, "171": 4, "177": 4, "182": 4, "188": 4, "194": 4, "199": 4, "205": 4, "210": 4, "216": 4, "222": 4, "227": 4, "233": 4, "239": 4, "244": 4, "250": 4, "261": 4, "267": 4, "272": 4, "278": 4, "284": 4, "289": 4, "295": 4, "300": 4, "306": 4, "312": 4, "317": 4, "323": 4, "329": 4, "334": 4, "340": 4, "345": 4, "351": 4, "357": 4, "294": [4, 5, 10], "pyvista_grid": [4, 5, 10], "00": [5, 10], "02": [5, 10], "679": [5, 10], "execut": [5, 10], "file": [5, 7, 10], "auto_exampl": 5, "mem": [5, 10], "mb": [5, 10], "01": [5, 10], "first": 6, "publicli": 6, "avail": 6, "releas": 6, "welcom": 7, "thei": 7, "greatli": 7, "appreci": 7, "everi": 7, "littl": 7, "bit": 7, "help": 7, "credit": 7, "alwai": [7, 9], "given": 7, "version": 7, "copyright": 7, "2004": 7, "2006": 7, "linux": 7, "foundat": 7, "contributor": 7, "everyon": 7, "permit": 7, "copi": [7, 9], "distribut": 7, "verbatim": 7, "licens": 7, "document": 7, "chang": 7, "allow": 7, "By": 7, "make": 7, "project": [7, 11], "certifi": 7, "wa": 7, "creat": 7, "whole": 7, "part": 7, "me": 7, "right": 7, "submit": 7, "under": 7, "open": 7, "indic": 7, "upon": 7, "previou": 7, "work": 7, "best": 7, "my": 7, "knowledg": 7, "cover": 7, "appropri": 7, "modif": 7, "whether": 7, "same": 7, "unless": 7, "am": 7, "differ": 7, "provid": 7, "directli": 7, "some": 7, "other": 7, "person": 7, "who": 7, "modifi": 7, "d": 7, "understand": 7, "agre": 7, "public": [7, 9], "record": 7, "inform": 7, "sign": 7, "off": 7, "maintain": 7, "indefinit": 7, "redistribut": 7, "involv": 7, "instal": [7, 8], "pre": 7, "commit": 7, "hook": 7, "checkout": 7, "featur": 7, "branch": 7, "git": [7, 9], "when": 7, "write": 7, "group": 7, "logic": 7, "messi": 7, "usual": 7, "result": 7, "excess": 7, "multitask": 7, "If": [7, 9], "you": [7, 9], "one": 7, "thing": 7, "your": [7, 9], "cleaner": 7, "name": 7, "imper": 7, "verb": 7, "subject": 7, "e": 7, "g": 7, "some_modul": 7, "sure": 7, "fit": 7, "line": 7, "context": 7, "messag": 7, "explain": 7, "state": 7, "why": 7, "need": 7, "focu": 7, "motiv": 7, "rather": 7, "than": 7, "changeset": 7, "test": 7, "suit": 7, "unittest": 7, "doc": 7, "push": 7, "repo": [7, 9], "u": 7, "mr": 7, "ask": 7, "review": 7, "remind": 7, "how": 7, "entri": 7, "changelog": [7, 8], "md": 7, "Then": 7, "poetri": 7, "bump2vers": 7, "patch": 7, "possibl": 7, "major": 7, "minor": 7, "tag": 7, "github": [7, 9], "action": 7, "pypi": 7, "pass": 7, "usag": 8, "api": 8, "contribut": 8, "search": 8, "page": 8, "To": [9, 11], "earth2": [9, 11], "util": [9, 11], "command": 9, "termin": 9, "pip": 9, "prefer": 9, "method": 9, "most": 9, "recent": 9, "don": 9, "t": 9, "guid": 9, "through": 9, "process": 9, "either": 9, "clone": 9, "repositori": 9, "com": 9, "waynerv": 9, "Or": 9, "tarbal": 9, "curl": 9, "ojl": 9, "http": 9, "master": 9, "onc": 9}, "objects": {"earth2grid": [[0, 0, 1, "", "get_regridder"]], "earth2grid.healpix": [[0, 1, 1, "", "Grid"], [0, 0, 1, "", "pad"]], "earth2grid.healpix.Grid": [[0, 2, 1, "", "get_bilinear_regridder_to"], [0, 2, 1, "", "reorder"], [0, 2, 1, "", "to_image"]], "earth2grid.latlon": [[0, 1, 1, "", "LatLonGrid"], [0, 0, 1, "", "equiangular_lat_lon_grid"]], "earth2grid.latlon.LatLonGrid": [[0, 2, 1, "", "get_bilinear_regridder_to"]]}, "objtypes": {"0": "py:function", "1": "py:class", "2": "py:method"}, "objnames": {"0": ["py", "function", "Python function"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"]}, "titleterms": {"api": 0, "grid": [0, 4, 8], "regrid": [0, 3], "other": 0, "util": 0, "healpix": [1, 3], "imag": 1, "visual": 1, "exampl": 2, "plot": 4, "pyvista": 4, "comput": [5, 10], "time": [5, 10], "changelog": 6, "v2024": 6, "5": 6, "2": 6, "contribut": 7, "develop": 7, "certif": 7, "origin": 7, "get": 7, "start": 7, "tip": 7, "deploi": 7, "welcom": 8, "earth2": 8, "": 8, "document": 8, "content": 8, "indic": 8, "tabl": 8, "instal": 9, "stabl": 9, "releas": 9, "from": 9, "sourc": 9, "usag": 11}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 57}, "alltitles": {"API": [[0, "api"]], "Grids": [[0, "grids"]], "Regridding": [[0, "regridding"]], "Other utilities": [[0, "other-utilities"]], "HealPIX Image visualization": [[1, "healpix-image-visualization"]], "Examples": [[2, "examples"]], "HealPIX regridding": [[3, "healpix-regridding"]], "Plot grids with PyVista": [[4, "plot-grids-with-pyvista"]], "Computation times": [[5, "computation-times"], [10, "computation-times"]], "Changelog": [[6, "changelog"]], "v2024.5.2": [[6, "v2024-5-2"]], "Contributing": [[7, "contributing"]], "Developer Certificate of Origin": [[7, "developer-certificate-of-origin"]], "Getting started": [[7, "getting-started"]], "Tips": [[7, "tips"]], "Deploying": [[7, "deploying"]], "Welcome to Earth2-Grid\u2019s documentation!": [[8, "welcome-to-earth2-grid-s-documentation"]], "Contents:": [[8, null]], "Indices and tables": [[8, "indices-and-tables"]], "Installation": [[9, "installation"]], "Stable release": [[9, "stable-release"]], "From source": [[9, "from-source"]], "Usage": [[11, "usage"]]}, "indexentries": {"grid (class in earth2grid.healpix)": [[0, "earth2grid.healpix.Grid"]], "latlongrid (class in earth2grid.latlon)": [[0, "earth2grid.latlon.LatLonGrid"]], "equiangular_lat_lon_grid() (in module earth2grid.latlon)": [[0, "earth2grid.latlon.equiangular_lat_lon_grid"]], "get_bilinear_regridder_to() (earth2grid.healpix.grid method)": [[0, "earth2grid.healpix.Grid.get_bilinear_regridder_to"]], "get_bilinear_regridder_to() (earth2grid.latlon.latlongrid method)": [[0, "earth2grid.latlon.LatLonGrid.get_bilinear_regridder_to"]], "get_regridder() (in module earth2grid)": [[0, "earth2grid.get_regridder"]], "pad() (in module earth2grid.healpix)": [[0, "earth2grid.healpix.pad"]], "reorder() (earth2grid.healpix.grid method)": [[0, "earth2grid.healpix.Grid.reorder"]], "to_image() (earth2grid.healpix.grid method)": [[0, "earth2grid.healpix.Grid.to_image"]]}}) \ No newline at end of file diff --git a/sg_execution_times.html b/sg_execution_times.html new file mode 100644 index 0000000..04aaf2a --- /dev/null +++ b/sg_execution_times.html @@ -0,0 +1,149 @@ + + + + + + + + + Computation times — Earth2-Grid documentation + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Computation times

+

00:02.679 total execution time for 3 files from all galleries:

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +

Example

Time

Mem (MB)

HealPIX Image visualization (../examples/sphinx_gallery/hpx2grid.py)

00:01.719

0.0

HealPIX regridding (../examples/sphinx_gallery/latlon_to_healpix.py)

00:00.666

0.0

Plot grids with PyVista (../examples/sphinx_gallery/pyvista_grids.py)

00:00.294

0.0

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/usage.html b/usage.html new file mode 100644 index 0000000..058045e --- /dev/null +++ b/usage.html @@ -0,0 +1,132 @@ + + + + + + + + + Usage — Earth2-Grid documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Usage

+

To use Earth2 Grid Utilities in a project

+
import earth2grid
+# level is the resolution
+level = 6
+hpx = earth2grid.healpix.Grid(level=level, pixel_order=earth2grid.healpix.PixelOrder.XY)
+src = earth2grid.latlon.equiangular_lat_lon_grid(32, 64)
+z_torch = torch.as_tensor(z)
+z_torch = torch.as_tensor(z)
+regrid = earth2grid.get_regridder(src, hpx)
+z_hpx = regrid(z_torch)
+z_hpx.shape
+nside = 2**level
+reshaped = z_hpx.reshape(12, nside, nside)
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file