From 9030181592096421d65371ee696d3a89aea65356 Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Mon, 25 Nov 2024 15:25:25 -0500 Subject: [PATCH 01/14] MAINT: use SPEC0 --- .github/workflows/main.yml | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2c599693..f34464ac 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,14 +11,19 @@ jobs: fail-fast: false matrix: os: ["ubuntu-latest", "macos-latest", "windows-latest"] - python-version: ["3.11", "3.12"] + python-version: ["3.12", "3.13"] numpy_ver: ["latest"] test_config: ["latest"] include: - - python-version: "3.10" + - python-version: "3.11" numpy_ver: "1.24" + pandas_ver: "2.0" + scipy_ver: "1.4" + xarray_ver: "2020.12" + pysat_ver: "3.2" + cdflib_ver: "1.0" os: ubuntu-latest - test_config: "NEP29" + test_config: "SPEC0" - python-version: "3.9" numpy_ver: "1.23.5" os: "ubuntu-20.04" @@ -43,10 +48,15 @@ jobs: pip install --no-cache-dir numpy==${{ matrix.numpy_ver }} pip install --upgrade-strategy only-if-needed .[test] - - name: Install NEP29 dependencies - if: ${{ matrix.test_config == 'NEP29'}} + - name: Install SPEC0 dependencies + if: ${{ matrix.test_config == 'SPEC0'}} run: | pip install numpy==${{ matrix.numpy_ver }} + pip install pandas==${{ matrix.pandas_ver }} + pip install scipy==${{ matrix.scipy_ver }} + pip install xarray==${{ matrix.xarray_ver }} + pip install pysat==${{ matrix.pysat_ver }} + pip install cdflib==${{ matrix.cdflib_ver }} pip install --upgrade-strategy only-if-needed .[test] - name: Install standard dependencies From 63cd51b60e62f82d78b08cc8407164ab74160d2e Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Mon, 25 Nov 2024 15:25:34 -0500 Subject: [PATCH 02/14] DOC: update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90318c10..532c7e5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](https://semver.org/). ## [0.1.0] - 2025-XX-XX * New Instruments * Mars Global Surveyor Magnetometer (MGS Mag) +* Maintenance + * Implement SPEC0 tests in main workflow ## [0.0.6] - 2024-10-03 * New Instruments From 713cb8c01143044f1c60f04d8611452b9b5e3a3e Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Mon, 25 Nov 2024 15:33:11 -0500 Subject: [PATCH 03/14] MAINT: set scipy 1.10 as minimum for SPEC0 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f34464ac..b54f114a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,7 +18,7 @@ jobs: - python-version: "3.11" numpy_ver: "1.24" pandas_ver: "2.0" - scipy_ver: "1.4" + scipy_ver: "1.10" xarray_ver: "2020.12" pysat_ver: "3.2" cdflib_ver: "1.0" From b39597f1d73130039b7390e8e496d59dc99d3dd9 Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Mon, 25 Nov 2024 15:36:17 -0500 Subject: [PATCH 04/14] BUG: xarray version --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b54f114a..4244bea2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,7 +19,7 @@ jobs: numpy_ver: "1.24" pandas_ver: "2.0" scipy_ver: "1.10" - xarray_ver: "2020.12" + xarray_ver: "2020.12.0" pysat_ver: "3.2" cdflib_ver: "1.0" os: ubuntu-latest From a623cd45760825c9b84ea518be52e30666794685 Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Mon, 25 Nov 2024 15:40:31 -0500 Subject: [PATCH 05/14] BUG: xarray version --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4244bea2..29e1190d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,7 +19,7 @@ jobs: numpy_ver: "1.24" pandas_ver: "2.0" scipy_ver: "1.10" - xarray_ver: "2020.12.0" + xarray_ver: "2022.12.0" pysat_ver: "3.2" cdflib_ver: "1.0" os: ubuntu-latest From 34028bd6cb3899ddff0633c73916d1d820cd6dba Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Mon, 25 Nov 2024 15:41:26 -0500 Subject: [PATCH 06/14] MAINT: remove beta cdflib support --- pyproject.toml | 2 +- pysatNASA/instruments/methods/_cdf.py | 22 ++++------------------ pysatNASA/instruments/methods/cdaweb.py | 7 +------ 3 files changed, 6 insertions(+), 25 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 49306051..b5950de0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ keywords = [ dependencies = [ "beautifulsoup4", "cdasws", - "cdflib >= 0.4.4", + "cdflib >= 1.0", "lxml", "netCDF4", "numpy", diff --git a/pysatNASA/instruments/methods/_cdf.py b/pysatNASA/instruments/methods/_cdf.py index 34f6dd10..493f0813 100644 --- a/pysatNASA/instruments/methods/_cdf.py +++ b/pysatNASA/instruments/methods/_cdf.py @@ -104,7 +104,6 @@ def __init__(self, filename, self._variable_names = (self._cdf_info.rVariables + self._cdf_info.zVariables) else: - # cdflib < 1.0 stores info as a dict self._variable_names = (self._cdf_info['rVariables'] + self._cdf_info['zVariables']) @@ -170,13 +169,8 @@ def set_epoch(self, x_axis_var): """ - if hasattr(self._cdf_file.varinq(x_axis_var), 'Data_Type_Description'): - data_type_description = self._cdf_file.varinq( - x_axis_var).Data_Type_Description - else: - # cdflib < 1.0 stores this as a dict - data_type_description = self._cdf_file.varinq( - x_axis_var)['Data_Type_Description'] + data_type_description = self._cdf_file.varinq( + x_axis_var).Data_Type_Description center_measurement = self._center_measurement cdf_file = self._cdf_file @@ -317,11 +311,7 @@ def load_variables(self): if not re.match(var_regex, variable_name): # Skip this variable continue - try: - var_atts = self._cdf_file.varattsget(variable_name, to_np=True) - except TypeError: - # cdflib 1.0+ drops to_np kwarg, assumes True - var_atts = self._cdf_file.varattsget(variable_name) + var_atts = self._cdf_file.varattsget(variable_name, to_np=True) for k in var_atts: var_atts[k] = var_atts[k] # [0] @@ -343,11 +333,7 @@ def load_variables(self): continue if "FILLVAL" in var_atts: - if hasattr(var_properties, 'Data_Type_Description'): - data_type_desc = var_properties.Data_Type_Description - else: - # cdflib < 1.0 stores this as a dict - data_type_desc = var_properties['Data_Type_Description'] + data_type_desc = var_properties.Data_Type_Description if data_type_desc in ['CDF_FLOAT', 'CDF_REAL4', 'CDF_DOUBLE', 'CDF_REAL8']: diff --git a/pysatNASA/instruments/methods/cdaweb.py b/pysatNASA/instruments/methods/cdaweb.py index b0e71803..f3efea7d 100644 --- a/pysatNASA/instruments/methods/cdaweb.py +++ b/pysatNASA/instruments/methods/cdaweb.py @@ -36,12 +36,7 @@ from pysat.utils import io from pysatNASA.instruments.methods import CDF as libCDF -try: - # cdflib 1.0 syntax - from cdflib.xarray import cdf_to_xarray -except ModuleNotFoundError: - # cdflib 0.4 syntax required for backwards compatibility - from cdflib import cdf_to_xarray +from cdflib.xarray import cdf_to_xarray try: # Use pysatCDF as default for pandas data sets From 00bdb0d6a40e8a75260cdb7b0267bfbe855d8c12 Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Mon, 25 Nov 2024 15:46:03 -0500 Subject: [PATCH 07/14] BUG: cdflib version --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 29e1190d..42d3e9d7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,7 +21,7 @@ jobs: scipy_ver: "1.10" xarray_ver: "2022.12.0" pysat_ver: "3.2" - cdflib_ver: "1.0" + cdflib_ver: "1.0.2" os: ubuntu-latest test_config: "SPEC0" - python-version: "3.9" From 6ce617d6eb7cd5a333a568b4a51d7e39c7f5f1a2 Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Mon, 25 Nov 2024 16:23:46 -0500 Subject: [PATCH 08/14] BUG: cdflib syntax --- pysatNASA/instruments/methods/_cdf.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/pysatNASA/instruments/methods/_cdf.py b/pysatNASA/instruments/methods/_cdf.py index 493f0813..abac68cb 100644 --- a/pysatNASA/instruments/methods/_cdf.py +++ b/pysatNASA/instruments/methods/_cdf.py @@ -100,12 +100,8 @@ def __init__(self, filename, self.meta = {} self._dependencies = {} - if hasattr(self._cdf_info, 'rVariables'): - self._variable_names = (self._cdf_info.rVariables - + self._cdf_info.zVariables) - else: - self._variable_names = (self._cdf_info['rVariables'] - + self._cdf_info['zVariables']) + self._variable_names = (self._cdf_info.rVariables + + self._cdf_info.zVariables) self.load_variables() @@ -311,7 +307,7 @@ def load_variables(self): if not re.match(var_regex, variable_name): # Skip this variable continue - var_atts = self._cdf_file.varattsget(variable_name, to_np=True) + var_atts = self._cdf_file.varattsget(variable_name) for k in var_atts: var_atts[k] = var_atts[k] # [0] From 97cca384bd2e99aacb8f028e241d8e68224e59fe Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Mon, 25 Nov 2024 16:24:12 -0500 Subject: [PATCH 09/14] MAINT: remove python 3.6 syntax --- pysatNASA/__init__.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pysatNASA/__init__.py b/pysatNASA/__init__.py index 3fbbb608..e7b36328 100644 --- a/pysatNASA/__init__.py +++ b/pysatNASA/__init__.py @@ -15,10 +15,7 @@ """ -try: - from importlib import metadata -except ImportError: - import importlib_metadata as metadata +from importlib import metadata import os From 5dea25e169a58cbc5b6cbdcd14dc03414d8b0087 Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Mon, 25 Nov 2024 16:26:32 -0500 Subject: [PATCH 10/14] DOC: update reqs --- README.md | 16 ++++++++-------- docs/installation.rst | 8 ++++---- pyproject.toml | 10 +++++----- requirements.txt | 4 ++-- setup.cfg | 6 ------ 5 files changed, 19 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 86d45ad5..9357e9d4 100644 --- a/README.md +++ b/README.md @@ -20,12 +20,12 @@ some examples on how to use the routines pysatNASA uses common Python modules, as well as modules developed by and for the Space Physics community. This module officially supports -Python 3.6+. +Python 3.9+. | Common modules | Community modules | Optional Modules | | ---------------- | ----------------- |------------------| -| beautifulsoup4 | cdflib>=0.4.4 | pysatCDF | -| lxml | pysat>=3.1.0 | | +| beautifulsoup4 | cdflib>=1.0.2 | pysatCDF | +| lxml | pysat>=3.2.0 | | | netCDF4 | | | | numpy | | | | pandas | | | @@ -54,7 +54,7 @@ pip install . Note: pre-1.0.0 version ----------------------- -pysatNASA is currently in an initial development phase and requires pysat 3.1.0. +pysatNASA is currently in an initial development phase and requires pysat 3.2.0. Feedback and contributions are appreciated. # Using with pysat @@ -68,7 +68,7 @@ from pysatNASA.instruments import icon_ivm ivm = pysat.Instrument(inst_module=icon_ivm, inst_id='a') ``` Another way to use the instruments in an external repository is to register the -instruments. This only needs to be done the first time you load an instrument. +instruments. This only needs to be done the first time you load an instrument. Afterward, pysat will identify them using the `platform` and `name` keywords. ``` @@ -81,10 +81,10 @@ ivm = pysat.Instrument('icon', 'ivm', inst_id='a') # CDF Integration For data products stored as CDF files, this package can use either `cdflib` or `pysatCDF`. Note that `cdflib` is a pure python package and more readily -deployable across systems, whereas `pysatCDF` interfaces with the fortran. -This is a faster approach for loading data, but may not install on all systems. +deployable across systems, whereas `pysatCDF` interfaces with the fortran. +This is a faster approach for loading data, but may not install on all systems. There are known issues with `numpy`>=1.24. Therefore, `pysatCDF` is optional -rather than required. +rather than required. You can specify which load routine to use via the optional `use_cdflib` kwarg. If no kwarg is specified, `pysatNASA` will default to `pysatCDF` if it is diff --git a/docs/installation.rst b/docs/installation.rst index 2722700f..694ebf92 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -14,18 +14,18 @@ Prerequisites pysatNASA uses common Python modules, as well as modules developed by and for the Space Physics community. This module officially supports -Python 3.6+ and pysat 3.1.0+. +Python 3.9+ and pysat 3.2.0+. ================== ================= Common modules Community modules ================== ================= - beautifulsoup4 cdflib>=0.4.4 - lxml pysat>=3.1.0 + beautifulsoup4 cdflib>=1.0.2 + lxml pysat>=3.2.0 netCDF4 numpy pandas requests - scipy>=1.4.0 + scipy>=1.10.0 xarray ================== ================= diff --git a/pyproject.toml b/pyproject.toml index b5950de0..4ae71e1a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ name = "pysatNASA" version = "0.0.6" description = "pysat support for NASA Instruments" readme = "README.md" -requires-python = ">=3.6" +requires-python = ">=3.9" license = {file = "LICENSE"} authors = [ {name = "Jeff Klenzing, et al.", email = "pysat.developers@gmail.com"}, @@ -21,10 +21,10 @@ classifiers = [ "License :: OSI Approved :: BSD License", "Natural Language :: English", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Operating System :: POSIX :: Linux", "Operating System :: MacOS :: MacOS X", "Operating System :: Microsoft :: Windows" @@ -39,14 +39,14 @@ keywords = [ dependencies = [ "beautifulsoup4", "cdasws", - "cdflib >= 1.0", + "cdflib >= 1.0.2", "lxml", "netCDF4", "numpy", "pandas", "pysat >= 3.2", "requests", - "scipy >= 1.4", + "scipy >= 1.10", "xarray" ] diff --git a/requirements.txt b/requirements.txt index 3684998a..0ae6c10e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,10 +1,10 @@ beautifulsoup4 cdasws -cdflib>=0.4.4 +cdflib>=1.0.2 lxml netCDF4 numpy pandas -pysat>=3.1.0 +pysat>=3.2.0 requests xarray diff --git a/setup.cfg b/setup.cfg index 32dc6c9c..ccced987 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,9 +1,3 @@ -# name and version must be maintained here as well for python 3.6 compatibility - -[metadata] -name = pysatNASA -version = 0.0.6 - [flake8] max-line-length = 80 ignore = From 7c0bec55a16410320e6ecf0fe1a253be95387a09 Mon Sep 17 00:00:00 2001 From: Jeff Klenzing <19592220+jklenzing@users.noreply.github.com> Date: Tue, 26 Nov 2024 10:32:53 -0500 Subject: [PATCH 11/14] Update main.yml --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 42d3e9d7..0385977b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,7 +21,7 @@ jobs: scipy_ver: "1.10" xarray_ver: "2022.12.0" pysat_ver: "3.2" - cdflib_ver: "1.0.2" + cdflib_ver: "1.0.3" os: ubuntu-latest test_config: "SPEC0" - python-version: "3.9" From ec5043cd2aaec2cc0c6b8c1379a7ed574f093b8f Mon Sep 17 00:00:00 2001 From: Jeff Klenzing <19592220+jklenzing@users.noreply.github.com> Date: Tue, 26 Nov 2024 11:05:02 -0500 Subject: [PATCH 12/14] Update main.yml --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0385977b..afc91a3e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -21,7 +21,7 @@ jobs: scipy_ver: "1.10" xarray_ver: "2022.12.0" pysat_ver: "3.2" - cdflib_ver: "1.0.3" + cdflib_ver: "1.0.4" os: ubuntu-latest test_config: "SPEC0" - python-version: "3.9" From 2b67cd1ac00737df3ce30ff4188c51861da07dd7 Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Mon, 2 Dec 2024 10:02:57 -0500 Subject: [PATCH 13/14] MAINT: update minimum versions --- .github/workflows/main.yml | 16 ++++++++++------ README.md | 8 ++++---- docs/installation.rst | 6 +++--- pyproject.toml | 6 +++--- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index afc91a3e..8a4bb525 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,19 +15,21 @@ jobs: numpy_ver: ["latest"] test_config: ["latest"] include: - - python-version: "3.11" + - test_config: "SPEC0" + python-version: "3.11" numpy_ver: "1.24" pandas_ver: "2.0" scipy_ver: "1.10" xarray_ver: "2022.12.0" - pysat_ver: "3.2" + cdasws_ver: "1.7.42" cdflib_ver: "1.0.4" + netcdf_ver: "1.6" + pysat_ver: "3.2" os: ubuntu-latest - test_config: "SPEC0" - - python-version: "3.9" + - test_config: "Ops" + python-version: "3.9" numpy_ver: "1.23.5" os: "ubuntu-20.04" - test_config: "Ops" name: Python ${{ matrix.python-version }} on ${{ matrix.os }} with numpy ${{ matrix.numpy_ver }} runs-on: ${{ matrix.os }} @@ -55,8 +57,10 @@ jobs: pip install pandas==${{ matrix.pandas_ver }} pip install scipy==${{ matrix.scipy_ver }} pip install xarray==${{ matrix.xarray_ver }} - pip install pysat==${{ matrix.pysat_ver }} + pip install cdasws==${{ matrix.cdasws_ver }} pip install cdflib==${{ matrix.cdflib_ver }} + pip install netCDF4==${{ matrix.netcdf_ver }} + pip install pysat==${{ matrix.pysat_ver }} pip install --upgrade-strategy only-if-needed .[test] - name: Install standard dependencies diff --git a/README.md b/README.md index 9357e9d4..a8577eec 100644 --- a/README.md +++ b/README.md @@ -24,13 +24,13 @@ Python 3.9+. | Common modules | Community modules | Optional Modules | | ---------------- | ----------------- |------------------| -| beautifulsoup4 | cdflib>=1.0.2 | pysatCDF | -| lxml | pysat>=3.2.0 | | -| netCDF4 | | | +| beautifulsoup4 | cdasws>=1.7.42 | pysatCDF | +| lxml | cdflib>=1.0.4 | | +| netCDF4>=1.6 | pysat>=3.2.0 | | | numpy | | | | pandas | | | | requests | | | -| scipy>=1.4.0 | | | +| scipy>=1.10.0 | | | | xarray | | | ## PyPi Installation diff --git a/docs/installation.rst b/docs/installation.rst index 694ebf92..76f32074 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -19,9 +19,9 @@ Python 3.9+ and pysat 3.2.0+. ================== ================= Common modules Community modules ================== ================= - beautifulsoup4 cdflib>=1.0.2 - lxml pysat>=3.2.0 - netCDF4 + beautifulsoup4 cdasws>=1.7.42 + lxml cdflib>=1.0.4 + netCDF4>=1.6.0 pysat>=3.2.0 numpy pandas requests diff --git a/pyproject.toml b/pyproject.toml index 4ae71e1a..4a4a4aba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,10 +38,10 @@ keywords = [ ] dependencies = [ "beautifulsoup4", - "cdasws", - "cdflib >= 1.0.2", + "cdasws >= 1.7.42", + "cdflib >= 1.0.4", "lxml", - "netCDF4", + "netCDF4 >= 1.6", "numpy", "pandas", "pysat >= 3.2", From fcb7f75ccceeac39c6f49177b2964db5992f3dcd Mon Sep 17 00:00:00 2001 From: Jeff Klenzing Date: Mon, 2 Dec 2024 10:04:09 -0500 Subject: [PATCH 14/14] DOC: add SPEC0 badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a8577eec..4bc4bc60 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ [![PyPI Package latest release](https://img.shields.io/pypi/v/pysatNASA.svg)](https://pypi.python.org/pypi/pysatNASA) [![Build Status](https://github.com/github/docs/actions/workflows/main.yml/badge.svg)](https://github.com/github/docs/actions/workflows/main.yml/badge.svg) [![Coverage Status](https://coveralls.io/repos/github/pysat/pysatNASA/badge.svg?branch=main)](https://coveralls.io/github/pysat/pysatNASA?branch=main) +[![SPEC 0 — Minimum Supported Dependencies](https://img.shields.io/badge/SPEC-0-green?labelColor=%23004811&color=%235CA038)](https://scientific-python.org/specs/spec-0000/) + [![Documentation Status](https://readthedocs.org/projects/pysatnasa/badge/?version=latest)](https://pysatnasa.readthedocs.io/en/latest/?badge=latest) [![DOI](https://zenodo.org/badge/287387638.svg)](https://zenodo.org/badge/latestdoi/287387638)