Repository: SHTOOLS/SHTOOLS (language: python)

Issue:
Version 4.11
## Version 4.11

**Support for Python 3.12 using the Meson build system**

This version no longer relies on `distutils` (which was deprecated in python 3.12) and instead makes use of [Meson](https://mesonbuild.com/) and [Meson-Python](https://meson-python.readthedocs.io) to build and test the pyshtools package. The package can be built from source using pip as before, however, if you need to create an editable install, it will be necessary to use the slightly modified command
```bash
pip install --no-build-isolation -e .
```
Please see the online documentation for instructions on how to run the test suites and benchmarks.

**Other changes**

* We no longer use `versioneer` to determine the package version, but instead set the version in the main `meson.build` file using `setuptools_scm`. At the present time, it is not possible to determine the version when using a source tarball, and for this case, the build will fail. Please ensure that when building from source that you are doing so from a git versioned repository.
* Fixed a problem with `SHCoeffs.volume()` when the coefficient normalization was `ortho`.
* Fixed a potential LAPACK underscore problem when compiling with `LAPACK_UNDERSCORE` specified.
* Minor changes were made to the python source files to ensure numpy v2 compatibility.

M. A. Wieczorek, M. Meschede, A. Broquet, T. Brugere, A. Corbin, EricAtORS, A. Hattori, A. Kalinin, J. Kohler, D. Kutra, K. Leinweber, P. Lobo, I. Oshchepkov, P.-L. Phan, O. Poplawski, M. Reinecke, E. Sales de Andrade, E. Schnetter, S. Schröder, J. Sierra, A. Vasishta, A. Walker, xoviat, B. Xu (2024). SHTOOLS: Version 4.11, Zenodo, doi:[10.5281/zenodo.592762](https://doi.org/10.5281/zenodo.592762)




**Reminders**

- [x] Base all changes on the `develop` branch: the `master` branch is used only when releasing new versions.
- [x] Run `make check` to ensure that the python code follows standard formatting conventions.
- [x] If adding new features, update the docstring to provide all information that is required to use the feature.



Discussion / hints:

Fix patch:
diff --git a/.github/ISSUE_TEMPLATE/release_checklist.md b/.github/ISSUE_TEMPLATE/release_checklist.md
index 4b3b58c03..e15ef6dbc 100644
--- a/.github/ISSUE_TEMPLATE/release_checklist.md
+++ b/.github/ISSUE_TEMPLATE/release_checklist.md
@@ -17,7 +17,6 @@ Make all changes on the branch `develop`. Verify that the version numbers and ot
 - [ ] `docs/pages/mydoc/release-notes-v4.md` : update release notes
 - [ ] `docs/pages/fortran/fortran-release-notes-v4.md` : update release notes
 - [ ] `requirements.txt` : update version numbers of the python dependencies, if necessary
-- [ ] `requirements-dev.txt` : update version numbers of the python developer dependencies, if necessary
 - [ ] `environment.yml` : update version numbers of the conda environment, if necesseary
 - [ ] `binder/environment.yml` : update version number of pyshtools and other dependencies
 - [ ] `fpm.toml` : update shtools version number
@@ -26,7 +25,7 @@ Make all changes on the branch `develop`. Verify that the version numbers and ot
 Update the documentation files and man pages
 - [ ] `cd docs; bundle update; cd ..` : update the Gemfile for the jekyll web documentation
 - [ ] `make remove-doc` : this ensures that the correct version number will be written to the fortran man pages
-- [ ] `make doc` : make the fortran man pages, create markdown files from the python docstrings, create web documentation, and create python docstrings for wrapped functions.
+- [ ] `make doc` : make the fortran man pages, create markdown files from the python docstrings, and create web documentation.
 
 ### Release ###
 - [ ] Commit all changes to the `develop` branch and then merge all changes to the `master` branch.
diff --git a/.github/workflows/pypi_publish.yml b/.github/workflows/pypi_publish.yml
index 2d612bba8..12e695dbc 100644
--- a/.github/workflows/pypi_publish.yml
+++ b/.github/workflows/pypi_publish.yml
@@ -11,13 +11,16 @@ jobs:
 
     steps:
     - name: Checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
+      with:
+        fetch-depth: 1
+        fetch-tags: true
 
     - name: Set env
       run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
 
     - name: Setup Miniconda
-      uses: conda-incubator/setup-miniconda@v2
+      uses: conda-incubator/setup-miniconda@v3
       with:
         python-version: 3.11
         mamba-version: "*"
@@ -31,12 +34,13 @@ jobs:
       shell: bash -l {0}
       run: |
         mamba config --set always_yes yes --set changeps1 no
-        mamba install -q -n pypi fftw \
-                                 liblapack \
-                                 openblas \
+        mamba install -q -n pypi blas-devel \
+                                 fftw \
+                                 meson-python \
                                  numpy \
-                                 setuptools \
-                                 versioneer \
+                                 pkg-config \
+                                 setuptools_scm \
+                                 build \
                                  twine
         mamba list -n pypi
 
@@ -52,7 +56,7 @@ jobs:
       shell: bash -l {0}
       run: |
         mamba env list
-        python setup.py sdist
+        python -m build -s
         twine upload dist/*
 
     - name: Trigger a build on the SHTOOLS/build-shtools repo
@@ -64,7 +68,7 @@ jobs:
         --data '{"event_type": "New pyshtools release", "client_payload": { "repository": "'"$GITHUB_REPOSITORY"'" }}'
 
     - name: Download tarball archive
-      uses: carlosperate/download-file-action@v2.0.0
+      uses: carlosperate/download-file-action@v2
       id: download-tarball
       with:
         file-url: 'https://github.com/SHTOOLS/SHTOOLS/archive/${{ env.RELEASE_VERSION }}.tar.gz'
diff --git a/.gitignore b/.gitignore
index 9b634a887..be9393d22 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,8 +10,6 @@ dist/
 docs/vendor/
 examples/notebooks/.ipynb_checkpoints/
 pyshtools.egg-info/
-src/_SHTOOLS-f2pywrappers.f
-src/_SHTOOLSmodule.c
 examples/fortran/MarsCrustalThickness/MarsCrustalThickness
 examples/fortran/SHCilmPlus/TestCilmPlus
 examples/fortran/SHExpandDH/TestExpandDH
diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index b03242ac3..000000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1,19 +0,0 @@
-include README.md
-include LICENSE.txt
-include AUTHORS.md
-include Makefile
-include versioneer.py
-include pyshtools/_version.py
-
-graft examples/ExampleDataFiles
-graft pyshtools/doc
-recursive-include examples/fortran *.f95 input* Makefile
-recursive-include examples/python *.py Makefile
-recursive-include examples/notebooks *.ipynb
-recursive-include examples/cpp *.cpp Makefile
-
-graft src/pydoc
-graft src/fdoc
-recursive-include src *.py *.pyf
-
-graft man
diff --git a/Makefile b/Makefile
index 9b4afa15f..311759b6e 100644
--- a/Makefile
+++ b/Makefile
@@ -98,21 +98,19 @@
 #       Remove html notebooks.
 #
 #   make doc
-#       Create the man pages from input markdown files, reformat md files for
-#			  use with the static web site, and create python docstrings for the
-#	      wrapped functions. These files are PRE-MADE in the distribution and
-# 			need to be rebuilt manually before each release. To remake these files
-#       for a new release, it will be necessary to install "pandoc", "ghc" and
-#       "cabal-install" (all using brew on macOS), and then execute
-#       "cabal update" and "cabal install --lib pandoc-types". If errors are
-#			  encountered, determine which version of pandoc-types was used to
-#       compile pandoc using "pandoc --version", delete ~/.cabal, run cabal
-#       update, and then reinstall pandoc-types
+#       Create the man pages from input markdown files, and reformat md files
+#       for use with the static web site. These files are PRE-MADE in the
+#       distribution and need to be rebuilt manually before each release.
+#       To remake these files for a new release, it will be necessary to
+#       install "pandoc", "ghc" and "cabal-install" (using brew on macOS), and
+#       then execute "cabal update" and "cabal install --lib pandoc-types".
+#       If errors are encountered, determine which version of pandoc-types was
+#       used to compile pandoc using "pandoc --version", delete ~/.cabal, run
+#       cabal update, and then reinstall pandoc-types
 #       "cabal install --lib pandoc-types-1.22".
 #
 #   make remove-doc
-#       Remove the man, html-man pages, and python docstrings for wrapped
-#		    functions.
+#       Remove the man and html-man pages.
 #
 #   make www
 #       Make the static html web documention in the directory www using Jekyll.
@@ -128,7 +126,7 @@
 ###############################################################################
 
 # The VERSION number is used only for generating the man pages
-VERSION = 4.10
+VERSION = 4.11
 
 LIBNAME = SHTOOLS
 LIBNAMEMP = SHTOOLS-mp
@@ -168,7 +166,7 @@ FFTLIBPATH = /usr/local
 FFTW = -L$(FFTLIBPATH) -lfftw3 -lm
 LAPACK_UNDERSCORE = 0
 
-FLAKE8_FILES = setup.py pyshtools examples/python
+FLAKE8_FILES = pyshtools examples/python
 
 # Set default compiler flags based on the name of the F95 compiler by searching
 # if the short name of the compiler is in $(F95).
@@ -309,7 +307,6 @@ uninstall:
 	$(MAKE) -C $(FDOCDIR) -f Makefile uninstall PREFIX=$(PREFIX)
 
 doc:
-	@$(PYTHON) pyshtools/doc/make_docs.py
 	@echo "--> Building Fortran 95 man pages"
 	@$(MAKE) -C $(FDOCDIR) -f Makefile VERSION=$(VERSION)
 	@$(MAKE) -C $(PYDOCDIR) -f Makefile
@@ -319,8 +316,7 @@ remove-doc:
 	@-rm -f man/man3/*.3
 	@-rm -f doc/pages/fortran/fdoc/*.md
 	@-rm -f doc/pages/mydoc/pydoc/*.md
-	@-rm -f pyshtools/doc/*.doc
-	@echo "--> Removed man files, web site source md files, and python docstrings"
+	@echo "--> Removed man files and web site source md files"
 
 www:
 	@cd $(WWWSRC) ; bundle update ; $(JEKYLL) build -d ../$(WWWDEST)
diff --git a/README.md b/README.md
index 61cdf3d5e..773ca7160 100644
--- a/README.md
+++ b/README.md
@@ -70,7 +70,7 @@ SHTOOLS can be invoked in any Fortran 95 or Python program. The core software is
 
 ##### Install using `conda`:
 ```bash
-conda install -c conda-forge pyshtools  # Linux and macOS only
+conda install -c conda-forge pyshtools
 conda update -c conda-forge pyshtools  # to upgrade a pre-existing installation
 ```
 
@@ -83,22 +83,22 @@ pip install git+https://github.com/SHTOOLS/SHTOOLS@develop  # install the develo
 ```
 
 ##### For developers:
-Install the requirements:
+Install the system level build requirements:
 ```bash
-# Linux: install gfortran, fftw3, blas, and lapack
-sudo apt-get install g++ gfortran libfftw3-dev libblas-dev liblapack-dev
-# macOS: install fftw using brew or macports
-brew install fftw
-sudo port install fftw-3
-# macOS: for LAPACK, link to the system '-framework Accelerate' or install openblas
+sudo apt-get install build-essential cmake gfortran  # Debian, Ubuntu and derivatives
+sudo dnf group install "C Development Tools and Libraries" "Development Tools"  # Fedora, Centos, RHEL and derivatives
+sudo dnf install cmake gcc-fortran  # Fedora, Centos, RHEL and derivatives
+xcode-select --install  # macOS
 ```
 
-Then clone the shtools repo and install manually:
+Then clone the shtools repo, install the other dependencies, and install manually in a conda environment:
 ```bash
 git clone https://github.com/SHTOOLS/SHTOOLS.git
 cd shtools
-git checkout develop
-pip install -e .  # install into the shtools folder and link to the active python environment
+conda create -n your_env_name python=3.xx  # create a new conda environment, if desired
+conda env update -n your_env_name -f environment.yml
+conda activate your_env_name  # activate the new conda environment
+pip install --no-build-isolation -e .  # install into the shtools folder and link to the active python environment
 ```
 
 #### SHTOOLS (for Fortran 95)
diff --git a/binder/environment.yml b/binder/environment.yml
index 1b4c59b2a..610ecfe91 100644
--- a/binder/environment.yml
+++ b/binder/environment.yml
@@ -2,6 +2,6 @@ name: pyshtools
 channels:
     - conda-forge
 dependencies:
-    - python=3.11
-    - pyshtools>=4.10.0
+    - python=3.12
+    - pyshtools>=4.11.0
     - palettable>=3.3
diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock
index 97bd5523f..7c2149e41 100644
--- a/docs/Gemfile.lock
+++ b/docs/Gemfile.lock
@@ -1,13 +1,20 @@
 GEM
   remote: https://rubygems.org/
   specs:
-    activesupport (7.0.7.2)
+    activesupport (7.1.2)
+      base64
+      bigdecimal
       concurrent-ruby (~> 1.0, >= 1.0.2)
+      connection_pool (>= 2.2.5)
+      drb
       i18n (>= 1.6, < 2)
       minitest (>= 5.1)
+      mutex_m
       tzinfo (~> 2.0)
-    addressable (2.8.5)
+    addressable (2.8.6)
       public_suffix (>= 2.0.2, < 6.0)
+    base64 (0.2.0)
+    bigdecimal (3.1.5)
     coffee-script (2.4.1)
       coffee-script-source
       execjs
@@ -15,20 +22,23 @@ GEM
     colorator (1.1.0)
     commonmarker (0.23.10)
     concurrent-ruby (1.2.2)
+    connection_pool (2.4.1)
     dnsruby (1.70.0)
       simpleidn (~> 0.2.1)
+    drb (2.2.0)
+      ruby2_keywords
     em-websocket (0.5.3)
       eventmachine (>= 0.12.9)
       http_parser.rb (~> 0)
     ethon (0.16.0)
       ffi (>= 1.15.0)
     eventmachine (1.2.7)
-    execjs (2.8.1)
-    faraday (2.7.10)
-      faraday-net_http (>= 2.0, < 3.1)
-      ruby2_keywords (>= 0.0.4)
-    faraday-net_http (3.0.2)
-    ffi (1.15.5)
+    execjs (2.9.1)
+    faraday (2.9.0)
+      faraday-net_http (>= 2.0, < 3.2)
+    faraday-net_http (3.1.0)
+      net-http
+    ffi (1.16.3)
     forwardable-extended (2.6.0)
     gemoji (3.0.1)
     github-pages (228)
@@ -209,10 +219,13 @@ GEM
       jekyll (>= 3.5, < 5.0)
       jekyll-feed (~> 0.9)
       jekyll-seo-tag (~> 2.1)
-    minitest (5.19.0)
-    nokogiri (1.15.4-arm64-darwin)
+    minitest (5.21.1)
+    mutex_m (0.2.0)
+    net-http (0.4.1)
+      uri
+    nokogiri (1.16.0-arm64-darwin)
       racc (~> 1.4)
-    nokogiri (1.15.4-x86_64-darwin)
+    nokogiri (1.16.0-x86_64-darwin)
       racc (~> 1.4)
     octokit (4.25.1)
       faraday (>= 1, < 3)
@@ -220,7 +233,7 @@ GEM
     pathutil (0.16.2)
       forwardable-extended (~> 2.6)
     public_suffix (4.0.7)
-    racc (1.7.1)
+    racc (1.7.3)
     rb-fsevent (0.11.2)
     rb-inotify (0.10.1)
       ffi (~> 1.0)
@@ -241,14 +254,15 @@ GEM
       unf (~> 0.1.4)
     terminal-table (1.8.0)
       unicode-display_width (~> 1.1, >= 1.1.1)
-    typhoeus (1.4.0)
+    typhoeus (1.4.1)
       ethon (>= 0.9.0)
     tzinfo (2.0.6)
       concurrent-ruby (~> 1.0)
     unf (0.1.4)
       unf_ext
-    unf_ext (0.0.8.2)
+    unf_ext (0.0.9.1)
     unicode-display_width (1.8.0)
+    uri (0.13.0)
     webrick (1.8.1)
 
 PLATFORMS
diff --git a/docs/_data/sidebars/fortran_sidebar.yml b/docs/_data/sidebars/fortran_sidebar.yml
index a31cb2576..eb46937cb 100755
--- a/docs/_data/sidebars/fortran_sidebar.yml
+++ b/docs/_data/sidebars/fortran_sidebar.yml
@@ -3,7 +3,7 @@
 entries:
 - title: sidebar
   product: SHTOOLS
-  version: '4.10'
+  version: '4.11'
   folders:
 
   - title:
diff --git a/docs/_data/sidebars/mydoc_sidebar.yml b/docs/_data/sidebars/mydoc_sidebar.yml
index 352803b53..d24e68fab 100755
--- a/docs/_data/sidebars/mydoc_sidebar.yml
+++ b/docs/_data/sidebars/mydoc_sidebar.yml
@@ -3,7 +3,7 @@
 entries:
 - title: sidebar
   product: pyshtools
-  version: '4.10'
+  version: '4.11'
   folders:
 
   - title:
diff --git a/docs/pages/fortran/fortran-release-notes-v4.md b/docs/pages/fortran/fortran-release-notes-v4.md
index efd3517b6..427e2881b 100644
--- a/docs/pages/fortran/fortran-release-notes-v4.md
+++ b/docs/pages/fortran/fortran-release-notes-v4.md
@@ -7,6 +7,25 @@ summary:
 toc: true
 folder: fortran
 ---
+## Version 4.11
+
+**Support for Python 3.12 using Meson**
+
+This version no longer relies on `distutils` (which was deprecated in python 3.12) and instead makes use of [Meson](https://mesonbuild.com/) and [Meson-Python](https://meson-python.readthedocs.io) to build and test the pyshtools package. The package can be built from source using pip as before, however, if you need to create an editable install, it will be necessary to use the slightly modified command
+```bash
+pip install --no-build-isolation -e .
+```
+Please see the online documentation for instructions on how to run the test suites and benchmarks.
+
+**Other changes**
+
+* We no longer use `versioneer` to determine the package version, but instead set the version in the main `meson.build` file using `setuptools_scm`. At the present time, it is not possible to determine the version when using a source tarball, and for this case, the build will fail. Please ensure that when building from source that you are doing so from a git versioned repository.
+* Fixed a problem with `SHCoeffs.volume()` when the coefficient normalization was `ortho`.
+* Fixed a potential LAPACK underscore problem when compiling with `LAPACK_UNDERSCORE` specified.
+* Minor changes were made to the python source files to ensure numpy v2 compatibility.
+
+M. A. Wieczorek, M. Meschede, A. Broquet, T. Brugere, A. Corbin, EricAtORS, A. Hattori, A. Kalinin, J. Kohler, D. Kutra, K. Leinweber, P. Lobo, I. Oshchepkov, P.-L. Phan, O. Poplawski, M. Reinecke, E. Sales de Andrade, E. Schnetter, S. Schröder, J. Sierra, A. Vasishta, A. Walker, xoviat, B. Xu (2024). SHTOOLS: Version 4.11, Zenodo, doi:[10.5281/zenodo.592762](https://doi.org/10.5281/zenodo.592762)
+
 ## Version 4.10.4
 
 **Bug fixes, minor enhancements, and deprecations**
diff --git a/docs/pages/mydoc/python-installing.md b/docs/pages/mydoc/python-installing.md
index df962bdd7..7176cb544 100644
--- a/docs/pages/mydoc/python-installing.md
+++ b/docs/pages/mydoc/python-installing.md
@@ -12,14 +12,13 @@ folder: mydoc
 
 The binary pre-compiled pyshtools library, with all required dependencies, can be installed with the conda package manager using the command:
 ```bash
-conda install -c conda-forge pyshtools  # Linux and macOS only
+conda install -c conda-forge pyshtools
 conda update -c conda-forge pyshtools  # to upgrade a pre-existing installation
 ```
-The conda packages do not support Windows architectures at the present time.
 
 ## Python package installer (pip)
 
-On Linux, macOS and Windows architectures, the binary wheels can be installed using `pip` by executing one of the following commands:
+The binary wheels can be installed using `pip` by executing one of the following commands:
 ```bash
 pip install pyshtools
 pip install --upgrade pyshtools  # to upgrade a pre-existing installation
@@ -28,52 +27,62 @@ In order to use the map projection routines, it will be necessary to install eit
 
 ## Build from source
 
-If you wish to compile the archive yourself, first make sure that you have the required dependencies installed for the Fortran-95 components, which inlcude FFTW3 and LAPACK compatible libraries (see [these instructions](fortran-installing.html)). This can be accomplished on most Linux distributions using
+If you wish to compile the archive yourself, you will need to make sure that you have the required dependencies installed, which include a fortran and C compiler, and FFTW3, BLAS and LAPACK compatible libraries. First, ensure that the relevant build utilities and compilers are installed:
 ```bash
-sudo apt-get install gcc gfortran libfftw3-dev libblas-dev liblapack-dev
+# Debian, Ubuntu and derivatives
+sudo apt-get install build-essential cmake gfortran
+# Fedora, Centos, RHEL and derivatives
+sudo dnf group install "C Development Tools and Libraries" "Development Tools"
+sudo dnf install cmake gcc-fortran
+# macOS
+xcode-select --install
 ```
-or on macOS by using one of the following
+Next, clone the SHTOOLS repo and enter the directory
 ```bash
-brew install fftw  # using brew
-sudo port install fftw-3  # using macports
-conda install fftw  # using conda
+git clone https://github.com/SHTOOLS/SHTOOLS.git
+cd shtools
 ```
-Alternatively, all dependencies (with the exception of the fortran compiler) can be installed using the conda `environment.yml` file found in the main shtools Github repository:
+All dependencies can be then be installed using the conda `environment.yml` file that is found in the top level directory:
 ```bash
-conda env create -n your_env_name -f environment.yml
-conda activate your_env_name
+conda create -n your_env_name python=3.xx  # create a new conda environment, if desired
+conda env update -n your_env_name -f environment.yml
+conda activate your_env_name  # activate the new environment
 ```
-Then build from source using the command
+To build pyshtools from source and install in the active Python environment lib folder, use the command
 ```bash
-pip install pyshtools --no-binary pyshtools
+pip install .
 ```
-Note that pyshtools supports the use of any FFTW3-compatible library, such as Intel's [MKL](https://software.intel.com/en-us/mkl).
-
-If you would like to modify the source code, you should clone the SHTOOLS repo:
+To instead install the files in the current working directory in editable mode and link them to the system Python directory, use the command
 ```bash
-git clone https://github.com/SHTOOLS/SHTOOLS.git
+pip install --no-build-isolation -e .
 ```
-Once the repo is cloned, enter the directory, and use either the command
+
+When pyshtools is installed in editable mode, a number of tests and benchmarks can be run from within the repo. First, you will need to find out the name of the build directory by typing
 ```bash
-pip install .
+ls build
 ```
-to install pyshtools in the active Python environment lib folder, or
+which should return something like `cp312`. Then, the tests and benchmarks can be run by executing the following commands in the top level directory
 ```bash
-pip install -e .
+meson test -C build/cp312 --suite python
+meson test -C build/cp312 --suite python-notebooks
+meson test -C build/cp312 --suite fortran
+meson test -C build/cp312 --benchmark --suite python
+meson test -C build/cp312 --benchmark --suite fortran
 ```
-to install the files in the current working directory and link them to the system Python directory.
 
 To uninstall pyshtools from your system directory, use the command
 ```bash
 pip uninstall pyshtools
 ```
-Note that these commands will install only the Python version that corresponds to the version of `pip` being used. On some systems, it may be necessary to specify explicitly `pip3` or `pip3.x`.
+Note that on some systems, it may be necessary to specify explicitly `pip3` or `pip3.x` for the `pip` command.
 
 ## Python dependencies {#dependencies}
 
 When installing pyshtools using `pip` or `conda`, the following packages should be installed automatically:
 
-* [numpy](https://numpy.org/): required for all numerical calculations
+* [numpy](https://numpy.org/): required for all numerical calculations.
+* [meson-python](https://meson-python.readthedocs.io/en/latest/#): required to build pyshtools.
+* [setuptools_scm](https://setuptools-scm.readthedocs.io/en/latest/): required to obtain the pyshtools version number.
 * [scipy](https://www.scipy.org/): required for a few specialized functions.
 * [matplotlib](https://matplotlib.org/): required for most plotting functions.
 * [astropy](https://www.astropy.org/): required for the constants module.
@@ -84,12 +93,28 @@ When installing pyshtools using `pip` or `conda`, the following packages should
 
 When installing pyshtools using `conda`, the following will also be installed automatically:
 
+* [fftw](https://www.fftw.org/): required for the fortran library.
+* [blas-devel](https://anaconda.org/conda-forge/blas-devel): required for the fortran components.
 * [cartopy](https://scitools.org.uk/cartopy/docs/latest/): required for Cartopy map projections. Cartopy requires (see below) *proj*, *geos*, *cython*, *pyshp*, *six*, and *shapely*.
 * [pygmt](https://www.pygmt.org) (>=0.3): required for pygmt map projections. pygmt requires (see below) *gmt (>=6.1.1)*.
 * [ducc0](https://gitlab.mpcdf.mpg.de/mtr/ducc) (>=0.15): required for using the 'ducc' backend for spherical harmonic transforms.
 * [palettable](https://jiffyclub.github.io/palettable/): scientific color maps required by one of the tutorials.
 
-The above four packages will need to be installed separately when installing pyshtools with `pip`, as described in the following subsections.
+Thus, when installing pyshtools with `pip`, it will be necessary to install compatible versions of BLAS, LAPACK and FFTW3, as well as Cartopy, pygmt, and ducc0.
+
+### How to install BLAS, LAPACK and FFTW3
+
+The easiest way to install BLAS, LAPACK and FFTW is with `conda`:
+```bash
+conda install -c conda-forge blas-devel>=3.8 fftw>=3.3.8
+```
+If it is not possible to use conda, these can instead be installed using the system package manager:
+```bash
+sudo apt-get install libfftw3-dev libblas-dev liblapack-dev  # Debian, Ubuntu and derivatives
+sudo dnf install blas-devel lapack-devel fftw-devel  # Fedora, Centos, RHEL and derivatives
+brew install fftw  # macOS
+```
+Note that pyshtools supports the use of any FFTW3-compatible library, such as Intel's [MKL](https://software.intel.com/en-us/mkl).
 
 ### How to install Cartopy
 
@@ -109,6 +134,7 @@ pip install cartopy
 See [these instructions](https://scitools.org.uk/cartopy/docs/latest/installing.html#installing) for further details.
 
 ### How to install pygmt
+
 In order to use the *pygmt* plotting routines, it will be necessary to install both *pygmt (>=0.3)* and the *gmt (>=6.1.1)* library. This is most easily achieved using conda with
 ```bash
 conda install -c conda-forge pygmt gmt
@@ -116,20 +142,23 @@ conda install -c conda-forge pygmt gmt
 Alternatively, *pygmt* can be installed using `pip`
 ```bash
 pip install pyshtools[pygmt]  # installs pygmt at the same time as pyshtools
-pip install pygmt  # if pyshtools is already installed
+pip install pygmt  # install pygmt with pip
 ```
-For this case, the *gmt* library will then need to be installed using other means, such as with brew, macports or apt-get:
+For this case, however, the *gmt* library will need to be installed using other means, such as with your system package manager:
 ```bash
-brew install gmt  # using brew on macOS
-sudo port install gmt6  # using macports on macOS
-sudo apt-get install gmt  # using apt-get on linux
+sudo apt-get install gmt  # Debian, Ubuntu and derivatives
+sudo dnf install gmt-devel  # Fedora, Centos, RHEL and derivatives
+brew install gmt  # macOS using brew
+sudo port install gmt6  # macOS using macports
 ```
 
 ### How to install ducc
-To make use of the 'ducc' backend for the spherical harmonic transforms, it will be necessary to install the *ducc0 (>=0.15)* package, preferably via `pip`:
+
+To make use of the 'ducc' backend for the spherical harmonic transforms, it will be necessary to install the *ducc0 (>=0.15)* package using either `pip` or `conda`:
 ```bash
+conda install -c conda-forge ducc0>=0.15  # install using conda
+pip install ducc0>=0.15  # install using pip
 pip install pyshtools[ducc]  # installs ducc at the same time as pyshtools
-pip install ducc0>=0.15  # if pyshtools is already installed
 pip install ducc0>=0.15 -no-binary ducc0  # install ducc from source
 ```
-Note: By installing *ducc0* from source, it might be possible to benefit from the use of AVX instructions which can improve execution speeds by a factor of about 2.
+Note: By installing *ducc0* from source, it might be possible to benefit from the use of AVX instructions that can improve execution speeds by a factor of about 2.
diff --git a/docs/pages/mydoc/release-notes-v4.md b/docs/pages/mydoc/release-notes-v4.md
index 0cadf2d85..491b988a8 100644
--- a/docs/pages/mydoc/release-notes-v4.md
+++ b/docs/pages/mydoc/release-notes-v4.md
@@ -7,6 +7,27 @@ summary:
 toc: true
 folder: mydoc
 ---
+
+## Version 4.11
+
+**Support for Python 3.12 using Meson**
+
+This version no longer relies on `distutils` (which was deprecated in python 3.12) and instead makes use of [Meson](https://mesonbuild.com/) and [Meson-Python](https://meson-python.readthedocs.io) to build and test the pyshtools package. The package can be built from source using pip as before, however, if you need to create an editable install, it will be necessary to use the slightly modified command
+```bash
+pip install --no-build-isolation -e .
+```
+Please see the online documentation for instructions on how to run the test suites and benchmarks.
+
+**Other changes**
+
+* We no longer use `versioneer` to determine the package version, but instead set the version in the main `meson.build` file using `setuptools_scm`. At the present time, it is not possible to determine the version when using a source tarball, and for this case, the build will fail. Please ensure that when building from source that you are doing so from a git versioned repository.
+* Fixed a problem with `SHCoeffs.volume()` when the coefficient normalization was `ortho`.
+* Fixed a potential LAPACK underscore problem when compiling with `LAPACK_UNDERSCORE` specified.
+* Minor changes were made to the python source files to ensure numpy v2 compatibility.
+
+M. A. Wieczorek, M. Meschede, A. Broquet, T. Brugere, A. Corbin, EricAtORS, A. Hattori, A. Kalinin, J. Kohler, D. Kutra, K. Leinweber, P. Lobo, I. Oshchepkov, P.-L. Phan, O. Poplawski, M. Reinecke, E. Sales de Andrade, E. Schnetter, S. Schröder, J. Sierra, A. Vasishta, A. Walker, xoviat, B. Xu (2024). SHTOOLS: Version 4.11, Zenodo, doi:[10.5281/zenodo.592762](https://doi.org/10.5281/zenodo.592762)
+
+
 ## Version 4.10.4
 
 **Bug fixes, minor enhancements, and deprecations**
diff --git a/environment-dev.yml b/environment-dev.yml
deleted file mode 100644
index ded36f2bb..000000000
--- a/environment-dev.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-channels:
-    - conda-forge
-dependencies:
-    - fftw>=3.3.8
-    - liblapack>=3.8
-    - numpy
-    - scipy>=0.14.0
-    - matplotlib-base>=3.3
-    - astropy>=4.0
-    - xarray
-    - requests
-    - pooch>=1.1
-    - tqdm
-    - cartopy>=0.18.0
-    - gmt>=6.1.1
-    - pygmt>=0.3.0
-    - palettable>=3.3
-    - jupyter
-    - pip
-    - ducc0>=0.15
-    - flake8
diff --git a/environment.yml b/environment.yml
index 3d3ccbd7e..b7f48dc5d 100644
--- a/environment.yml
+++ b/environment.yml
@@ -1,8 +1,11 @@
 channels:
     - conda-forge
 dependencies:
+    - pkg-config
+    - meson-python>=0.14
+    - setuptools_scm>=8
     - fftw>=3.3.8
-    - liblapack>=3.8
+    - blas-devel>=3.8
     - numpy
     - scipy>=0.14.0
     - matplotlib-base>=3.3
@@ -14,7 +17,8 @@ dependencies:
     - cartopy>=0.18.0
     - gmt>=6.1.1
     - pygmt>=0.3.0
+    - ducc0>=0.15
     - palettable>=3.3
     - jupyter
     - pip
-    - ducc0>=0.15
+    - flake8
diff --git a/examples/cpp/meson.build b/examples/cpp/meson.build
new file mode 100644
index 000000000..b8b0a4d79
--- /dev/null
+++ b/examples/cpp/meson.build
@@ -0,0 +1,10 @@
+add_languages('cpp', native: false)
+
+cpptest = executable('cpptest',
+  'test.cpp',
+  include_directories: main_incdir,
+  link_with: shtools,
+  build_by_default: false)
+
+# FIXME: Add this when the file actually compiles.
+# test('cpptest', cpptest, args: [meson.current_source_dir() / '../ExampleDataFiles'])
diff --git a/examples/fortran/MarsCrustalThickness/MarsCrustalThickness.f95 b/examples/fortran/MarsCrustalThickness/MarsCrustalThickness.f95
index fe387ba53..f74892b55 100644
--- a/examples/fortran/MarsCrustalThickness/MarsCrustalThickness.f95
+++ b/examples/fortran/MarsCrustalThickness/MarsCrustalThickness.f95
@@ -14,7 +14,7 @@ program MarsCrustalThickness
 !   approximation is probably ok, espeically considering that the iterations
 !   are filtered.
 !
-!   In order to improve stability when iterating for the Moho relief, the 
+!   In order to improve stability when iterating for the Moho relief, the
 !   following iterative scheme is used:
 !
 !       h3 = (h2+h1)/2
@@ -43,7 +43,7 @@ program MarsCrustalThickness
     integer(int32) :: l, m, lmax, i, nmax, nlat, nlong, gridtype, astat(12), &
                       n_out, iter, j, r1, lmaxp, lmaxt, filter_type, half, &
                       degmax, sampling
-    character(120) :: grav_file, moho_out, thick_grid_out, topo_file, &
+    character(240) :: grav_file, moho_out, thick_grid_out, topo_file, &
                       misfit_file, infile
 
     ! Path to example data files may be passed as first argument, or use a default.
@@ -149,7 +149,7 @@ program MarsCrustalThickness
 
     !--------------------------------------------------------------------------
     !
-    !    Read topo and grav files 
+    !    Read topo and grav files
     !
     !--------------------------------------------------------------------------
 
@@ -184,7 +184,7 @@ program MarsCrustalThickness
     !--------------------------------------------------------------------------
 
     print*, "Creating Bouger anomaly"
-    
+
     call MakeGridDH(topo_grid, n_out, topo_c, lmax, norm = 1, &
                     sampling = sampling, csphase = 1, lmax_calc = degmax)
 
diff --git a/examples/fortran/MarsCrustalThickness/meson.build b/examples/fortran/MarsCrustalThickness/meson.build
new file mode 100644
index 000000000..9de7978a3
--- /dev/null
+++ b/examples/fortran/MarsCrustalThickness/meson.build
@@ -0,0 +1,13 @@
+TestMarsCrustalThickness = executable(
+  'MarsCrustalThickness',
+  'MarsCrustalThickness.f95',
+  link_with: shtools)
+
+test(
+  'MarsCrustalThickness',
+  TestMarsCrustalThickness,
+  args: [
+    meson.current_source_dir() / '../../ExampleDataFiles',
+    meson.current_source_dir() / 'input.txt',
+  ],
+  suite: 'fortran')
diff --git a/examples/fortran/SHCilmPlus/TestCilmPlus.f95 b/examples/fortran/SHCilmPlus/TestCilmPlus.f95
index d83ff0d56..d4fedc0a0 100644
--- a/examples/fortran/SHCilmPlus/TestCilmPlus.f95
+++ b/examples/fortran/SHCilmPlus/TestCilmPlus.f95
@@ -61,7 +61,7 @@ program TestCilmPlus
     real(dp), allocatable :: plxn(:,:),  plx(:,:)
     integer(int32) :: lmax, i, j, l, m, nlat, nlong, nmax, n, astat, &
                       lmaxfile, lmaxn, nlatn, nlongn, precomputeplx
-    character(200) :: infile, outfile
+    character(240) :: infile, outfile
 
     call cpu_time(timein)
 
@@ -192,7 +192,7 @@ program TestCilmPlus
 
     !--------------------------------------------------------------------------
     !
-    !    Next, compute the maximum error in the space domain 
+    !    Next, compute the maximum error in the space domain
     !    at the gauss points.
     !
     !--------------------------------------------------------------------------
diff --git a/examples/fortran/SHCilmPlus/meson.build b/examples/fortran/SHCilmPlus/meson.build
new file mode 100644
index 000000000..d8470bbd1
--- /dev/null
+++ b/examples/fortran/SHCilmPlus/meson.build
@@ -0,0 +1,13 @@
+TestCilmPlus = executable(
+  'TestCilmPlus',
+  'TestCilmPlus.f95',
+  link_with: shtools)
+
+test(
+  'CilmPlus',
+  TestCilmPlus,
+  args: [
+    meson.current_source_dir() / '../../ExampleDataFiles',
+  ],
+  timeout: 120,
+  suite: 'fortran')
diff --git a/examples/fortran/SHExpandDH/TestExpandDH.f95 b/examples/fortran/SHExpandDH/TestExpandDH.f95
index 93a5dd235..ad26e7af5 100644
--- a/examples/fortran/SHExpandDH/TestExpandDH.f95
+++ b/examples/fortran/SHExpandDH/TestExpandDH.f95
@@ -14,7 +14,7 @@ Program TestExpandDH
 
     implicit none
     integer(int32), parameter :: maxdeg = 120, maxgrid = 800
-    character(120) :: infile
+    character(240) :: infile
     real(dp) :: cilm(2, maxdeg+1, maxdeg+1), grid(maxgrid, maxgrid), &
                 griddh(maxgrid, maxgrid), cilm2(2, maxdeg+1, maxdeg+1), &
                 interval, error, maxerror
diff --git a/examples/fortran/SHExpandDH/meson.build b/examples/fortran/SHExpandDH/meson.build
new file mode 100644
index 000000000..c27c8a2fe
--- /dev/null
+++ b/examples/fortran/SHExpandDH/meson.build
@@ -0,0 +1,12 @@
+TestExpandDH = executable(
+  'TestExpandDH',
+  'TestExpandDH.f95',
+  link_with: shtools)
+
+test(
+  'ExpandDH',
+  TestExpandDH,
+  args: [
+    meson.current_source_dir() / '../../ExampleDataFiles',
+  ],
+  suite: 'fortran')
diff --git a/examples/fortran/SHExpandLSQ/TestSHExpandLSQ.f95 b/examples/fortran/SHExpandLSQ/TestSHExpandLSQ.f95
index 8db9a5eb8..bb7be9700 100644
--- a/examples/fortran/SHExpandLSQ/TestSHExpandLSQ.f95
+++ b/examples/fortran/SHExpandLSQ/TestSHExpandLSQ.f95
@@ -22,7 +22,7 @@ program TestSHExpandLSQ
                 x, y, z, pi, maxerror, cilm1(2,degmax+1, degmax+1), &
                 dd(dmax), misfit
     integer(int32) :: nmax, lmax, l, i, seed, lmaxfile
-    character(120) :: infile
+    character(240) :: infile
 
     d = 0.0_dp
     dd = 0.0_dp
diff --git a/examples/fortran/SHExpandLSQ/meson.build b/examples/fortran/SHExpandLSQ/meson.build
new file mode 100644
index 000000000..943f0011f
--- /dev/null
+++ b/examples/fortran/SHExpandLSQ/meson.build
@@ -0,0 +1,13 @@
+TestSHExpandLSQ = executable(
+  'TestSHExpandLSQ',
+  'TestSHExpandLSQ.f95',
+  link_with: shtools)
+
+test(
+  'SHExpandLSQ',
+  TestSHExpandLSQ,
+  args: [
+    meson.current_source_dir() / '../../ExampleDataFiles',
+    meson.current_source_dir() / 'input.txt',
+  ],
+  suite: 'fortran')
diff --git a/examples/fortran/SHLocalizedAdmitCorr/LocalizedAdmitCorr.f95 b/examples/fortran/SHLocalizedAdmitCorr/LocalizedAdmitCorr.f95
index fb15d3b56..3869d9433 100644
--- a/examples/fortran/SHLocalizedAdmitCorr/LocalizedAdmitCorr.f95
+++ b/examples/fortran/SHLocalizedAdmitCorr/LocalizedAdmitCorr.f95
@@ -14,7 +14,7 @@ Program LocalizedAdmitCorr
 
     implicit none
 
-    character(120) :: infile, topography_file, potential_file, outfile
+    character(240) :: infile, topography_file, potential_file, outfile
     real(dp) :: header(8), mpr,  r0_pot, gm, mass, lat, lon, pi, theta0, &
                 alpha, sn, r
     real(dp), allocatable :: grav(:,:,:), admit(:), corr(:), admit_error(:), &
diff --git a/examples/fortran/SHLocalizedAdmitCorr/meson.build b/examples/fortran/SHLocalizedAdmitCorr/meson.build
new file mode 100644
index 000000000..f1ed50d05
--- /dev/null
+++ b/examples/fortran/SHLocalizedAdmitCorr/meson.build
@@ -0,0 +1,14 @@
+TestLocalizedAdmitCorr = executable(
+  'LocalizedAdmitCorr',
+  'LocalizedAdmitCorr.f95',
+  link_with: shtools)
+
+test(
+  'LocalizedAdmitCorr',
+  TestLocalizedAdmitCorr,
+  args: [
+    meson.current_source_dir() / '../../ExampleDataFiles',
+    meson.current_source_dir() / 'input.txt',
+  ],
+  timeout: 120,
+  suite: 'fortran')
diff --git a/examples/fortran/SHMag/SHMag.f95 b/examples/fortran/SHMag/SHMag.f95
index 92926a9de..d659bee3f 100644
--- a/examples/fortran/SHMag/SHMag.f95
+++ b/examples/fortran/SHMag/SHMag.f95
@@ -19,7 +19,7 @@ program SHMag
 
     implicit none
 
-    character(200) :: infile, radf, thetaf, phif, totalf, potf
+    character(240) :: infile, radf, thetaf, phif, totalf, potf
     real(dp) :: header(4), interval, r0, a, f, mpr, z, timein, timeout, temp
     real(dp), allocatable :: glm(:,:,:), rad(:,:), phi(:,:), theta(:,:), &
                              total(:,:), pot(:,:)
@@ -126,7 +126,7 @@ program SHMag
         write(16,*) pot(i,1)
     end do
 
-    ! write out values at 90 S, which are not calculated in the Driscoll and 
+    ! write out values at 90 S, which are not calculated in the Driscoll and
     ! Healy routine, and which are just the average of the values of the last row.
     temp = sum(rad(nlat,1:nlong)) / dble(nlong)
     do j = 1, nlong + 1
diff --git a/examples/fortran/SHMag/meson.build b/examples/fortran/SHMag/meson.build
new file mode 100644
index 000000000..bd80d442d
--- /dev/null
+++ b/examples/fortran/SHMag/meson.build
@@ -0,0 +1,13 @@
+TestSHMag = executable(
+  'SHMag',
+  'SHMag.f95',
+  link_with: shtools)
+
+test(
+  'SHMag',
+  TestSHMag,
+  args: [
+    meson.current_source_dir() / '../../ExampleDataFiles',
+  ],
+  timeout: 60,
+  suite: 'fortran')
diff --git a/examples/fortran/SHRotate/TestSHRotate.f95 b/examples/fortran/SHRotate/TestSHRotate.f95
index b5d8cb34e..7ca68175f 100644
--- a/examples/fortran/SHRotate/TestSHRotate.f95
+++ b/examples/fortran/SHRotate/TestSHRotate.f95
@@ -15,7 +15,7 @@ program TestSHRotate
 
     real(dp) :: x(3), pi, interval, alpha, beta, gamma
     real(dp), allocatable :: cilm1(:,:,:), cilm2(:,:,:), dj(:,:,:), grid(:,:)
-    character(120) :: outsh, outgrid, infile
+    character(240) :: outsh, outgrid, infile
     integer(int32) :: lmax, nlat, nlong, i, j, l, m, bodycoord, astat(4)
 
     pi = acos(-1.0_dp)
diff --git a/examples/fortran/SHRotate/meson.build b/examples/fortran/SHRotate/meson.build
new file mode 100644
index 000000000..4be00768a
--- /dev/null
+++ b/examples/fortran/SHRotate/meson.build
@@ -0,0 +1,13 @@
+TestSHRotate = executable(
+  'TestSHRotate',
+  'TestSHRotate.f95',
+  link_with: shtools)
+
+test(
+  'SHRotate',
+  TestSHRotate,
+  args: [
+    meson.current_source_dir() / '../../ExampleDataFiles',
+    meson.current_source_dir() / 'input.txt',
+  ],
+  suite: 'fortran')
diff --git a/examples/fortran/TimingAccuracy/TimingAccuracyDH.f95 b/examples/fortran/TimingAccuracy/TimingAccuracyDH.f95
index 95a6f9fd3..d48894a21 100644
--- a/examples/fortran/TimingAccuracy/TimingAccuracyDH.f95
+++ b/examples/fortran/TimingAccuracy/TimingAccuracyDH.f95
@@ -16,7 +16,7 @@ Program TimingAccuracyDH
     implicit none
 
     integer(int32), parameter :: maxdeg = 2800
-    character(200) :: outfile1, outfile2, outfile3, outfile4, outfile
+    character(240) :: outfile1, outfile2, outfile3, outfile4, outfile, infile
     real(dp), allocatable :: cilm(:,:,:), cilm2(:,:,:), griddh(:,:)
     real(dp) :: maxerror, err1, err2, beta, rms, timein(3), timeout(3)
     integer(int32) :: lmax, l, m, seed, n, sampling, lmaxout, astat(3)
@@ -32,11 +32,20 @@ Program TimingAccuracyDH
     end if
 
     sampling = 1
-    print*, "Value of beta for power law Sff = l^(-beta) > "
-    read(*,*) beta
 
-    print*, "output file name > "
-    read(*,*) outfile
+    ! A data input file may be passed as the first argument. Otherwise prompt for required settings.
+    if (command_argument_count() > 0) then
+        call get_command_argument(1, infile)
+        open(unit=20, file=infile, action="read")
+        read(20,*) beta, outfile
+        close(20)
+    else
+        print*, "Value of beta for power law Sff = l^(-beta) > "
+        read(*,*) beta
+
+        print*, "output file name > "
+        read(*,*) outfile
+    end if
 
     outfile1 = trim(outfile) // ".timef"
     outfile2 = trim(outfile) // ".timei"
diff --git a/examples/fortran/TimingAccuracy/TimingAccuracyDHC.f95 b/examples/fortran/TimingAccuracy/TimingAccuracyDHC.f95
index 77a21942e..d5300c2ba 100644
--- a/examples/fortran/TimingAccuracy/TimingAccuracyDHC.f95
+++ b/examples/fortran/TimingAccuracy/TimingAccuracyDHC.f95
@@ -16,7 +16,7 @@ Program TimingAccuracyDHC
     implicit none
 
     integer(int32), parameter :: maxdeg = 2800
-    character(200) :: outfile1, outfile2, outfile3, outfile4, outfile
+    character(240) :: outfile1, outfile2, outfile3, outfile4, outfile, infile
     complex(dp), allocatable :: cilm(:,:,:), cilm2(:,:,:), griddh(:,:)
     real(dp) :: maxerror, err1, err2, beta, rms, timein(3), timeout(3)
     integer(int32) :: lmax, l, m, seed, n, sampling, lmaxout, astat(3)
@@ -32,11 +32,20 @@ Program TimingAccuracyDHC
     end if
 
     sampling = 1
-    print*, "Value of beta for power law Sff = l^(-beta) > "
-    read(*,*) beta
 
-    print*, "output file name > "
-    read(*,*) outfile
+    ! A data input file may be passed as the first argument. Otherwise prompt for required settings.
+    if (command_argument_count() > 0) then
+        call get_command_argument(1, infile)
+        open(unit=20, file=infile, action="read")
+        read(20,*) beta, outfile
+        close(20)
+    else
+        print*, "Value of beta for power law Sff = l^(-beta) > "
+        read(*,*) beta
+
+        print*, "output file name > "
+        read(*,*) outfile
+    end if
 
     outfile1 = trim(outfile) // ".timef"
     outfile2 = trim(outfile) // ".timei"
diff --git a/examples/fortran/TimingAccuracy/TimingAccuracyGLQ.f95 b/examples/fortran/TimingAccuracy/TimingAccuracyGLQ.f95
index a0e4bb35b..895a038d6 100644
--- a/examples/fortran/TimingAccuracy/TimingAccuracyGLQ.f95
+++ b/examples/fortran/TimingAccuracy/TimingAccuracyGLQ.f95
@@ -16,7 +16,7 @@ Program TimingAccuracyGLQ
     implicit none
 
     integer(int32), parameter :: maxdeg = 2800
-    character(200) :: outfile1, outfile2, outfile3, outfile4, outfile
+    character(240) :: outfile1, outfile2, outfile3, outfile4, outfile, infile
     real(dp), allocatable :: cilm(:,:,:), cilm2(:,:,:), zero(:), &
                              gridglq(:,:), w(:)
     real(dp) :: maxerror, err1, err2, beta, rms, timein(3), timeout(3)
@@ -34,11 +34,19 @@ Program TimingAccuracyGLQ
         stop
     end if
 
-    print*, "Value of beta for power law Sff = l^(-beta) > "
-    read(*,*) beta
-
-    print*, "output file name > "
-    read(*,*) outfile
+    ! A data input file may be passed as the first argument. Otherwise prompt for required settings.
+    if (command_argument_count() > 0) then
+        call get_command_argument(1, infile)
+        open(unit=20, file=infile, action="read")
+        read(20,*) beta, outfile
+        close(20)
+    else
+        print*, "Value of beta for power law Sff = l^(-beta) > "
+        read(*,*) beta
+
+        print*, "output file name > "
+        read(*,*) outfile
+    end if
 
     outfile1 = trim(outfile) // ".timef"
     outfile2 = trim(outfile) // ".timei"
diff --git a/examples/fortran/TimingAccuracy/TimingAccuracyGLQC.f95 b/examples/fortran/TimingAccuracy/TimingAccuracyGLQC.f95
index ca741215e..7cdaa0ae6 100644
--- a/examples/fortran/TimingAccuracy/TimingAccuracyGLQC.f95
+++ b/examples/fortran/TimingAccuracy/TimingAccuracyGLQC.f95
@@ -16,7 +16,7 @@ Program TimingAccuracyGLQC
     implicit none
 
     integer(int32), parameter :: maxdeg = 2800
-    character(200) :: outfile1, outfile2, outfile3, outfile4, outfile
+    character(240) :: outfile1, outfile2, outfile3, outfile4, outfile, infile
     complex(dp), allocatable :: cilm(:,:,:), cilm2(:,:,:), gridglq(:,:)
     real(dp), allocatable :: zero(:), w(:)
     real(dp) :: maxerror, err1, err2, beta, rms, timein(3), timeout(3)
@@ -34,11 +34,19 @@ Program TimingAccuracyGLQC
         stop
     end if
 
-    print*, "Value of beta for power law Sff = l^(-beta) > "
-    read(*,*) beta
-
-    print*, "output file name > "
-    read(*,*) outfile
+    ! A data input file may be passed as the first argument. Otherwise prompt for required settings.
+    if (command_argument_count() > 0) then
+        call get_command_argument(1, infile)
+        open(unit=20, file=infile, action="read")
+        read(20,*) beta, outfile
+        close(20)
+    else
+        print*, "Value of beta for power law Sff = l^(-beta) > "
+        read(*,*) beta
+
+        print*, "output file name > "
+        read(*,*) outfile
+    end if
 
     outfile1 = trim(outfile) // ".timef"
     outfile2 = trim(outfile) // ".timei"
diff --git a/examples/fortran/TimingAccuracy/meson.build b/examples/fortran/TimingAccuracy/meson.build
new file mode 100644
index 000000000..67cca7235
--- /dev/null
+++ b/examples/fortran/TimingAccuracy/meson.build
@@ -0,0 +1,32 @@
+timing_tests = {}
+
+foreach timing: ['TimingAccuracyGLQ', 'TimingAccuracyDH', 'TimingAccuracyDHC', 'TimingAccuracyGLQC']
+  e = executable(
+    timing,
+    f'@timing@.f95',
+    link_with: shtools)
+  timing_tests += {timing: e}
+endforeach
+
+BENCHS = {
+  'TimingAccuracyGLQ1': ['TimingAccuracyGLQ', 'input1'],
+  'TimingAccuracyGLQ2': ['TimingAccuracyGLQ', 'input2'],
+  'TimingAccuracyDH1': ['TimingAccuracyDH', 'input3'],
+  'TimingAccuracyDH2': ['TimingAccuracyDH', 'input4'],
+  'TimingAccuracyDHC1': ['TimingAccuracyDHC', 'input5'],
+  'TimingAccuracyDHC2': ['TimingAccuracyDHC', 'input6'],
+  'TimingAccuracyGLQC1': ['TimingAccuracyGLQC', 'input7'],
+  'TimingAccuracyGLQC2': ['TimingAccuracyGLQC', 'input8'],
+}
+foreach name, args : BENCHS
+  test_name = args[0]
+  input = args[1]
+  benchmark(
+    name,
+    timing_tests[test_name],
+    args: [
+      meson.current_source_dir() / input,
+    ],
+    timeout: 0,
+    suite: 'fortran')
+endforeach
diff --git a/examples/fortran/meson.build b/examples/fortran/meson.build
new file mode 100644
index 000000000..ff6537c00
--- /dev/null
+++ b/examples/fortran/meson.build
@@ -0,0 +1,8 @@
+subdir('MarsCrustalThickness')
+subdir('SHCilmPlus')
+subdir('SHExpandDH')
+subdir('SHExpandLSQ')
+subdir('SHLocalizedAdmitCorr')
+subdir('SHMag')
+subdir('SHRotate')
+subdir('TimingAccuracy')
diff --git a/examples/meson.build b/examples/meson.build
new file mode 100644
index 000000000..89bccfdab
--- /dev/null
+++ b/examples/meson.build
@@ -0,0 +1,4 @@
+subdir('cpp')
+subdir('fortran')
+subdir('python')
+subdir('notebooks')
diff --git a/examples/notebooks/meson.build b/examples/notebooks/meson.build
new file mode 100644
index 000000000..9c59d9650
--- /dev/null
+++ b/examples/notebooks/meson.build
@@ -0,0 +1,27 @@
+jupyter = find_program('jupyter')
+
+ipynb_files = [
+  'grids-and-coefficients.ipynb',
+  'localized-spectral-analysis.ipynb',
+  'gravity-and-magnetic-fields.ipynb',
+  'plotting-maps.ipynb',
+  'low-level-spherical-harmonic-analyses.ipynb',
+  'advanced-localized-spectral-analysis.ipynb',
+  'advanced-shcoeffs-and-shgrid-usage.ipynb',
+  'spherical-harmonic-normalizations.ipynb',
+  'advanced-shwindow-usage.ipynb',
+  '3d-plots.ipynb',
+]
+
+foreach file : ipynb_files
+  test_name = file.split('.')[0]
+  test(
+    test_name,
+    jupyter,
+    args: [
+      'execute',
+      meson.current_source_dir() / file
+    ],
+    timeout: 0,
+    suite: 'python-notebooks')
+endforeach
diff --git a/examples/python/ClassInterface/WindowExample.py b/examples/python/ClassInterface/WindowExample.py
index 23a97a111..ab1d8dc96 100755
--- a/examples/python/ClassInterface/WindowExample.py
+++ b/examples/python/ClassInterface/WindowExample.py
@@ -1,6 +1,8 @@
 """
 This script tests the python class interface
 """
+import sys
+import os
 import pyshtools as pysh
 
 pysh.utils.figstyle()
@@ -31,8 +33,13 @@ def example2():
     lmax = 15
     nwins = 15
 
-    coeffs = pysh.SHCoeffs.from_file(
-        '../../ExampleDataFiles/srtmp300.msl')
+    topofile = 'srtmp300.msl'
+    if len(sys.argv) > 1:
+        topofile = os.path.join(sys.argv[1], topofile)
+    else:
+        topofile = os.path.join('../../ExampleDataFiles', topofile)
+
+    coeffs = pysh.SHCoeffs.from_file(topofile)
     topo = coeffs.expand(grid='DH2')
     dh_mask = topo.data > 0.
     print(dh_mask.shape)
diff --git a/examples/python/ClassInterface/exact_power.py b/examples/python/ClassInterface/exact_power.py
index 639690be9..d62962aee 100755
--- a/examples/python/ClassInterface/exact_power.py
+++ b/examples/python/ClassInterface/exact_power.py
@@ -23,7 +23,7 @@ def example():
     ax.grid(which='both')
     ax.legend()
 
-    plt.show()
+    plt.savefig('exact_power.png')
 
 
 def main():
diff --git a/examples/python/ClassInterface/meson.build b/examples/python/ClassInterface/meson.build
new file mode 100644
index 000000000..bdd2cc3d2
--- /dev/null
+++ b/examples/python/ClassInterface/meson.build
@@ -0,0 +1,21 @@
+test(
+  'ClassExample',
+  python,
+  args: files('ClassExample.py'),
+  timeout: 120,
+  suite: 'python')
+
+test(
+  'ExactPower',
+  python,
+  args: files('exact_power.py'),
+  timeout: 60,
+  suite: 'python')
+
+test(
+  'WindowExample',
+  python,
+  args: [files('WindowExample.py'),
+         meson.current_source_dir() / '../../ExampleDataFiles'],
+  timeout: 120,
+  suite: 'python')
diff --git a/examples/python/GlobalSpectralAnalysis/GlobalSpectralAnalysis.py b/examples/python/GlobalSpectralAnalysis/GlobalSpectralAnalysis.py
index d34dd044d..0079726bf 100755
--- a/examples/python/GlobalSpectralAnalysis/GlobalSpectralAnalysis.py
+++ b/examples/python/GlobalSpectralAnalysis/GlobalSpectralAnalysis.py
@@ -2,6 +2,7 @@
 This script tests the different Spherical Harmonics Transforms on the Mars
 topography data set
 """
+import sys
 import os
 import numpy as np
 import matplotlib.pyplot as plt
@@ -22,9 +23,13 @@ def example():
     example that plots the power spectrum of Mars topography data
     """
     # --- input data filename ---
-    infile = os.path.join(os.path.dirname(__file__),
-                          '../../ExampleDataFiles/MarsTopo719.shape')
-    coeffs, lmax = pysh.shio.shread(infile)
+    topofile = 'MarsTopo719.shape'
+    if len(sys.argv) > 1:
+        topofile = os.path.join(sys.argv[1], topofile)
+    else:
+        topofile = os.path.join('../../ExampleDataFiles', topofile)
+
+    coeffs, lmax = pysh.shio.shread(topofile)
 
     # --- plot grid ---
     grid = pysh.expand.MakeGridDH(coeffs, csphase=-1)
diff --git a/examples/python/GlobalSpectralAnalysis/meson.build b/examples/python/GlobalSpectralAnalysis/meson.build
new file mode 100644
index 000000000..097c8be21
--- /dev/null
+++ b/examples/python/GlobalSpectralAnalysis/meson.build
@@ -0,0 +1,7 @@
+test(
+  'GlobalSpectralAnalysis',
+  python,
+  args: [files('GlobalSpectralAnalysis.py'),
+         meson.current_source_dir() / '../../ExampleDataFiles'],
+  timeout: 60,
+  suite: 'python')
diff --git a/examples/python/GravMag/TestCT.py b/examples/python/GravMag/TestCT.py
index 5f85cd774..1cc24546c 100755
--- a/examples/python/GravMag/TestCT.py
+++ b/examples/python/GravMag/TestCT.py
@@ -1,6 +1,8 @@
 """
 This script creates a crustal thickness map of Mars.
 """
+import sys
+import os
 import numpy as np
 import matplotlib.pyplot as plt
 import pyshtools as pysh
@@ -29,14 +31,24 @@ def TestCrustalThickness():
     filter_type = 0
     half = 0
 
-    gravfile = '../../ExampleDataFiles/gmm3_120_sha.tab'
+    gravfile = 'gmm3_120_sha.tab'
+    if len(sys.argv) > 1:
+        gravfile = os.path.join(sys.argv[1], gravfile)
+    else:
+        gravfile = os.path.join('../../ExampleDataFiles', gravfile)
+
     pot, lmaxp, header = pysh.shio.shread(gravfile, lmax=degmax, header=True)
     gm = float(header[1]) * 1.e9
     mass = gm / pysh.constants.G.value
     r_grav = float(header[0]) * 1.e3
     print(r_grav, gm, mass, lmaxp)
 
-    topofile = '../../ExampleDataFiles/MarsTopo719.shape'
+    topofile = 'MarsTopo719.shape'
+    if len(sys.argv) > 1:
+        topofile = os.path.join(sys.argv[1], topofile)
+    else:
+        topofile = os.path.join('../../ExampleDataFiles', topofile)
+
     hlm, lmaxt = pysh.shio.shread(topofile)
     r0 = hlm[0, 0, 0]
     d = r0 - 45.217409924028445e3
diff --git a/examples/python/GravMag/TestGrav.py b/examples/python/GravMag/TestGrav.py
index 2c8415dce..eea8ebe29 100755
--- a/examples/python/GravMag/TestGrav.py
+++ b/examples/python/GravMag/TestGrav.py
@@ -1,6 +1,8 @@
 """
 This script tests the gravity and magnetics routines.
 """
+import sys
+import os
 import numpy as np
 import matplotlib.pyplot as plt
 import pyshtools as pysh
@@ -21,8 +23,13 @@ def main():
 # ==== TEST FUNCTIONS ====
 
 def TestMakeGravGrid():
-    infile = '../../ExampleDataFiles/gmm3_120_sha.tab'
-    clm, lmax, header = pysh.shio.shread(infile, header=True)
+    gravfile = 'gmm3_120_sha.tab'
+    if len(sys.argv) > 1:
+        gravfile = os.path.join(sys.argv[1], gravfile)
+    else:
+        gravfile = os.path.join('../../ExampleDataFiles', gravfile)
+
+    clm, lmax, header = pysh.shio.shread(gravfile, header=True)
     r0 = float(header[0]) * 1.e3
     gm = float(header[1]) * 1.e9
     clm[0, 0, 0] = 1.0
@@ -128,8 +135,13 @@ def TestFilter():
 
 
 def TestMakeMagGrid():
-    infile = '../../ExampleDataFiles/FSU_mars90.sh'
-    clm, lmax, header = pysh.shio.shread(infile, header=True, skip=1)
+    magfile = 'FSU_mars90.sh'
+    if len(sys.argv) > 1:
+        magfile = os.path.join(sys.argv[1], magfile)
+    else:
+        magfile = os.path.join('../../ExampleDataFiles/', magfile)
+
+    clm, lmax, header = pysh.shio.shread(magfile, header=True, skip=1)
     r0 = float(header[0]) * 1.e3
     a = pysh.constants.Mars.mean_radius.value + 145.0e3
     # radius to evaluate the field
diff --git a/examples/python/GravMag/meson.build b/examples/python/GravMag/meson.build
new file mode 100644
index 000000000..26ffbb6e4
--- /dev/null
+++ b/examples/python/GravMag/meson.build
@@ -0,0 +1,15 @@
+test(
+  'TestCT',
+  python,
+  args: [files('TestCT.py'),
+         meson.current_source_dir() / '../../ExampleDataFiles'],
+  timeout: 60,
+  suite: 'python')
+
+test(
+  'TestGrav',
+  python,
+  args: [files('TestGrav.py'),
+         meson.current_source_dir() / '../../ExampleDataFiles'],
+  timeout: 120,
+  suite: 'python')
diff --git a/examples/python/IOStorageConversions/SHConversions.py b/examples/python/IOStorageConversions/SHConversions.py
index 38c7d932d..0ed77aed1 100755
--- a/examples/python/IOStorageConversions/SHConversions.py
+++ b/examples/python/IOStorageConversions/SHConversions.py
@@ -2,6 +2,8 @@
 This script tests the conversions between real and complex spherical harmonics
 coefficients
 """
+import sys
+import os
 import numpy as np
 import matplotlib.pyplot as plt
 import pyshtools as pysh
@@ -31,8 +33,13 @@ def test_SHConversions():
 def example():
     print('---- SHrtoc example ----')
     # --- input data filename ---
-    infile = '../../ExampleDataFiles/MarsTopo719.shape'
-    coeffs1, lmax = pysh.shio.shread(infile)
+    topofile = 'MarsTopo719.shape'
+    if len(sys.argv) > 1:
+        topofile = os.path.join(sys.argv[1], topofile)
+    else:
+        topofile = os.path.join('../../ExampleDataFiles', topofile)
+
+    coeffs1, lmax = pysh.shio.shread(topofile)
     coeffs1 = coeffs1[:, :lmax + 1, :lmax + 1]
 
     # --- convert to complex coefficients, fill negative order coefficients ---
diff --git a/examples/python/IOStorageConversions/meson.build b/examples/python/IOStorageConversions/meson.build
new file mode 100644
index 000000000..28b77eafb
--- /dev/null
+++ b/examples/python/IOStorageConversions/meson.build
@@ -0,0 +1,13 @@
+test(
+  'SHConversions',
+  python,
+  args: [files('SHConversions.py'),
+         meson.current_source_dir() / '../../ExampleDataFiles'],
+  timeout: 60,
+  suite: 'python')
+
+test(
+  'SHStorage',
+  python,
+  args: files('SHStorage.py'),
+  suite: 'python')
diff --git a/examples/python/LocalizedSpectralAnalysis/meson.build b/examples/python/LocalizedSpectralAnalysis/meson.build
new file mode 100644
index 000000000..729cf2d93
--- /dev/null
+++ b/examples/python/LocalizedSpectralAnalysis/meson.build
@@ -0,0 +1,18 @@
+test(
+  'SHMTCouplingMatrix',
+  python,
+  args: files('SHMTCouplingMatrix.py'),
+  suite: 'python')
+
+test(
+  'SHMultitaperSE',
+  python,
+  args: files('SHMultitaperSE.py'),
+  suite: 'python')
+
+test(
+  'SHWindowsBiasOther',
+  python,
+  args: files('SHWindowsBiasOther.py'),
+  timeout: 60,
+  suite: 'python')
diff --git a/examples/python/Other/TestOther.py b/examples/python/Other/TestOther.py
index 810d6f283..562cd6ccd 100755
--- a/examples/python/Other/TestOther.py
+++ b/examples/python/Other/TestOther.py
@@ -1,6 +1,8 @@
 """
 This script tests the gravity and magnetics routines.
 """
+import sys
+import os
 import numpy as np
 import matplotlib.pyplot as plt
 import pyshtools as pysh
@@ -47,8 +49,13 @@ def TestWigner():
 
 
 def TestSHExpandWLSQ():
-    file = "../../ExampleDataFiles/MarsTopo719.shape"
-    clm = pysh.SHCoeffs.from_file(file, lmax=9)
+    topofile = 'MarsTopo719.shape'
+    if len(sys.argv) > 1:
+        topofile = os.path.join(sys.argv[1], topofile)
+    else:
+        topofile = os.path.join('../../ExampleDataFiles', topofile)
+
+    clm = pysh.SHCoeffs.from_file(topofile, lmax=9)
     nmax = 100
     np.random.seed(seed=123456)
     x = 2*np.random.random_sample(nmax)-1
diff --git a/examples/python/Other/meson.build b/examples/python/Other/meson.build
new file mode 100644
index 000000000..222d278d9
--- /dev/null
+++ b/examples/python/Other/meson.build
@@ -0,0 +1,7 @@
+test(
+  'TestOther',
+  python,
+  args: [files('TestOther.py'),
+         meson.current_source_dir() / '../../ExampleDataFiles'],
+  timeout: 60,
+  suite: 'python')
diff --git a/examples/python/SHRotations/meson.build b/examples/python/SHRotations/meson.build
new file mode 100644
index 000000000..b4b0805d3
--- /dev/null
+++ b/examples/python/SHRotations/meson.build
@@ -0,0 +1,5 @@
+test(
+  'SHRotations',
+  python,
+  args: files('SHRotations.py'),
+  suite: 'python')
diff --git a/examples/python/TestLegendre/meson.build b/examples/python/TestLegendre/meson.build
new file mode 100644
index 000000000..6aaca5aa3
--- /dev/null
+++ b/examples/python/TestLegendre/meson.build
@@ -0,0 +1,6 @@
+test(
+  'TestLegendre',
+  python,
+  args: files('TestLegendre.py'),
+  timeout: 120,
+  suite: 'python')
diff --git a/examples/python/TimingAccuracy/meson.build b/examples/python/TimingAccuracy/meson.build
new file mode 100644
index 000000000..296fd9340
--- /dev/null
+++ b/examples/python/TimingAccuracy/meson.build
@@ -0,0 +1,27 @@
+benchmark(
+  'TimingAccuracyDH',
+  python,
+  args: files('TimingAccuracyDH.py'),
+  timeout: 0,
+  suite: 'python')
+
+benchmark(
+  'TimingAccuracyDHC',
+  python,
+  args: files('TimingAccuracyDHC.py'),
+  timeout: 0,
+  suite: 'python')
+
+benchmark(
+  'TimingAccuracyGLQ',
+  python,
+  args: files('TimingAccuracyGLQ.py'),
+  timeout: 0,
+  suite: 'python')
+
+benchmark(
+  'TimingAccuracyGLQC',
+  python,
+  args: files('TimingAccuracyGLQC.py'),
+  timeout: 0,
+  suite: 'python')
diff --git a/examples/python/meson.build b/examples/python/meson.build
new file mode 100644
index 000000000..fe942c4b3
--- /dev/null
+++ b/examples/python/meson.build
@@ -0,0 +1,9 @@
+subdir('ClassInterface')
+subdir('GlobalSpectralAnalysis')
+subdir('GravMag')
+subdir('IOStorageConversions')
+subdir('LocalizedSpectralAnalysis')
+subdir('Other')
+subdir('SHRotations')
+subdir('TestLegendre')
+subdir('TimingAccuracy')
diff --git a/fpm.toml b/fpm.toml
index 4f0aff604..6afb63e91 100644
--- a/fpm.toml
+++ b/fpm.toml
@@ -1,5 +1,5 @@
 name = "SHTOOLS"
-version = "4.10"
+version = "4.11"
 license = "BSD-3-Clause"
 author = "Mark A. Wieczorek"
 maintainer = "mark.a.wieczorek@gmail.com"
diff --git a/man/man3/batohilm.3 b/man/man3/batohilm.3
index 0d9b6237e..823e3406f 100644
--- a/man/man3/batohilm.3
+++ b/man/man3/batohilm.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "batohilm" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "batohilm" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH BAtoHilm
 .PP
diff --git a/man/man3/batohilmrhoh.3 b/man/man3/batohilmrhoh.3
index 4ccb339fe..18f007fc4 100644
--- a/man/man3/batohilmrhoh.3
+++ b/man/man3/batohilmrhoh.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "batohilmrhoh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "batohilmrhoh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH BAtoHilmRhoH
 .PP
diff --git a/man/man3/cilmminus.3 b/man/man3/cilmminus.3
index 98a70794b..792d84fc9 100644
--- a/man/man3/cilmminus.3
+++ b/man/man3/cilmminus.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "cilmminus" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "cilmminus" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH CilmMinus
 .PP
diff --git a/man/man3/cilmminusrhoh.3 b/man/man3/cilmminusrhoh.3
index 1d58aa53d..0c8bb0281 100644
--- a/man/man3/cilmminusrhoh.3
+++ b/man/man3/cilmminusrhoh.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "cilmminusrhoh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "cilmminusrhoh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH CilmMinusRhoH
 .PP
diff --git a/man/man3/cilmplus.3 b/man/man3/cilmplus.3
index 80d30c205..595c2ebbc 100644
--- a/man/man3/cilmplus.3
+++ b/man/man3/cilmplus.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "cilmplus" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "cilmplus" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH CilmPlus
 .PP
diff --git a/man/man3/cilmplusrhoh.3 b/man/man3/cilmplusrhoh.3
index 5afeb6fdd..03ed3d5be 100644
--- a/man/man3/cilmplusrhoh.3
+++ b/man/man3/cilmplusrhoh.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "cilmplusrhoh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "cilmplusrhoh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH CilmPlusRhoH
 .PP
diff --git a/man/man3/computedg82.3 b/man/man3/computedg82.3
index b6a7411c1..96cf3c9ba 100644
--- a/man/man3/computedg82.3
+++ b/man/man3/computedg82.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "computedg82" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "computedg82" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH ComputeDG82
 .PP
diff --git a/man/man3/computedm.3 b/man/man3/computedm.3
index 81dd704f7..24f520add 100644
--- a/man/man3/computedm.3
+++ b/man/man3/computedm.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "computedm" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "computedm" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH ComputeDM
 .PP
diff --git a/man/man3/computedmap.3 b/man/man3/computedmap.3
index 8f4124be1..7bd1f88d5 100644
--- a/man/man3/computedmap.3
+++ b/man/man3/computedmap.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "computedmap" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "computedmap" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH ComputeDMap
 .PP
diff --git a/man/man3/curve2mask.3 b/man/man3/curve2mask.3
index ef168d162..456e25c76 100644
--- a/man/man3/curve2mask.3
+++ b/man/man3/curve2mask.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "curve2mask" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "curve2mask" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH Curve2Mask
 .PP
diff --git a/man/man3/dhaj.3 b/man/man3/dhaj.3
index 5d49e2b76..3a262d52b 100644
--- a/man/man3/dhaj.3
+++ b/man/man3/dhaj.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "dhaj" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "dhaj" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH DHaj
 .PP
diff --git a/man/man3/djpi2.3 b/man/man3/djpi2.3
index b19b53a87..b31566799 100644
--- a/man/man3/djpi2.3
+++ b/man/man3/djpi2.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "djpi2" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "djpi2" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH djpi2
 .PP
diff --git a/man/man3/downcontfilterma.3 b/man/man3/downcontfilterma.3
index 0b0159d7a..08711c9b8 100644
--- a/man/man3/downcontfilterma.3
+++ b/man/man3/downcontfilterma.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "downcontfilterma" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "downcontfilterma" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH DownContFilterMA
 .PP
diff --git a/man/man3/downcontfiltermc.3 b/man/man3/downcontfiltermc.3
index ee75e0ca6..c3202fb61 100644
--- a/man/man3/downcontfiltermc.3
+++ b/man/man3/downcontfiltermc.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "downcontfiltermc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "downcontfiltermc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH DownContFilterMC
 .PP
diff --git a/man/man3/eigvalsym.3 b/man/man3/eigvalsym.3
index b8d2c7187..422f3b751 100644
--- a/man/man3/eigvalsym.3
+++ b/man/man3/eigvalsym.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "eigvalsym" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "eigvalsym" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH EigValSym
 .PP
diff --git a/man/man3/eigvalvecsym.3 b/man/man3/eigvalvecsym.3
index 42eae61a3..8b402e25d 100644
--- a/man/man3/eigvalvecsym.3
+++ b/man/man3/eigvalvecsym.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "eigvalvecsym" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "eigvalvecsym" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH EigValVecSym
 .PP
diff --git a/man/man3/eigvalvecsymtri.3 b/man/man3/eigvalvecsymtri.3
index 5a8a60073..4c8d96569 100644
--- a/man/man3/eigvalvecsymtri.3
+++ b/man/man3/eigvalvecsymtri.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "eigvalvecsymtri" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "eigvalvecsymtri" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH EigValVecSymTri
 .PP
diff --git a/man/man3/glqgridcoord.3 b/man/man3/glqgridcoord.3
index 64924b879..cea584e98 100644
--- a/man/man3/glqgridcoord.3
+++ b/man/man3/glqgridcoord.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "glqgridcoord" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "glqgridcoord" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH GLQGridCoord
 .PP
diff --git a/man/man3/makecirclecoord.3 b/man/man3/makecirclecoord.3
index 2524beea3..ccb9b0d4d 100644
--- a/man/man3/makecirclecoord.3
+++ b/man/man3/makecirclecoord.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "makecirclecoord" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "makecirclecoord" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH MakeCircleCoord
 .PP
diff --git a/man/man3/makeellipsecoord.3 b/man/man3/makeellipsecoord.3
index b45c196df..54c0183f3 100644
--- a/man/man3/makeellipsecoord.3
+++ b/man/man3/makeellipsecoord.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "makeellipsecoord" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "makeellipsecoord" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH MakeEllipseCoord
 .PP
diff --git a/man/man3/makegeoidgrid.3 b/man/man3/makegeoidgrid.3
index 364a2a8f1..a0457fd54 100644
--- a/man/man3/makegeoidgrid.3
+++ b/man/man3/makegeoidgrid.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "makegeoidgrid" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "makegeoidgrid" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH MakeGeoidGrid
 .PP
diff --git a/man/man3/makegradientdh.3 b/man/man3/makegradientdh.3
index 6c7f349b8..18f9c0df2 100644
--- a/man/man3/makegradientdh.3
+++ b/man/man3/makegradientdh.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "makegradientdh" "1" "2023-05-04" "Fortran 95" "SHTOOLS 4.10"
+.TH "makegradientdh" "1" "2023-05-04" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH MakeGradientDH
 .PP
diff --git a/man/man3/makegravgradgriddh.3 b/man/man3/makegravgradgriddh.3
index 4df03e191..1a3042384 100644
--- a/man/man3/makegravgradgriddh.3
+++ b/man/man3/makegravgradgriddh.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "makegravgradgriddh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "makegravgradgriddh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH MakeGravGradGridDH
 .PP
diff --git a/man/man3/makegravgriddh.3 b/man/man3/makegravgriddh.3
index c02d34a73..deed8a3c1 100644
--- a/man/man3/makegravgriddh.3
+++ b/man/man3/makegravgriddh.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "makegravgriddh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "makegravgriddh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH MakeGravGridDH
 .PP
diff --git a/man/man3/makegravgridpoint.3 b/man/man3/makegravgridpoint.3
index 4a00556c2..4888f75df 100644
--- a/man/man3/makegravgridpoint.3
+++ b/man/man3/makegravgridpoint.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "makegravgridpoint" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "makegravgridpoint" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH MakeGravGridPoint
 .PP
diff --git a/man/man3/makegrid2d.3 b/man/man3/makegrid2d.3
index 4c8f7cddd..4d13d658d 100644
--- a/man/man3/makegrid2d.3
+++ b/man/man3/makegrid2d.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "makegrid2d" "1" "2021-10-22" "Fortran 95" "SHTOOLS 4.10"
+.TH "makegrid2d" "1" "2021-10-22" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH MakeGrid2D
 .PP
diff --git a/man/man3/makegriddh.3 b/man/man3/makegriddh.3
index c80e24370..724d6e748 100644
--- a/man/man3/makegriddh.3
+++ b/man/man3/makegriddh.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "makegriddh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "makegriddh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH MakeGridDH
 .PP
diff --git a/man/man3/makegriddhc.3 b/man/man3/makegriddhc.3
index 3930faf32..70538b213 100644
--- a/man/man3/makegriddhc.3
+++ b/man/man3/makegriddhc.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "makegriddhc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "makegriddhc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH MakeGridDHC
 .PP
diff --git a/man/man3/makegridglq.3 b/man/man3/makegridglq.3
index aeabab8e1..a92c93419 100644
--- a/man/man3/makegridglq.3
+++ b/man/man3/makegridglq.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "makegridglq" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "makegridglq" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH MakeGridGLQ
 .PP
diff --git a/man/man3/makegridglqc.3 b/man/man3/makegridglqc.3
index b4495c4b8..91f13a5f4 100644
--- a/man/man3/makegridglqc.3
+++ b/man/man3/makegridglqc.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "makegridglqc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "makegridglqc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH MakeGridGLQC
 .PP
diff --git a/man/man3/makegridpoint.3 b/man/man3/makegridpoint.3
index 3de4d6262..1debc02d5 100644
--- a/man/man3/makegridpoint.3
+++ b/man/man3/makegridpoint.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "makegridpoint" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "makegridpoint" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH MakeGridPoint
 .PP
diff --git a/man/man3/makegridpointc.3 b/man/man3/makegridpointc.3
index 7c9265155..74444a9dc 100644
--- a/man/man3/makegridpointc.3
+++ b/man/man3/makegridpointc.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "makegridpointc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "makegridpointc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH MakeGridPointC
 .PP
diff --git a/man/man3/makemaggradgriddh.3 b/man/man3/makemaggradgriddh.3
index 66c93a905..0fcd67ff3 100644
--- a/man/man3/makemaggradgriddh.3
+++ b/man/man3/makemaggradgriddh.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "makemaggradgriddh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "makemaggradgriddh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH MakeMagGradGridDH
 .PP
diff --git a/man/man3/makemaggriddh.3 b/man/man3/makemaggriddh.3
index 990c8cf8f..6889bd852 100644
--- a/man/man3/makemaggriddh.3
+++ b/man/man3/makemaggriddh.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "makemaggriddh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "makemaggriddh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH MakeMagGridDH
 .PP
diff --git a/man/man3/makemaggridpoint.3 b/man/man3/makemaggridpoint.3
index 4c06d6f1e..d88697c6b 100644
--- a/man/man3/makemaggridpoint.3
+++ b/man/man3/makemaggridpoint.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "makemaggridpoint" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "makemaggridpoint" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH MakeMagGridPoint
 .PP
diff --git a/man/man3/normalgravity.3 b/man/man3/normalgravity.3
index eafcd3ce4..d9f3c7edf 100644
--- a/man/man3/normalgravity.3
+++ b/man/man3/normalgravity.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "normalgravity" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "normalgravity" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH NormalGravity
 .PP
diff --git a/man/man3/planetsconstants.3 b/man/man3/planetsconstants.3
index bf7a96684..84ee13f55 100644
--- a/man/man3/planetsconstants.3
+++ b/man/man3/planetsconstants.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "planetsconstants" "1" "2020-03-09" "Fortran 95" "SHTOOLS 4.10"
+.TH "planetsconstants" "1" "2020-03-09" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PlanetsConstants
 .PP
diff --git a/man/man3/plbar.3 b/man/man3/plbar.3
index 6d5c61b6e..a4111576e 100644
--- a/man/man3/plbar.3
+++ b/man/man3/plbar.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "plbar" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "plbar" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PlBar
 .PP
diff --git a/man/man3/plbar_d1.3 b/man/man3/plbar_d1.3
index 6e197590e..4e23f9446 100644
--- a/man/man3/plbar_d1.3
+++ b/man/man3/plbar_d1.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "plbar_d1" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "plbar_d1" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PlBar_d1
 .PP
diff --git a/man/man3/plegendre.3 b/man/man3/plegendre.3
index a8312851e..2023c6122 100644
--- a/man/man3/plegendre.3
+++ b/man/man3/plegendre.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "plegendre" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "plegendre" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PLegendre
 .PP
diff --git a/man/man3/plegendre_d1.3 b/man/man3/plegendre_d1.3
index 36f33198a..133eaa948 100644
--- a/man/man3/plegendre_d1.3
+++ b/man/man3/plegendre_d1.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "plegendre_d1" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "plegendre_d1" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PLegendre_d1
 .PP
diff --git a/man/man3/plegendrea.3 b/man/man3/plegendrea.3
index ea84bb06c..4dd5290a4 100644
--- a/man/man3/plegendrea.3
+++ b/man/man3/plegendrea.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "plegendrea" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "plegendrea" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PLegendreA
 .PP
diff --git a/man/man3/plegendrea_d1.3 b/man/man3/plegendrea_d1.3
index 4f7a298b0..231026e3b 100644
--- a/man/man3/plegendrea_d1.3
+++ b/man/man3/plegendrea_d1.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "plegendrea_d1" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "plegendrea_d1" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PLegendreA_d1
 .PP
diff --git a/man/man3/plmbar.3 b/man/man3/plmbar.3
index cae88b53d..16270c5b5 100644
--- a/man/man3/plmbar.3
+++ b/man/man3/plmbar.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "plmbar" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "plmbar" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PlmBar
 .PP
diff --git a/man/man3/plmbar_d1.3 b/man/man3/plmbar_d1.3
index 2416048e2..83549819e 100644
--- a/man/man3/plmbar_d1.3
+++ b/man/man3/plmbar_d1.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "plmbar_d1" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "plmbar_d1" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PlmBar_d1
 .PP
diff --git a/man/man3/plmindex.3 b/man/man3/plmindex.3
index 9da5cd1ac..172671e72 100644
--- a/man/man3/plmindex.3
+++ b/man/man3/plmindex.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "plmindex" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "plmindex" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PlmIndex
 .PP
diff --git a/man/man3/plmon.3 b/man/man3/plmon.3
index 6b41d3742..d979e1f8e 100644
--- a/man/man3/plmon.3
+++ b/man/man3/plmon.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "plmon" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "plmon" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PlmON
 .PP
diff --git a/man/man3/plmon_d1.3 b/man/man3/plmon_d1.3
index 50f2b9f4d..07f3f73bb 100644
--- a/man/man3/plmon_d1.3
+++ b/man/man3/plmon_d1.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "plmon_d1" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "plmon_d1" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PlmON_d1
 .PP
diff --git a/man/man3/plmschmidt.3 b/man/man3/plmschmidt.3
index 907df4990..3df7b5751 100644
--- a/man/man3/plmschmidt.3
+++ b/man/man3/plmschmidt.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "plmschmidt" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "plmschmidt" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PlmSchmidt
 .PP
diff --git a/man/man3/plmschmidt_d1.3 b/man/man3/plmschmidt_d1.3
index 4485a0c82..66721d642 100644
--- a/man/man3/plmschmidt_d1.3
+++ b/man/man3/plmschmidt_d1.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "plmschmidt_d1" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "plmschmidt_d1" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PlmSchmidt_d1
 .PP
diff --git a/man/man3/plon.3 b/man/man3/plon.3
index b74dc3ee8..edc53d6e1 100644
--- a/man/man3/plon.3
+++ b/man/man3/plon.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "plon" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "plon" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PlON
 .PP
diff --git a/man/man3/plon_d1.3 b/man/man3/plon_d1.3
index e33d1975d..82c05a0d6 100644
--- a/man/man3/plon_d1.3
+++ b/man/man3/plon_d1.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "plon_d1" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "plon_d1" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PlON_d1
 .PP
diff --git a/man/man3/plschmidt.3 b/man/man3/plschmidt.3
index fe107554a..c16f9d6dc 100644
--- a/man/man3/plschmidt.3
+++ b/man/man3/plschmidt.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "plschmidt" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "plschmidt" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PlSchmidt
 .PP
diff --git a/man/man3/plschmidt_d1.3 b/man/man3/plschmidt_d1.3
index a0435529a..3a9ffd914 100644
--- a/man/man3/plschmidt_d1.3
+++ b/man/man3/plschmidt_d1.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "plschmidt_d1" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "plschmidt_d1" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PlSchmidt_d1
 .PP
diff --git a/man/man3/preglq.3 b/man/man3/preglq.3
index c94b4f691..a4a05410b 100644
--- a/man/man3/preglq.3
+++ b/man/man3/preglq.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "preglq" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "preglq" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH PreGLQ
 .PP
diff --git a/man/man3/randomgaussian.3 b/man/man3/randomgaussian.3
index 5c46e5d1c..0cb58aacb 100644
--- a/man/man3/randomgaussian.3
+++ b/man/man3/randomgaussian.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "randomgaussian" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "randomgaussian" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH RandomGaussian
 .PP
diff --git a/man/man3/randomn.3 b/man/man3/randomn.3
index ed5c37c44..3c5827455 100644
--- a/man/man3/randomn.3
+++ b/man/man3/randomn.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "randomn" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "randomn" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH RandomN
 .PP
diff --git a/man/man3/shadmitcorr.3 b/man/man3/shadmitcorr.3
index 1f360fc3f..98d223bb5 100644
--- a/man/man3/shadmitcorr.3
+++ b/man/man3/shadmitcorr.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shadmitcorr" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shadmitcorr" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHAdmitCorr
 .PP
diff --git a/man/man3/shbias.3 b/man/man3/shbias.3
index 80855a504..f7b6a4c2d 100644
--- a/man/man3/shbias.3
+++ b/man/man3/shbias.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shbias" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shbias" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHBias
 .PP
diff --git a/man/man3/shbiasadmitcorr.3 b/man/man3/shbiasadmitcorr.3
index e0cf1b21b..647a29f5f 100644
--- a/man/man3/shbiasadmitcorr.3
+++ b/man/man3/shbiasadmitcorr.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shbiasadmitcorr" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shbiasadmitcorr" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHBiasAdmitCorr
 .PP
diff --git a/man/man3/shbiask.3 b/man/man3/shbiask.3
index 414d93d7c..b028bdea2 100644
--- a/man/man3/shbiask.3
+++ b/man/man3/shbiask.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shbiask" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shbiask" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHBiasK
 .PP
diff --git a/man/man3/shbiaskmask.3 b/man/man3/shbiaskmask.3
index c5d27d27d..d8b025efa 100644
--- a/man/man3/shbiaskmask.3
+++ b/man/man3/shbiaskmask.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shbiaskmask" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shbiaskmask" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHBiasKMask
 .PP
diff --git a/man/man3/shcilmtocindex.3 b/man/man3/shcilmtocindex.3
index 55f343679..4e3580605 100644
--- a/man/man3/shcilmtocindex.3
+++ b/man/man3/shcilmtocindex.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shcilmtocindex" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shcilmtocindex" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHCilmToCindex
 .PP
diff --git a/man/man3/shcilmtovector.3 b/man/man3/shcilmtovector.3
index 77c816dac..f51ee0075 100644
--- a/man/man3/shcilmtovector.3
+++ b/man/man3/shcilmtovector.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shcilmtovector" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shcilmtovector" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHCilmToVector
 .PP
diff --git a/man/man3/shcindextocilm.3 b/man/man3/shcindextocilm.3
index 5cbb257c5..491a48ad1 100644
--- a/man/man3/shcindextocilm.3
+++ b/man/man3/shcindextocilm.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shcindextocilm" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shcindextocilm" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHCindexToCilm
 .PP
diff --git a/man/man3/shconfidence.3 b/man/man3/shconfidence.3
index d57d32e3f..42cc09169 100644
--- a/man/man3/shconfidence.3
+++ b/man/man3/shconfidence.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shconfidence" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shconfidence" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHConfidence
 .PP
diff --git a/man/man3/shcrosspowerdensityl.3 b/man/man3/shcrosspowerdensityl.3
index 6db941955..2e04215eb 100644
--- a/man/man3/shcrosspowerdensityl.3
+++ b/man/man3/shcrosspowerdensityl.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shcrosspowerdensityl" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shcrosspowerdensityl" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHCrossPowerDensityL
 .PP
diff --git a/man/man3/shcrosspowerdensitylc.3 b/man/man3/shcrosspowerdensitylc.3
index 04b0ad6ac..8403fb1b3 100644
--- a/man/man3/shcrosspowerdensitylc.3
+++ b/man/man3/shcrosspowerdensitylc.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shcrosspowerdensitylc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shcrosspowerdensitylc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHCrossPowerDensityLC
 .PP
diff --git a/man/man3/shcrosspowerl.3 b/man/man3/shcrosspowerl.3
index ca4ad74ce..c09f66c7a 100644
--- a/man/man3/shcrosspowerl.3
+++ b/man/man3/shcrosspowerl.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shcrosspowerl" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shcrosspowerl" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHCrossPowerL
 .PP
diff --git a/man/man3/shcrosspowerlc.3 b/man/man3/shcrosspowerlc.3
index 1936c8007..d846540bf 100644
--- a/man/man3/shcrosspowerlc.3
+++ b/man/man3/shcrosspowerlc.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shcrosspowerlc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shcrosspowerlc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHCrossPowerLC
 .PP
diff --git a/man/man3/shcrosspowerspectrum.3 b/man/man3/shcrosspowerspectrum.3
index 3b1f86902..735efa099 100644
--- a/man/man3/shcrosspowerspectrum.3
+++ b/man/man3/shcrosspowerspectrum.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shcrosspowerspectrum" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shcrosspowerspectrum" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHCrossPowerSpectrum
 .PP
diff --git a/man/man3/shcrosspowerspectrumc.3 b/man/man3/shcrosspowerspectrumc.3
index eed8f7fa5..6c938c8d1 100644
--- a/man/man3/shcrosspowerspectrumc.3
+++ b/man/man3/shcrosspowerspectrumc.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shcrosspowerspectrumc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shcrosspowerspectrumc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHCrossPowerSpectrumC
 .PP
diff --git a/man/man3/shcrosspowerspectrumdensity.3 b/man/man3/shcrosspowerspectrumdensity.3
index 5965c116e..ee3535a78 100644
--- a/man/man3/shcrosspowerspectrumdensity.3
+++ b/man/man3/shcrosspowerspectrumdensity.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shcrosspowerspectrumdensity" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shcrosspowerspectrumdensity" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHCrossPowerSpectrumDensity
 .PP
diff --git a/man/man3/shcrosspowerspectrumdensityc.3 b/man/man3/shcrosspowerspectrumdensityc.3
index fda398aed..bea9d3978 100644
--- a/man/man3/shcrosspowerspectrumdensityc.3
+++ b/man/man3/shcrosspowerspectrumdensityc.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shcrosspowerspectrumdensityc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shcrosspowerspectrumdensityc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHCrossPowerSpectrumDensityC
 .PP
diff --git a/man/man3/shctor.3 b/man/man3/shctor.3
index 205822582..1540191e6 100644
--- a/man/man3/shctor.3
+++ b/man/man3/shctor.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shctor" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shctor" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHctor
 .PP
diff --git a/man/man3/shexpanddh.3 b/man/man3/shexpanddh.3
index 146f0fa13..b1fb0aee1 100644
--- a/man/man3/shexpanddh.3
+++ b/man/man3/shexpanddh.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shexpanddh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shexpanddh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHExpandDH
 .PP
diff --git a/man/man3/shexpanddhc.3 b/man/man3/shexpanddhc.3
index 8b8e26e81..72908507a 100644
--- a/man/man3/shexpanddhc.3
+++ b/man/man3/shexpanddhc.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shexpanddhc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shexpanddhc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHExpandDHC
 .PP
diff --git a/man/man3/shexpandglq.3 b/man/man3/shexpandglq.3
index 1b0b785af..b79ed2f0d 100644
--- a/man/man3/shexpandglq.3
+++ b/man/man3/shexpandglq.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shexpandglq" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shexpandglq" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHExpandGLQ
 .PP
diff --git a/man/man3/shexpandglqc.3 b/man/man3/shexpandglqc.3
index 035052739..50823040a 100644
--- a/man/man3/shexpandglqc.3
+++ b/man/man3/shexpandglqc.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shexpandglqc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shexpandglqc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHExpandGLQC
 .PP
diff --git a/man/man3/shexpandlsq.3 b/man/man3/shexpandlsq.3
index d179d06cd..da521cf28 100644
--- a/man/man3/shexpandlsq.3
+++ b/man/man3/shexpandlsq.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shexpandlsq" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shexpandlsq" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHExpandLSQ
 .PP
diff --git a/man/man3/shfindlwin.3 b/man/man3/shfindlwin.3
index 0aa730dfc..b7d21e163 100644
--- a/man/man3/shfindlwin.3
+++ b/man/man3/shfindlwin.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shfindlwin" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shfindlwin" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHFindLWin
 .PP
diff --git a/man/man3/shglq.3 b/man/man3/shglq.3
index 32dab9504..bd120c33c 100644
--- a/man/man3/shglq.3
+++ b/man/man3/shglq.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shglq" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shglq" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHGLQ
 .PP
diff --git a/man/man3/shlocalizedadmitcorr.3 b/man/man3/shlocalizedadmitcorr.3
index e34711fbc..c2a15da0f 100644
--- a/man/man3/shlocalizedadmitcorr.3
+++ b/man/man3/shlocalizedadmitcorr.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shlocalizedadmitcorr" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shlocalizedadmitcorr" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHLocalizedAdmitCorr
 .PP
diff --git a/man/man3/shmagpowerl.3 b/man/man3/shmagpowerl.3
index 0384b8119..a88f34946 100644
--- a/man/man3/shmagpowerl.3
+++ b/man/man3/shmagpowerl.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shmagpowerl" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shmagpowerl" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHMagPowerL
 .PP
diff --git a/man/man3/shmagpowerspectrum.3 b/man/man3/shmagpowerspectrum.3
index 3081ca0db..b8b52325f 100644
--- a/man/man3/shmagpowerspectrum.3
+++ b/man/man3/shmagpowerspectrum.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shmagpowerspectrum" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shmagpowerspectrum" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHMagPowerSpectrum
 .PP
diff --git a/man/man3/shmtcouplingmatrix.3 b/man/man3/shmtcouplingmatrix.3
index 62c080dda..b5fd26ba3 100644
--- a/man/man3/shmtcouplingmatrix.3
+++ b/man/man3/shmtcouplingmatrix.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shmtcouplingmatrix" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shmtcouplingmatrix" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHMTCouplingMatrix
 .PP
diff --git a/man/man3/shmtdebias.3 b/man/man3/shmtdebias.3
index ea905e224..f8a80bcf2 100644
--- a/man/man3/shmtdebias.3
+++ b/man/man3/shmtdebias.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shmtdebias" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shmtdebias" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHMTDebias
 .PP
diff --git a/man/man3/shmtvaropt.3 b/man/man3/shmtvaropt.3
index 5f9278510..500a81bb2 100644
--- a/man/man3/shmtvaropt.3
+++ b/man/man3/shmtvaropt.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shmtvaropt" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shmtvaropt" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHMTVarOpt
 .PP
diff --git a/man/man3/shmultiply.3 b/man/man3/shmultiply.3
index 2252e2b0b..81e9b4867 100644
--- a/man/man3/shmultiply.3
+++ b/man/man3/shmultiply.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shmultiply" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shmultiply" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHMultiply
 .PP
diff --git a/man/man3/shmultitapercse.3 b/man/man3/shmultitapercse.3
index 04a42c37b..53db0aa70 100644
--- a/man/man3/shmultitapercse.3
+++ b/man/man3/shmultitapercse.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shmultitapercse" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shmultitapercse" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHMultiTaperCSE
 .PP
diff --git a/man/man3/shmultitapermaskcse.3 b/man/man3/shmultitapermaskcse.3
index db099e56b..147f92fe3 100644
--- a/man/man3/shmultitapermaskcse.3
+++ b/man/man3/shmultitapermaskcse.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shmultitapermaskcse" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shmultitapermaskcse" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHMultiTaperMaskCSE
 .PP
diff --git a/man/man3/shmultitapermaskse.3 b/man/man3/shmultitapermaskse.3
index 8e75566d7..2186b416e 100644
--- a/man/man3/shmultitapermaskse.3
+++ b/man/man3/shmultitapermaskse.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shmultitapermaskse" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shmultitapermaskse" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHMultiTaperMaskSE
 .PP
diff --git a/man/man3/shmultitaperse.3 b/man/man3/shmultitaperse.3
index dbeeafd5b..57d34f979 100644
--- a/man/man3/shmultitaperse.3
+++ b/man/man3/shmultitaperse.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shmultitaperse" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shmultitaperse" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHMultiTaperSE
 .PP
diff --git a/man/man3/shpowerdensityl.3 b/man/man3/shpowerdensityl.3
index a16c74cf0..adc12f2f7 100644
--- a/man/man3/shpowerdensityl.3
+++ b/man/man3/shpowerdensityl.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shpowerdensityl" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shpowerdensityl" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHPowerDensityL
 .PP
diff --git a/man/man3/shpowerdensitylc.3 b/man/man3/shpowerdensitylc.3
index b008c137b..2f0feb99d 100644
--- a/man/man3/shpowerdensitylc.3
+++ b/man/man3/shpowerdensitylc.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shpowerdensitylc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shpowerdensitylc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHPowerDensityLC
 .PP
diff --git a/man/man3/shpowerl.3 b/man/man3/shpowerl.3
index 88b0c2ec5..aa3044d3d 100644
--- a/man/man3/shpowerl.3
+++ b/man/man3/shpowerl.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shpowerl" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shpowerl" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHPowerL
 .PP
diff --git a/man/man3/shpowerlc.3 b/man/man3/shpowerlc.3
index b7f6aacbb..9073054aa 100644
--- a/man/man3/shpowerlc.3
+++ b/man/man3/shpowerlc.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shpowerlc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shpowerlc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHPowerLC
 .PP
diff --git a/man/man3/shpowerspectrum.3 b/man/man3/shpowerspectrum.3
index 9557cfaf6..5c253139a 100644
--- a/man/man3/shpowerspectrum.3
+++ b/man/man3/shpowerspectrum.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shpowerspectrum" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shpowerspectrum" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHPowerSpectrum
 .PP
diff --git a/man/man3/shpowerspectrumc.3 b/man/man3/shpowerspectrumc.3
index b4b76c304..ef5e0b788 100644
--- a/man/man3/shpowerspectrumc.3
+++ b/man/man3/shpowerspectrumc.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shpowerspectrumc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shpowerspectrumc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHPowerSpectrumC
 .PP
diff --git a/man/man3/shpowerspectrumdensity.3 b/man/man3/shpowerspectrumdensity.3
index 907c0d156..588e5429a 100644
--- a/man/man3/shpowerspectrumdensity.3
+++ b/man/man3/shpowerspectrumdensity.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shpowerspectrumdensity" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shpowerspectrumdensity" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHPowerSpectrumDensity
 .PP
diff --git a/man/man3/shpowerspectrumdensityc.3 b/man/man3/shpowerspectrumdensityc.3
index c7f48e5d0..0bb46df09 100644
--- a/man/man3/shpowerspectrumdensityc.3
+++ b/man/man3/shpowerspectrumdensityc.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shpowerspectrumdensityc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shpowerspectrumdensityc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHPowerSpectrumDensityC
 .PP
diff --git a/man/man3/shread.3 b/man/man3/shread.3
index 4ff84881a..062de03e7 100644
--- a/man/man3/shread.3
+++ b/man/man3/shread.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shread" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shread" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHRead
 .PP
diff --git a/man/man3/shread2.3 b/man/man3/shread2.3
index 39389c0ff..1b7eee13c 100644
--- a/man/man3/shread2.3
+++ b/man/man3/shread2.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shread2" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shread2" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHRead2
 .PP
diff --git a/man/man3/shreadjpl.3 b/man/man3/shreadjpl.3
index c730223f7..140994eb8 100644
--- a/man/man3/shreadjpl.3
+++ b/man/man3/shreadjpl.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shreadjpl" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shreadjpl" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHReadJPL
 .PP
diff --git a/man/man3/shreturntapers.3 b/man/man3/shreturntapers.3
index c6977eee2..173348d98 100644
--- a/man/man3/shreturntapers.3
+++ b/man/man3/shreturntapers.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shreturntapers" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shreturntapers" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHReturnTapers
 .PP
diff --git a/man/man3/shreturntapersm.3 b/man/man3/shreturntapersm.3
index f40b8269d..ba41cf5e4 100644
--- a/man/man3/shreturntapersm.3
+++ b/man/man3/shreturntapersm.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shreturntapersm" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shreturntapersm" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHReturnTapersM
 .PP
diff --git a/man/man3/shreturntapersmap.3 b/man/man3/shreturntapersmap.3
index fae915a2e..2b4430166 100644
--- a/man/man3/shreturntapersmap.3
+++ b/man/man3/shreturntapersmap.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shreturntapersmap" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shreturntapersmap" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHReturnTapersMap
 .PP
diff --git a/man/man3/shrotatecoef.3 b/man/man3/shrotatecoef.3
index d5587d88f..e859aba72 100644
--- a/man/man3/shrotatecoef.3
+++ b/man/man3/shrotatecoef.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shrotatecoef" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shrotatecoef" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHRotateCoef
 .PP
diff --git a/man/man3/shrotaterealcoef.3 b/man/man3/shrotaterealcoef.3
index c8612ecaa..a62de3b7b 100644
--- a/man/man3/shrotaterealcoef.3
+++ b/man/man3/shrotaterealcoef.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shrotaterealcoef" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shrotaterealcoef" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHRotateRealCoef
 .PP
diff --git a/man/man3/shrotatetapers.3 b/man/man3/shrotatetapers.3
index 216c482c3..e4b1e351c 100644
--- a/man/man3/shrotatetapers.3
+++ b/man/man3/shrotatetapers.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shrotatetapers" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shrotatetapers" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHRotateTapers
 .PP
diff --git a/man/man3/shrtoc.3 b/man/man3/shrtoc.3
index 31a24ce0f..6d7c6d5c9 100644
--- a/man/man3/shrtoc.3
+++ b/man/man3/shrtoc.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shrtoc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shrtoc" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHrtoc
 .PP
diff --git a/man/man3/shscouplingmatrix.3 b/man/man3/shscouplingmatrix.3
index c10ce1863..fd0180a33 100644
--- a/man/man3/shscouplingmatrix.3
+++ b/man/man3/shscouplingmatrix.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shscouplingmatrix" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shscouplingmatrix" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHSCouplingMatrix
 .PP
diff --git a/man/man3/shscouplingmatrixcap.3 b/man/man3/shscouplingmatrixcap.3
index b02ff74c8..03c14513a 100644
--- a/man/man3/shscouplingmatrixcap.3
+++ b/man/man3/shscouplingmatrixcap.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shscouplingmatrixcap" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shscouplingmatrixcap" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHSCouplingMatrixCap
 .PP
diff --git a/man/man3/shsjkpg.3 b/man/man3/shsjkpg.3
index 2528228d0..ae085cc28 100644
--- a/man/man3/shsjkpg.3
+++ b/man/man3/shsjkpg.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shsjkpg" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shsjkpg" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHSjkPG
 .PP
diff --git a/man/man3/shslepianvar.3 b/man/man3/shslepianvar.3
index 3daa8701d..99186d3fc 100644
--- a/man/man3/shslepianvar.3
+++ b/man/man3/shslepianvar.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shslepianvar" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shslepianvar" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHSlepianVar
 .PP
diff --git a/man/man3/shtools.3 b/man/man3/shtools.3
index 3fa059c05..aae1f953d 100644
--- a/man/man3/shtools.3
+++ b/man/man3/shtools.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shtools" "1" "2023-05-04" "Fortran 95" "SHTOOLS 4.10"
+.TH "shtools" "1" "2023-05-04" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHTOOLS
 .PP
diff --git a/man/man3/shvectortocilm.3 b/man/man3/shvectortocilm.3
index dd4cf433e..b7f5c8af6 100644
--- a/man/man3/shvectortocilm.3
+++ b/man/man3/shvectortocilm.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "shvectortocilm" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "shvectortocilm" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SHVectorToCilm
 .PP
diff --git a/man/man3/slepiancoeffs.3 b/man/man3/slepiancoeffs.3
index cc11da4b2..2561499c1 100644
--- a/man/man3/slepiancoeffs.3
+++ b/man/man3/slepiancoeffs.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "slepiancoeffs" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "slepiancoeffs" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SlepianCoeffs
 .PP
diff --git a/man/man3/slepiancoeffstosh.3 b/man/man3/slepiancoeffstosh.3
index 61a0befa6..ac272175c 100644
--- a/man/man3/slepiancoeffstosh.3
+++ b/man/man3/slepiancoeffstosh.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "slepiancoeffstosh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "slepiancoeffstosh" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SlepianCoeffsToSH
 .PP
diff --git a/man/man3/sphericalcapcoef.3 b/man/man3/sphericalcapcoef.3
index 6b9f3739e..49891ba9e 100644
--- a/man/man3/sphericalcapcoef.3
+++ b/man/man3/sphericalcapcoef.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "sphericalcapcoef" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "sphericalcapcoef" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH SphericalCapCoef
 .PP
diff --git a/man/man3/wigner3j.3 b/man/man3/wigner3j.3
index 6023a4a5f..c9ebeed7b 100644
--- a/man/man3/wigner3j.3
+++ b/man/man3/wigner3j.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "wigner3j" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "wigner3j" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH Wigner3j
 .PP
diff --git a/man/man3/yilmindexvector.3 b/man/man3/yilmindexvector.3
index 8ef55aa8b..bb470bd5c 100644
--- a/man/man3/yilmindexvector.3
+++ b/man/man3/yilmindexvector.3
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 2.19.2
+.\" Automatically generated by Pandoc 3.1.3
 .\"
 .\" Define V font for inline verbatim, using C font in formats
 .\" that render this, and otherwise B font.
@@ -14,7 +14,7 @@
 . ftr VB CB
 . ftr VBI CBI
 .\}
-.TH "yilmindexvector" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.10"
+.TH "yilmindexvector" "1" "2021-02-15" "Fortran 95" "SHTOOLS 4.11"
 .hy
 .SH YilmIndexVector
 .PP
diff --git a/meson.build b/meson.build
new file mode 100644
index 000000000..e8324ebf8
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,28 @@
+project('shtools', 'c', 'fortran',
+  version: run_command(find_program('python3'), '-m', 'setuptools_scm').stdout().strip(),
+  license: 'BSD-3-Clause',
+  meson_version: '>=1.1.0',
+  default_options: [
+    'buildtype=release',
+  ])
+
+cc = meson.get_compiler('c')
+
+main_incdir = include_directories('include')
+
+blas = get_option('blas')
+if blas == ''
+  blas = dependency('openblas', 'BLAS')
+else
+  blas = dependency(blas)
+endif
+lapack = get_option('lapack')
+if lapack == ''
+  lapack = dependency('lapack')
+else
+  lapack = dependency(lapack)
+endif
+
+subdir('src')
+subdir('pyshtools')
+subdir('examples')
diff --git a/meson.options b/meson.options
new file mode 100644
index 000000000..cb0442cd9
--- /dev/null
+++ b/meson.options
@@ -0,0 +1,4 @@
+option('blas', type: 'string', value: '',
+        description: 'option for BLAS library switching')
+option('lapack', type: 'string', value: '',
+        description: 'option for LAPACK library switching')
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 000000000..595e6f937
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,67 @@
+[project]
+name = 'pyshtools'
+dynamic = [
+  'version',
+]
+description = 'SHTOOLS - Spherical Harmonic Tools'
+readme = 'README.md'
+license = { text = 'BSD-3-Clause' }
+requires-python = '>=3.6'
+keywords = ['Spherical Harmonics', 'Spectral Estimation', 'Slepian Functions',
+            'Legendre Functions', 'Gravity Field', 'Magnetic Field']
+classifiers = [
+  'Development Status :: 5 - Production/Stable',
+  'Environment :: Console',
+  'Intended Audience :: Science/Research',
+  'Intended Audience :: Developers',
+  'License :: OSI Approved :: BSD License',
+  'Natural Language :: English',
+  'Operating System :: OS Independent',
+  'Programming Language :: Fortran',
+  'Programming Language :: Python',
+  'Programming Language :: Python :: 3',
+  'Topic :: Scientific/Engineering',
+  'Topic :: Scientific/Engineering :: GIS',
+  'Topic :: Scientific/Engineering :: Mathematics',
+  'Topic :: Scientific/Engineering :: Physics',
+]
+authors = [
+  { name = 'The SHTOOLS developers', email = 'mark.wieczorek@ipgp.fr' },
+]
+dependencies = [
+  'numpy',
+  'scipy>=0.14.0',
+  'matplotlib>=3.3',
+  'astropy>=4.0',
+  'xarray',
+  'requests',
+  'pooch>=1.1',
+  'tqdm',
+]
+
+[project.urls]
+homepage = 'https://shtools.github.io/SHTOOLS/'
+download = 'https://github.com/SHTOOLS/SHTOOLS/zipball/master'
+
+[project.optional-dependencies]
+cartopy = ['cython', 'pyshp', 'six', 'shapely', 'cartopy>=0.18.0']
+pygmt = ['pygmt>=0.3']
+palettable = ['palettable>=3.3']
+ducc = ['ducc0>=0.15']
+
+[build-system]
+build-backend = 'mesonpy'
+requires = [
+  'meson-python>=0.14',
+  'oldest-supported-numpy',
+  'setuptools>=64',
+  'setuptools_scm>=8',
+]
+
+[tool.meson-python.args]
+setup = ['--default-library=static']
+install = ['--tags=doc,python-runtime,runtime']
+
+[tool.setuptools_scm]
+version_scheme =  'no-guess-dev'
+local_scheme =  'dirty-tag'
diff --git a/pyshtools/__init__.py b/pyshtools/__init__.py
index 2163310c5..6935f3fcc 100644
--- a/pyshtools/__init__.py
+++ b/pyshtools/__init__.py
@@ -40,7 +40,7 @@
 
    https://github.com/SHTOOLS/SHTOOLS
 """
-from ._version import get_versions as _get_versions
+from importlib.metadata import version, PackageNotFoundError
 
 # ---- Import shtools subpackages ----
 from . import backends
@@ -63,8 +63,12 @@
 from .shclasses import SHGravCoeffs
 from .shclasses import SHMagCoeffs
 
-__version__ = _get_versions()["version"]
-__commit__ = _get_versions()["full-revisionid"]
+try:
+    __version__ = version('pyshtools')
+except PackageNotFoundError:
+    # package is not installed
+    pass
+
 __author__ = 'SHTOOLS developers'
 
 # ---- Define __all__ for use with: from pyshtools import * ----
diff --git a/pyshtools/_version.py b/pyshtools/_version.py
deleted file mode 100644
index 0fd1e13a7..000000000
--- a/pyshtools/_version.py
+++ /dev/null
@@ -1,623 +0,0 @@
-
-# This file helps to compute a version number in source trees obtained from
-# git-archive tarball (such as those provided by githubs download-from-tag
-# feature). Distribution tarballs (built by setup.py sdist) and build
-# directories (produced by setup.py build) will contain a much shorter file
-# that just contains the computed version number.
-
-# This file is released into the public domain. Generated by
-# versioneer-0.20 (https://github.com/python-versioneer/python-versioneer)
-
-"""Git implementation of _version.py."""
-
-import errno
-import os
-import re
-import subprocess
-import sys
-
-
-def get_keywords():
-    """Get the keywords needed to look up the version information."""
-    # these strings will be replaced by git during git-archive.
-    # setup.py/versioneer.py will grep for the variable names, so they must
-    # each be defined on a line of their own. _version.py will just call
-    # get_keywords().
-    git_refnames = "$Format:%d$"
-    git_full = "$Format:%H$"
-    git_date = "$Format:%ci$"
-    keywords = {"refnames": git_refnames, "full": git_full, "date": git_date}
-    return keywords
-
-
-class VersioneerConfig:  # pylint: disable=too-few-public-methods
-    """Container for Versioneer configuration parameters."""
-
-
-def get_config():
-    """Create, populate and return the VersioneerConfig() object."""
-    # these strings are filled in when 'setup.py versioneer' creates
-    # _version.py
-    cfg = VersioneerConfig()
-    cfg.VCS = "git"
-    cfg.style = "pep440"
-    cfg.tag_prefix = ""
-    cfg.parentdir_prefix = "None"
-    cfg.versionfile_source = "pyshtools/_version.py"
-    cfg.verbose = False
-    return cfg
-
-
-class NotThisMethod(Exception):
-    """Exception raised if a method is not valid for the current scenario."""
-
-
-LONG_VERSION_PY = {}
-HANDLERS = {}
-
-
-def register_vcs_handler(vcs, method):  # decorator
-    """Create decorator to mark a method as the handler of a VCS."""
-    def decorate(f):
-        """Store f in HANDLERS[vcs][method]."""
-        if vcs not in HANDLERS:
-            HANDLERS[vcs] = {}
-        HANDLERS[vcs][method] = f
-        return f
-    return decorate
-
-
-# pylint:disable=too-many-arguments,consider-using-with # noqa
-def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False,
-                env=None):
-    """Call the given command(s)."""
-    assert isinstance(commands, list)
-    process = None
-    for command in commands:
-        try:
-            dispcmd = str([command] + args)
-            # remember shell=False, so use git.cmd on windows, not just git
-            process = subprocess.Popen([command] + args, cwd=cwd, env=env,
-                                       stdout=subprocess.PIPE,
-                                       stderr=(subprocess.PIPE if hide_stderr
-                                               else None))
-            break
-        except EnvironmentError:
-            e = sys.exc_info()[1]
-            if e.errno == errno.ENOENT:
-                continue
-            if verbose:
-                print("unable to run %s" % dispcmd)
-                print(e)
-            return None, None
-    else:
-        if verbose:
-            print("unable to find command, tried %s" % (commands,))
-        return None, None
-    stdout = process.communicate()[0].strip().decode()
-    if process.returncode != 0:
-        if verbose:
-            print("unable to run %s (error)" % dispcmd)
-            print("stdout was %s" % stdout)
-        return None, process.returncode
-    return stdout, process.returncode
-
-
-def versions_from_parentdir(parentdir_prefix, root, verbose):
-    """Try to determine the version from the parent directory name.
-
-    Source tarballs conventionally unpack into a directory that includes both
-    the project name and a version string. We will also support searching up
-    two directory levels for an appropriately named parent directory
-    """
-    rootdirs = []
-
-    for _ in range(3):
-        dirname = os.path.basename(root)
-        if dirname.startswith(parentdir_prefix):
-            return {"version": dirname[len(parentdir_prefix):],
-                    "full-revisionid": None,
-                    "dirty": False, "error": None, "date": None}
-        rootdirs.append(root)
-        root = os.path.dirname(root)  # up a level
-
-    if verbose:
-        print("Tried directories %s but none started with prefix %s" %
-              (str(rootdirs), parentdir_prefix))
-    raise NotThisMethod("rootdir doesn't start with parentdir_prefix")
-
-
-@register_vcs_handler("git", "get_keywords")
-def git_get_keywords(versionfile_abs):
-    """Extract version information from the given file."""
-    # the code embedded in _version.py can just fetch the value of these
-    # keywords. When used from setup.py, we don't want to import _version.py,
-    # so we do it with a regexp instead. This function is not used from
-    # _version.py.
-    keywords = {}
-    try:
-        with open(versionfile_abs, "r") as fobj:
-            for line in fobj:
-                if line.strip().startswith("git_refnames ="):
-                    mo = re.search(r'=\s*"(.*)"', line)
-                    if mo:
-                        keywords["refnames"] = mo.group(1)
-                if line.strip().startswith("git_full ="):
-                    mo = re.search(r'=\s*"(.*)"', line)
-                    if mo:
-                        keywords["full"] = mo.group(1)
-                if line.strip().startswith("git_date ="):
-                    mo = re.search(r'=\s*"(.*)"', line)
-                    if mo:
-                        keywords["date"] = mo.group(1)
-    except EnvironmentError:
-        pass
-    return keywords
-
-
-@register_vcs_handler("git", "keywords")
-def git_versions_from_keywords(keywords, tag_prefix, verbose):
-    """Get version information from git keywords."""
-    if "refnames" not in keywords:
-        raise NotThisMethod("Short version file found")
-    date = keywords.get("date")
-    if date is not None:
-        # Use only the last line.  Previous lines may contain GPG signature
-        # information.
-        date = date.splitlines()[-1]
-
-        # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant
-        # datestamp. However we prefer "%ci" (which expands to an "ISO-8601
-        # -like" string, which we must then edit to make compliant), because
-        # it's been around since git-1.5.3, and it's too difficult to
-        # discover which version we're using, or to work around using an
-        # older one.
-        date = date.strip().replace(" ", "T", 1).replace(" ", "", 1)
-    refnames = keywords["refnames"].strip()
-    if refnames.startswith("$Format"):
-        if verbose:
-            print("keywords are unexpanded, not using")
-        raise NotThisMethod("unexpanded keywords, not a git-archive tarball")
-    refs = {r.strip() for r in refnames.strip("()").split(",")}
-    # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
-    # just "foo-1.0". If we see a "tag: " prefix, prefer those.
-    TAG = "tag: "
-    tags = {r[len(TAG):] for r in refs if r.startswith(TAG)}
-    if not tags:
-        # Either we're using git < 1.8.3, or there really are no tags. We use
-        # a heuristic: assume all version tags have a digit. The old git %d
-        # expansion behaves like git log --decorate=short and strips out the
-        # refs/heads/ and refs/tags/ prefixes that would let us distinguish
-        # between branches and tags. By ignoring refnames without digits, we
-        # filter out many common branch names like "release" and
-        # "stabilization", as well as "HEAD" and "master".
-        tags = {r for r in refs if re.search(r'\d', r)}
-        if verbose:
-            print("discarding '%s', no digits" % ",".join(refs - tags))
-    if verbose:
-        print("likely tags: %s" % ",".join(sorted(tags)))
-    for ref in sorted(tags):
-        # sorting will prefer e.g. "2.0" over "2.0rc1"
-        if ref.startswith(tag_prefix):
-            r = ref[len(tag_prefix):]
-            # Filter out refs that exactly match prefix or that don't start
-            # with a number once the prefix is stripped (mostly a concern
-            # when prefix is '')
-            if not re.match(r'\d', r):
-                continue
-            if verbose:
-                print("picking %s" % r)
-            return {"version": r,
-                    "full-revisionid": keywords["full"].strip(),
-                    "dirty": False, "error": None,
-                    "date": date}
-    # no suitable tags, so version is "0+unknown", but full hex is still there
-    if verbose:
-        print("no suitable tags, using unknown + full revision id")
-    return {"version": "0+unknown",
-            "full-revisionid": keywords["full"].strip(),
-            "dirty": False, "error": "no suitable tags", "date": None}
-
-
-@register_vcs_handler("git", "pieces_from_vcs")
-def git_pieces_from_vcs(tag_prefix, root, verbose, runner=run_command):
-    """Get version from 'git describe' in the root of the source tree.
-
-    This only gets called if the git-archive 'subst' keywords were *not*
-    expanded, and _version.py hasn't already been rewritten with a short
-    version string, meaning we're inside a checked out source tree.
-    """
-    GITS = ["git"]
-    if sys.platform == "win32":
-        GITS = ["git.cmd", "git.exe"]
-
-    _, rc = runner(GITS, ["rev-parse", "--git-dir"], cwd=root,
-                   hide_stderr=True)
-    if rc != 0:
-        if verbose:
-            print("Directory %s not under git control" % root)
-        raise NotThisMethod("'git rev-parse --git-dir' returned error")
-
-    # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty]
-    # if there isn't one, this yields HEX[-dirty] (no NUM)
-    describe_out, rc = runner(GITS, ["describe", "--tags", "--dirty",
-                                     "--always", "--long",
-                                     "--match", "%s*" % tag_prefix],
-                              cwd=root)
-    # --long was added in git-1.5.5
-    if describe_out is None:
-        raise NotThisMethod("'git describe' failed")
-    describe_out = describe_out.strip()
-    full_out, rc = runner(GITS, ["rev-parse", "HEAD"], cwd=root)
-    if full_out is None:
-        raise NotThisMethod("'git rev-parse' failed")
-    full_out = full_out.strip()
-
-    pieces = {}
-    pieces["long"] = full_out
-    pieces["short"] = full_out[:7]  # maybe improved later
-    pieces["error"] = None
-
-    branch_name, rc = runner(GITS, ["rev-parse", "--abbrev-ref", "HEAD"],
-                             cwd=root)
-    # --abbrev-ref was added in git-1.6.3
-    if rc != 0 or branch_name is None:
-        raise NotThisMethod("'git rev-parse --abbrev-ref' returned error")
-    branch_name = branch_name.strip()
-
-    if branch_name == "HEAD":
-        # If we aren't exactly on a branch, pick a branch which represents
-        # the current commit. If all else fails, we are on a branchless
-        # commit.
-        branches, rc = runner(GITS, ["branch", "--contains"], cwd=root)
-        # --contains was added in git-1.5.4
-        if rc != 0 or branches is None:
-            raise NotThisMethod("'git branch --contains' returned error")
-        branches = branches.split("\n")
-
-        # Remove the first line if we're running detached
-        if "(" in branches[0]:
-            branches.pop(0)
-
-        # Strip off the leading "* " from the list of branches.
-        branches = [branch[2:] for branch in branches]
-        if "master" in branches:
-            branch_name = "master"
-        elif not branches:
-            branch_name = None
-        else:
-            # Pick the first branch that is returned. Good or bad.
-            branch_name = branches[0]
-
-    pieces["branch"] = branch_name
-
-    # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty]
-    # TAG might have hyphens.
-    git_describe = describe_out
-
-    # look for -dirty suffix
-    dirty = git_describe.endswith("-dirty")
-    pieces["dirty"] = dirty
-    if dirty:
-        git_describe = git_describe[:git_describe.rindex("-dirty")]
-
-    # now we have TAG-NUM-gHEX or HEX
-
-    if "-" in git_describe:
-        # TAG-NUM-gHEX
-        mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe)
-        if not mo:
-            # unparseable. Maybe git-describe is misbehaving?
-            pieces["error"] = ("unable to parse git-describe output: '%s'"
-                               % describe_out)
-            return pieces
-
-        # tag
-        full_tag = mo.group(1)
-        if not full_tag.startswith(tag_prefix):
-            if verbose:
-                fmt = "tag '%s' doesn't start with prefix '%s'"
-                print(fmt % (full_tag, tag_prefix))
-            pieces["error"] = ("tag '%s' doesn't start with prefix '%s'"
-                               % (full_tag, tag_prefix))
-            return pieces
-        pieces["closest-tag"] = full_tag[len(tag_prefix):]
-
-        # distance: number of commits since tag
-        pieces["distance"] = int(mo.group(2))
-
-        # commit: short hex revision ID
-        pieces["short"] = mo.group(3)
-
-    else:
-        # HEX: no tags
-        pieces["closest-tag"] = None
-        count_out, rc = runner(GITS, ["rev-list", "HEAD", "--count"], cwd=root)
-        pieces["distance"] = int(count_out)  # total number of commits
-
-    # commit date: see ISO-8601 comment in git_versions_from_keywords()
-    date = runner(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[0].strip()
-    # Use only the last line.  Previous lines may contain GPG signature
-    # information.
-    date = date.splitlines()[-1]
-    pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1)
-
-    return pieces
-
-
-def plus_or_dot(pieces):
-    """Return a + if we don't already have one, else return a ."""
-    if "+" in pieces.get("closest-tag", ""):
-        return "."
-    return "+"
-
-
-def render_pep440(pieces):
-    """Build up version string, with post-release "local version identifier".
-
-    Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
-    get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
-
-    Exceptions:
-    1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"] or pieces["dirty"]:
-            rendered += plus_or_dot(pieces)
-            rendered += "%d.g%s" % (pieces["distance"], pieces["short"])
-            if pieces["dirty"]:
-                rendered += ".dirty"
-    else:
-        # exception #1
-        rendered = "0+untagged.%d.g%s" % (pieces["distance"],
-                                          pieces["short"])
-        if pieces["dirty"]:
-            rendered += ".dirty"
-    return rendered
-
-
-def render_pep440_branch(pieces):
-    """TAG[[.dev0]+DISTANCE.gHEX[.dirty]] .
-
-    The ".dev0" means not master branch. Note that .dev0 sorts backwards
-    (a feature branch will appear "older" than the master branch).
-
-    Exceptions:
-    1: no tags. 0[.dev0]+untagged.DISTANCE.gHEX[.dirty]
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"] or pieces["dirty"]:
-            if pieces["branch"] != "master":
-                rendered += ".dev0"
-            rendered += plus_or_dot(pieces)
-            rendered += "%d.g%s" % (pieces["distance"], pieces["short"])
-            if pieces["dirty"]:
-                rendered += ".dirty"
-    else:
-        # exception #1
-        rendered = "0"
-        if pieces["branch"] != "master":
-            rendered += ".dev0"
-        rendered += "+untagged.%d.g%s" % (pieces["distance"],
-                                          pieces["short"])
-        if pieces["dirty"]:
-            rendered += ".dirty"
-    return rendered
-
-
-def render_pep440_pre(pieces):
-    """TAG[.post0.devDISTANCE] -- No -dirty.
-
-    Exceptions:
-    1: no tags. 0.post0.devDISTANCE
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"]:
-            rendered += ".post0.dev%d" % pieces["distance"]
-    else:
-        # exception #1
-        rendered = "0.post0.dev%d" % pieces["distance"]
-    return rendered
-
-
-def render_pep440_post(pieces):
-    """TAG[.postDISTANCE[.dev0]+gHEX] .
-
-    The ".dev0" means dirty. Note that .dev0 sorts backwards
-    (a dirty tree will appear "older" than the corresponding clean one),
-    but you shouldn't be releasing software with -dirty anyways.
-
-    Exceptions:
-    1: no tags. 0.postDISTANCE[.dev0]
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"] or pieces["dirty"]:
-            rendered += ".post%d" % pieces["distance"]
-            if pieces["dirty"]:
-                rendered += ".dev0"
-            rendered += plus_or_dot(pieces)
-            rendered += "g%s" % pieces["short"]
-    else:
-        # exception #1
-        rendered = "0.post%d" % pieces["distance"]
-        if pieces["dirty"]:
-            rendered += ".dev0"
-        rendered += "+g%s" % pieces["short"]
-    return rendered
-
-
-def render_pep440_post_branch(pieces):
-    """TAG[.postDISTANCE[.dev0]+gHEX[.dirty]] .
-
-    The ".dev0" means not master branch.
-
-    Exceptions:
-    1: no tags. 0.postDISTANCE[.dev0]+gHEX[.dirty]
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"] or pieces["dirty"]:
-            rendered += ".post%d" % pieces["distance"]
-            if pieces["branch"] != "master":
-                rendered += ".dev0"
-            rendered += plus_or_dot(pieces)
-            rendered += "g%s" % pieces["short"]
-            if pieces["dirty"]:
-                rendered += ".dirty"
-    else:
-        # exception #1
-        rendered = "0.post%d" % pieces["distance"]
-        if pieces["branch"] != "master":
-            rendered += ".dev0"
-        rendered += "+g%s" % pieces["short"]
-        if pieces["dirty"]:
-            rendered += ".dirty"
-    return rendered
-
-
-def render_pep440_old(pieces):
-    """TAG[.postDISTANCE[.dev0]] .
-
-    The ".dev0" means dirty.
-
-    Exceptions:
-    1: no tags. 0.postDISTANCE[.dev0]
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"] or pieces["dirty"]:
-            rendered += ".post%d" % pieces["distance"]
-            if pieces["dirty"]:
-                rendered += ".dev0"
-    else:
-        # exception #1
-        rendered = "0.post%d" % pieces["distance"]
-        if pieces["dirty"]:
-            rendered += ".dev0"
-    return rendered
-
-
-def render_git_describe(pieces):
-    """TAG[-DISTANCE-gHEX][-dirty].
-
-    Like 'git describe --tags --dirty --always'.
-
-    Exceptions:
-    1: no tags. HEX[-dirty]  (note: no 'g' prefix)
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"]:
-            rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
-    else:
-        # exception #1
-        rendered = pieces["short"]
-    if pieces["dirty"]:
-        rendered += "-dirty"
-    return rendered
-
-
-def render_git_describe_long(pieces):
-    """TAG-DISTANCE-gHEX[-dirty].
-
-    Like 'git describe --tags --dirty --always -long'.
-    The distance/hash is unconditional.
-
-    Exceptions:
-    1: no tags. HEX[-dirty]  (note: no 'g' prefix)
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
-    else:
-        # exception #1
-        rendered = pieces["short"]
-    if pieces["dirty"]:
-        rendered += "-dirty"
-    return rendered
-
-
-def render(pieces, style):
-    """Render the given version pieces into the requested style."""
-    if pieces["error"]:
-        return {"version": "unknown",
-                "full-revisionid": pieces.get("long"),
-                "dirty": None,
-                "error": pieces["error"],
-                "date": None}
-
-    if not style or style == "default":
-        style = "pep440"  # the default
-
-    if style == "pep440":
-        rendered = render_pep440(pieces)
-    elif style == "pep440-branch":
-        rendered = render_pep440_branch(pieces)
-    elif style == "pep440-pre":
-        rendered = render_pep440_pre(pieces)
-    elif style == "pep440-post":
-        rendered = render_pep440_post(pieces)
-    elif style == "pep440-post-branch":
-        rendered = render_pep440_post_branch(pieces)
-    elif style == "pep440-old":
-        rendered = render_pep440_old(pieces)
-    elif style == "git-describe":
-        rendered = render_git_describe(pieces)
-    elif style == "git-describe-long":
-        rendered = render_git_describe_long(pieces)
-    else:
-        raise ValueError("unknown style '%s'" % style)
-
-    return {"version": rendered, "full-revisionid": pieces["long"],
-            "dirty": pieces["dirty"], "error": None,
-            "date": pieces.get("date")}
-
-
-def get_versions():
-    """Get version information or return default if unable to do so."""
-    # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
-    # __file__, we can work backwards from there to the root. Some
-    # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
-    # case we can only use expanded keywords.
-
-    cfg = get_config()
-    verbose = cfg.verbose
-
-    try:
-        return git_versions_from_keywords(get_keywords(), cfg.tag_prefix,
-                                          verbose)
-    except NotThisMethod:
-        pass
-
-    try:
-        root = os.path.realpath(__file__)
-        # versionfile_source is the relative path from the top of the source
-        # tree (where the .git directory might live) to this file. Invert
-        # this to find the root from __file__.
-        for _ in cfg.versionfile_source.split('/'):
-            root = os.path.dirname(root)
-    except NameError:
-        return {"version": "0+unknown", "full-revisionid": None,
-                "dirty": None,
-                "error": "unable to find root of source tree",
-                "date": None}
-
-    try:
-        pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose)
-        return render(pieces, cfg.style)
-    except NotThisMethod:
-        pass
-
-    try:
-        if cfg.parentdir_prefix:
-            return versions_from_parentdir(cfg.parentdir_prefix, root, verbose)
-    except NotThisMethod:
-        pass
-
-    return {"version": "0+unknown", "full-revisionid": None,
-            "dirty": None,
-            "error": "unable to compute version", "date": None}
diff --git a/pyshtools/backends/meson.build b/pyshtools/backends/meson.build
new file mode 100644
index 000000000..7e81f3877
--- /dev/null
+++ b/pyshtools/backends/meson.build
@@ -0,0 +1,8 @@
+python_sources = [
+  '__init__.py',
+  'backends.py',
+  'ducc0_wrapper.py',
+  'shtools.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/backends')
diff --git a/pyshtools/constants/meson.build b/pyshtools/constants/meson.build
new file mode 100644
index 000000000..ec030b2ae
--- /dev/null
+++ b/pyshtools/constants/meson.build
@@ -0,0 +1,10 @@
+python_sources = [
+  '__init__.py',
+  'Earth.py',
+  'Mars.py',
+  'Mercury.py',
+  'Moon.py',
+  'Venus.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/constants')
diff --git a/pyshtools/datasets/Earth/Earth2012/meson.build b/pyshtools/datasets/Earth/Earth2012/meson.build
new file mode 100644
index 000000000..ebb51ed5b
--- /dev/null
+++ b/pyshtools/datasets/Earth/Earth2012/meson.build
@@ -0,0 +1,5 @@
+python_sources = [
+  '__init__.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/datasets/Earth/Earth2012')
diff --git a/pyshtools/datasets/Earth/Earth2014/meson.build b/pyshtools/datasets/Earth/Earth2014/meson.build
new file mode 100644
index 000000000..8779a62d7
--- /dev/null
+++ b/pyshtools/datasets/Earth/Earth2014/meson.build
@@ -0,0 +1,5 @@
+python_sources = [
+  '__init__.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/datasets/Earth/Earth2014')
diff --git a/pyshtools/datasets/Earth/meson.build b/pyshtools/datasets/Earth/meson.build
new file mode 100644
index 000000000..c97e5061e
--- /dev/null
+++ b/pyshtools/datasets/Earth/meson.build
@@ -0,0 +1,8 @@
+python_sources = [
+  '__init__.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/datasets/Earth')
+
+subdir('Earth2012')
+subdir('Earth2014')
diff --git a/pyshtools/datasets/Mars/historical/meson.build b/pyshtools/datasets/Mars/historical/meson.build
new file mode 100644
index 000000000..ae0e9df75
--- /dev/null
+++ b/pyshtools/datasets/Mars/historical/meson.build
@@ -0,0 +1,7 @@
+python_sources = [
+  '__init__.py',
+  'gravity.py',
+  'magnetic.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/datasets/Mars/historical')
diff --git a/pyshtools/datasets/Mars/meson.build b/pyshtools/datasets/Mars/meson.build
new file mode 100644
index 000000000..5122adbae
--- /dev/null
+++ b/pyshtools/datasets/Mars/meson.build
@@ -0,0 +1,7 @@
+python_sources = [
+  '__init__.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/datasets/Mars')
+
+subdir('historical')
diff --git a/pyshtools/datasets/Moon/historical/meson.build b/pyshtools/datasets/Moon/historical/meson.build
new file mode 100644
index 000000000..53d57789a
--- /dev/null
+++ b/pyshtools/datasets/Moon/historical/meson.build
@@ -0,0 +1,7 @@
+python_sources = [
+  '__init__.py',
+  'gravity.py',
+  'topography.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/datasets/Moon/historical')
diff --git a/pyshtools/datasets/Moon/meson.build b/pyshtools/datasets/Moon/meson.build
new file mode 100644
index 000000000..9d7fb019c
--- /dev/null
+++ b/pyshtools/datasets/Moon/meson.build
@@ -0,0 +1,7 @@
+python_sources = [
+  '__init__.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/datasets/Moon')
+
+subdir('historical')
diff --git a/pyshtools/datasets/Venus/historical/meson.build b/pyshtools/datasets/Venus/historical/meson.build
new file mode 100644
index 000000000..bb834a322
--- /dev/null
+++ b/pyshtools/datasets/Venus/historical/meson.build
@@ -0,0 +1,6 @@
+python_sources = [
+  '__init__.py',
+  'topography.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/datasets/Venus/historical')
diff --git a/pyshtools/datasets/Venus/meson.build b/pyshtools/datasets/Venus/meson.build
new file mode 100644
index 000000000..a34f23585
--- /dev/null
+++ b/pyshtools/datasets/Venus/meson.build
@@ -0,0 +1,7 @@
+python_sources = [
+  '__init__.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/datasets/Venus')
+
+subdir('historical')
diff --git a/pyshtools/datasets/meson.build b/pyshtools/datasets/meson.build
new file mode 100644
index 000000000..ea49f0713
--- /dev/null
+++ b/pyshtools/datasets/meson.build
@@ -0,0 +1,14 @@
+python_sources = [
+  '__init__.py',
+  'Ceres.py',
+  'Ganymede.py',
+  'Mercury.py',
+  'Vesta.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/datasets')
+
+subdir('Earth')
+subdir('Mars')
+subdir('Moon')
+subdir('Venus')
diff --git a/pyshtools/doc/make_docs.py b/pyshtools/doc/make_docs.py
deleted file mode 100755
index 4aba36cbe..000000000
--- a/pyshtools/doc/make_docs.py
+++ /dev/null
@@ -1,201 +0,0 @@
-"""
-This script builds the python documentation from the function signature and the
-customized markdown files. The processed documentation is saved as ascii text
-files which are loaded on runtime and replace the __doc__ string of the f2py
-wrapped functions.
-"""
-import sys
-import os
-import re
-import textwrap
-
-
-def main():
-    # ---- input/output folders ----
-    pydocfolder = os.path.dirname(os.path.abspath(__file__))
-    sys.path.append(os.path.join(pydocfolder, '..'))
-    import _SHTOOLS  # noqa: E402
-
-    mddocfolder = os.path.join(pydocfolder, '../../src/pydoc')
-    print('--> Building python doc strings')
-    print('searching documentation in folder: {} --'.format(mddocfolder))
-
-    # ---- loop through the f2py _SHTOOLS functions and make docstrings ----
-    for name, func in _SHTOOLS.__dict__.items():
-        if callable(func):
-            try:
-                # ---- process and load documentation ----
-                # ---- read md file documentation: ----
-                fname_mddoc = os.path.join(mddocfolder, 'py' +
-                                           name.lower() + '.md')
-                if (os.path.isfile(fname_mddoc)):
-                    docstring = process_mddoc(fname_mddoc)
-                    # ---- save combined docstring in the pydoc folder ----
-                    fname_pydoc = os.path.join(pydocfolder, name.lower() +
-                                               '.doc')
-                    with open(fname_pydoc, 'w') as pydocfile:
-                        pydocfile.write(docstring)
-
-            except IOError as msg:
-                print(msg)
-
-    # ---- loop through functions that are defined in python ----
-    pyfunctions = ['PlmIndex', 'YilmIndexVector']
-    for name in pyfunctions:
-        try:
-            # ---- process and load documentation
-            # read md file documentation:
-            fname_mddoc = os.path.join(mddocfolder, 'py' + name.lower() +
-                                       '.md')
-            docstring = process_mddoc(fname_mddoc)
-            # ---- save combined docstring in the pydoc folder--
-            fname_pydoc = os.path.join(pydocfolder, name.lower() + '.doc')
-            with open(fname_pydoc, 'w') as pydocfile:
-                pydocfile.write(docstring)
-
-        except IOError as msg:
-            print(msg)
-
-    print('python doc strings created successfully')
-
-
-# ===== PROCESS MD DOCUMENTATION FILE ====
-def process_mddoc(fname_mddoc):
-    # ---- md file search patterns ----
-    revalue = re.compile(r'## Value\n\n', re.DOTALL)
-    retail = re.compile(r'# See (.*)', re.DOTALL)
-    reh2 = re.compile(r'## (.*?)\n', re.DOTALL)
-    reh1 = re.compile(r'\A# (.*?)\n', re.DOTALL)
-    reh1b = re.compile(r'\n# (.*?)\n', re.DOTALL)
-    recode = re.compile(r'`(.*?)`', re.DOTALL)
-    restaresc = re.compile(r'(\\\*)', re.DOTALL)
-    repycodestart = re.compile(r'```python\n', re.DOTALL)
-    repycodeend = re.compile(r'```\n', re.DOTALL)
-    # rebold = re.compile(r'(?![\])[*](.*?)(?![\])[*]',re.DOTALL)
-
-    # ---- open md file and search for patterns ----
-    with open(fname_mddoc, 'r') as mdfile:
-        # remove the first two lines
-        mdstring = mdfile.read().split('\n', 2)[2]
-
-    # First, remove '## Value\n\n' from constant documentation
-    match = revalue.search(mdstring)
-    if match is not None:
-        mdstring = re.sub(match.group(0), '', mdstring)
-
-    # Remove python code block around usage StringEnd
-    match = repycodestart.search(mdstring)
-    if match is not None:
-        mdstring = mdstring.replace(match.group(0), '')
-    match = repycodeend.search(mdstring)
-    if match is not None:
-        mdstring = mdstring.replace(match.group(0), '')
-
-    match = retail.search(mdstring)
-    if match is not None:
-        mdstring = mdstring.replace(match.group(0), '')
-
-    match = reh1.search(mdstring)
-    while match is not None:
-        mdstring = re.sub(match.group(0), match.group(1) + '\n' +
-                          len(match.group(1)) * '-', mdstring)
-        match = reh1.search(mdstring)
-
-    match = reh1b.search(mdstring)
-    while match is not None:
-        mdstring = re.sub(match.group(0), '\n' + match.group(1) + '\n' +
-                          len(match.group(1)) * '-', mdstring)
-        match = reh1b.search(mdstring)
-
-    match = reh2.search(mdstring)
-    while match is not None:
-        mdstring = re.sub(match.group(0), match.group(1) + '\n' +
-                          len(match.group(1)) * '-', mdstring)
-        match = reh2.search(mdstring)
-
-    match = recode.search(mdstring)
-    while match is not None:
-        mdstring = mdstring.replace(match.group(0), match.group(1))
-        match = recode.search(mdstring)
-
-    match = restaresc.search(mdstring)
-    while match is not None:
-        mdstring = mdstring.replace(match.group(0), '*')
-        match = recode.search(mdstring)
-
-    # ---- combine into docstring ----
-    docstring = ''
-    tmp = mdstring.splitlines(True)
-
-    # --- remove line breaks between parameters ---
-    for i in range(0, len(tmp)-3):
-        if tmp[i][0:4] == ':   ' and tmp[i+3][0:4] == ':   ':
-            tmp[i+1] = ''
-
-    for i in range(0, len(tmp)):
-        if tmp[i][0:4] == ':   ':
-            docstring += textwrap.fill(tmp[i][4:], width=80,
-                                       replace_whitespace=False,
-                                       initial_indent='    ',
-                                       subsequent_indent='    ') + '\n'
-        elif tmp[i] == '':
-            pass
-        else:
-            docstring += textwrap.fill(tmp[i], width=80,
-                                       replace_whitespace=False) + '\n'
-
-    return docstring
-
-
-# ===== PROCESS F2PY DOCUMENTATION ====
-def process_f2pydoc(f2pydoc):
-    """
-    this function replace all optional _d0 arguments with their default values
-    in the function signature. These arguments are not intended to be used and
-    signify merely the array dimensions of the associated argument.
-    """
-    # ---- split f2py document in its parts
-    # 0=Call Signature
-    # 1=Parameters
-    # 2=Other (optional) Parameters (only if present)
-    # 3=Returns
-    docparts = re.split(r'\n--', f2pydoc)
-
-    if len(docparts) == 4:
-        doc_has_optionals = True
-    elif len(docparts) == 3:
-        doc_has_optionals = False
-    else:
-        print('-- uninterpretable f2py documentation --')
-        return f2pydoc
-
-    # ---- replace arguments with _d suffix with empty string in ----
-    # ---- function signature (remove them): ----
-    docparts[0] = re.sub(r'[\[(,]\w+_d\d', '', docparts[0])
-
-    # ---- replace _d arguments of the return arrays with their default value:
-    if doc_has_optionals:
-
-        returnarray_dims = re.findall(r'[\[(,](\w+_d\d)', docparts[3])
-        for arg in returnarray_dims:
-            searchpattern = arg + ' : input.*\n.*Default: (.*)\n'
-            match = re.search(searchpattern, docparts[2])
-            if match:
-                default = match.group(1)
-                docparts[3] = re.sub(arg, default, docparts[3])
-                docparts[2] = re.sub(searchpattern, '', docparts[2])
-
-    # ---- remove all optional _d# from optional argument list:
-    if doc_has_optionals:
-        searchpattern = r'\w+_d\d : input.*\n.*Default: (.*)\n'
-        docparts[2] = re.sub(searchpattern, '', docparts[2])
-
-    # ---- combine doc parts to a single string
-    processed_signature = '\n--'.join(docparts)
-
-    return processed_signature
-
-
-# ==== EXECUTE SCRIPT ====
-if __name__ == "__main__":
-    main()
diff --git a/pyshtools/doc/meson.build b/pyshtools/doc/meson.build
new file mode 100644
index 000000000..69c4c60f3
--- /dev/null
+++ b/pyshtools/doc/meson.build
@@ -0,0 +1,106 @@
+doc_files = [
+  'batohilmdh.doc',
+  'batohilmrhohdh.doc',
+  'cilmminusdh.doc',
+  'cilmminusrhohdh.doc',
+  'cilmplusdh.doc',
+  'cilmplusrhohdh.doc',
+  'computedg82.doc',
+  'computedm.doc',
+  'computedmap.doc',
+  'curve2mask.doc',
+  'dhaj.doc',
+  'djpi2.doc',
+  'downcontfilterma.doc',
+  'downcontfiltermc.doc',
+  'glqgridcoord.doc',
+  'makecirclecoord.doc',
+  'makeellipsecoord.doc',
+  'makegeoidgriddh.doc',
+  'makegradientdh.doc',
+  'makegravgradgriddh.doc',
+  'makegravgriddh.doc',
+  'makegravgridpoint.doc',
+  'makegrid2d.doc',
+  'makegriddh.doc',
+  'makegriddhc.doc',
+  'makegridglq.doc',
+  'makegridglqc.doc',
+  'makegridpoint.doc',
+  'makegridpointc.doc',
+  'makemaggradgriddh.doc',
+  'makemaggriddh.doc',
+  'makemaggridpoint.doc',
+  'normalgravity.doc',
+  'plbar.doc',
+  'plbar_d1.doc',
+  'plegendre.doc',
+  'plegendre_d1.doc',
+  'plegendrea.doc',
+  'plegendrea_d1.doc',
+  'plmbar.doc',
+  'plmbar_d1.doc',
+  'plmindex.doc',
+  'plmon.doc',
+  'plmon_d1.doc',
+  'plmschmidt.doc',
+  'plmschmidt_d1.doc',
+  'plon.doc',
+  'plon_d1.doc',
+  'plschmidt.doc',
+  'plschmidt_d1.doc',
+  'shadmitcorr.doc',
+  'shbias.doc',
+  'shbiasadmitcorr.doc',
+  'shbiask.doc',
+  'shbiaskmask.doc',
+  'shcilmtocindex.doc',
+  'shcilmtovector.doc',
+  'shcindextocilm.doc',
+  'shconfidence.doc',
+  'shctor.doc',
+  'shexpanddh.doc',
+  'shexpanddhc.doc',
+  'shexpandglq.doc',
+  'shexpandglqc.doc',
+  'shexpandlsq.doc',
+  'shexpandwlsq.doc',
+  'shfindlwin.doc',
+  'shglq.doc',
+  'shlocalizedadmitcorr.doc',
+  'shmtcouplingmatrix.doc',
+  'shmtdebias.doc',
+  'shmtvar.doc',
+  'shmtvaropt.doc',
+  'shmultiply.doc',
+  'shmultitapercse.doc',
+  'shmultitapermaskcse.doc',
+  'shmultitapermaskse.doc',
+  'shmultitaperse.doc',
+  'shread2.doc',
+  'shread2error.doc',
+  'shreadjpl.doc',
+  'shreadjplerror.doc',
+  'shreturntapers.doc',
+  'shreturntapersm.doc',
+  'shreturntapersmap.doc',
+  'shrotatecoef.doc',
+  'shrotaterealcoef.doc',
+  'shrotatetapers.doc',
+  'shrtoc.doc',
+  'shscouplingmatrix.doc',
+  'shscouplingmatrixcap.doc',
+  'shsjkpg.doc',
+  'shslepianvar.doc',
+  'shvectortocilm.doc',
+  'slepiancoeffs.doc',
+  'slepiancoeffstosh.doc',
+  'sphericalcapcoef.doc',
+  'wigner3j.doc',
+  'yilmindexvector.doc',
+]
+
+install_data(
+  doc_files,
+  install_dir: python.get_install_dir(subdir: 'pyshtools/doc'),
+  install_tag: 'doc')
diff --git a/pyshtools/expand/meson.build b/pyshtools/expand/meson.build
new file mode 100644
index 000000000..076284dff
--- /dev/null
+++ b/pyshtools/expand/meson.build
@@ -0,0 +1,6 @@
+python_sources = [
+  '__init__.py',
+  'spharm_functions.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/expand')
diff --git a/pyshtools/gravmag/meson.build b/pyshtools/gravmag/meson.build
new file mode 100644
index 000000000..778a10079
--- /dev/null
+++ b/pyshtools/gravmag/meson.build
@@ -0,0 +1,6 @@
+python_sources = [
+  '__init__.py',
+  'mag_spectrum.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/gravmag')
diff --git a/pyshtools/legendre/meson.build b/pyshtools/legendre/meson.build
new file mode 100644
index 000000000..6db336427
--- /dev/null
+++ b/pyshtools/legendre/meson.build
@@ -0,0 +1,7 @@
+python_sources = [
+  '__init__.py',
+  'legendre_functions.py',
+  'plm_index.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/legendre')
diff --git a/pyshtools/meson.build b/pyshtools/meson.build
new file mode 100644
index 000000000..d6b3df24c
--- /dev/null
+++ b/pyshtools/meson.build
@@ -0,0 +1,75 @@
+python_sources = [
+  '__init__.py',
+]
+
+pymod = import('python')
+python = pymod.find_installation(pure: false)
+
+# NumPy include directory
+# This section was copied from SciPy, except for the a) part about `signal`
+# since that directory does not exist here, and b) the absolute paths, since we
+# don't link to NumPy core libraries.
+# The try-except is needed because when things are split across drives on
+# Windows, there is no relative path and an exception gets raised. There may be
+# other such cases, so add a catch-all and switch to an absolute path. Relative
+# paths are needed when for example a virtualenv is placed inside the source
+# tree; Meson rejects absolute paths to places inside the source tree.
+# For cross-compilation it is often not possible to run the Python interpreter
+# in order to retrieve numpy's include directory. It can be specified in the
+# cross file instead:
+#
+#   [properties]
+#   numpy-include-dir = /abspath/to/host-pythons/site-packages/numpy/core/include
+#
+# This uses the path as is, and avoids running the interpreter.
+incdir_numpy = meson.get_external_property('numpy-include-dir', 'not-given')
+if incdir_numpy == 'not-given'
+  incdir_numpy = run_command(python,
+    [
+      '-c',
+      '''import os
+import numpy as np
+try:
+    incdir = os.path.relpath(np.get_include())
+except Exception:
+    incdir = np.get_include()
+print(incdir)'''
+    ],
+    check: true
+  ).stdout().strip()
+endif
+inc_np = include_directories(incdir_numpy)
+
+incdir_f2py = incdir_numpy / '..' / '..' / 'f2py' / 'src'
+inc_f2py = include_directories(incdir_f2py)
+fortranobject_c = incdir_f2py / 'fortranobject.c'
+
+
+pyshtools_pyf = custom_target('pyshtools_c',
+  input: '../src/pyshtools.pyf',
+  output: ['_SHTOOLS-f2pywrappers.f', '_SHTOOLSmodule.c'],
+  command: [python, '-m', 'numpy.f2py', '@INPUT@', '--build-dir', '@OUTDIR@'])
+
+pyshtool = python.extension_module('_SHTOOLS',
+  pyshtools_pyf, '../src/PythonWrapper.f95', fortranobject_c,
+  c_args: '-DNPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION',
+  include_directories: [inc_np, inc_f2py],
+  link_with: shtools,
+  dependencies: python.dependency(),
+  install: true,
+  subdir: 'pyshtools')
+
+python.install_sources(python_sources, subdir: 'pyshtools')
+
+subdir('backends')
+subdir('constants')
+subdir('datasets')
+subdir('doc')
+subdir('expand')
+subdir('gravmag')
+subdir('legendre')
+subdir('rotate')
+subdir('shclasses')
+subdir('shio')
+subdir('spectralanalysis')
+subdir('utils')
diff --git a/pyshtools/rotate/meson.build b/pyshtools/rotate/meson.build
new file mode 100644
index 000000000..452d1af64
--- /dev/null
+++ b/pyshtools/rotate/meson.build
@@ -0,0 +1,5 @@
+python_sources = [
+  '__init__.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/rotate')
diff --git a/pyshtools/shclasses/meson.build b/pyshtools/shclasses/meson.build
new file mode 100644
index 000000000..2f3256a1c
--- /dev/null
+++ b/pyshtools/shclasses/meson.build
@@ -0,0 +1,17 @@
+python_sources = [
+  '__init__.py',
+  'shcoeffs.py',
+  'shgeoid.py',
+  'shgradient.py',
+  'shgravcoeffs.py',
+  'shgravgrid.py',
+  'shgrid.py',
+  'shmagcoeffs.py',
+  'shmaggrid.py',
+  'shtensor.py',
+  'shwindow.py',
+  'slepian.py',
+  'slepiancoeffs.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/shclasses')
diff --git a/pyshtools/shclasses/shcoeffs.py b/pyshtools/shclasses/shcoeffs.py
index 754abb7bd..c62828d66 100644
--- a/pyshtools/shclasses/shcoeffs.py
+++ b/pyshtools/shclasses/shcoeffs.py
@@ -1833,6 +1833,8 @@ def volume(self, lmax=None, backend=None, nthreads=None):
             lmax = min(3*lmax, 2800)
 
         r0 = self.coeffs[0, 0, 0]
+        if self.normalization == 'ortho':
+            r0 = r0 / _np.sqrt(4 * _np.pi)
         grid = self.expand(lmax=lmax, backend=backend,
                            nthreads=nthreads) - r0
         h200 = (grid**2).expand(lmax_calc=0, backend=backend,
@@ -2902,7 +2904,7 @@ def plot_spectrum2d(self, convention='power', ticks='WSen',
         if cmap_limits is None and cmap_rlimits is None:
             if cmap_scale.lower() == 'log':
                 _temp = spectrum
-                _temp[_temp == 0] = _np.NaN
+                _temp[_temp == 0] = _np.nan
                 vmin = _np.nanmin(_temp)
             else:
                 vmin = _np.nanmin(spectrum)
@@ -3401,7 +3403,7 @@ def plot_cross_spectrum2d(self, clm, convention='power', ticks='WSen',
         if cmap_limits is None and cmap_rlimits is None:
             if cmap_scale.lower() == 'log':
                 _temp = spectrum
-                _temp[_temp == 0] = _np.NaN
+                _temp[_temp == 0] = _np.nan
                 vmin = _np.nanmin(_temp)
             else:
                 vmin = _np.nanmin(spectrum)
@@ -4161,7 +4163,7 @@ def _expand_coord(self, lat, lon, lmax_calc, degrees):
                              'Input types are {:s} and {:s}.'
                              .format(repr(type(lat)), repr(type(lon))))
 
-        if type(lat) is int or type(lat) is float or type(lat) is _np.float_:
+        if type(lat) is int or type(lat) is float or type(lat) is _np.float64:
             return _shtools.MakeGridPoint(self.coeffs, lat=latin, lon=lonin,
                                           lmax=lmax_calc, norm=norm,
                                           csphase=self.csphase)
@@ -4447,7 +4449,7 @@ def _expand_coord(self, lat, lon, lmax_calc, degrees):
                              'Input types are {:s} and {:s}.'
                              .format(repr(type(lat)), repr(type(lon))))
 
-        if type(lat) is int or type(lat) is float or type(lat) is _np.float_:
+        if type(lat) is int or type(lat) is float or type(lat) is _np.float64:
             return _shtools.MakeGridPointC(self.coeffs, lat=latin, lon=lonin,
                                            lmax=lmax_calc, norm=norm,
                                            csphase=self.csphase)
diff --git a/pyshtools/shclasses/shgravcoeffs.py b/pyshtools/shclasses/shgravcoeffs.py
index 672523814..39d435c9f 100644
--- a/pyshtools/shclasses/shgravcoeffs.py
+++ b/pyshtools/shclasses/shgravcoeffs.py
@@ -3144,7 +3144,7 @@ def plot_spectrum2d(self, function='geoid', ticks='WSen',
         if cmap_limits is None and cmap_rlimits is None:
             if cmap_scale.lower() == 'log':
                 _temp = spectrum
-                _temp[_temp == 0] = _np.NaN
+                _temp[_temp == 0] = _np.nan
                 vmin = _np.nanmin(_temp)
             else:
                 vmin = _np.nanmin(spectrum)
@@ -3853,7 +3853,7 @@ def _expand_coord(self, a, f, lat, lon, degrees, lmax_calc, omega):
                              'Input types are {:s} and {:s}.'
                              .format(repr(type(lat)), repr(type(lon))))
 
-        if type(lat) is int or type(lat) is float or type(lat) is _np.float_:
+        if type(lat) is int or type(lat) is float or type(lat) is _np.float64:
             if f == 0.:
                 r = a
             else:
diff --git a/pyshtools/shclasses/shmagcoeffs.py b/pyshtools/shclasses/shmagcoeffs.py
index c97c3be99..1a88fdfc9 100644
--- a/pyshtools/shclasses/shmagcoeffs.py
+++ b/pyshtools/shclasses/shmagcoeffs.py
@@ -2530,7 +2530,7 @@ def plot_spectrum2d(self, function='total', ticks='WSen',
         if cmap_limits is None and cmap_rlimits is None:
             if cmap_scale.lower() == 'log':
                 _temp = spectrum
-                _temp[_temp == 0] = _np.NaN
+                _temp[_temp == 0] = _np.nan
                 vmin = _np.nanmin(_temp)
             else:
                 vmin = _np.nanmin(spectrum)
@@ -2989,7 +2989,7 @@ def _expand_coord(self, a, f, lat, lon, degrees, lmax_calc):
                              'Input types are {:s} and {:s}.'
                              .format(repr(type(lat)), repr(type(lon))))
 
-        if type(lat) is int or type(lat) is float or type(lat) is _np.float_:
+        if type(lat) is int or type(lat) is float or type(lat) is _np.float64:
             if f == 0.:
                 r = a
             else:
diff --git a/pyshtools/shio/meson.build b/pyshtools/shio/meson.build
new file mode 100644
index 000000000..3ad69cb79
--- /dev/null
+++ b/pyshtools/shio/meson.build
@@ -0,0 +1,12 @@
+python_sources = [
+  '__init__.py',
+  'bshc.py',
+  'convert.py',
+  'dov.py',
+  'icgem.py',
+  'read_igrf.py',
+  'shtools.py',
+  'yilm_index_vector.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/shio')
diff --git a/pyshtools/spectralanalysis/meson.build b/pyshtools/spectralanalysis/meson.build
new file mode 100644
index 000000000..8b7b94094
--- /dev/null
+++ b/pyshtools/spectralanalysis/meson.build
@@ -0,0 +1,7 @@
+python_sources = [
+  '__init__.py',
+  'cross_spectrum.py',
+  'spectrum.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/spectralanalysis')
diff --git a/pyshtools/utils/meson.build b/pyshtools/utils/meson.build
new file mode 100644
index 000000000..797b11fd3
--- /dev/null
+++ b/pyshtools/utils/meson.build
@@ -0,0 +1,7 @@
+python_sources = [
+  '__init__.py',
+  'datetime.py',
+  'figstyle.py',
+]
+
+python.install_sources(python_sources, subdir: 'pyshtools/utils')
diff --git a/requirements-dev.txt b/requirements-dev.txt
deleted file mode 100644
index 422344160..000000000
--- a/requirements-dev.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-ipython
-palettable>=3.3
-jupyter
-cython
-pyshp
-six
-shapely
-cartopy>=0.18.0
-pygmt>=0.3
-ducc0>=0.15
-flake8
diff --git a/requirements.txt b/requirements.txt
index a6ec1e159..639ecea5b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,5 @@
+meson-python>=0.14
+setuptools-scm>=8
 numpy
 scipy>=0.14.0
 matplotlib>=3.3
@@ -6,3 +8,13 @@ xarray
 requests
 pooch>=1.1
 tqdm
+cartopy>=0.18.0
+cython
+pyshp
+six
+shapely
+pygmt>=0.3
+ducc0>=0.15
+palettable>=3.3
+jupyter
+flake8
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 2bce94ce4..000000000
--- a/setup.cfg
+++ /dev/null
@@ -1,6 +0,0 @@
-[versioneer]
-VCS = git
-style = pep440
-versionfile_source = pyshtools/_version.py
-versionfile_build = pyshtools/_version.py
-tag_prefix = ''
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 912a51a2d..000000000
--- a/setup.py
+++ /dev/null
@@ -1,180 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-
-"""Setup script for pyshtools"""
-
-import sys
-
-min_version = (3, 6)
-
-if sys.version_info < min_version:
-    error = '\n*** Beginning with pyshtools 4.6, Python {:} or above \n' \
-            '*** is required. This error may be a result of using a \n' \
-            '*** python-2.7 version of pip. \n' \
-            '*** {:}'.format(('.'.join(str(n) for n in min_version)),
-                             sys.version_info)
-    raise SystemError(error)
-
-import os  # noqa: E402
-from pathlib import Path  # noqa: E402
-import pkg_resources  # noqa: E402
-import sysconfig  # noqa: E402
-
-import setuptools  # noqa: E402
-import numpy  # noqa: E402
-import versioneer  # noqa: E402
-from numpy.distutils.core import setup  # noqa: E402
-from numpy.distutils.core import numpy_cmdclass  # noqa: E402
-from numpy.distutils.fcompiler import FCompiler  # noqa: E402
-from numpy.distutils.fcompiler import get_default_fcompiler  # noqa: E402
-from numpy.distutils.misc_util import Configuration  # noqa: E402
-from numpy.distutils.system_info import get_info, dict_append  # noqa: E402
-
-
-CLASSIFIERS = [
-    'Development Status :: 5 - Production/Stable',
-    'Environment :: Console',
-    'Intended Audience :: Science/Research',
-    'Intended Audience :: Developers',
-    'License :: OSI Approved :: BSD License',
-    'Natural Language :: English',
-    'Operating System :: OS Independent',
-    'Programming Language :: Fortran',
-    'Programming Language :: Python',
-    'Programming Language :: Python :: 3',
-    'Topic :: Scientific/Engineering',
-    'Topic :: Scientific/Engineering :: GIS',
-    'Topic :: Scientific/Engineering :: Mathematics',
-    'Topic :: Scientific/Engineering :: Physics'
-]
-
-KEYWORDS = ['Spherical Harmonics', 'Spectral Estimation', 'Slepian Functions',
-            'Legendre Functions', 'Gravity Field', 'Magnetic Field']
-
-PYTHON_REQUIRES = '>={}'.format('.'.join(str(n) for n in min_version))
-
-INSTALL_REQUIRES = [
-    'numpy>=' + str(numpy.__version__),
-    'scipy>=0.14.0',
-    'matplotlib>=3.3',
-    'astropy>=4.0',
-    'xarray',
-    'requests',
-    'pooch>=1.1',
-    'tqdm'
-]
-
-EXTRAS_REQUIRE = {
-    'cartopy': ['cython', 'pyshp', 'six', 'shapely', 'cartopy>=0.18.0'],
-    'pygmt': ['pygmt>=0.3'],
-    'palettable': ['palettable>=3.3'],
-    'ducc': ['ducc0>=0.15']
-}
-
-VERSION = versioneer.get_version()
-print('INSTALLING SHTOOLS {}'.format(VERSION))
-
-
-def distutils_dir_name(dname):
-    """Returns the name of a distutils build directory"""
-    parse_version = pkg_resources.packaging.version.parse
-    if parse_version(setuptools.__version__) < parse_version('62.1.0'):
-        f = "{dirname}.{platform}-{version[0]}.{version[1]}"
-        return f.format(dirname=dname,
-                        platform=sysconfig.get_platform(),
-                        version=sys.version_info)
-    else:
-        f = "{dirname}.{platform}-{cache_tag}"
-        return f.format(dirname=dname,
-                        platform=sysconfig.get_platform(),
-                        cache_tag=sys.implementation.cache_tag)
-
-
-# configure python extension to be compiled with f2py
-def configuration(parent_package='', top_path=None):
-    """Configure all packages that need to be built."""
-    config = Configuration('', parent_package, top_path)
-
-    kwargs = {
-        'libraries': [],
-        'include_dirs': [],
-        'library_dirs': []
-    }
-
-    # numpy.distutils.fcompiler.FCompiler doesn't support .F95 extension
-    compiler = FCompiler(get_default_fcompiler())
-    compiler.src_extensions.append('.F95')
-    compiler.language_map['.F95'] = 'f90'
-
-    # collect all Fortran sources
-    files = os.listdir('src')
-    exclude_sources = ['PlanetsConstants.f95', 'PythonWrapper.f95',
-                       'cWrapper.f95']
-    sources = [os.path.join('src', file) for file in files if
-               file.lower().endswith(('.f95', '.c')) and file not in
-               exclude_sources]
-
-    libdir = os.path.join('build', distutils_dir_name('temp'))
-    print('searching SHTOOLS in:', libdir)
-
-    # Fortran compilation
-    config.add_library('SHTOOLS', sources=sources)
-
-    # SHTOOLS
-    kwargs['libraries'].extend(['SHTOOLS'])
-    kwargs['include_dirs'].extend([libdir])
-    kwargs['library_dirs'].extend([libdir])
-    kwargs['f2py_options'] = ['--quiet']
-
-    # FFTW info
-    fftw_info = get_info('fftw', notfound_action=2)
-    dict_append(kwargs, **fftw_info)
-
-    if sys.platform != 'win32':
-        kwargs['libraries'].extend(['m'])
-
-    # BLAS / Lapack info
-    lapack_info = get_info('lapack_opt', notfound_action=2)
-    blas_info = get_info('blas_opt', notfound_action=2)
-    dict_append(kwargs, **blas_info)
-    dict_append(kwargs, **lapack_info)
-
-    if sys.platform == 'win32':
-        kwargs['runtime_library_dirs'] = []
-
-    config.add_extension('pyshtools._SHTOOLS',
-                         sources=['src/pyshtools.pyf',
-                                  'src/PythonWrapper.f95'],
-                         **kwargs)
-
-    return config
-
-
-CMDCLASS = numpy_cmdclass
-CMDCLASS = versioneer.get_cmdclass(CMDCLASS)
-
-metadata = dict(
-    name='pyshtools',
-    version=VERSION,
-    description='SHTOOLS - Spherical Harmonic Tools',
-    long_description=Path('README.md').read_text(encoding='utf-8'),
-    long_description_content_type='text/markdown',
-    url='https://shtools.github.io/SHTOOLS/',
-    download_url='https://github.com/SHTOOLS/SHTOOLS/zipball/master',
-    author='The SHTOOLS developers',
-    author_email="mark.wieczorek@ipgp.fr",
-    license='BSD-3-Clause',
-    keywords=KEYWORDS,
-    python_requires=PYTHON_REQUIRES,
-    install_requires=INSTALL_REQUIRES,
-    extras_require=EXTRAS_REQUIRE,
-    platforms='OS Independent',
-    packages=setuptools.find_packages(),
-    package_data={'pyshtools': ['doc/*.doc']},
-    classifiers=CLASSIFIERS,
-    configuration=configuration,
-    cmdclass=CMDCLASS
-)
-
-
-setup(**metadata)
diff --git a/src/SHExpandLSQ.F95 b/src/SHExpandLSQ.F95
index 12e5dcf14..6861bd7f9 100644
--- a/src/SHExpandLSQ.F95
+++ b/src/SHExpandLSQ.F95
@@ -33,7 +33,7 @@ subroutine SHExpandLSQ(cilm, d, lat, lon, nmax, lmax, norm, chi2, &
 !           nmax    Number of data points.
 !           lmax    Maximum degree of spherical harmonic expansion.
 !
-!       OUT 
+!       OUT
 !           cilm    The spherical harmonic coefficients.
 !
 !       OPTIONAL (IN)
@@ -84,6 +84,7 @@ subroutine SHExpandLSQ(cilm, d, lat, lon, nmax, lmax, norm, chi2, &
                              din(:)
 #ifdef LAPACK_UNDERSCORE
 #define dgels dgels_
+#define dggglm dggglm_
 #endif
     external :: dgels, dggglm
 
diff --git a/src/meson.build b/src/meson.build
new file mode 100644
index 000000000..ea2a754a4
--- /dev/null
+++ b/src/meson.build
@@ -0,0 +1,113 @@
+SOURCES = [
+  'BAtoHilm.f95',
+  'BAtoHilmRhoH.f95',
+  'CilmMinus.f95',
+  'CilmMinusRhoH.f95',
+  'CilmPlus.f95',
+  'CilmPlusRhoH.f95',
+  'ComputeDG82.f95',
+  'ComputeDMap.f95',
+  'ComputeDm.f95',
+  'Curve2Mask.f95',
+  'DHaj.f95',
+  'djpi2.f95',
+  'DownContFilter.f95',
+  'EigValSym.F95',
+  'EigValVecSym.F95',
+  'EigValVecSymTri.F95',
+  'FFTW3.f95',
+  'ftypes.f95',
+  'GLQGridCoord.f95',
+  'MakeCircleCoord.f95',
+  'MakeEllipseCoord.f95',
+  'MakeGeoidGrid.f95',
+  'MakeGradientDH.f95',
+  'MakeGravGradGridDH.f95',
+  'MakeGravGridDH.f95',
+  'MakeGravGridPoint.f95',
+  'MakeGrid2D.f95',
+  'MakeGridDHC.f95',
+  'MakeGridDH.f95',
+  'MakeGridGLQC.f95',
+  'MakeGridGLQ.f95',
+  'MakeGridPointC.f95',
+  'MakeGridPoint.f95',
+  'MakeMagGradGridDH.f95',
+  'MakeMagGridDH.f95',
+  'MakeMagGridPoint.f95',
+  'NormalGravity.f95',
+  'PlanetsConstants.f95',
+  'PlBar_d1.f95',
+  'PlBar.f95',
+  'PLegendreA_d1.f95',
+  'PLegendreA.f95',
+  'PLegendre_d1.f95',
+  'PLegendre.f95',
+  'PlmBar_d1.f95',
+  'PlmBar.f95',
+  'PlmIndex.f95',
+  'PlmON_d1.f95',
+  'PlmON.f95',
+  'PlmSchmidt_d1.f95',
+  'PlmSchmidt.f95',
+  'PlON_d1.f95',
+  'PlON.f95',
+  'PlSchmidt_d1.f95',
+  'PlSchmidt.f95',
+  'PreGLQ.f95',
+  'Random.f95',
+  'SHAdmitCorr.f95',
+  'SHBiasAdmitCorr.f95',
+  'SHBias.f95',
+  'SHBiasK.f95',
+  'SHBiasKMask.f95',
+  'SHCilmToVector.f95',
+  'SHConfidence.f95',
+  'SHConvertCoef.f95',
+  'SHExpandDHC.f95',
+  'SHExpandDH.f95',
+  'SHExpandGLQC.f95',
+  'SHExpandGLQ.f95',
+  'SHExpandLSQ.F95',
+  'SHFindLWin.f95',
+  'SHGLQ.f95',
+  'SHLocalizedAdmitCorr.f95',
+  'SHMagPowerSpectra.f95',
+  'SHMTCouplingMatrix.f95',
+  'SHMTDebias.F95',
+  'SHMTVar.f95',
+  'SHMTVarOpt.F95',
+  'SHMultiply.f95',
+  'SHMultiTaperCSE.f95',
+  'SHMultiTaperMaskCSE.f95',
+  'SHMultiTaperMaskSE.f95',
+  'SHMultiTaperSE.f95',
+  'SHPowerSpectraC.f95',
+  'SHPowerSpectra.f95',
+  'SHRead2.f95',
+  'SHRead.f95',
+  'SHReadJPL.f95',
+  'SHReturnTapers.f95',
+  'SHReturnTapersMap.f95',
+  'SHReturnTapersM.f95',
+  'SHRotateCoef.f95',
+  'SHRotateRealCoef.f95',
+  'SHRotateTapers.f95',
+  'SHSCouplingMatrixCap.f95',
+  'SHSCouplingMatrix.f95',
+  'SHSjkPG.f95',
+  'SHSlepianVar.f95',
+  'SHTOOLS.f95',
+  'SlepianCoeffs.f95',
+  'SlepianCoeffsToSH.f95',
+  'SphericalCapCoef.f95',
+  'Wigner3j.f95',
+  'YilmIndexVector.f95',
+]
+
+fftw3 = dependency('fftw3')
+
+shtools = library('SHTOOLS',
+  SOURCES,
+  dependencies: [fftw3, lapack],
+  install: true)
diff --git a/versioneer.py b/versioneer.py
deleted file mode 100644
index 971300705..000000000
--- a/versioneer.py
+++ /dev/null
@@ -1,2064 +0,0 @@
-
-# Version: 0.20
-
-"""The Versioneer - like a rocketeer, but for versions.
-
-The Versioneer
-==============
-
-* like a rocketeer, but for versions!
-* https://github.com/python-versioneer/python-versioneer
-* Brian Warner
-* License: Public Domain
-* Compatible with: Python 3.6, 3.7, 3.8, 3.9 and pypy3
-* [![Latest Version][pypi-image]][pypi-url]
-* [![Build Status][travis-image]][travis-url]
-
-This is a tool for managing a recorded version number in distutils-based
-python projects. The goal is to remove the tedious and error-prone "update
-the embedded version string" step from your release process. Making a new
-release should be as easy as recording a new tag in your version-control
-system, and maybe making new tarballs.
-
-
-## Quick Install
-
-* `pip install versioneer` to somewhere in your $PATH
-* add a `[versioneer]` section to your setup.cfg (see [Install](INSTALL.md))
-* run `versioneer install` in your source tree, commit the results
-* Verify version information with `python setup.py version`
-
-## Version Identifiers
-
-Source trees come from a variety of places:
-
-* a version-control system checkout (mostly used by developers)
-* a nightly tarball, produced by build automation
-* a snapshot tarball, produced by a web-based VCS browser, like github's
-  "tarball from tag" feature
-* a release tarball, produced by "setup.py sdist", distributed through PyPI
-
-Within each source tree, the version identifier (either a string or a number,
-this tool is format-agnostic) can come from a variety of places:
-
-* ask the VCS tool itself, e.g. "git describe" (for checkouts), which knows
-  about recent "tags" and an absolute revision-id
-* the name of the directory into which the tarball was unpacked
-* an expanded VCS keyword ($Id$, etc)
-* a `_version.py` created by some earlier build step
-
-For released software, the version identifier is closely related to a VCS
-tag. Some projects use tag names that include more than just the version
-string (e.g. "myproject-1.2" instead of just "1.2"), in which case the tool
-needs to strip the tag prefix to extract the version identifier. For
-unreleased software (between tags), the version identifier should provide
-enough information to help developers recreate the same tree, while also
-giving them an idea of roughly how old the tree is (after version 1.2, before
-version 1.3). Many VCS systems can report a description that captures this,
-for example `git describe --tags --dirty --always` reports things like
-"0.7-1-g574ab98-dirty" to indicate that the checkout is one revision past the
-0.7 tag, has a unique revision id of "574ab98", and is "dirty" (it has
-uncommitted changes).
-
-The version identifier is used for multiple purposes:
-
-* to allow the module to self-identify its version: `myproject.__version__`
-* to choose a name and prefix for a 'setup.py sdist' tarball
-
-## Theory of Operation
-
-Versioneer works by adding a special `_version.py` file into your source
-tree, where your `__init__.py` can import it. This `_version.py` knows how to
-dynamically ask the VCS tool for version information at import time.
-
-`_version.py` also contains `$Revision$` markers, and the installation
-process marks `_version.py` to have this marker rewritten with a tag name
-during the `git archive` command. As a result, generated tarballs will
-contain enough information to get the proper version.
-
-To allow `setup.py` to compute a version too, a `versioneer.py` is added to
-the top level of your source tree, next to `setup.py` and the `setup.cfg`
-that configures it. This overrides several distutils/setuptools commands to
-compute the version when invoked, and changes `setup.py build` and `setup.py
-sdist` to replace `_version.py` with a small static file that contains just
-the generated version data.
-
-## Installation
-
-See [INSTALL.md](./INSTALL.md) for detailed installation instructions.
-
-## Version-String Flavors
-
-Code which uses Versioneer can learn about its version string at runtime by
-importing `_version` from your main `__init__.py` file and running the
-`get_versions()` function. From the "outside" (e.g. in `setup.py`), you can
-import the top-level `versioneer.py` and run `get_versions()`.
-
-Both functions return a dictionary with different flavors of version
-information:
-
-* `['version']`: A condensed version string, rendered using the selected
-  style. This is the most commonly used value for the project's version
-  string. The default "pep440" style yields strings like `0.11`,
-  `0.11+2.g1076c97`, or `0.11+2.g1076c97.dirty`. See the "Styles" section
-  below for alternative styles.
-
-* `['full-revisionid']`: detailed revision identifier. For Git, this is the
-  full SHA1 commit id, e.g. "1076c978a8d3cfc70f408fe5974aa6c092c949ac".
-
-* `['date']`: Date and time of the latest `HEAD` commit. For Git, it is the
-  commit date in ISO 8601 format. This will be None if the date is not
-  available.
-
-* `['dirty']`: a boolean, True if the tree has uncommitted changes. Note that
-  this is only accurate if run in a VCS checkout, otherwise it is likely to
-  be False or None
-
-* `['error']`: if the version string could not be computed, this will be set
-  to a string describing the problem, otherwise it will be None. It may be
-  useful to throw an exception in setup.py if this is set, to avoid e.g.
-  creating tarballs with a version string of "unknown".
-
-Some variants are more useful than others. Including `full-revisionid` in a
-bug report should allow developers to reconstruct the exact code being tested
-(or indicate the presence of local changes that should be shared with the
-developers). `version` is suitable for display in an "about" box or a CLI
-`--version` output: it can be easily compared against release notes and lists
-of bugs fixed in various releases.
-
-The installer adds the following text to your `__init__.py` to place a basic
-version in `YOURPROJECT.__version__`:
-
-    from ._version import get_versions
-    __version__ = get_versions()['version']
-    del get_versions
-
-## Styles
-
-The setup.cfg `style=` configuration controls how the VCS information is
-rendered into a version string.
-
-The default style, "pep440", produces a PEP440-compliant string, equal to the
-un-prefixed tag name for actual releases, and containing an additional "local
-version" section with more detail for in-between builds. For Git, this is
-TAG[+DISTANCE.gHEX[.dirty]] , using information from `git describe --tags
---dirty --always`. For example "0.11+2.g1076c97.dirty" indicates that the
-tree is like the "1076c97" commit but has uncommitted changes (".dirty"), and
-that this commit is two revisions ("+2") beyond the "0.11" tag. For released
-software (exactly equal to a known tag), the identifier will only contain the
-stripped tag, e.g. "0.11".
-
-Other styles are available. See [details.md](details.md) in the Versioneer
-source tree for descriptions.
-
-## Debugging
-
-Versioneer tries to avoid fatal errors: if something goes wrong, it will tend
-to return a version of "0+unknown". To investigate the problem, run `setup.py
-version`, which will run the version-lookup code in a verbose mode, and will
-display the full contents of `get_versions()` (including the `error` string,
-which may help identify what went wrong).
-
-## Known Limitations
-
-Some situations are known to cause problems for Versioneer. This details the
-most significant ones. More can be found on Github
-[issues page](https://github.com/python-versioneer/python-versioneer/issues).
-
-### Subprojects
-
-Versioneer has limited support for source trees in which `setup.py` is not in
-the root directory (e.g. `setup.py` and `.git/` are *not* siblings). The are
-two common reasons why `setup.py` might not be in the root:
-
-* Source trees which contain multiple subprojects, such as
-  [Buildbot](https://github.com/buildbot/buildbot), which contains both
-  "master" and "slave" subprojects, each with their own `setup.py`,
-  `setup.cfg`, and `tox.ini`. Projects like these produce multiple PyPI
-  distributions (and upload multiple independently-installable tarballs).
-* Source trees whose main purpose is to contain a C library, but which also
-  provide bindings to Python (and perhaps other languages) in subdirectories.
-
-Versioneer will look for `.git` in parent directories, and most operations
-should get the right version string. However `pip` and `setuptools` have bugs
-and implementation details which frequently cause `pip install .` from a
-subproject directory to fail to find a correct version string (so it usually
-defaults to `0+unknown`).
-
-`pip install --editable .` should work correctly. `setup.py install` might
-work too.
-
-Pip-8.1.1 is known to have this problem, but hopefully it will get fixed in
-some later version.
-
-[Bug #38](https://github.com/python-versioneer/python-versioneer/issues/38) is tracking
-this issue. The discussion in
-[PR #61](https://github.com/python-versioneer/python-versioneer/pull/61) describes the
-issue from the Versioneer side in more detail.
-[pip PR#3176](https://github.com/pypa/pip/pull/3176) and
-[pip PR#3615](https://github.com/pypa/pip/pull/3615) contain work to improve
-pip to let Versioneer work correctly.
-
-Versioneer-0.16 and earlier only looked for a `.git` directory next to the
-`setup.cfg`, so subprojects were completely unsupported with those releases.
-
-### Editable installs with setuptools <= 18.5
-
-`setup.py develop` and `pip install --editable .` allow you to install a
-project into a virtualenv once, then continue editing the source code (and
-test) without re-installing after every change.
-
-"Entry-point scripts" (`setup(entry_points={"console_scripts": ..})`) are a
-convenient way to specify executable scripts that should be installed along
-with the python package.
-
-These both work as expected when using modern setuptools. When using
-setuptools-18.5 or earlier, however, certain operations will cause
-`pkg_resources.DistributionNotFound` errors when running the entrypoint
-script, which must be resolved by re-installing the package. This happens
-when the install happens with one version, then the egg_info data is
-regenerated while a different version is checked out. Many setup.py commands
-cause egg_info to be rebuilt (including `sdist`, `wheel`, and installing into
-a different virtualenv), so this can be surprising.
-
-[Bug #83](https://github.com/python-versioneer/python-versioneer/issues/83) describes
-this one, but upgrading to a newer version of setuptools should probably
-resolve it.
-
-
-## Updating Versioneer
-
-To upgrade your project to a new release of Versioneer, do the following:
-
-* install the new Versioneer (`pip install -U versioneer` or equivalent)
-* edit `setup.cfg`, if necessary, to include any new configuration settings
-  indicated by the release notes. See [UPGRADING](./UPGRADING.md) for details.
-* re-run `versioneer install` in your source tree, to replace
-  `SRC/_version.py`
-* commit any changed files
-
-## Future Directions
-
-This tool is designed to make it easily extended to other version-control
-systems: all VCS-specific components are in separate directories like
-src/git/ . The top-level `versioneer.py` script is assembled from these
-components by running make-versioneer.py . In the future, make-versioneer.py
-will take a VCS name as an argument, and will construct a version of
-`versioneer.py` that is specific to the given VCS. It might also take the
-configuration arguments that are currently provided manually during
-installation by editing setup.py . Alternatively, it might go the other
-direction and include code from all supported VCS systems, reducing the
-number of intermediate scripts.
-
-## Similar projects
-
-* [setuptools_scm](https://github.com/pypa/setuptools_scm/) - a non-vendored build-time
-  dependency
-* [minver](https://github.com/jbweston/miniver) - a lightweight reimplementation of
-  versioneer
-* [versioningit](https://github.com/jwodder/versioningit) - a PEP 518-based setuptools
-  plugin
-
-## License
-
-To make Versioneer easier to embed, all its code is dedicated to the public
-domain. The `_version.py` that it creates is also in the public domain.
-Specifically, both are released under the Creative Commons "Public Domain
-Dedication" license (CC0-1.0), as described in
-https://creativecommons.org/publicdomain/zero/1.0/ .
-
-[pypi-image]: https://img.shields.io/pypi/v/versioneer.svg
-[pypi-url]: https://pypi.python.org/pypi/versioneer/
-[travis-image]:
-https://img.shields.io/travis/com/python-versioneer/python-versioneer.svg
-[travis-url]: https://travis-ci.com/github/python-versioneer/python-versioneer
-
-"""
-
-import configparser
-import errno
-import json
-import os
-import re
-import subprocess
-import sys
-
-
-class VersioneerConfig:  # pylint: disable=too-few-public-methods # noqa
-    """Container for Versioneer configuration parameters."""
-
-
-def get_root():
-    """Get the project root directory.
-
-    We require that all commands are run from the project root, i.e. the
-    directory that contains setup.py, setup.cfg, and versioneer.py .
-    """
-    root = os.path.realpath(os.path.abspath(os.getcwd()))
-    setup_py = os.path.join(root, "setup.py")
-    versioneer_py = os.path.join(root, "versioneer.py")
-    if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)):
-        # allow 'python path/to/setup.py COMMAND'
-        root = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0])))
-        setup_py = os.path.join(root, "setup.py")
-        versioneer_py = os.path.join(root, "versioneer.py")
-    if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)):
-        err = ("Versioneer was unable to run the project root directory. "
-               "Versioneer requires setup.py to be executed from "
-               "its immediate directory (like 'python setup.py COMMAND'), "
-               "or in a way that lets it use sys.argv[0] to find the root "
-               "(like 'python path/to/setup.py COMMAND').")
-        raise VersioneerBadRootError(err)
-    try:
-        # Certain runtime workflows (setup.py install/develop in a setuptools
-        # tree) execute all dependencies in a single python process, so
-        # "versioneer" may be imported multiple times, and python's shared
-        # module-import table will cache the first one. So we can't use
-        # os.path.dirname(__file__), as that will find whichever
-        # versioneer.py was first imported, even in later projects.
-        my_path = os.path.realpath(os.path.abspath(__file__))
-        me_dir = os.path.normcase(os.path.splitext(my_path)[0])
-        vsr_dir = os.path.normcase(os.path.splitext(versioneer_py)[0])
-        if me_dir != vsr_dir:
-            print("Warning: build in %s is using versioneer.py from %s"
-                  % (os.path.dirname(my_path), versioneer_py))
-    except NameError:
-        pass
-    return root
-
-
-def get_config_from_root(root):
-    """Read the project setup.cfg file to determine Versioneer config."""
-    # This might raise EnvironmentError (if setup.cfg is missing), or
-    # configparser.NoSectionError (if it lacks a [versioneer] section), or
-    # configparser.NoOptionError (if it lacks "VCS="). See the docstring at
-    # the top of versioneer.py for instructions on writing your setup.cfg .
-    setup_cfg = os.path.join(root, "setup.cfg")
-    parser = configparser.ConfigParser()
-    with open(setup_cfg, "r") as cfg_file:
-        parser.read_file(cfg_file)
-    VCS = parser.get("versioneer", "VCS")  # mandatory
-
-    # Dict-like interface for non-mandatory entries
-    section = parser["versioneer"]
-
-    # pylint:disable=attribute-defined-outside-init # noqa
-    cfg = VersioneerConfig()
-    cfg.VCS = VCS
-    cfg.style = section.get("style", "")
-    cfg.versionfile_source = section.get("versionfile_source")
-    cfg.versionfile_build = section.get("versionfile_build")
-    cfg.tag_prefix = section.get("tag_prefix")
-    if cfg.tag_prefix in ("''", '""'):
-        cfg.tag_prefix = ""
-    cfg.parentdir_prefix = section.get("parentdir_prefix")
-    cfg.verbose = section.get("verbose")
-    return cfg
-
-
-class NotThisMethod(Exception):
-    """Exception raised if a method is not valid for the current scenario."""
-
-
-# these dictionaries contain VCS-specific tools
-LONG_VERSION_PY = {}
-HANDLERS = {}
-
-
-def register_vcs_handler(vcs, method):  # decorator
-    """Create decorator to mark a method as the handler of a VCS."""
-    def decorate(f):
-        """Store f in HANDLERS[vcs][method]."""
-        HANDLERS.setdefault(vcs, {})[method] = f
-        return f
-    return decorate
-
-
-# pylint:disable=too-many-arguments,consider-using-with # noqa
-def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False,
-                env=None):
-    """Call the given command(s)."""
-    assert isinstance(commands, list)
-    process = None
-    for command in commands:
-        try:
-            dispcmd = str([command] + args)
-            # remember shell=False, so use git.cmd on windows, not just git
-            process = subprocess.Popen([command] + args, cwd=cwd, env=env,
-                                       stdout=subprocess.PIPE,
-                                       stderr=(subprocess.PIPE if hide_stderr
-                                               else None))
-            break
-        except EnvironmentError:
-            e = sys.exc_info()[1]
-            if e.errno == errno.ENOENT:
-                continue
-            if verbose:
-                print("unable to run %s" % dispcmd)
-                print(e)
-            return None, None
-    else:
-        if verbose:
-            print("unable to find command, tried %s" % (commands,))
-        return None, None
-    stdout = process.communicate()[0].strip().decode()
-    if process.returncode != 0:
-        if verbose:
-            print("unable to run %s (error)" % dispcmd)
-            print("stdout was %s" % stdout)
-        return None, process.returncode
-    return stdout, process.returncode
-
-
-LONG_VERSION_PY['git'] = r'''
-# This file helps to compute a version number in source trees obtained from
-# git-archive tarball (such as those provided by githubs download-from-tag
-# feature). Distribution tarballs (built by setup.py sdist) and build
-# directories (produced by setup.py build) will contain a much shorter file
-# that just contains the computed version number.
-
-# This file is released into the public domain. Generated by
-# versioneer-0.20 (https://github.com/python-versioneer/python-versioneer)
-
-"""Git implementation of _version.py."""
-
-import errno
-import os
-import re
-import subprocess
-import sys
-
-
-def get_keywords():
-    """Get the keywords needed to look up the version information."""
-    # these strings will be replaced by git during git-archive.
-    # setup.py/versioneer.py will grep for the variable names, so they must
-    # each be defined on a line of their own. _version.py will just call
-    # get_keywords().
-    git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s"
-    git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s"
-    git_date = "%(DOLLAR)sFormat:%%ci%(DOLLAR)s"
-    keywords = {"refnames": git_refnames, "full": git_full, "date": git_date}
-    return keywords
-
-
-class VersioneerConfig:  # pylint: disable=too-few-public-methods
-    """Container for Versioneer configuration parameters."""
-
-
-def get_config():
-    """Create, populate and return the VersioneerConfig() object."""
-    # these strings are filled in when 'setup.py versioneer' creates
-    # _version.py
-    cfg = VersioneerConfig()
-    cfg.VCS = "git"
-    cfg.style = "%(STYLE)s"
-    cfg.tag_prefix = "%(TAG_PREFIX)s"
-    cfg.parentdir_prefix = "%(PARENTDIR_PREFIX)s"
-    cfg.versionfile_source = "%(VERSIONFILE_SOURCE)s"
-    cfg.verbose = False
-    return cfg
-
-
-class NotThisMethod(Exception):
-    """Exception raised if a method is not valid for the current scenario."""
-
-
-LONG_VERSION_PY = {}
-HANDLERS = {}
-
-
-def register_vcs_handler(vcs, method):  # decorator
-    """Create decorator to mark a method as the handler of a VCS."""
-    def decorate(f):
-        """Store f in HANDLERS[vcs][method]."""
-        if vcs not in HANDLERS:
-            HANDLERS[vcs] = {}
-        HANDLERS[vcs][method] = f
-        return f
-    return decorate
-
-
-# pylint:disable=too-many-arguments,consider-using-with # noqa
-def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False,
-                env=None):
-    """Call the given command(s)."""
-    assert isinstance(commands, list)
-    process = None
-    for command in commands:
-        try:
-            dispcmd = str([command] + args)
-            # remember shell=False, so use git.cmd on windows, not just git
-            process = subprocess.Popen([command] + args, cwd=cwd, env=env,
-                                       stdout=subprocess.PIPE,
-                                       stderr=(subprocess.PIPE if hide_stderr
-                                               else None))
-            break
-        except EnvironmentError:
-            e = sys.exc_info()[1]
-            if e.errno == errno.ENOENT:
-                continue
-            if verbose:
-                print("unable to run %%s" %% dispcmd)
-                print(e)
-            return None, None
-    else:
-        if verbose:
-            print("unable to find command, tried %%s" %% (commands,))
-        return None, None
-    stdout = process.communicate()[0].strip().decode()
-    if process.returncode != 0:
-        if verbose:
-            print("unable to run %%s (error)" %% dispcmd)
-            print("stdout was %%s" %% stdout)
-        return None, process.returncode
-    return stdout, process.returncode
-
-
-def versions_from_parentdir(parentdir_prefix, root, verbose):
-    """Try to determine the version from the parent directory name.
-
-    Source tarballs conventionally unpack into a directory that includes both
-    the project name and a version string. We will also support searching up
-    two directory levels for an appropriately named parent directory
-    """
-    rootdirs = []
-
-    for _ in range(3):
-        dirname = os.path.basename(root)
-        if dirname.startswith(parentdir_prefix):
-            return {"version": dirname[len(parentdir_prefix):],
-                    "full-revisionid": None,
-                    "dirty": False, "error": None, "date": None}
-        rootdirs.append(root)
-        root = os.path.dirname(root)  # up a level
-
-    if verbose:
-        print("Tried directories %%s but none started with prefix %%s" %%
-              (str(rootdirs), parentdir_prefix))
-    raise NotThisMethod("rootdir doesn't start with parentdir_prefix")
-
-
-@register_vcs_handler("git", "get_keywords")
-def git_get_keywords(versionfile_abs):
-    """Extract version information from the given file."""
-    # the code embedded in _version.py can just fetch the value of these
-    # keywords. When used from setup.py, we don't want to import _version.py,
-    # so we do it with a regexp instead. This function is not used from
-    # _version.py.
-    keywords = {}
-    try:
-        with open(versionfile_abs, "r") as fobj:
-            for line in fobj:
-                if line.strip().startswith("git_refnames ="):
-                    mo = re.search(r'=\s*"(.*)"', line)
-                    if mo:
-                        keywords["refnames"] = mo.group(1)
-                if line.strip().startswith("git_full ="):
-                    mo = re.search(r'=\s*"(.*)"', line)
-                    if mo:
-                        keywords["full"] = mo.group(1)
-                if line.strip().startswith("git_date ="):
-                    mo = re.search(r'=\s*"(.*)"', line)
-                    if mo:
-                        keywords["date"] = mo.group(1)
-    except EnvironmentError:
-        pass
-    return keywords
-
-
-@register_vcs_handler("git", "keywords")
-def git_versions_from_keywords(keywords, tag_prefix, verbose):
-    """Get version information from git keywords."""
-    if "refnames" not in keywords:
-        raise NotThisMethod("Short version file found")
-    date = keywords.get("date")
-    if date is not None:
-        # Use only the last line.  Previous lines may contain GPG signature
-        # information.
-        date = date.splitlines()[-1]
-
-        # git-2.2.0 added "%%cI", which expands to an ISO-8601 -compliant
-        # datestamp. However we prefer "%%ci" (which expands to an "ISO-8601
-        # -like" string, which we must then edit to make compliant), because
-        # it's been around since git-1.5.3, and it's too difficult to
-        # discover which version we're using, or to work around using an
-        # older one.
-        date = date.strip().replace(" ", "T", 1).replace(" ", "", 1)
-    refnames = keywords["refnames"].strip()
-    if refnames.startswith("$Format"):
-        if verbose:
-            print("keywords are unexpanded, not using")
-        raise NotThisMethod("unexpanded keywords, not a git-archive tarball")
-    refs = {r.strip() for r in refnames.strip("()").split(",")}
-    # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
-    # just "foo-1.0". If we see a "tag: " prefix, prefer those.
-    TAG = "tag: "
-    tags = {r[len(TAG):] for r in refs if r.startswith(TAG)}
-    if not tags:
-        # Either we're using git < 1.8.3, or there really are no tags. We use
-        # a heuristic: assume all version tags have a digit. The old git %%d
-        # expansion behaves like git log --decorate=short and strips out the
-        # refs/heads/ and refs/tags/ prefixes that would let us distinguish
-        # between branches and tags. By ignoring refnames without digits, we
-        # filter out many common branch names like "release" and
-        # "stabilization", as well as "HEAD" and "master".
-        tags = {r for r in refs if re.search(r'\d', r)}
-        if verbose:
-            print("discarding '%%s', no digits" %% ",".join(refs - tags))
-    if verbose:
-        print("likely tags: %%s" %% ",".join(sorted(tags)))
-    for ref in sorted(tags):
-        # sorting will prefer e.g. "2.0" over "2.0rc1"
-        if ref.startswith(tag_prefix):
-            r = ref[len(tag_prefix):]
-            # Filter out refs that exactly match prefix or that don't start
-            # with a number once the prefix is stripped (mostly a concern
-            # when prefix is '')
-            if not re.match(r'\d', r):
-                continue
-            if verbose:
-                print("picking %%s" %% r)
-            return {"version": r,
-                    "full-revisionid": keywords["full"].strip(),
-                    "dirty": False, "error": None,
-                    "date": date}
-    # no suitable tags, so version is "0+unknown", but full hex is still there
-    if verbose:
-        print("no suitable tags, using unknown + full revision id")
-    return {"version": "0+unknown",
-            "full-revisionid": keywords["full"].strip(),
-            "dirty": False, "error": "no suitable tags", "date": None}
-
-
-@register_vcs_handler("git", "pieces_from_vcs")
-def git_pieces_from_vcs(tag_prefix, root, verbose, runner=run_command):
-    """Get version from 'git describe' in the root of the source tree.
-
-    This only gets called if the git-archive 'subst' keywords were *not*
-    expanded, and _version.py hasn't already been rewritten with a short
-    version string, meaning we're inside a checked out source tree.
-    """
-    GITS = ["git"]
-    if sys.platform == "win32":
-        GITS = ["git.cmd", "git.exe"]
-
-    _, rc = runner(GITS, ["rev-parse", "--git-dir"], cwd=root,
-                   hide_stderr=True)
-    if rc != 0:
-        if verbose:
-            print("Directory %%s not under git control" %% root)
-        raise NotThisMethod("'git rev-parse --git-dir' returned error")
-
-    # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty]
-    # if there isn't one, this yields HEX[-dirty] (no NUM)
-    describe_out, rc = runner(GITS, ["describe", "--tags", "--dirty",
-                                     "--always", "--long",
-                                     "--match", "%%s*" %% tag_prefix],
-                              cwd=root)
-    # --long was added in git-1.5.5
-    if describe_out is None:
-        raise NotThisMethod("'git describe' failed")
-    describe_out = describe_out.strip()
-    full_out, rc = runner(GITS, ["rev-parse", "HEAD"], cwd=root)
-    if full_out is None:
-        raise NotThisMethod("'git rev-parse' failed")
-    full_out = full_out.strip()
-
-    pieces = {}
-    pieces["long"] = full_out
-    pieces["short"] = full_out[:7]  # maybe improved later
-    pieces["error"] = None
-
-    branch_name, rc = runner(GITS, ["rev-parse", "--abbrev-ref", "HEAD"],
-                             cwd=root)
-    # --abbrev-ref was added in git-1.6.3
-    if rc != 0 or branch_name is None:
-        raise NotThisMethod("'git rev-parse --abbrev-ref' returned error")
-    branch_name = branch_name.strip()
-
-    if branch_name == "HEAD":
-        # If we aren't exactly on a branch, pick a branch which represents
-        # the current commit. If all else fails, we are on a branchless
-        # commit.
-        branches, rc = runner(GITS, ["branch", "--contains"], cwd=root)
-        # --contains was added in git-1.5.4
-        if rc != 0 or branches is None:
-            raise NotThisMethod("'git branch --contains' returned error")
-        branches = branches.split("\n")
-
-        # Remove the first line if we're running detached
-        if "(" in branches[0]:
-            branches.pop(0)
-
-        # Strip off the leading "* " from the list of branches.
-        branches = [branch[2:] for branch in branches]
-        if "master" in branches:
-            branch_name = "master"
-        elif not branches:
-            branch_name = None
-        else:
-            # Pick the first branch that is returned. Good or bad.
-            branch_name = branches[0]
-
-    pieces["branch"] = branch_name
-
-    # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty]
-    # TAG might have hyphens.
-    git_describe = describe_out
-
-    # look for -dirty suffix
-    dirty = git_describe.endswith("-dirty")
-    pieces["dirty"] = dirty
-    if dirty:
-        git_describe = git_describe[:git_describe.rindex("-dirty")]
-
-    # now we have TAG-NUM-gHEX or HEX
-
-    if "-" in git_describe:
-        # TAG-NUM-gHEX
-        mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe)
-        if not mo:
-            # unparseable. Maybe git-describe is misbehaving?
-            pieces["error"] = ("unable to parse git-describe output: '%%s'"
-                               %% describe_out)
-            return pieces
-
-        # tag
-        full_tag = mo.group(1)
-        if not full_tag.startswith(tag_prefix):
-            if verbose:
-                fmt = "tag '%%s' doesn't start with prefix '%%s'"
-                print(fmt %% (full_tag, tag_prefix))
-            pieces["error"] = ("tag '%%s' doesn't start with prefix '%%s'"
-                               %% (full_tag, tag_prefix))
-            return pieces
-        pieces["closest-tag"] = full_tag[len(tag_prefix):]
-
-        # distance: number of commits since tag
-        pieces["distance"] = int(mo.group(2))
-
-        # commit: short hex revision ID
-        pieces["short"] = mo.group(3)
-
-    else:
-        # HEX: no tags
-        pieces["closest-tag"] = None
-        count_out, rc = runner(GITS, ["rev-list", "HEAD", "--count"], cwd=root)
-        pieces["distance"] = int(count_out)  # total number of commits
-
-    # commit date: see ISO-8601 comment in git_versions_from_keywords()
-    date = runner(GITS, ["show", "-s", "--format=%%ci", "HEAD"], cwd=root)[0].strip()
-    # Use only the last line.  Previous lines may contain GPG signature
-    # information.
-    date = date.splitlines()[-1]
-    pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1)
-
-    return pieces
-
-
-def plus_or_dot(pieces):
-    """Return a + if we don't already have one, else return a ."""
-    if "+" in pieces.get("closest-tag", ""):
-        return "."
-    return "+"
-
-
-def render_pep440(pieces):
-    """Build up version string, with post-release "local version identifier".
-
-    Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
-    get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
-
-    Exceptions:
-    1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"] or pieces["dirty"]:
-            rendered += plus_or_dot(pieces)
-            rendered += "%%d.g%%s" %% (pieces["distance"], pieces["short"])
-            if pieces["dirty"]:
-                rendered += ".dirty"
-    else:
-        # exception #1
-        rendered = "0+untagged.%%d.g%%s" %% (pieces["distance"],
-                                          pieces["short"])
-        if pieces["dirty"]:
-            rendered += ".dirty"
-    return rendered
-
-
-def render_pep440_branch(pieces):
-    """TAG[[.dev0]+DISTANCE.gHEX[.dirty]] .
-
-    The ".dev0" means not master branch. Note that .dev0 sorts backwards
-    (a feature branch will appear "older" than the master branch).
-
-    Exceptions:
-    1: no tags. 0[.dev0]+untagged.DISTANCE.gHEX[.dirty]
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"] or pieces["dirty"]:
-            if pieces["branch"] != "master":
-                rendered += ".dev0"
-            rendered += plus_or_dot(pieces)
-            rendered += "%%d.g%%s" %% (pieces["distance"], pieces["short"])
-            if pieces["dirty"]:
-                rendered += ".dirty"
-    else:
-        # exception #1
-        rendered = "0"
-        if pieces["branch"] != "master":
-            rendered += ".dev0"
-        rendered += "+untagged.%%d.g%%s" %% (pieces["distance"],
-                                          pieces["short"])
-        if pieces["dirty"]:
-            rendered += ".dirty"
-    return rendered
-
-
-def render_pep440_pre(pieces):
-    """TAG[.post0.devDISTANCE] -- No -dirty.
-
-    Exceptions:
-    1: no tags. 0.post0.devDISTANCE
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"]:
-            rendered += ".post0.dev%%d" %% pieces["distance"]
-    else:
-        # exception #1
-        rendered = "0.post0.dev%%d" %% pieces["distance"]
-    return rendered
-
-
-def render_pep440_post(pieces):
-    """TAG[.postDISTANCE[.dev0]+gHEX] .
-
-    The ".dev0" means dirty. Note that .dev0 sorts backwards
-    (a dirty tree will appear "older" than the corresponding clean one),
-    but you shouldn't be releasing software with -dirty anyways.
-
-    Exceptions:
-    1: no tags. 0.postDISTANCE[.dev0]
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"] or pieces["dirty"]:
-            rendered += ".post%%d" %% pieces["distance"]
-            if pieces["dirty"]:
-                rendered += ".dev0"
-            rendered += plus_or_dot(pieces)
-            rendered += "g%%s" %% pieces["short"]
-    else:
-        # exception #1
-        rendered = "0.post%%d" %% pieces["distance"]
-        if pieces["dirty"]:
-            rendered += ".dev0"
-        rendered += "+g%%s" %% pieces["short"]
-    return rendered
-
-
-def render_pep440_post_branch(pieces):
-    """TAG[.postDISTANCE[.dev0]+gHEX[.dirty]] .
-
-    The ".dev0" means not master branch.
-
-    Exceptions:
-    1: no tags. 0.postDISTANCE[.dev0]+gHEX[.dirty]
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"] or pieces["dirty"]:
-            rendered += ".post%%d" %% pieces["distance"]
-            if pieces["branch"] != "master":
-                rendered += ".dev0"
-            rendered += plus_or_dot(pieces)
-            rendered += "g%%s" %% pieces["short"]
-            if pieces["dirty"]:
-                rendered += ".dirty"
-    else:
-        # exception #1
-        rendered = "0.post%%d" %% pieces["distance"]
-        if pieces["branch"] != "master":
-            rendered += ".dev0"
-        rendered += "+g%%s" %% pieces["short"]
-        if pieces["dirty"]:
-            rendered += ".dirty"
-    return rendered
-
-
-def render_pep440_old(pieces):
-    """TAG[.postDISTANCE[.dev0]] .
-
-    The ".dev0" means dirty.
-
-    Exceptions:
-    1: no tags. 0.postDISTANCE[.dev0]
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"] or pieces["dirty"]:
-            rendered += ".post%%d" %% pieces["distance"]
-            if pieces["dirty"]:
-                rendered += ".dev0"
-    else:
-        # exception #1
-        rendered = "0.post%%d" %% pieces["distance"]
-        if pieces["dirty"]:
-            rendered += ".dev0"
-    return rendered
-
-
-def render_git_describe(pieces):
-    """TAG[-DISTANCE-gHEX][-dirty].
-
-    Like 'git describe --tags --dirty --always'.
-
-    Exceptions:
-    1: no tags. HEX[-dirty]  (note: no 'g' prefix)
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"]:
-            rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"])
-    else:
-        # exception #1
-        rendered = pieces["short"]
-    if pieces["dirty"]:
-        rendered += "-dirty"
-    return rendered
-
-
-def render_git_describe_long(pieces):
-    """TAG-DISTANCE-gHEX[-dirty].
-
-    Like 'git describe --tags --dirty --always -long'.
-    The distance/hash is unconditional.
-
-    Exceptions:
-    1: no tags. HEX[-dirty]  (note: no 'g' prefix)
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"])
-    else:
-        # exception #1
-        rendered = pieces["short"]
-    if pieces["dirty"]:
-        rendered += "-dirty"
-    return rendered
-
-
-def render(pieces, style):
-    """Render the given version pieces into the requested style."""
-    if pieces["error"]:
-        return {"version": "unknown",
-                "full-revisionid": pieces.get("long"),
-                "dirty": None,
-                "error": pieces["error"],
-                "date": None}
-
-    if not style or style == "default":
-        style = "pep440"  # the default
-
-    if style == "pep440":
-        rendered = render_pep440(pieces)
-    elif style == "pep440-branch":
-        rendered = render_pep440_branch(pieces)
-    elif style == "pep440-pre":
-        rendered = render_pep440_pre(pieces)
-    elif style == "pep440-post":
-        rendered = render_pep440_post(pieces)
-    elif style == "pep440-post-branch":
-        rendered = render_pep440_post_branch(pieces)
-    elif style == "pep440-old":
-        rendered = render_pep440_old(pieces)
-    elif style == "git-describe":
-        rendered = render_git_describe(pieces)
-    elif style == "git-describe-long":
-        rendered = render_git_describe_long(pieces)
-    else:
-        raise ValueError("unknown style '%%s'" %% style)
-
-    return {"version": rendered, "full-revisionid": pieces["long"],
-            "dirty": pieces["dirty"], "error": None,
-            "date": pieces.get("date")}
-
-
-def get_versions():
-    """Get version information or return default if unable to do so."""
-    # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
-    # __file__, we can work backwards from there to the root. Some
-    # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
-    # case we can only use expanded keywords.
-
-    cfg = get_config()
-    verbose = cfg.verbose
-
-    try:
-        return git_versions_from_keywords(get_keywords(), cfg.tag_prefix,
-                                          verbose)
-    except NotThisMethod:
-        pass
-
-    try:
-        root = os.path.realpath(__file__)
-        # versionfile_source is the relative path from the top of the source
-        # tree (where the .git directory might live) to this file. Invert
-        # this to find the root from __file__.
-        for _ in cfg.versionfile_source.split('/'):
-            root = os.path.dirname(root)
-    except NameError:
-        return {"version": "0+unknown", "full-revisionid": None,
-                "dirty": None,
-                "error": "unable to find root of source tree",
-                "date": None}
-
-    try:
-        pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose)
-        return render(pieces, cfg.style)
-    except NotThisMethod:
-        pass
-
-    try:
-        if cfg.parentdir_prefix:
-            return versions_from_parentdir(cfg.parentdir_prefix, root, verbose)
-    except NotThisMethod:
-        pass
-
-    return {"version": "0+unknown", "full-revisionid": None,
-            "dirty": None,
-            "error": "unable to compute version", "date": None}
-'''
-
-
-@register_vcs_handler("git", "get_keywords")
-def git_get_keywords(versionfile_abs):
-    """Extract version information from the given file."""
-    # the code embedded in _version.py can just fetch the value of these
-    # keywords. When used from setup.py, we don't want to import _version.py,
-    # so we do it with a regexp instead. This function is not used from
-    # _version.py.
-    keywords = {}
-    try:
-        with open(versionfile_abs, "r") as fobj:
-            for line in fobj:
-                if line.strip().startswith("git_refnames ="):
-                    mo = re.search(r'=\s*"(.*)"', line)
-                    if mo:
-                        keywords["refnames"] = mo.group(1)
-                if line.strip().startswith("git_full ="):
-                    mo = re.search(r'=\s*"(.*)"', line)
-                    if mo:
-                        keywords["full"] = mo.group(1)
-                if line.strip().startswith("git_date ="):
-                    mo = re.search(r'=\s*"(.*)"', line)
-                    if mo:
-                        keywords["date"] = mo.group(1)
-    except EnvironmentError:
-        pass
-    return keywords
-
-
-@register_vcs_handler("git", "keywords")
-def git_versions_from_keywords(keywords, tag_prefix, verbose):
-    """Get version information from git keywords."""
-    if "refnames" not in keywords:
-        raise NotThisMethod("Short version file found")
-    date = keywords.get("date")
-    if date is not None:
-        # Use only the last line.  Previous lines may contain GPG signature
-        # information.
-        date = date.splitlines()[-1]
-
-        # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant
-        # datestamp. However we prefer "%ci" (which expands to an "ISO-8601
-        # -like" string, which we must then edit to make compliant), because
-        # it's been around since git-1.5.3, and it's too difficult to
-        # discover which version we're using, or to work around using an
-        # older one.
-        date = date.strip().replace(" ", "T", 1).replace(" ", "", 1)
-    refnames = keywords["refnames"].strip()
-    if refnames.startswith("$Format"):
-        if verbose:
-            print("keywords are unexpanded, not using")
-        raise NotThisMethod("unexpanded keywords, not a git-archive tarball")
-    refs = {r.strip() for r in refnames.strip("()").split(",")}
-    # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
-    # just "foo-1.0". If we see a "tag: " prefix, prefer those.
-    TAG = "tag: "
-    tags = {r[len(TAG):] for r in refs if r.startswith(TAG)}
-    if not tags:
-        # Either we're using git < 1.8.3, or there really are no tags. We use
-        # a heuristic: assume all version tags have a digit. The old git %d
-        # expansion behaves like git log --decorate=short and strips out the
-        # refs/heads/ and refs/tags/ prefixes that would let us distinguish
-        # between branches and tags. By ignoring refnames without digits, we
-        # filter out many common branch names like "release" and
-        # "stabilization", as well as "HEAD" and "master".
-        tags = {r for r in refs if re.search(r'\d', r)}
-        if verbose:
-            print("discarding '%s', no digits" % ",".join(refs - tags))
-    if verbose:
-        print("likely tags: %s" % ",".join(sorted(tags)))
-    for ref in sorted(tags):
-        # sorting will prefer e.g. "2.0" over "2.0rc1"
-        if ref.startswith(tag_prefix):
-            r = ref[len(tag_prefix):]
-            # Filter out refs that exactly match prefix or that don't start
-            # with a number once the prefix is stripped (mostly a concern
-            # when prefix is '')
-            if not re.match(r'\d', r):
-                continue
-            if verbose:
-                print("picking %s" % r)
-            return {"version": r,
-                    "full-revisionid": keywords["full"].strip(),
-                    "dirty": False, "error": None,
-                    "date": date}
-    # no suitable tags, so version is "0+unknown", but full hex is still there
-    if verbose:
-        print("no suitable tags, using unknown + full revision id")
-    return {"version": "0+unknown",
-            "full-revisionid": keywords["full"].strip(),
-            "dirty": False, "error": "no suitable tags", "date": None}
-
-
-@register_vcs_handler("git", "pieces_from_vcs")
-def git_pieces_from_vcs(tag_prefix, root, verbose, runner=run_command):
-    """Get version from 'git describe' in the root of the source tree.
-
-    This only gets called if the git-archive 'subst' keywords were *not*
-    expanded, and _version.py hasn't already been rewritten with a short
-    version string, meaning we're inside a checked out source tree.
-    """
-    GITS = ["git"]
-    if sys.platform == "win32":
-        GITS = ["git.cmd", "git.exe"]
-
-    _, rc = runner(GITS, ["rev-parse", "--git-dir"], cwd=root,
-                   hide_stderr=True)
-    if rc != 0:
-        if verbose:
-            print("Directory %s not under git control" % root)
-        raise NotThisMethod("'git rev-parse --git-dir' returned error")
-
-    # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty]
-    # if there isn't one, this yields HEX[-dirty] (no NUM)
-    describe_out, rc = runner(GITS, ["describe", "--tags", "--dirty",
-                                     "--always", "--long",
-                                     "--match", "%s*" % tag_prefix],
-                              cwd=root)
-    # --long was added in git-1.5.5
-    if describe_out is None:
-        raise NotThisMethod("'git describe' failed")
-    describe_out = describe_out.strip()
-    full_out, rc = runner(GITS, ["rev-parse", "HEAD"], cwd=root)
-    if full_out is None:
-        raise NotThisMethod("'git rev-parse' failed")
-    full_out = full_out.strip()
-
-    pieces = {}
-    pieces["long"] = full_out
-    pieces["short"] = full_out[:7]  # maybe improved later
-    pieces["error"] = None
-
-    branch_name, rc = runner(GITS, ["rev-parse", "--abbrev-ref", "HEAD"],
-                             cwd=root)
-    # --abbrev-ref was added in git-1.6.3
-    if rc != 0 or branch_name is None:
-        raise NotThisMethod("'git rev-parse --abbrev-ref' returned error")
-    branch_name = branch_name.strip()
-
-    if branch_name == "HEAD":
-        # If we aren't exactly on a branch, pick a branch which represents
-        # the current commit. If all else fails, we are on a branchless
-        # commit.
-        branches, rc = runner(GITS, ["branch", "--contains"], cwd=root)
-        # --contains was added in git-1.5.4
-        if rc != 0 or branches is None:
-            raise NotThisMethod("'git branch --contains' returned error")
-        branches = branches.split("\n")
-
-        # Remove the first line if we're running detached
-        if "(" in branches[0]:
-            branches.pop(0)
-
-        # Strip off the leading "* " from the list of branches.
-        branches = [branch[2:] for branch in branches]
-        if "master" in branches:
-            branch_name = "master"
-        elif not branches:
-            branch_name = None
-        else:
-            # Pick the first branch that is returned. Good or bad.
-            branch_name = branches[0]
-
-    pieces["branch"] = branch_name
-
-    # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty]
-    # TAG might have hyphens.
-    git_describe = describe_out
-
-    # look for -dirty suffix
-    dirty = git_describe.endswith("-dirty")
-    pieces["dirty"] = dirty
-    if dirty:
-        git_describe = git_describe[:git_describe.rindex("-dirty")]
-
-    # now we have TAG-NUM-gHEX or HEX
-
-    if "-" in git_describe:
-        # TAG-NUM-gHEX
-        mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe)
-        if not mo:
-            # unparseable. Maybe git-describe is misbehaving?
-            pieces["error"] = ("unable to parse git-describe output: '%s'"
-                               % describe_out)
-            return pieces
-
-        # tag
-        full_tag = mo.group(1)
-        if not full_tag.startswith(tag_prefix):
-            if verbose:
-                fmt = "tag '%s' doesn't start with prefix '%s'"
-                print(fmt % (full_tag, tag_prefix))
-            pieces["error"] = ("tag '%s' doesn't start with prefix '%s'"
-                               % (full_tag, tag_prefix))
-            return pieces
-        pieces["closest-tag"] = full_tag[len(tag_prefix):]
-
-        # distance: number of commits since tag
-        pieces["distance"] = int(mo.group(2))
-
-        # commit: short hex revision ID
-        pieces["short"] = mo.group(3)
-
-    else:
-        # HEX: no tags
-        pieces["closest-tag"] = None
-        count_out, rc = runner(GITS, ["rev-list", "HEAD", "--count"], cwd=root)
-        pieces["distance"] = int(count_out)  # total number of commits
-
-    # commit date: see ISO-8601 comment in git_versions_from_keywords()
-    date = runner(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[0].strip()
-    # Use only the last line.  Previous lines may contain GPG signature
-    # information.
-    date = date.splitlines()[-1]
-    pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1)
-
-    return pieces
-
-
-def do_vcs_install(manifest_in, versionfile_source, ipy):
-    """Git-specific installation logic for Versioneer.
-
-    For Git, this means creating/changing .gitattributes to mark _version.py
-    for export-subst keyword substitution.
-    """
-    GITS = ["git"]
-    if sys.platform == "win32":
-        GITS = ["git.cmd", "git.exe"]
-    files = [manifest_in, versionfile_source]
-    if ipy:
-        files.append(ipy)
-    try:
-        my_path = __file__
-        if my_path.endswith(".pyc") or my_path.endswith(".pyo"):
-            my_path = os.path.splitext(my_path)[0] + ".py"
-        versioneer_file = os.path.relpath(my_path)
-    except NameError:
-        versioneer_file = "versioneer.py"
-    files.append(versioneer_file)
-    present = False
-    try:
-        with open(".gitattributes", "r") as fobj:
-            for line in fobj:
-                if line.strip().startswith(versionfile_source):
-                    if "export-subst" in line.strip().split()[1:]:
-                        present = True
-                        break
-    except EnvironmentError:
-        pass
-    if not present:
-        with open(".gitattributes", "a+") as fobj:
-            fobj.write(f"{versionfile_source} export-subst\n")
-        files.append(".gitattributes")
-    run_command(GITS, ["add", "--"] + files)
-
-
-def versions_from_parentdir(parentdir_prefix, root, verbose):
-    """Try to determine the version from the parent directory name.
-
-    Source tarballs conventionally unpack into a directory that includes both
-    the project name and a version string. We will also support searching up
-    two directory levels for an appropriately named parent directory
-    """
-    rootdirs = []
-
-    for _ in range(3):
-        dirname = os.path.basename(root)
-        if dirname.startswith(parentdir_prefix):
-            return {"version": dirname[len(parentdir_prefix):],
-                    "full-revisionid": None,
-                    "dirty": False, "error": None, "date": None}
-        rootdirs.append(root)
-        root = os.path.dirname(root)  # up a level
-
-    if verbose:
-        print("Tried directories %s but none started with prefix %s" %
-              (str(rootdirs), parentdir_prefix))
-    raise NotThisMethod("rootdir doesn't start with parentdir_prefix")
-
-
-SHORT_VERSION_PY = """
-# This file was generated by 'versioneer.py' (0.20) from
-# revision-control system data, or from the parent directory name of an
-# unpacked source archive. Distribution tarballs contain a pre-generated copy
-# of this file.
-
-import json
-
-version_json = '''
-%s
-'''  # END VERSION_JSON
-
-
-def get_versions():
-    return json.loads(version_json)
-"""
-
-
-def versions_from_file(filename):
-    """Try to determine the version from _version.py if present."""
-    try:
-        with open(filename) as f:
-            contents = f.read()
-    except EnvironmentError:
-        raise NotThisMethod("unable to read _version.py")
-    mo = re.search(r"version_json = '''\n(.*)'''  # END VERSION_JSON",
-                   contents, re.M | re.S)
-    if not mo:
-        mo = re.search(r"version_json = '''\r\n(.*)'''  # END VERSION_JSON",
-                       contents, re.M | re.S)
-    if not mo:
-        raise NotThisMethod("no version_json in _version.py")
-    return json.loads(mo.group(1))
-
-
-def write_to_version_file(filename, versions):
-    """Write the given version number to the given _version.py file."""
-    os.unlink(filename)
-    contents = json.dumps(versions, sort_keys=True,
-                          indent=1, separators=(",", ": "))
-    with open(filename, "w") as f:
-        f.write(SHORT_VERSION_PY % contents)
-
-    print("set %s to '%s'" % (filename, versions["version"]))
-
-
-def plus_or_dot(pieces):
-    """Return a + if we don't already have one, else return a ."""
-    if "+" in pieces.get("closest-tag", ""):
-        return "."
-    return "+"
-
-
-def render_pep440(pieces):
-    """Build up version string, with post-release "local version identifier".
-
-    Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you
-    get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty
-
-    Exceptions:
-    1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty]
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"] or pieces["dirty"]:
-            rendered += plus_or_dot(pieces)
-            rendered += "%d.g%s" % (pieces["distance"], pieces["short"])
-            if pieces["dirty"]:
-                rendered += ".dirty"
-    else:
-        # exception #1
-        rendered = "0+untagged.%d.g%s" % (pieces["distance"],
-                                          pieces["short"])
-        if pieces["dirty"]:
-            rendered += ".dirty"
-    return rendered
-
-
-def render_pep440_branch(pieces):
-    """TAG[[.dev0]+DISTANCE.gHEX[.dirty]] .
-
-    The ".dev0" means not master branch. Note that .dev0 sorts backwards
-    (a feature branch will appear "older" than the master branch).
-
-    Exceptions:
-    1: no tags. 0[.dev0]+untagged.DISTANCE.gHEX[.dirty]
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"] or pieces["dirty"]:
-            if pieces["branch"] != "master":
-                rendered += ".dev0"
-            rendered += plus_or_dot(pieces)
-            rendered += "%d.g%s" % (pieces["distance"], pieces["short"])
-            if pieces["dirty"]:
-                rendered += ".dirty"
-    else:
-        # exception #1
-        rendered = "0"
-        if pieces["branch"] != "master":
-            rendered += ".dev0"
-        rendered += "+untagged.%d.g%s" % (pieces["distance"],
-                                          pieces["short"])
-        if pieces["dirty"]:
-            rendered += ".dirty"
-    return rendered
-
-
-def render_pep440_pre(pieces):
-    """TAG[.post0.devDISTANCE] -- No -dirty.
-
-    Exceptions:
-    1: no tags. 0.post0.devDISTANCE
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"]:
-            rendered += ".post0.dev%d" % pieces["distance"]
-    else:
-        # exception #1
-        rendered = "0.post0.dev%d" % pieces["distance"]
-    return rendered
-
-
-def render_pep440_post(pieces):
-    """TAG[.postDISTANCE[.dev0]+gHEX] .
-
-    The ".dev0" means dirty. Note that .dev0 sorts backwards
-    (a dirty tree will appear "older" than the corresponding clean one),
-    but you shouldn't be releasing software with -dirty anyways.
-
-    Exceptions:
-    1: no tags. 0.postDISTANCE[.dev0]
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"] or pieces["dirty"]:
-            rendered += ".post%d" % pieces["distance"]
-            if pieces["dirty"]:
-                rendered += ".dev0"
-            rendered += plus_or_dot(pieces)
-            rendered += "g%s" % pieces["short"]
-    else:
-        # exception #1
-        rendered = "0.post%d" % pieces["distance"]
-        if pieces["dirty"]:
-            rendered += ".dev0"
-        rendered += "+g%s" % pieces["short"]
-    return rendered
-
-
-def render_pep440_post_branch(pieces):
-    """TAG[.postDISTANCE[.dev0]+gHEX[.dirty]] .
-
-    The ".dev0" means not master branch.
-
-    Exceptions:
-    1: no tags. 0.postDISTANCE[.dev0]+gHEX[.dirty]
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"] or pieces["dirty"]:
-            rendered += ".post%d" % pieces["distance"]
-            if pieces["branch"] != "master":
-                rendered += ".dev0"
-            rendered += plus_or_dot(pieces)
-            rendered += "g%s" % pieces["short"]
-            if pieces["dirty"]:
-                rendered += ".dirty"
-    else:
-        # exception #1
-        rendered = "0.post%d" % pieces["distance"]
-        if pieces["branch"] != "master":
-            rendered += ".dev0"
-        rendered += "+g%s" % pieces["short"]
-        if pieces["dirty"]:
-            rendered += ".dirty"
-    return rendered
-
-
-def render_pep440_old(pieces):
-    """TAG[.postDISTANCE[.dev0]] .
-
-    The ".dev0" means dirty.
-
-    Exceptions:
-    1: no tags. 0.postDISTANCE[.dev0]
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"] or pieces["dirty"]:
-            rendered += ".post%d" % pieces["distance"]
-            if pieces["dirty"]:
-                rendered += ".dev0"
-    else:
-        # exception #1
-        rendered = "0.post%d" % pieces["distance"]
-        if pieces["dirty"]:
-            rendered += ".dev0"
-    return rendered
-
-
-def render_git_describe(pieces):
-    """TAG[-DISTANCE-gHEX][-dirty].
-
-    Like 'git describe --tags --dirty --always'.
-
-    Exceptions:
-    1: no tags. HEX[-dirty]  (note: no 'g' prefix)
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        if pieces["distance"]:
-            rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
-    else:
-        # exception #1
-        rendered = pieces["short"]
-    if pieces["dirty"]:
-        rendered += "-dirty"
-    return rendered
-
-
-def render_git_describe_long(pieces):
-    """TAG-DISTANCE-gHEX[-dirty].
-
-    Like 'git describe --tags --dirty --always -long'.
-    The distance/hash is unconditional.
-
-    Exceptions:
-    1: no tags. HEX[-dirty]  (note: no 'g' prefix)
-    """
-    if pieces["closest-tag"]:
-        rendered = pieces["closest-tag"]
-        rendered += "-%d-g%s" % (pieces["distance"], pieces["short"])
-    else:
-        # exception #1
-        rendered = pieces["short"]
-    if pieces["dirty"]:
-        rendered += "-dirty"
-    return rendered
-
-
-def render(pieces, style):
-    """Render the given version pieces into the requested style."""
-    if pieces["error"]:
-        return {"version": "unknown",
-                "full-revisionid": pieces.get("long"),
-                "dirty": None,
-                "error": pieces["error"],
-                "date": None}
-
-    if not style or style == "default":
-        style = "pep440"  # the default
-
-    if style == "pep440":
-        rendered = render_pep440(pieces)
-    elif style == "pep440-branch":
-        rendered = render_pep440_branch(pieces)
-    elif style == "pep440-pre":
-        rendered = render_pep440_pre(pieces)
-    elif style == "pep440-post":
-        rendered = render_pep440_post(pieces)
-    elif style == "pep440-post-branch":
-        rendered = render_pep440_post_branch(pieces)
-    elif style == "pep440-old":
-        rendered = render_pep440_old(pieces)
-    elif style == "git-describe":
-        rendered = render_git_describe(pieces)
-    elif style == "git-describe-long":
-        rendered = render_git_describe_long(pieces)
-    else:
-        raise ValueError("unknown style '%s'" % style)
-
-    return {"version": rendered, "full-revisionid": pieces["long"],
-            "dirty": pieces["dirty"], "error": None,
-            "date": pieces.get("date")}
-
-
-class VersioneerBadRootError(Exception):
-    """The project root directory is unknown or missing key files."""
-
-
-def get_versions(verbose=False):
-    """Get the project version from whatever source is available.
-
-    Returns dict with two keys: 'version' and 'full'.
-    """
-    if "versioneer" in sys.modules:
-        # see the discussion in cmdclass.py:get_cmdclass()
-        del sys.modules["versioneer"]
-
-    root = get_root()
-    cfg = get_config_from_root(root)
-
-    assert cfg.VCS is not None, "please set [versioneer]VCS= in setup.cfg"
-    handlers = HANDLERS.get(cfg.VCS)
-    assert handlers, "unrecognized VCS '%s'" % cfg.VCS
-    verbose = verbose or cfg.verbose
-    assert cfg.versionfile_source is not None, \
-        "please set versioneer.versionfile_source"
-    assert cfg.tag_prefix is not None, "please set versioneer.tag_prefix"
-
-    versionfile_abs = os.path.join(root, cfg.versionfile_source)
-
-    # extract version from first of: _version.py, VCS command (e.g. 'git
-    # describe'), parentdir. This is meant to work for developers using a
-    # source checkout, for users of a tarball created by 'setup.py sdist',
-    # and for users of a tarball/zipball created by 'git archive' or github's
-    # download-from-tag feature or the equivalent in other VCSes.
-
-    get_keywords_f = handlers.get("get_keywords")
-    from_keywords_f = handlers.get("keywords")
-    if get_keywords_f and from_keywords_f:
-        try:
-            keywords = get_keywords_f(versionfile_abs)
-            ver = from_keywords_f(keywords, cfg.tag_prefix, verbose)
-            if verbose:
-                print("got version from expanded keyword %s" % ver)
-            return ver
-        except NotThisMethod:
-            pass
-
-    try:
-        ver = versions_from_file(versionfile_abs)
-        if verbose:
-            print("got version from file %s %s" % (versionfile_abs, ver))
-        return ver
-    except NotThisMethod:
-        pass
-
-    from_vcs_f = handlers.get("pieces_from_vcs")
-    if from_vcs_f:
-        try:
-            pieces = from_vcs_f(cfg.tag_prefix, root, verbose)
-            ver = render(pieces, cfg.style)
-            if verbose:
-                print("got version from VCS %s" % ver)
-            return ver
-        except NotThisMethod:
-            pass
-
-    try:
-        if cfg.parentdir_prefix:
-            ver = versions_from_parentdir(cfg.parentdir_prefix, root, verbose)
-            if verbose:
-                print("got version from parentdir %s" % ver)
-            return ver
-    except NotThisMethod:
-        pass
-
-    if verbose:
-        print("unable to compute version")
-
-    return {"version": "0+unknown", "full-revisionid": None,
-            "dirty": None, "error": "unable to compute version",
-            "date": None}
-
-
-def get_version():
-    """Get the short version string for this project."""
-    return get_versions()["version"]
-
-
-def get_cmdclass(cmdclass=None):
-    """Get the custom setuptools/distutils subclasses used by Versioneer.
-
-    If the package uses a different cmdclass (e.g. one from numpy), it
-    should be provide as an argument.
-    """
-    if "versioneer" in sys.modules:
-        del sys.modules["versioneer"]
-        # this fixes the "python setup.py develop" case (also 'install' and
-        # 'easy_install .'), in which subdependencies of the main project are
-        # built (using setup.py bdist_egg) in the same python process. Assume
-        # a main project A and a dependency B, which use different versions
-        # of Versioneer. A's setup.py imports A's Versioneer, leaving it in
-        # sys.modules by the time B's setup.py is executed, causing B to run
-        # with the wrong versioneer. Setuptools wraps the sub-dep builds in a
-        # sandbox that restores sys.modules to it's pre-build state, so the
-        # parent is protected against the child's "import versioneer". By
-        # removing ourselves from sys.modules here, before the child build
-        # happens, we protect the child from the parent's versioneer too.
-        # Also see https://github.com/python-versioneer/python-versioneer/issues/52
-
-    cmds = {} if cmdclass is None else cmdclass.copy()
-
-    # we add "version" to both distutils and setuptools
-    from distutils.core import Command
-
-    class cmd_version(Command):
-        description = "report generated version string"
-        user_options = []
-        boolean_options = []
-
-        def initialize_options(self):
-            pass
-
-        def finalize_options(self):
-            pass
-
-        def run(self):
-            vers = get_versions(verbose=True)
-            print("Version: %s" % vers["version"])
-            print(" full-revisionid: %s" % vers.get("full-revisionid"))
-            print(" dirty: %s" % vers.get("dirty"))
-            print(" date: %s" % vers.get("date"))
-            if vers["error"]:
-                print(" error: %s" % vers["error"])
-    cmds["version"] = cmd_version
-
-    # we override "build_py" in both distutils and setuptools
-    #
-    # most invocation pathways end up running build_py:
-    #  distutils/build -> build_py
-    #  distutils/install -> distutils/build ->..
-    #  setuptools/bdist_wheel -> distutils/install ->..
-    #  setuptools/bdist_egg -> distutils/install_lib -> build_py
-    #  setuptools/install -> bdist_egg ->..
-    #  setuptools/develop -> ?
-    #  pip install:
-    #   copies source tree to a tempdir before running egg_info/etc
-    #   if .git isn't copied too, 'git describe' will fail
-    #   then does setup.py bdist_wheel, or sometimes setup.py install
-    #  setup.py egg_info -> ?
-
-    # we override different "build_py" commands for both environments
-    if 'build_py' in cmds:
-        _build_py = cmds['build_py']
-    elif "setuptools" in sys.modules:
-        from setuptools.command.build_py import build_py as _build_py
-    else:
-        from distutils.command.build_py import build_py as _build_py
-
-    class cmd_build_py(_build_py):
-        def run(self):
-            root = get_root()
-            cfg = get_config_from_root(root)
-            versions = get_versions()
-            _build_py.run(self)
-            # now locate _version.py in the new build/ directory and replace
-            # it with an updated value
-            if cfg.versionfile_build:
-                target_versionfile = os.path.join(self.build_lib,
-                                                  cfg.versionfile_build)
-                print("UPDATING %s" % target_versionfile)
-                write_to_version_file(target_versionfile, versions)
-    cmds["build_py"] = cmd_build_py
-
-    if 'build_ext' in cmds:
-        _build_ext = cmds['build_ext']
-    elif "setuptools" in sys.modules:
-        from setuptools.command.build_ext import build_ext as _build_ext
-    else:
-        from distutils.command.build_ext import build_ext as _build_ext
-
-    class cmd_build_ext(_build_ext):
-        def run(self):
-            root = get_root()
-            cfg = get_config_from_root(root)
-            versions = get_versions()
-            _build_ext.run(self)
-            if self.inplace:
-                # build_ext --inplace will only build extensions in
-                # build/lib<..> dir with no _version.py to write to.
-                # As in place builds will already have a _version.py
-                # in the module dir, we do not need to write one.
-                return
-            # now locate _version.py in the new build/ directory and replace
-            # it with an updated value
-            target_versionfile = os.path.join(self.build_lib,
-                                              cfg.versionfile_build)
-            print("UPDATING %s" % target_versionfile)
-            write_to_version_file(target_versionfile, versions)
-    cmds["build_ext"] = cmd_build_ext
-
-    if "cx_Freeze" in sys.modules:  # cx_freeze enabled?
-        from cx_Freeze.dist import build_exe as _build_exe
-        # nczeczulin reports that py2exe won't like the pep440-style string
-        # as FILEVERSION, but it can be used for PRODUCTVERSION, e.g.
-        # setup(console=[{
-        #   "version": versioneer.get_version().split("+", 1)[0], # FILEVERSION
-        #   "product_version": versioneer.get_version(),
-        #   ...
-
-        class cmd_build_exe(_build_exe):
-            def run(self):
-                root = get_root()
-                cfg = get_config_from_root(root)
-                versions = get_versions()
-                target_versionfile = cfg.versionfile_source
-                print("UPDATING %s" % target_versionfile)
-                write_to_version_file(target_versionfile, versions)
-
-                _build_exe.run(self)
-                os.unlink(target_versionfile)
-                with open(cfg.versionfile_source, "w") as f:
-                    LONG = LONG_VERSION_PY[cfg.VCS]
-                    f.write(LONG %
-                            {"DOLLAR": "$",
-                             "STYLE": cfg.style,
-                             "TAG_PREFIX": cfg.tag_prefix,
-                             "PARENTDIR_PREFIX": cfg.parentdir_prefix,
-                             "VERSIONFILE_SOURCE": cfg.versionfile_source,
-                             })
-        cmds["build_exe"] = cmd_build_exe
-        del cmds["build_py"]
-
-    if 'py2exe' in sys.modules:  # py2exe enabled?
-        from py2exe.distutils_buildexe import py2exe as _py2exe
-
-        class cmd_py2exe(_py2exe):
-            def run(self):
-                root = get_root()
-                cfg = get_config_from_root(root)
-                versions = get_versions()
-                target_versionfile = cfg.versionfile_source
-                print("UPDATING %s" % target_versionfile)
-                write_to_version_file(target_versionfile, versions)
-
-                _py2exe.run(self)
-                os.unlink(target_versionfile)
-                with open(cfg.versionfile_source, "w") as f:
-                    LONG = LONG_VERSION_PY[cfg.VCS]
-                    f.write(LONG %
-                            {"DOLLAR": "$",
-                             "STYLE": cfg.style,
-                             "TAG_PREFIX": cfg.tag_prefix,
-                             "PARENTDIR_PREFIX": cfg.parentdir_prefix,
-                             "VERSIONFILE_SOURCE": cfg.versionfile_source,
-                             })
-        cmds["py2exe"] = cmd_py2exe
-
-    # we override different "sdist" commands for both environments
-    if 'sdist' in cmds:
-        _sdist = cmds['sdist']
-    elif "setuptools" in sys.modules:
-        from setuptools.command.sdist import sdist as _sdist
-    else:
-        from distutils.command.sdist import sdist as _sdist
-
-    class cmd_sdist(_sdist):
-        def run(self):
-            versions = get_versions()
-            # pylint:disable=attribute-defined-outside-init # noqa
-            self._versioneer_generated_versions = versions
-            # unless we update this, the command will keep using the old
-            # version
-            self.distribution.metadata.version = versions["version"]
-            return _sdist.run(self)
-
-        def make_release_tree(self, base_dir, files):
-            root = get_root()
-            cfg = get_config_from_root(root)
-            _sdist.make_release_tree(self, base_dir, files)
-            # now locate _version.py in the new base_dir directory
-            # (remembering that it may be a hardlink) and replace it with an
-            # updated value
-            target_versionfile = os.path.join(base_dir, cfg.versionfile_source)
-            print("UPDATING %s" % target_versionfile)
-            write_to_version_file(target_versionfile,
-                                  self._versioneer_generated_versions)
-    cmds["sdist"] = cmd_sdist
-
-    return cmds
-
-
-CONFIG_ERROR = """
-setup.cfg is missing the necessary Versioneer configuration. You need
-a section like:
-
- [versioneer]
- VCS = git
- style = pep440
- versionfile_source = src/myproject/_version.py
- versionfile_build = myproject/_version.py
- tag_prefix =
- parentdir_prefix = myproject-
-
-You will also need to edit your setup.py to use the results:
-
- import versioneer
- setup(version=versioneer.get_version(),
-       cmdclass=versioneer.get_cmdclass(), ...)
-
-Please read the docstring in ./versioneer.py for configuration instructions,
-edit setup.cfg, and re-run the installer or 'python versioneer.py setup'.
-"""
-
-SAMPLE_CONFIG = """
-# See the docstring in versioneer.py for instructions. Note that you must
-# re-run 'versioneer.py setup' after changing this section, and commit the
-# resulting files.
-
-[versioneer]
-#VCS = git
-#style = pep440
-#versionfile_source =
-#versionfile_build =
-#tag_prefix =
-#parentdir_prefix =
-
-"""
-
-OLD_SNIPPET = """
-from ._version import get_versions
-__version__ = get_versions()['version']
-del get_versions
-"""
-
-INIT_PY_SNIPPET = """
-from . import {0}
-__version__ = {0}.get_versions()['version']
-"""
-
-
-def do_setup():
-    """Do main VCS-independent setup function for installing Versioneer."""
-    root = get_root()
-    try:
-        cfg = get_config_from_root(root)
-    except (EnvironmentError, configparser.NoSectionError,
-            configparser.NoOptionError) as e:
-        if isinstance(e, (EnvironmentError, configparser.NoSectionError)):
-            print("Adding sample versioneer config to setup.cfg",
-                  file=sys.stderr)
-            with open(os.path.join(root, "setup.cfg"), "a") as f:
-                f.write(SAMPLE_CONFIG)
-        print(CONFIG_ERROR, file=sys.stderr)
-        return 1
-
-    print(" creating %s" % cfg.versionfile_source)
-    with open(cfg.versionfile_source, "w") as f:
-        LONG = LONG_VERSION_PY[cfg.VCS]
-        f.write(LONG % {"DOLLAR": "$",
-                        "STYLE": cfg.style,
-                        "TAG_PREFIX": cfg.tag_prefix,
-                        "PARENTDIR_PREFIX": cfg.parentdir_prefix,
-                        "VERSIONFILE_SOURCE": cfg.versionfile_source,
-                        })
-
-    ipy = os.path.join(os.path.dirname(cfg.versionfile_source),
-                       "__init__.py")
-    if os.path.exists(ipy):
-        try:
-            with open(ipy, "r") as f:
-                old = f.read()
-        except EnvironmentError:
-            old = ""
-        module = os.path.splitext(os.path.basename(cfg.versionfile_source))[0]
-        snippet = INIT_PY_SNIPPET.format(module)
-        if OLD_SNIPPET in old:
-            print(" replacing boilerplate in %s" % ipy)
-            with open(ipy, "w") as f:
-                f.write(old.replace(OLD_SNIPPET, snippet))
-        elif snippet not in old:
-            print(" appending to %s" % ipy)
-            with open(ipy, "a") as f:
-                f.write(snippet)
-        else:
-            print(" %s unmodified" % ipy)
-    else:
-        print(" %s doesn't exist, ok" % ipy)
-        ipy = None
-
-    # Make sure both the top-level "versioneer.py" and versionfile_source
-    # (PKG/_version.py, used by runtime code) are in MANIFEST.in, so
-    # they'll be copied into source distributions. Pip won't be able to
-    # install the package without this.
-    manifest_in = os.path.join(root, "MANIFEST.in")
-    simple_includes = set()
-    try:
-        with open(manifest_in, "r") as f:
-            for line in f:
-                if line.startswith("include "):
-                    for include in line.split()[1:]:
-                        simple_includes.add(include)
-    except EnvironmentError:
-        pass
-    # That doesn't cover everything MANIFEST.in can do
-    # (http://docs.python.org/2/distutils/sourcedist.html#commands), so
-    # it might give some false negatives. Appending redundant 'include'
-    # lines is safe, though.
-    if "versioneer.py" not in simple_includes:
-        print(" appending 'versioneer.py' to MANIFEST.in")
-        with open(manifest_in, "a") as f:
-            f.write("include versioneer.py\n")
-    else:
-        print(" 'versioneer.py' already in MANIFEST.in")
-    if cfg.versionfile_source not in simple_includes:
-        print(" appending versionfile_source ('%s') to MANIFEST.in" %
-              cfg.versionfile_source)
-        with open(manifest_in, "a") as f:
-            f.write("include %s\n" % cfg.versionfile_source)
-    else:
-        print(" versionfile_source already in MANIFEST.in")
-
-    # Make VCS-specific changes. For git, this means creating/changing
-    # .gitattributes to mark _version.py for export-subst keyword
-    # substitution.
-    do_vcs_install(manifest_in, cfg.versionfile_source, ipy)
-    return 0
-
-
-def scan_setup_py():
-    """Validate the contents of setup.py against Versioneer's expectations."""
-    found = set()
-    setters = False
-    errors = 0
-    with open("setup.py", "r") as f:
-        for line in f.readlines():
-            if "import versioneer" in line:
-                found.add("import")
-            if "versioneer.get_cmdclass()" in line:
-                found.add("cmdclass")
-            if "versioneer.get_version()" in line:
-                found.add("get_version")
-            if "versioneer.VCS" in line:
-                setters = True
-            if "versioneer.versionfile_source" in line:
-                setters = True
-    if len(found) != 3:
-        print("")
-        print("Your setup.py appears to be missing some important items")
-        print("(but I might be wrong). Please make sure it has something")
-        print("roughly like the following:")
-        print("")
-        print(" import versioneer")
-        print(" setup( version=versioneer.get_version(),")
-        print("        cmdclass=versioneer.get_cmdclass(),  ...)")
-        print("")
-        errors += 1
-    if setters:
-        print("You should remove lines like 'versioneer.VCS = ' and")
-        print("'versioneer.versionfile_source = ' . This configuration")
-        print("now lives in setup.cfg, and should be removed from setup.py")
-        print("")
-        errors += 1
-    return errors
-
-
-if __name__ == "__main__":
-    cmd = sys.argv[1]
-    if cmd == "setup":
-        errors = do_setup()
-        errors += scan_setup_py()
-        if errors:
-            sys.exit(1)


Test patch:
diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml
index 092e75f78..f0c3129f8 100644
--- a/.github/workflows/ci_test.yml
+++ b/.github/workflows/ci_test.yml
@@ -12,19 +12,22 @@ jobs:
       fail-fast: false
       matrix:
         os: [ubuntu-latest, macos-latest]
-        python-version: ['3.8', '3.11']
+        python-version: ['3.8', '3.12']
 
     steps:
     - name: Cancel Previous Runs
-      uses: styfle/cancel-workflow-action@0.11.0
+      uses: styfle/cancel-workflow-action@0.12.0
       with:
         access_token: ${{ github.token }}
 
     - name: Checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
+      with:
+        fetch-depth: 250
+        fetch-tags: true
 
     - name: Setup Miniconda
-      uses: conda-incubator/setup-miniconda@v2
+      uses: conda-incubator/setup-miniconda@v3
       with:
         python-version: ${{ matrix.python-version }}
         mamba-version: "*"