From 7f2de23da3f84bce0f42f597874269c82624d74f Mon Sep 17 00:00:00 2001 From: Philipp Sommer Date: Fri, 8 Oct 2021 12:41:23 +0200 Subject: [PATCH 01/10] minor updates to the recipe --- ci/conda-recipe/meta.yaml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/ci/conda-recipe/meta.yaml b/ci/conda-recipe/meta.yaml index eedc73b..b6825cb 100644 --- a/ci/conda-recipe/meta.yaml +++ b/ci/conda-recipe/meta.yaml @@ -38,11 +38,6 @@ test: - netcdf4 - dask - scipy - # HACK: solve inconsistensies with libwebp - # this should be removed when - # https://github.com/conda-forge/libwebp-feedstock/issues/26 - # is solved - - libtiff <4.1.0 # [osx] source_files: - tests commands: @@ -71,5 +66,5 @@ about: combines the plotting utilities of matplotlib and the data management of the xarray package and integrates them into a software that can be used via command-line and via a GUI. - doc_url: http://psyplot.github.io + doc_url: https://psyplot.github.io dev_url: https://github.com/psyplot/psyplot From 25d83207a553a8decafdbceb7dff61263c9bbcc3 Mon Sep 17 00:00:00 2001 From: "Philipp S. Sommer" Date: Sun, 21 Nov 2021 23:22:14 +0100 Subject: [PATCH 02/10] Fix/38 (#39) * check dimensions prior to update * minor fix for ci * small fix for variable name * first select the data, then transform to dataset * always use isel for default_slice in from_dataset * add convert_coordinate method for Plotter and Formatoption * use psyplot-ci-orb@1.5.27 * [skip ci] Update Changelog --- .appveyor.yml | 4 +-- .circleci/config.yml | 2 +- CHANGELOG.rst | 25 +++++++++++++++++ psyplot/data.py | 64 ++++++++++++++++++++++++++++---------------- psyplot/plotter.py | 57 +++++++++++++++++++++++++++++++++++++++ tests/test_data.py | 12 +++++++++ 6 files changed, 138 insertions(+), 26 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 84b744b..13649da 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -24,7 +24,7 @@ install: - cmd: endlocal - cmd: 'SET PYTHONWARNINGS=ignore:mode:DeprecationWarning:docutils.io:245' - cmd: "IF NOT DEFINED APPVEYOR_REPO_TAG_NAME (SET GIT_BRANCH=%APPVEYOR_REPO_BRANCH%)" - - cmd: "IF NOT DEFINED APPVEYOR_REPO_TAG_NAME (conda config --add channels psyplot/label/%APPVEYOR_REPO_BRANCH%)" + - cmd: "IF NOT DEFINED APPVEYOR_REPO_TAG_NAME (conda config --add channels psyplot/label/%APPVEYOR_REPO_BRANCH:/=-%)" build: off @@ -37,7 +37,7 @@ test_script: deploy_script: - cmd: " IF NOT DEFINED APPVEYOR_REPO_TAG_NAME ( - deploy-conda-recipe -l %APPVEYOR_REPO_BRANCH% -py %PYTHON_VERSION% ci/conda-recipe + deploy-conda-recipe -l %APPVEYOR_REPO_BRANCH:/=-% -py %PYTHON_VERSION% ci/conda-recipe ) ELSE ( deploy-conda-recipe -py %PYTHON_VERSION% ci/conda-recipe )" diff --git a/.circleci/config.yml b/.circleci/config.yml index 60cbec7..7a6b8d4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,7 +1,7 @@ version: 2.1 orbs: - psyplot: psyplot/psyplot-ci-orb@1.5.24 + psyplot: psyplot/psyplot-ci-orb@1.5.27 mattermost-plugin-notify: nathanaelhoun/mattermost-plugin-notify@1.2.0 executors: diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a941efb..bc85dc8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,28 @@ +v1.4.1 +====== +Compatibility fixes and minor improvements + +Added +----- +- An abstract ``convert_coordinate`` method has been implemented for the + ``Plotter`` and ``Formatoption`` class that can be used in subclasses to + convert coordinates for the required visualization. The default + implementation does nothing (see + `#39 `__) + +Fixed +----- +- the update method now only takes the coordinates that are dimensions in the + dataset see `#39 `__ + +Changed +------- +- loading more than one variables into a ``DataArray`` now first selects the + corresponding dimensions, then puts it into a single ``DataArray``. This + avoids loading the entire data (see + `#39 `__) + + v1.4.0 ====== Compatibility fixes and LGPL license diff --git a/psyplot/data.py b/psyplot/data.py index ca41979..65d2478 100755 --- a/psyplot/data.py +++ b/psyplot/data.py @@ -145,7 +145,7 @@ def _fix_times(dims): # https://github.com/pydata/xarray/issues/4283 for key, val in dims.items(): if np.issubdtype(np.asarray(val).dtype, np.datetime64): - dims[key] = to_datetime(val) + dims[key] = to_datetime([val])[0] @docstrings.get_sections(base='setup_coords') @@ -2650,10 +2650,11 @@ def filter_attrs(item): name = dims.pop('name') else: name = list(self.arr.coords['variable'].values) + base_dims = self.base[name].dims if method == 'isel': self.idims.update(dims) dims = self.idims - for dim in set(self.base[name].dims) - set(dims): + for dim in set(base_dims) - set(dims): dims[dim] = slice(None) for dim in set(dims) - set(self.base[name].dims): del dims[dim] @@ -2661,7 +2662,7 @@ def filter_attrs(item): else: self._idims = None for key, val in six.iteritems(self.arr.coords): - if key != 'variable': + if key in base_dims and key != 'variable': dims.setdefault(key, val) kws = dims.copy() # the sel method does not work with slice objects @@ -2724,7 +2725,8 @@ def filter_attrs(item): self._idims = None old_dims = self.arr.dims[:] for key, val in six.iteritems(self.arr.coords): - dims.setdefault(key, val) + if key in base_var.dims: + dims.setdefault(key, val) kws = dims.copy() # the sel method does not work with slice objects if not any(isinstance(idx, slice) for idx in dims.values()): @@ -3664,7 +3666,8 @@ def from_dataset(cls, base, method='isel', default_slice=None, default_slice: indexer Index (e.g. 0 if `method` is 'isel') that shall be used for dimensions not covered by `dims` and `furtherdims`. If None, the - whole slice will be used. + whole slice will be used. Note that the `default_slice` is always + based on the `isel` method. decoder: CFDecoder or dict Arguments for the decoder. This can be one of @@ -3771,19 +3774,22 @@ def sel_method(key, dims, name=None): elif (isinstance(name, six.string_types) or not utils.is_iterable(name)): arr = base[name] + decoder = get_decoder(arr) + dims = decoder.correct_dims(arr, dims) else: arr = base[list(name)] - add_missing_dimensions(arr) - if not isinstance(arr, xr.DataArray): - arr = ds2arr(arr) + decoder = get_decoder(base[name[0]]) + dims = decoder.correct_dims(base[name[0]], dims) def_slice = slice(None) if default_slice is None else \ default_slice - decoder = get_decoder(arr) - dims = decoder.correct_dims(arr, dims) dims.update({ dim: def_slice for dim in set(arr.dims).difference( dims) if dim != 'variable'}) - ret = squeeze_array(arr.isel(**dims)) + add_missing_dimensions(arr) + ret = arr.isel(**dims) + if not isinstance(ret, xr.DataArray): + ret = ds2arr(ret) + ret = squeeze_array(ret) # delete the variable dimension for the idims dims.pop('variable', None) ret.psy.init_accessor(arr_name=key, base=base, idims=dims, @@ -3796,28 +3802,40 @@ def sel_method(key, dims, name=None): elif (isinstance(name, six.string_types) or not utils.is_iterable(name)): arr = base[name] + decoder = get_decoder(arr) + dims = decoder.correct_dims(arr, dims) else: arr = base[list(name)] - add_missing_dimensions(arr) - if not isinstance(arr, xr.DataArray): - arr = ds2arr(arr) - # idims will be calculated by the array (maybe not the most - # efficient way...) - decoder = get_decoder(arr) - dims = decoder.correct_dims(arr, dims) + decoder = get_decoder(base[name[0]]) + dims = decoder.correct_dims(base[name[0]], dims) if default_slice is not None: - dims.update({ - key: default_slice for key in set(arr.dims).difference( - dims) if key != 'variable'}) + if isinstance(default_slice, slice): + dims.update({ + dim: default_slice + for dim in set(arr.dims).difference(dims) + if dim != 'variable'}) + else: + dims.update({ + dim: arr.coords[dim][default_slice] + for dim in set(arr.dims).difference(dims) + if dim != 'variable'}) kws = dims.copy() + kws['method'] = method # the sel method does not work with slice objects - if not any(isinstance(idx, slice) for idx in dims.values()): - kws['method'] = method + for dim, val in dims.items(): + if isinstance(val, slice): + if val == slice(None): + kws.pop(dim) # the full slice is the default + else: + kws.pop("method", None) + add_missing_dimensions(arr) try: ret = arr.sel(**kws) except KeyError: _fix_times(kws) ret = arr.sel(**kws) + if not isinstance(ret, xr.DataArray): + ret = ds2arr(ret) ret = squeeze_array(ret) ret.psy.init_accessor(arr_name=key, base=base, decoder=decoder) return maybe_load(ret) diff --git a/psyplot/plotter.py b/psyplot/plotter.py index 9884388..620c6de 100755 --- a/psyplot/plotter.py +++ b/psyplot/plotter.py @@ -752,6 +752,42 @@ def remove(self): are removed by the usual :meth:`matplotlib.axes.Axes.clear` method.""" pass + @docstrings.get_extended_summary(base="Formatoption.convert_coordinate") + @docstrings.get_sections( + base="Formatoption.convert_coordinate", + sections=["Parameters", "Returns"] + ) + def convert_coordinate(self, coord, *variables): + """Convert a coordinate to units necessary for the plot. + + This method takes a single coordinate variable (e.g. the `bounds` of a + coordinate, or the coordinate itself) and transforms the units that the + plotter requires. + + One might also provide additional `variables` that are supposed to be + on the same unit, in case the given `coord` does not specify a `units` + attribute. `coord` might be a CF-conform `bounds` variable, and one of + the variables might be the corresponding `coordinate`. + + Parameters + ---------- + coord: xr.Variable + The variable to transform + ``*variables`` + The variables that are on the same unit as `coord` + + Returns + ------- + xr.Variable + The transformed `coord` + + Notes + ----- + By default, this method uses the :meth:`~Plotter.convert_coordinate` + method of the :attr:`plotter`. + """ + return self.plotter.convert_coordinate(coord, *variables) + class DictFormatoption(Formatoption): """ @@ -2434,3 +2470,24 @@ def _get_sample_projection(cls): """Returns None. May be subclassed to return a projection that can be used when creating a subplot""" pass + + @docstrings.dedent + def convert_coordinate(self, coord, *variables): + """Convert a coordinate to units necessary for the plot. + + %(Formatoption.convert_coordinate.summary_ext)s + + Parameters + ---------- + %(Formatoption.convert_coordinate.parameters)s + + Returns + ------- + %(Formatoption.convert_coordinate.returns)s + + Notes + ----- + This method is supposed to be implemented by subclasses. The default + implementation by the :class:`Plotter` class does nothing. + """ + return coord diff --git a/tests/test_data.py b/tests/test_data.py index 6170a79..e3aca3f 100755 --- a/tests/test_data.py +++ b/tests/test_data.py @@ -1335,6 +1335,18 @@ def test_from_dataset_15_decoder_kws(self): decoder=dict(x={'myx'})) self.assertEqual(l[0].psy.decoder.x, {'myx'}) + def test_from_dataset_16_default_slice(self): + """Test selection with default_slice=0""" + variables, coords = self._from_dataset_test_variables + ds = xr.Dataset(variables, coords) + l = self.list_class.from_dataset(ds, ydim=2, default_slice=0, method=None, + name=['v0', 'v2']) + self.assertEqual(len(l), 2) + self.assertEqual(set(l.names), {'v0', 'v2'}) + for arr in l: + self.assertEqual(arr.ydim, 2, + msg="Wrong ydim slice for " + arr.name) + def test_array_info(self): variables, coords = self._from_dataset_test_variables From db51d62f521597d4ca001f735618108690c949b9 Mon Sep 17 00:00:00 2001 From: "Philipp S. Sommer" Date: Mon, 22 Nov 2021 14:19:06 +0100 Subject: [PATCH 03/10] fix compatibility issues for python 3.10 (#43) * fix compatibility issues for python 3.10 closes #42 * remove _validate parameter when loading figure (compatibility fix for matplotlib=3.5) * add pipeline parameter for python version * remove unnecessary specifications * update changelog --- .circleci/config.yml | 8 ++++++-- CHANGELOG.rst | 1 + psyplot/__init__.py | 37 ++++++++++++++++++++++++++----------- psyplot/__main__.py | 2 +- psyplot/config/rcsetup.py | 29 ++++++++++++++++++++--------- psyplot/project.py | 1 + 6 files changed, 55 insertions(+), 23 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7a6b8d4..a8c6cdf 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -25,6 +25,10 @@ parameters: description: Build the documentation type: boolean default: true + python_version: + description: The python version to build + type: string + default: "3.8" workflows: build-and-test: @@ -36,8 +40,8 @@ workflows: setup_env: << pipeline.parameters.run-tests >> build_args: "--no-test" build_docs: << pipeline.parameters.build_docs >> - # HACK: force netcdf4 and hdf5 version to resolve dependency issue - env_packages: dask netcdf4 scipy netcdf4=1.5.7 h5py=3.4.0 hdf5=1.12.1 + python_version: << pipeline.parameters.python_version >> + env_packages: dask netcdf4 scipy - psyplot/test-parallel: name: test-xarray-latest parallelism: 2 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bc85dc8..499da4c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,7 @@ Fixed ----- - the update method now only takes the coordinates that are dimensions in the dataset see `#39 `__ +- psyplot is now compatible with matplotlib 3.5 and python 3.10 Changed ------- diff --git a/psyplot/__init__.py b/psyplot/__init__.py index 0358f05..7f40203 100755 --- a/psyplot/__init__.py +++ b/psyplot/__init__.py @@ -123,24 +123,39 @@ def get_versions(requirements=True, key=None): } } """ - from pkg_resources import iter_entry_points + from importlib.metadata import entry_points ret = {'psyplot': _get_versions(requirements)} - for ep in iter_entry_points(group='psyplot', name='plugin'): + + try: + eps = entry_points(group='psyplot', name='plugin') + except TypeError: # python<3.10 + eps = [ep for ep in entry_points().get('psyplot', []) + if ep.name == 'plugin'] + for ep in eps: if str(ep) in rcParams._plugins: logger.debug('Loading entrypoint %s', ep) - if key is not None and not key(ep.module_name): + + try: + ep.module + except AttributeError: # python<3.10 + ep.module = ep.pattern.match(ep.value).group("module") + + if key is not None and not key(ep.module): continue try: mod = ep.load() except (ImportError, ModuleNotFoundError) as e: - logger.debug("Could not import %s" % ep, exc_info=True) - logger.warning("Could not import %s" % ep) - try: - ret[str(ep.module_name)] = mod.get_versions(requirements) - except AttributeError: - ret[str(ep.module_name)] = { - 'version': getattr(mod, 'plugin_version', - getattr(mod, '__version__', ''))} + logger.debug("Could not import %s" % (ep, ), exc_info=True) + logger.warning("Could not import %s" % (ep, ), exc_info=True) + else: + try: + ret[str(ep.module)] = mod.get_versions(requirements) + except AttributeError: + ret[str(ep.module)] = { + 'version': getattr( + mod, 'plugin_version', + getattr(mod, '__version__', '')) + } if key is None: try: import psyplot_gui diff --git a/psyplot/__main__.py b/psyplot/__main__.py index 5acd83f..796e754 100644 --- a/psyplot/__main__.py +++ b/psyplot/__main__.py @@ -61,7 +61,7 @@ def main(args=None): The parser that has been used from the command line""" try: from psyplot_gui import get_parser as _get_parser - except ImportError: + except (ImportError, ModuleNotFoundError) as e: logger.debug('Failed to import gui', exc_info=True) parser = get_parser(create=False) parser.update_arg('output', required=True) diff --git a/psyplot/config/rcsetup.py b/psyplot/config/rcsetup.py index 3e90954..c186e7a 100755 --- a/psyplot/config/rcsetup.py +++ b/psyplot/config/rcsetup.py @@ -755,16 +755,22 @@ def _load_plugin_entrypoints(self): Yields ------ - pkg_resources.EntryPoint + importlib.metadata.EntryPoint The entry point for the psyplot plugin module""" - from pkg_resources import iter_entry_points + from importlib.metadata import entry_points def load_plugin(ep): + + try: + ep.module + except AttributeError: # python<3.10 + ep.module = ep.pattern.match(ep.value).group("module") + if plugins_env == ['no']: return False - elif ep.module_name in exclude_plugins: + elif ep.module in exclude_plugins: return False - elif include_plugins and ep.module_name not in include_plugins: + elif include_plugins and ep.module not in include_plugins: return False return True @@ -776,7 +782,12 @@ def load_plugin(ep): logger = logging.getLogger(__name__) - for ep in iter_entry_points(group='psyplot', name='plugin'): + try: + eps = entry_points(group='psyplot', name='plugin') + except TypeError: # python<3.10 + eps = [ep for ep in entry_points().get('psyplot', []) + if ep.name == 'plugin'] + for ep in eps: if not load_plugin(ep): logger.debug('Skipping entrypoint %s', ep) continue @@ -811,7 +822,7 @@ def load_plugins(self, raise_error=False): def_keys = {'default': defaultParams} def register_pm(ep, name): - full_name = '%s:%s' % (ep.module_name, name) + full_name = '%s:%s' % (ep.module, name) ret = True if pm_env == ['no']: ret = False @@ -828,8 +839,8 @@ def register_pm(ep, name): try: plugin_mod = ep.load() except (ModuleNotFoundError, ImportError): - logger.debug("Failed to import %s!" % ep, exc_info=True) - logger.warning("Failed to import %s!" % ep) + logger.debug("Failed to import %s!" % (ep, ), exc_info=True) + logger.warning("Failed to import %s!" % (ep, )) continue rc = plugin_mod.rcParams @@ -852,7 +863,7 @@ def register_pm(ep, name): else: warn(msg) for d in plugin_plotters.values(): - d['plugin'] = ep.module_name + d['plugin'] = ep.module plotters.update(plugin_plotters) def_plots[ep] = list(plugin_plotters) diff --git a/psyplot/project.py b/psyplot/project.py index cda542e..6336ce0 100755 --- a/psyplot/project.py +++ b/psyplot/project.py @@ -1634,6 +1634,7 @@ def load_figure(d, new_fig=True): subplotpars = d.pop('subplotpars', None) if subplotpars is not None: subplotpars.pop('validate', None) + subplotpars.pop('_validate', None) subplotpars = mfig.SubplotParams(**subplotpars) if new_fig: nums = plt.get_fignums() From 15c5974ac4da2ff5113d5873a3e73fb8b5b651be Mon Sep 17 00:00:00 2001 From: Philipp Sommer Date: Thu, 2 Dec 2021 17:24:56 +0100 Subject: [PATCH 04/10] do not modify gridweight arrays in place --- psyplot/data.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/psyplot/data.py b/psyplot/data.py index 65d2478..e61992d 100755 --- a/psyplot/data.py +++ b/psyplot/data.py @@ -3129,10 +3129,9 @@ def notnull(a): weights = broadcast_to(weights / weights.sum(), arr.shape) # set nans to zero weigths. This step takes quite a lot of time for # large arrays since it involves a copy of the entire `arr` - weights *= notnull(arr) + weights = weights * notnull(arr) # normalize the weights - weights /= weights.sum(axis=tuple(map(dims.index, sdims)), - keepdims=True) + weights /= weights.sum(axis=tuple(map(dims.index, sdims))) else: dims = arr.dims coords = arr.isel( From 696b545ac8ed43b961303e29d163160c0fb472dd Mon Sep 17 00:00:00 2001 From: Philipp Sommer Date: Thu, 2 Dec 2021 18:10:16 +0100 Subject: [PATCH 05/10] do not modify weights in-place --- psyplot/data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/psyplot/data.py b/psyplot/data.py index e61992d..48892f3 100755 --- a/psyplot/data.py +++ b/psyplot/data.py @@ -3131,7 +3131,7 @@ def notnull(a): # large arrays since it involves a copy of the entire `arr` weights = weights * notnull(arr) # normalize the weights - weights /= weights.sum(axis=tuple(map(dims.index, sdims))) + weights = weights / weights.sum(axis=tuple(map(dims.index, sdims))) else: dims = arr.dims coords = arr.isel( From 1dc247d0d25493e65d270ce80599e39a66a79d99 Mon Sep 17 00:00:00 2001 From: Philipp Sommer Date: Fri, 3 Dec 2021 10:05:00 +0100 Subject: [PATCH 06/10] keepdims only with dask --- psyplot/data.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/psyplot/data.py b/psyplot/data.py index 48892f3..92ff52b 100755 --- a/psyplot/data.py +++ b/psyplot/data.py @@ -3131,7 +3131,13 @@ def notnull(a): # large arrays since it involves a copy of the entire `arr` weights = weights * notnull(arr) # normalize the weights - weights = weights / weights.sum(axis=tuple(map(dims.index, sdims))) + if with_dask: + summed_weights = weights.sum( + axis=tuple(map(dims.index, sdims)), keepdims=True + ) + else: + summed_weights = weights.sum(axis=tuple(map(dims.index, sdims))) + weights = weights / summed_weights else: dims = arr.dims coords = arr.isel( From 9a63efad0821ac5bb4954d6d7ae1468dfa0641d9 Mon Sep 17 00:00:00 2001 From: Philipp Sommer Date: Fri, 3 Dec 2021 12:56:42 +0100 Subject: [PATCH 07/10] minor --- psyplot/data.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/psyplot/data.py b/psyplot/data.py index 92ff52b..2aacebd 100755 --- a/psyplot/data.py +++ b/psyplot/data.py @@ -3136,7 +3136,9 @@ def notnull(a): axis=tuple(map(dims.index, sdims)), keepdims=True ) else: - summed_weights = weights.sum(axis=tuple(map(dims.index, sdims))) + summed_weights = weights.sum( + axis=tuple(map(dims.index, sdims)) + ) weights = weights / summed_weights else: dims = arr.dims From aefcdab172b85ad599c367997cec2665eaef9520 Mon Sep 17 00:00:00 2001 From: Philipp Sommer Date: Wed, 5 Jan 2022 00:15:05 +0100 Subject: [PATCH 08/10] use psyplot-ci-orb@1.5.29 --- .circleci/config.yml | 2 +- docs/environment.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a8c6cdf..67cd829 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,7 +1,7 @@ version: 2.1 orbs: - psyplot: psyplot/psyplot-ci-orb@1.5.27 + psyplot: psyplot/psyplot-ci-orb@1.5.29 mattermost-plugin-notify: nathanaelhoun/mattermost-plugin-notify@1.2.0 executors: diff --git a/docs/environment.yml b/docs/environment.yml index b757f47..b70c999 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -1,6 +1,7 @@ name: psyplot_docs channels: - local + - psyplot/label/__CURRENTBRANCH__ - psyplot/label/master - conda-forge dependencies: From 1dd2a9e76183f3e0ac0c012cbe38bd95ffe18369 Mon Sep 17 00:00:00 2001 From: Philipp Sommer Date: Wed, 5 Jan 2022 00:55:29 +0100 Subject: [PATCH 09/10] minor doc fixes --- docs/about.rst | 8 ++++++-- docs/conf.py | 4 ++++ docs/environment.yml | 2 +- psyplot/config/rcsetup.py | 2 +- psyplot/utils.py | 2 +- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/docs/about.rst b/docs/about.rst index f961a0f..6495157 100644 --- a/docs/about.rst +++ b/docs/about.rst @@ -72,8 +72,8 @@ What it is visualization. No GUI, independent of it's intuitiveness, can ever beat the speed of a scientist that knows a bit of coding and how to use the different formatoptions in psyplot. -- it visualizes :ref:`unstructured grids `, - such as ICON or UGRID model data +- it visualizes :ref:`unstructured grids `, + such as ICON_ or UGRID_ model data - it automatically decodes CF-conventions - it intuitively integrates the structure of netCDF files. So if you often work with netCDF files, psyplot might be a good option @@ -93,6 +93,10 @@ What it is plotting methods - it will always be free and open-source under the LGPL License. +.. _ICON: http://www.mpimet.mpg.de/en/science/models/icon-esm.html +.. _UGRID: http://ugrid-conventions.github.io/ugrid-conventions/ + + What it is not ************** No software can do everything, neither can psyplot. Our main focus on diff --git a/docs/conf.py b/docs/conf.py index 161872d..2ee6d9e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -63,6 +63,10 @@ 'ignore', message='Using an implicitly registered datetime converter') warnings.filterwarnings( 'ignore', message=r"\s*The on_mappable_changed function") +warnings.filterwarnings( + 'ignore', message=r".+multi-part geometries is deprecated") +warnings.filterwarnings( + 'ignore', message=r"\s*The array interface is deprecated") # -- General configuration ------------------------------------------------ diff --git a/docs/environment.yml b/docs/environment.yml index b70c999..e1c9d7b 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -1,7 +1,7 @@ name: psyplot_docs channels: - local - - psyplot/label/__CURRENTBRANCH__ + - psyplot/label/develop - psyplot/label/master - conda-forge dependencies: diff --git a/psyplot/config/rcsetup.py b/psyplot/config/rcsetup.py index c186e7a..cfacfd5 100755 --- a/psyplot/config/rcsetup.py +++ b/psyplot/config/rcsetup.py @@ -430,7 +430,7 @@ def __init__(self, *args, **kwargs): Other Parameters ---------------- - ``*args, **kwargs`` + *args, **kwargs Any key-value pair for the initialization of the dictionary """ defaultParams = kwargs.pop('defaultParams', None) diff --git a/psyplot/utils.py b/psyplot/utils.py index 760b423..b10f66e 100644 --- a/psyplot/utils.py +++ b/psyplot/utils.py @@ -226,7 +226,7 @@ def check_key(key, possible_keys, raise_error=True, msg: str The additional message that shall be used if no close match to key is found - ``*args,**kwargs`` + *args, **kwargs They are passed to the :func:`difflib.get_close_matches` function (i.e. `n` to increase the number of returned similar keys and `cutoff` to change the sensibility) From 26e477beb556236e6c66e8b31b4723853246d82f Mon Sep 17 00:00:00 2001 From: Philipp Sommer Date: Wed, 5 Jan 2022 10:03:54 +0100 Subject: [PATCH 10/10] fix broken links --- docs/about.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/about.rst b/docs/about.rst index 6495157..93cbb74 100644 --- a/docs/about.rst +++ b/docs/about.rst @@ -93,8 +93,8 @@ What it is plotting methods - it will always be free and open-source under the LGPL License. -.. _ICON: http://www.mpimet.mpg.de/en/science/models/icon-esm.html -.. _UGRID: http://ugrid-conventions.github.io/ugrid-conventions/ +.. _ICON: https://mpimet.mpg.de/en/science/modeling-with-icon/icon-configurations +.. _UGRID: https://ugrid-conventions.github.io/ugrid-conventions/ What it is not