Source code for pymt.grids.field

import numpy as np

from .igrid import CENTERING_CHOICES, CenteringValueError, DimensionError, IField
from .raster import UniformRectilinear
from .rectilinear import Rectilinear
from .structured import Structured
from .unstructured import Unstructured


[docs]def combine_args_to_list(*args, **kwds): if len(args) == 0: args = kwds.get("default", []) args = list(args) combined_args = [] for arg in args: if isinstance(arg, str): combined_args.append(arg) else: combined_args.extend(arg) return combined_args
[docs]class GridField(Unstructured, IField): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._fields = {} self._field_units = {}
[docs] def add_field( self, field_name, val, centering="zonal", units="-", exist_action="clobber", time=None, ): if exist_action not in ("clobber", "append"): raise ValueError("'exist_action' must be on of {'clobber', 'append'}") try: val.shape = val.size except AttributeError: val = np.array(val) if centering not in CENTERING_CHOICES: raise CenteringValueError(centering) if centering == "zonal" and val.size != self.get_cell_count(): raise DimensionError(val.size, self.get_cell_count()) elif centering != "zonal" and val.size != self.get_point_count(): raise DimensionError(val.size, self.get_point_count()) self._field_times = {} if field_name not in self._fields or exist_action == "clobber": self._fields[field_name] = [val] self._field_times[field_name] = [time] else: self._fields[field_name].append(val) self._field_times[field_name].append(time) self._field_units[field_name] = units
# self._fields[field_name].shape = val.size
[docs] def pop_field(self, field_name, *args, **kwds): return_with_time = kwds.get("return_with_time", False) field = self._fields[field_name].pop(*args) if return_with_time: time = self._field_times[field_name].pop(*args) return (time, field) else: return field
[docs] def get_field(self, field_name): if len(self._fields[field_name]) == 1: return self._fields[field_name][0] else: return self._fields[field_name]
[docs] def get_field_units(self, field_name): return self._field_units[field_name]
[docs] def set_field_units(self, field_name, units): try: self._field_units[field_name] = units except KeyError: pass
[docs] def get_point_fields(self, *args): names = combine_args_to_list(*args, default=self._fields.keys()) fields = {} for name in names: array = self.get_field(name) if array.size == self.get_point_count(): fields[name] = array return fields
# fields = {} # for (field, array) in self._fields.items (): # if array.size == self.get_point_count (): # fields[field] = array # return fields
[docs] def get_cell_fields(self, *args): names = combine_args_to_list(*args, default=self._fields.keys()) fields = {} for name in names: array = self.get_field(name) if array.size == self.get_cell_count(): fields[name] = array return fields
[docs] def items(self): return self._fields.items()
[docs] def keys(self): return self._fields.keys()
[docs] def values(self): return self._fields.values()
[docs] def has_field(self, name): return name in self._fields
[docs]class UnstructuredField(GridField): pass
[docs]class StructuredField(Structured, GridField):
[docs] def add_field( self, field_name, val, centering="zonal", units="-", exist_action="clobber", time=None, ): if not hasattr(val, "ndim"): val = np.array(val) # try: # ndim = val.ndim # except AttributeError: # val = np.array (val) # ndim = val.ndim if centering == "zonal": if val.ndim > 1 and np.any(val.shape != self.get_shape() - 1): raise DimensionError(val.shape, self.get_shape() - 1) elif centering != "zonal": if val.ndim > 1 and np.any(val.shape != self.get_shape()): raise DimensionError(val.shape, self.get_shape()) try: super().add_field( field_name, val, centering=centering, units=units, exist_action=exist_action, time=time, ) except (DimensionError, CenteringValueError): raise
[docs]class RectilinearField(Rectilinear, StructuredField): pass
[docs]class RasterField(UniformRectilinear, StructuredField): """ Create a field that looks like this, :: (0) --- (1) --- (2) | | | | 0 | 1 | | | | (3) --- (4) --- (5) Create the field, >>> g = RasterField ((2,3), (1,2), (0, 0), indexing='ij') >>> g.get_cell_count () 2 >>> g.get_point_count () 6 Add some data at the points of our grid. >>> data = np.arange (6) >>> g.add_field ('var0', data, centering='point') >>> g.get_field ('var0') array([0, 1, 2, 3, 4, 5]) The data can be given either as a 1D array or with the same shape as the point grid. In either case, though, it will be flattened. >>> data = np.arange (6) >>> data.shape = (2, 3) >>> g.add_field ('var0', data, centering='point') >>> g.get_field ('var0') array([0, 1, 2, 3, 4, 5]) If the size or shape doesn't match, it's an error. >>> data = np.arange (2) >>> g.add_field ('bad var', data, centering='point') # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... DimensionError: 2 != 6 >>> data = np.ones ((3, 2)) >>> g.add_field ('bad var', data, centering='point') # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... DimensionError: (3, 2) != (2, 3) Add data to the cells of the grid. Again, the data can be given as a 1D array or with the same shape as the cell grid and if the size or shape doesn't match raise an exception. >>> data = np.arange (2) >>> g.add_field('var1', data, centering='zonal') >>> g.get_field('var1') array([0, 1]) >>> data = np.ones((2, 1)) >>> g.add_field('bad var', data, centering='zonal') # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... DimensionError: (2, 1) != (1, 2) >>> data = np.arange(3) >>> g.add_field('bad var', data, centering='zonal') # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... DimensionError: 3 != 2 >>> data = np.array(3) >>> g.add_field('bad var', data, centering='zonal') # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... DimensionError: 1 != 2 A 1D-Field, >>> g = RasterField ((6, ), (1.5, ), (0.5, ), indexing='ij') >>> g.get_point_count () 6 >>> g.get_cell_count () 5 >>> point_data = np.arange (6.) >>> g.add_field ('Point Data', point_data, centering='point') >>> cell_data = np.arange (5.)*10. >>> g.add_field ('Cell Data', cell_data, centering='zonal') >>> g.get_field ('Cell Data') array([ 0., 10., 20., 30., 40.]) >>> g.get_field ('Point Data') array([ 0., 1., 2., 3., 4., 5.]) A 3D-Field, >>> g = RasterField ((4, 3, 2), (1.5, 1., 3), (0.5, 0, -.5 ), indexing='ij') >>> g.get_point_count () 24 >>> g.get_cell_count () 6 >>> g.add_field ('Point Data', g.get_x (), centering='point') >>> cell_data = np.arange (6.)*10. >>> g.add_field ('Cell Data', cell_data, centering='zonal') >>> g.get_field ('Cell Data') array([ 0., 10., 20., 30., 40., 50.]) >>> g.get_field('Point Data') array([-0.5, 2.5, -0.5, 2.5, -0.5, 2.5, -0.5, 2.5, -0.5, 2.5, -0.5, 2.5, -0.5, 2.5, -0.5, 2.5, -0.5, 2.5, -0.5, 2.5, -0.5, 2.5, -0.5, 2.5]) >>> g.get_shape() array([4, 3, 2]) >>> g.get_x().size == g.get_field('Point Data').size True >>> x = g.get_x() >>> x.shape (24,) >>> x.shape = g.get_shape() >>> x.shape (4, 3, 2) """ pass
if __name__ == "__main__": import doctest doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE)