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:

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

license:

MIT License, see LICENSE for details.

The following functions are provided:

DIMMETHODS

Arithmetic methods implemented on dimensions.

add_cyclic(data[, x, y, axis, cyclic, precision])

Add a cyclic point to an array and optionally corresponding x/longitude and y/latitude coordinates.

clone_ncvmain(widget)

Duplicate the main ncvue window.

format_coord_contour(x, y, ax, xx, yy, zz)

Formatter function for contour plot including value of nearest array cell.

format_coord_map(x, y, ax, xx, yy, zz)

Formatter function for map including value of nearest array cell.

format_coord_scatter(x, y, ax, ax2, xdtype, ...)

Formatter function for scatter plot with left and right axis having the same x-axis.

get_slice(dimspins, y)

Get slice of variable y inquiring the spinboxes dimspins.

list_intersection(lst1, lst2)

Intersection of two lists.

selvar(self, var)

Extract variable from correct file.

set_axis_label(ncvar)

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

set_miss(miss, x)

Set x to NaN or NaT for all values in miss.

spinbox_values(ndim)

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

vardim2var(vardim[, groups])

Extract group index and variable name from 'group/variable (dim1=ndim1,)'.

zip_dim_name_length(ncvar)

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

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

  • Set correct missing value for date variable in numpy’s datetime64[ms] format May 2021, Matthias Cuntz

  • Added format_coord functions for scatter, contour, and map, May 2021, Matthias Cuntz

  • Replaced add_cyclic_point with add_cyclic as submitted to cartopy, Jun 2021, Matthias Cuntz

  • Removed SEPCHAR, Jun 2021, Matthias Cuntz

  • Final add_cyclic, has_cyclic from cartopy v0.20.1, Nov 2021, Matthias Cuntz

  • Address fi.variables[name] directly by fi[name], Jan 2024, Matthias Cuntz

  • Add selvar to allow multiple netcdf files, Jan 2024, Matthias Cuntz

  • Remove [ms] from check for datetime in format_coord on axes, Oct 2024, Matthias Cuntz

add_cyclic(data, x=None, y=None, axis=-1, cyclic=360, precision=0.0001)[source]#

Add a cyclic point to an array and optionally corresponding x/longitude and y/latitude coordinates.

Checks all differences between the first and last x-coordinates along axis to be less than precision.

Parameters:
  • data (ndarray) – An n-dimensional array of data to add a cyclic point to.

  • x (ndarray, optional) –

    An n-dimensional array which specifies the x-coordinate values for the dimension the cyclic point is to be added to, i.e. normally the longitudes. Defaults to None.

    If x is given then add_cyclic checks if a cyclic point is already present by checking all differences between the first and last coordinates to be less than precision. No point is added if a cyclic point was detected.

    If x is 1- or 2-dimensional, x.shape[-1] must equal data.shape[axis], otherwise x.shape[axis] must equal data.shape[axis].

  • y (ndarray, optional) –

    An n-dimensional array with the values of the y-coordinate, i.e. normally the latitudes. The cyclic point simply copies the last column. Defaults to None.

    No cyclic point is added if y is 1-dimensional. If y is 2-dimensional, y.shape[-1] must equal data.shape[axis], otherwise y.shape[axis] must equal data.shape[axis].

  • axis (int, optional) – Specifies the axis of the arrays to add the cyclic point to, i.e. axis with changing x-coordinates. Defaults to the right-most axis.

  • cyclic (int or float, optional) – Width of periodic domain (default: 360).

  • precision (float, optional) – Maximal difference between first and last x-coordinate to detect cyclic point (default: 1e-4).

Returns:

  • cyclic_data – The data array with a cyclic point added.

  • cyclic_x – The x-coordinate with a cyclic point, only returned if the x keyword was supplied.

  • cyclic_y – The y-coordinate with the last column of the cyclic axis duplicated, only returned if x was 2- or n-dimensional and the y keyword was supplied.

Examples

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

>>> import numpy as np
>>> data = np.ones([5, 6]) * np.arange(6)
>>> cyclic_data = add_cyclic(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 x-coordinate.

>>> lons = np.arange(0, 360, 60)
>>> cyclic_data, cyclic_lons = add_cyclic(data, x=lons)
>>> 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.]]
>>> print(cyclic_lons)
[  0  60 120 180 240 300 360]

Adding a cyclic point to a data array and an associated 2-dimensional x-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(data, x=lon2d)
>>> 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.]]
>>> 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 the associated 2-dimensional x- and y-coordinates.

>>> 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(
...     data, x=lon2d, y=lat2d)
>>> 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.]]
>>> 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 x.

>>> 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(
...     data, x=lon2d, y=lat2d)
>>> print(cyclic_data)  
[[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:

widget (ncvue.ncvMain) – widget of ncvMain class.

Return type:

Another ncvue window will be created.

Examples

>>> self.newwin = ttk.Button(
...     self.rowwin, text="New Window",
...     command=partial(clone_ncvmain, self.master))
format_coord_contour(x, y, ax, xx, yy, zz)[source]#

Formatter function for contour plot including value of nearest array cell.

Parameters:
  • x (float) – Data coordinates of ax.

  • y (float) – Data coordinates of ax.

  • ax (matplotlib.axes._subplots.AxesSubplot) – Matplotlib axes object for left-hand and right-hand y-axis, resp.

  • xx (ndarray) – Numpy arrays with x-values, y-values, and z-values

  • yy (ndarray) – Numpy arrays with x-values, y-values, and z-values

  • zz (ndarray) – Numpy arrays with x-values, y-values, and z-values

Return type:

String with coordinateds.

Examples

>>> ax = plt.subplot(111)
>>> ax.pcolormesh(xx, yy, zz)
>>> ax.format_coord = lambda x, y: format_coord_contour(
...     x, y, ax, xx, yy, zz)
format_coord_map(x, y, ax, xx, yy, zz)[source]#

Formatter function for map including value of nearest array cell.

Parameters:
  • x (float) – Data coordinates of ax.

  • y (float) – Data coordinates of ax.

  • ax (matplotlib.axes._subplots.AxesSubplot) – Matplotlib axes object for left-hand and right-hand y-axis, resp.

  • xx (ndarray) – Numpy arrays with x-values, y-values, and z-values

  • yy (ndarray) – Numpy arrays with x-values, y-values, and z-values

  • zz (ndarray) – Numpy arrays with x-values, y-values, and z-values

Return type:

String with coordinateds.

Examples

>>> ax = plt.subplot(111)
>>> ax.pcolormesh(xx, yy, zz)
>>> ax.format_coord = lambda x, y: format_coord_contour(
...     x, y, ax, xx, yy, zz)
format_coord_scatter(x, y, ax, ax2, xdtype, ydtype, y2dtype)[source]#

Formatter function for scatter plot with left and right axis having the same x-axis.

Parameters:
  • x (float) – Data coordinates of ax2.

  • y (float) – Data coordinates of ax2.

  • ax (matplotlib.axes._subplots.AxesSubplot) – Matplotlib axes object for left-hand and right-hand y-axis, resp.

  • ax2 (matplotlib.axes._subplots.AxesSubplot) – Matplotlib axes object for left-hand and right-hand y-axis, resp.

  • xdtype (numpy.dtype) – Numpy dtype of data of x-values (xdtype), left-hand side y-values (ydtype), and right-hand side y-values (y2dtype)

  • ydtype (numpy.dtype) – Numpy dtype of data of x-values (xdtype), left-hand side y-values (ydtype), and right-hand side y-values (y2dtype)

  • y2dtype (numpy.dtype) – Numpy dtype of data of x-values (xdtype), left-hand side y-values (ydtype), and right-hand side y-values (y2dtype)

Return type:

String with left-hand side and right hand-side coordinates.

Examples

>>> ax = plt.subplot(111)
>>> ax2 = ax.twinx()
>>> ax.plot(xx, yy)
>>> ax2.plot(xx, yy2)
>>> ax2.format_coord = lambda x, y: format_coord_scatter(
...     x, y, ax, ax2, xx.dtype, yy.dtype, yy2.dtype)
get_slice(dimspins, y)[source]#

Get slice of variable y inquiring the spinboxes dimspins.

Parameters:
  • dimspins (list) – List of tk.Spinbox widgets of dimensions

  • y (ndarray or netCDF4._netCDF4.Variable) – Input array or netcdf variable

Returns:

Slice of y chosen by with spinboxes.

Return type:

ndarray

Examples

>>> gy, vy = vardim2var(y, self.groups)
>>> yy = selvar(self, vy)
>>> miss = get_miss(self, yy)
>>> yy = get_slice_y(self.yd, yy).squeeze()
>>> yy = set_miss(miss, yy)
has_cyclic(x, axis=-1, cyclic=360, precision=0.0001)[source]#

Check if x/longitude coordinates already have a cyclic point.

Checks all differences between the first and last x-coordinates along axis to be less than precision.

Parameters:
  • x (ndarray) – An array with the x-coordinate values to be checked for cyclic points.

  • axis (int, optional) – Specifies the axis of the x array to be checked. Defaults to the right-most axis.

  • cyclic (float, optional) – Width of periodic domain (default: 360).

  • precision (float, optional) – Maximal difference between first and last x-coordinate to detect cyclic point (default: 1e-4).

Returns:

  • True if a cyclic point was detected along the given axis,

  • False otherwise.

Examples

Check for cyclic x-coordinate in one dimension. >>> import numpy as np >>> lons = np.arange(0, 360, 60) >>> clons = np.arange(0, 361, 60) >>> print(has_cyclic(lons)) False >>> print(has_cyclic(clons)) True

Check for cyclic x-coordinate in two dimensions. >>> lats = np.arange(-90, 90, 30) >>> lon2d, lat2d = np.meshgrid(lons, lats) >>> clon2d, clat2d = np.meshgrid(clons, lats) >>> print(has_cyclic(lon2d)) False >>> print(has_cyclic(clon2d)) True

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 (list) – Python lists

  • lst2 (list) – Python lists

Returns:

List with common elements in both input lists.

Return type:

list

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]
selvar(self, var)[source]#

Extract variable from correct file.

Parameters:
  • self (class) – ncvue Tk class having fi and groups

  • var (string) – Variable name including group or file identifier, such as ‘Qle’, ‘group1/Qle’, or ‘file0001/Qle’

Returns:

Pointer to variable in file

Return type:

netcdf variable

Examples

selvar(self, var)

set_axis_label(ncvar)[source]#

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

Parameters:

ncvar (netCDF4._netCDF4.Variable) – netcdf variables class

Returns:

Label string: name (unit)

Return type:

str

Examples

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

Set x to NaN or NaT for all values in miss.

Parameters:
  • miss (iterable) – values which shall be set to np.nan or np.datetime64(‘NaT’) in x

  • x (ndarray) – numpy array

Returns:

x with all values set np.nan or np.datetime64(‘NaT’) that are equal to any value in miss.

Return type:

ndarray

Examples

>>> x = fi['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:

ndim (int) – Size of dimension.

Returns:

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

Return type:

tuple

Examples

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

Extract group index and variable name from ‘group/variable (dim1=ndim1,)’.

Parameters:

vardim (string) – Variable name with dimensions, such as ‘latitude (lat=32,lon=64)’ or with group ‘file1/latitude (lat=32,lon=64)’

Returns:

group index, variable name

Return type:

int, string

Examples

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

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

Parameters:

ncvar (netCDF4._netCDF4.Variable) – netcdf variables class

Returns:

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

Return type:

list

Examples

>>> import netCDF4 as nc
>>> ifile = 'test.nc'
>>> fi = nc.Dataset(ifile, 'r')
>>> w_soil = fi['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