Source code for simphony_mayavi.core.cuba_data_accumulator

import warnings

import numpy

from simphony.testing.utils import dummy_cuba_value


[docs]class CUBADataAccumulator(object): """ Accumulate data information per CUBA key. A collector object that stores :class:``DataContainer`` data into a list of values per CUBA key. By appending :class:`DataContainer` instanced the user can effectively convert the per item mapping of data values in a CUDS container to a per CUBA key mapping of the data values (useful for coping data to vtk array containers). The Accumulator has two modes of operation ``fixed`` and ``expand``. ``fixed`` means that data will be stored for a predefined set of keys on every ``append`` call and missing values will be saved as ``None``. Where ``expand`` will extend the internal table of values whenever a new key is introduced. .. rubric:: expand operation >>> accumulator = CUBADataAccumulator(): >>> accumulator.append(DataContainer(TEMPERATURE=34)) >>> accumulator.keys() {CUBA.TEMPERATURE} >>> accumulator.append(DataContainer(VELOCITY=(0.1, 0.1, 0.1)) >>> accumulator.append(DataContainer(TEMPERATURE=56)) >>> accumulator.keys() {CUBA.TEMPERATURE, CUBA.VELOCITY} >>> accumulator[CUBA.TEMPERATURE] [34, None, 56] >>> accumulator[CUBA.VELOCITY] [None, (0.1, 0.1, 0.1), None] .. rubric:: fixed operation >>> accumulator = CUBADataAccumulator([CUBA.TEMPERATURE, CUBA.PRESSURE]): >>> accumulator.keys() {CUBA.TEMPERATURE, CUBA.PRESSURE} >>> accumulator.append(DataContainer(TEMPERATURE=34)) >>> accumulator.append(DataContainer(VELOCITY=(0.1, 0.1, 0.1)) >>> accumulator.append(DataContainer(TEMPERATURE=56)) >>> accumulator.keys() {CUBA.TEMPERATURE, CUBA.PRESSURE} >>> accumulator[CUBA.TEMPERATURE] [34, None, 56] >>> accumulator[CUBA.PRESSURE] [None, None, None] >>> accumulator[CUBA.VELOCITY] KeyError(...) """ def __init__(self, keys=None): """Constructor Parameters ---------- keys : list The list of keys that the accumulator should care about. Providing this value at initialisation sets up the accumulator to operate in ``fixed`` mode. An empty list is acceptable, and returns a trivial accumulator providing no data. If None is passed, then the accumulator operates in ``expand`` mode. """ self._expand_mode = keys is None keys = keys if keys is not None else () self._keys = set(keys) self._data = {} self._record_size = 0 self._expand(self._keys) @property def keys(self): """ The set of CUBA keys that this accumulator contains. """ return set(self._keys)
[docs] def append(self, data): """ Append info from a ``DataContainer``. Parameters ---------- data : DataContainer The data information to append. If the accumulator operates in ``fixed`` mode: - Any keys in :code:`self.keys()` that have values in ``data`` will be stored (appended to the related key lits). - Missing keys will be stored as ``None`` If the accumulator operates in ``expand`` mode: - Any new keys in `Data` will be added to the :code:`self.keys()` list and the related list of values with length equal to the current record size will be initialised with values of ``None``. - Any keys in the modified :code:`self.keys()` that have values in ``data`` will be stored (appended to the list of the related key). - Missing keys will be store as ``None``. """ if self._expand_mode: new_keys = set(data.keys()) - self._keys self._keys.update(new_keys) self._expand(new_keys) for key in self._keys: self._data[key].append(data.get(key, None)) self._record_size += 1
[docs] def load_onto_vtk(self, vtk_data): """ Load the stored information onto a vtk data container. Parameters ---------- vtk_data : vtkPointData or vtkCellData The vtk container to load the value onto. Data are loaded onto the vtk container based on their data type. The name of the added array is the name of the CUBA key (i.e. :samp:`{CUBA}.name`). Currently only scalars and three dimensional vectors are supported. """ def replacer(data): return nan if data is None else data for cuba in self.keys: default = dummy_cuba_value(cuba) if (numpy.issubdtype(type(default), numpy.float) or numpy.issubdtype(type(default), numpy.int)): data = numpy.array(self._data[cuba], dtype=float) index = vtk_data.add_array(data) vtk_data.get_array(index).name = cuba.name elif isinstance(default, numpy.ndarray) and default.size == 3: nan = numpy.array([None, None, None], dtype=float) data = numpy.array( tuple(replacer(data) for data in self._data[cuba]), dtype=numpy.float) index = vtk_data.add_array(data) vtk_data.get_array(index).name = cuba.name else: message = 'property {!r} is currently ignored' warnings.warn(message.format(cuba))
[docs] def __len__(self): """ The number of values that are stored per key .. note:: Behaviour is temporary and will probably change soon. """ return self._record_size
[docs] def __getitem__(self, key): """ Get the list of accumulated values for the CUBA key. Parameters ---------- key : CUBA A CUBA Enum value Returns ------- result : list A list of data values collected for ``key``. Missing values are designated with ``None``. """ return self._data[key]
def _expand(self, keys): for key in keys: self._data[key] = [None] * self._record_size
def gather_cells( iterable, vtk_mapping, point2index, counter, accumulator): """ Gather the vtk cell information from an element iterator. Arguments --------- iterable : The Element iterable object vtk_mapping : dict The mapping from points number to tvtk.Cell type. point2index: dict The mapping from points uid to the index of the vtk points array. counter : itertools.count The counter object to use when evaluating the ``elements2index`` mapping. accumulator : CUBADataAccumulator The accumulator instance to use and collect the data information Returns ------- cells : list The cell point information encoded in a one dimensional list. cells_size : list The list of points number per cell. cells_types : list The list of cell types in sequence. element2index : dict The mapping from element uid to iteration index. """ cells = [] cells_size = [] cell_types = [] element2index = {} for element in iter(iterable): element2index[element.uid] = counter.next() npoints = len(element.points) cells_size.append(npoints + 1) cells.append(npoints) cells.extend(point2index[uid] for uid in element.points) cell_types.append(vtk_mapping[npoints]) accumulator.append(element.data) return cells, cells_size, cell_types, element2index