ncvue.ncvutils

Utility functions for ncvue.

The utility functions do not depend on the ncvue class. Functions depending on the class are in ncvmethods.

This module was written by Matthias Cuntz while at Institut National de Recherche pour l’Agriculture, l’Alimentation et l’Environnement (INRAE), Nancy, France.

Copyright (c) 2020-2021 Matthias Cuntz - mc (at) macu (dot) de

Released under the MIT License; see LICENSE file for details.

History:

  • Written Nov-Dec 2020 by Matthias Cuntz (mc (at) macu (dot) de)

  • General get_slice function from individual methods for x, y, y2, z, Dec 2020, Matthias Cuntz

  • Added arithmetics to apply on axis/dimensions such as mean, std, etc., Dec 2020, Matthias Cuntz

  • Added clone_ncvmain, removing its own module, Dec 2020, Matthias Cuntz

  • added SEPCHAR and DIMMETHODS, Jan 2021, Matthias Cuntz

  • pass only ncvMain widget to clone_ncvmain, Jan 2021, Matthias Cuntz

  • pass only root widget to clone_ncvmain, Jan 2021, Matthias Cuntz

The following functions are provided:

DIMMETHODS

Arithmetic methods implemented on dimensions.

SEPCHAR

Invisible character to split strings.

add_cyclic_point(data[, coord, rowcoord, axis])

Add a cyclic point to an array and optionally a corresponding coordinate.

clone_ncvmain(widget)

Duplicate the main ncvue window.

get_slice(dimspins, y)

Get slice of variable y inquiring the spinboxes dimspins.

list_intersection(lst1, lst2)

Intersection of two lists.

set_axis_label(ncvar)

Set label plotting axis from name and unit of given variable ncvar.

set_miss(miss, x)

Set x to NaN for all values in miss.

spinbox_values(ndim)

Tuple for Spinbox values with ‘all’ before range(ndim) and ‘mean’, ‘std’, etc.

vardim2var(vardim)

Extract variable name from ‘variable (dim1=ndim1,)’ string.

zip_dim_name_length(ncvar)

Combines dimension names and length of netcdf variable in list of strings.

add_cyclic_point(data, coord=None, rowcoord=None, axis=- 1)[source]

Add a cyclic point to an array and optionally a corresponding coordinate.

Parameters
datandarray

An n-dimensional array of data to add a cyclic point to.

coord: ndarray, optional

A 1- or 2-dimensional array which specifies the coordinate values for the dimension the cyclic point is to be added to. Defaults to None.

If coord is given than add_cyclic_point checks if cyclic point is already present by checking sin(coord[0]) == sin(coord[-1]). No point is added if cyclic point was detected.

Length of coord must be data.shape[axis] if 1-dimensional.

coord.shape[-1] must be data.shape[axis] if 2-dimensional.

rowcoord: ndarray, optional

A 2-dimensional array with the variable of the row coordinate. The cyclic point simply copies the last column. Only considered if coord is 2-dimensional. Defaults to None.

rowcoord.shape[-1] must be data.shape[axis].

axis: optional

Specifies the axis of the data array to add the cyclic point to. Defaults to the right-most axis.

Returns
cyclic_data

The data array with a cyclic point added.

cyclic_coord

The coordinate with a cyclic point, only returned if the coord keyword was supplied.

cyclic_rowcoord

The row coordinate with the last column duplicated, only returned if coord was 2-dimensional and the lat keyword was supplied.

Examples

Adding a cyclic point to a data array, where the cyclic dimension is the right-most dimension. .. testsetup:

>>> from distutils.version import LooseVersion
>>> import numpy as np
>>> if LooseVersion(np.__version__) >= '1.14.0':
...     # To provide consistent doctests.
...     np.set_printoptions(legacy='1.13')
>>> import numpy as np
>>> data = np.ones([5, 6]) * np.arange(6)
>>> cyclic_data = add_cyclic_point(data)
>>> print(cyclic_data)  
[[ 0. 1. 2. 3. 4. 5. 0.]
 [ 0. 1. 2. 3. 4. 5. 0.]
 [ 0. 1. 2. 3. 4. 5. 0.]
 [ 0. 1. 2. 3. 4. 5. 0.]
 [ 0. 1. 2. 3. 4. 5. 0.]]

Adding a cyclic point to a data array and an associated coordinate. >>> lons = np.arange(0, 360, 60) >>> cyclic_data, cyclic_lons = add_cyclic_point(data, coord=lons) >>> print(cyclic_data) # doctest: +NORMALIZE_WHITESPACE [[ 0. 1. 2. 3. 4. 5. 0.]

[ 0. 1. 2. 3. 4. 5. 0.] [ 0. 1. 2. 3. 4. 5. 0.] [ 0. 1. 2. 3. 4. 5. 0.] [ 0. 1. 2. 3. 4. 5. 0.]]

>>> print(cyclic_lons)
[  0  60 120 180 240 300 360]

Adding a cyclic point to a data array and an associated 2-dimensional coordinate. >>> lons = np.arange(0, 360, 60) >>> lats = np.arange(-90, 90, 180/5) >>> lon2d, lat2d = np.meshgrid(lons, lats) >>> cyclic_data, cyclic_lon2d = add_cyclic_point(data, coord=lon2d) >>> print(cyclic_data) # doctest: +NORMALIZE_WHITESPACE [[ 0. 1. 2. 3. 4. 5. 0.]

[ 0. 1. 2. 3. 4. 5. 0.] [ 0. 1. 2. 3. 4. 5. 0.] [ 0. 1. 2. 3. 4. 5. 0.] [ 0. 1. 2. 3. 4. 5. 0.]]

>>> print(cyclic_lon2d)
[[  0  60 120 180 240 300 360]
 [  0  60 120 180 240 300 360]
 [  0  60 120 180 240 300 360]
 [  0  60 120 180 240 300 360]
 [  0  60 120 180 240 300 360]]

Adding a cyclic point to a data array and an associated 2-dimensional coordinate and a second raw variable. >>> lons = np.arange(0, 360, 60) >>> lats = np.arange(-90, 90, 180/5) >>> lon2d, lat2d = np.meshgrid(lons, lats) >>> cyclic_data, cyclic_lon2d, cyclic_lat2d = add_cyclic_point( … data, coord=lon2d, rowcoord=lat2d) >>> print(cyclic_data) # doctest: +NORMALIZE_WHITESPACE [[ 0. 1. 2. 3. 4. 5. 0.]

[ 0. 1. 2. 3. 4. 5. 0.] [ 0. 1. 2. 3. 4. 5. 0.] [ 0. 1. 2. 3. 4. 5. 0.] [ 0. 1. 2. 3. 4. 5. 0.]]

>>> print(cyclic_lon2d)
[[  0  60 120 180 240 300 360]
 [  0  60 120 180 240 300 360]
 [  0  60 120 180 240 300 360]
 [  0  60 120 180 240 300 360]
 [  0  60 120 180 240 300 360]]
>>> print(cyclic_lat2d)
[[-90. -90. -90. -90. -90. -90. -90.]
 [-54. -54. -54. -54. -54. -54. -54.]
 [-18. -18. -18. -18. -18. -18. -18.]
 [ 18.  18.  18.  18.  18.  18.  18.]
 [ 54.  54.  54.  54.  54.  54.  54.]]

Not adding a cyclic point if cyclic point detected in coord. >>> lons = np.arange(0, 361, 72) >>> lats = np.arange(-90, 90, 180/5) >>> lon2d, lat2d = np.meshgrid(lons, lats) >>> cyclic_data, cyclic_lon2d, cyclic_lat2d = add_cyclic_point( … data, coord=lon2d, rowcoord=lat2d) >>> print(cyclic_data) # doctest: +NORMALIZE_WHITESPACE [[ 0. 1. 2. 3. 4. 5.]

[ 0. 1. 2. 3. 4. 5.] [ 0. 1. 2. 3. 4. 5.] [ 0. 1. 2. 3. 4. 5.] [ 0. 1. 2. 3. 4. 5.]]

>>> print(cyclic_lon2d)
[[  0  72 144 216 288 360]
 [  0  72 144 216 288 360]
 [  0  72 144 216 288 360]
 [  0  72 144 216 288 360]
 [  0  72 144 216 288 360]]
>>> print(cyclic_lat2d)
[[-90. -90. -90. -90. -90. -90.]
 [-54. -54. -54. -54. -54. -54.]
 [-18. -18. -18. -18. -18. -18.]
 [ 18.  18.  18.  18.  18.  18.]
 [ 54.  54.  54.  54.  54.  54.]]
clone_ncvmain(widget)[source]

Duplicate the main ncvue window.

Parameters
widgetncvue.ncvMain

widget of ncvMain class.

finetCDF4._netCDF4.Dataset

netcdf dataset

missfloat

Additional value that will be set to np.nan in netcdf variables.

Returns
Another ncvue window will be created.

Examples

>>> self.newwin = ttk.Button(
...     self.rowwin, text="New Window",
...     command=partial(clone_ncvmain, self.master))
get_slice(dimspins, y)[source]

Get slice of variable y inquiring the spinboxes dimspins.

Parameters
dimspinslist

List of tk.Spinbox widgets of dimensions

yndarray or netCDF4._netCDF4.Variable

Input array or netcdf variable

Returns
ndarray

Slice of y chosen by with spinboxes.

Examples

>>> vy = vardim2var(y)
>>> yy = self.fi.variables[vy]
>>> miss = get_miss(self, yy)
>>> yy = get_slice_y(self.yd, yy).squeeze()
>>> yy = set_miss(miss, yy)
list_intersection(lst1, lst2)[source]

Intersection of two lists.

From: https://stackoverflow.com/questions/3697432/how-to-find-list-intersection Using list comprehension for small lists and set() method with builtin intersection for longer lists.

Parameters
lst1, lst2list

Python lists

Returns
list

List with common elements in both input lists.

Examples

>>> lst1 = [ 4, 9, 1, 17, 11, 26, 28, 28, 26, 66, 91]
>>> lst2 = [9, 9, 74, 21, 45, 11, 63]
>>> print(Intersection(lst1, lst2))
[9, 11]
set_axis_label(ncvar)[source]

Set label plotting axis from name and unit of given variable ncvar.

Parameters
ncvarnetCDF4._netCDF4.Variable

netcdf variables class

Returns
str

Label string: name (unit)

Examples

>>> ylab = set_axis_label(fi.variables['w_soil'])
set_miss(miss, x)[source]

Set x to NaN for all values in miss.

Parameters
missiterable

values which shall be set to np.nan in x

xndarray

numpy array

Returns
ndarray

x with all values set np.nan that are equal to any value in miss.

Examples

>>> x = fi.variables['time']
>>> miss = get_miss(self, x)
>>> x = set_miss(miss, x)
spinbox_values(ndim)[source]

Tuple for Spinbox values with ‘all’ before range(ndim) and ‘mean’, ‘std’, etc. after range(ndim) if ndim>1, otherwise single entry (0,).

Parameters
ndimint

Size of dimension.

Returns
tuple

((‘all’,) + tuple(range(ndim)) + (‘mean’,’std’,…)) if ndim > 1 (0,) else

Examples

>>> self.xd0.config(values=spinbox_values(xx.shape[0]))
vardim2var(vardim)[source]

Extract variable name from ‘variable (dim1=ndim1,)’ string.

Parameters
vardimstring

Variable name with dimensions, such as ‘latitude (lat=32,lon=64)’.

Returns
string

Variable name.

Examples

>>> vardim2var('latitude (lat=32,lon=64)')
latitude
zip_dim_name_length(ncvar)[source]

Combines dimension names and length of netcdf variable in list of strings.

Parameters
ncvarnetCDF4._netCDF4.Variable

netcdf variables class

Returns
list

List of dimension name and length in the form ‘dim=len’.

Examples

>>> import netCDF4 as nc
>>> ifile = 'test.nc'
>>> fi = nc.Dataset(ifile, 'r')
>>> w_soil = fi.variables['w_soil']
>>> print(zip_dim_name_length(w_soil))
('ntime=17520', 'nsoil=30')
DIMMETHODS = ('mean', 'std', 'min', 'max', 'ptp', 'sum', 'median', 'var')

Arithmetic methods implemented on dimensions.

mean - average std - standard deviation min - minimum max - maximum ptp - point-to-point amplitude = max - min sum - sum median - 50-percentile var - variance

SEPCHAR = '\x06'

Invisible character to split strings.

ASCII character 6 = ACKNOWLEDGE (ACK)