Source code for simphony_paraview.core.cuba_data_accumulator
import logging
import numpy
from paraview import vtk
from paraview.numpy_support import get_vtk_array_type, create_vtk_array
from simphony.core.cuba import CUBA
from .cuba_utils import supported_cuba, default_cuba_value
from .constants import cuba_value_types
logger = logging.getLogger(__name__)
[docs]class CUBADataAccumulator(object):
""" Accumulate data information per CUBA key.
A collector object that stores :class:``DataContainer`` data into
a vtkPointData or vtkCellData array containers where each CUBA key
is an array.
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. Where ``expand``
will extend the internal table of values whenever a new key is
introduced. Missing values will be stored using
:func:`~.default_cuba_value`.
.. rubric:: expand operation
>>> accumulator = CUBADataAccumulator():
>>> accumulator.append(DataContainer(TEMPERATURE=34))
>>> accumulator.keys
set([<CUBA.TEMPERATURE: 55>])
>>> accumulator.append(DataContainer(VELOCITY=(0.1, 0.1, 0.1))
>>> accumulator.append(DataContainer(TEMPERATURE=56))
>>> accumulator.keys
set([<CUBA.VELOCITY: 21>, <CUBA.TEMPERATURE: 55>])
>>> vtk_to_numpy(accumulator[CUBA.TEMPERATURE])
array([ 34., nan, 56.])
>>> vtk_to_numpy(accumulator[CUBA.VELOCITY])
array([[ nan, nan, nan], [ 0.1, 0.1, 0.1], [ nan, nan, nan]])
.. rubric:: fixed operation
>>> accumulator = CUBADataAccumulator([CUBA.TEMPERATURE, CUBA.PRESSURE])
>>> accumulator.keys
set([<CUBA.PRESSURE: 54>, <CUBA.TEMPERATURE: 55>])
>>> accumulator.append(DataContainer(TEMPERATURE=34))
>>> accumulator.append(DataContainer(VELOCITY=(0.1, 0.1, 0.1))
>>> accumulator.append(DataContainer(TEMPERATURE=56))
>>> accumulator.keys
set([<CUBA.PRESSURE: 54>, <CUBA.TEMPERATURE: 55>])
>>> vtk_to_numpy(accumulator[CUBA.TEMPERATURE])
array([ 34., nan, 56.])
>>> vtk_to_numpy(accumulator[CUBA.PRESSURE])
[nan, nan, nan]
>>> accumulator[CUBA.VELOCITY]
KeyError(...)
"""
def __init__(self, keys=(), container=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. If no keys are
provided then accumulator operates in ``expand`` mode.
"""
self.data = vtk.vtkPointData() if container is None else container
self._cuba_types = cuba_value_types()
self._number_of_items = 0
if len(keys) > 0:
self._keys = set(keys) & supported_cuba()
self._expand(self._keys)
else:
self._keys = supported_cuba()
self._expand_mode = len(keys) == 0
self._cubas = None
@property
def keys(self):
""" The set of CUBA keys that this accumulator contains.
"""
if self._cubas is None:
data = self.data
self._cubas = set(
CUBA[data.GetArray(index).GetName()]
for index in range(data.GetNumberOfArrays()))
return set(self._cubas)
[docs] def append(self, data):
"""Append data from a ``DataContainer``.
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 arrays).
- Missing keys will be stored with the
returned value of the :func:`~.default_cuba_value`.
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 the returned value of the :func:`~.default_cuba_value`.
- 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 stored with the
returned value of the :func:`~.default_cuba_value`.
Parameters
----------
data : DataContainer
The data information to append.
"""
if self._expand_mode:
new_keys = set(data.keys()) - self.keys & self._keys
self._expand(new_keys)
self._cubas = None
self._append(data)
self._number_of_items += 1
[docs] def __len__(self):
""" The number of values that are stored per key
"""
return self._number_of_items
[docs] def __getitem__(self, key):
""" Get the list of accumulated values for the CUBA key.
Parameters
----------
key : CUBA
A CUBA Enum value
Returns
-------
result : vtkDataArray
An array of data values collected for ``key``. Missing
values are assigned the default value as returned by
:function:`~.default_cuba_value`.
Raises
------
KeyError :
When values for the requested CUBA key do not exist.
"""
container = self.data
array = container.GetArray(key.name)
if array is None:
message = 'Could not find values stored for {}'
raise KeyError(message.format(key.name))
else:
return array
def _expand(self, cubas):
size = len(self)
for cuba in cubas:
default = default_cuba_value(cuba)
temp = numpy.asarray(default)
vtk_type = get_vtk_array_type(temp.dtype)
array = create_vtk_array(vtk_type)
array.SetNumberOfComponents(temp.size)
array.SetNumberOfTuples(size)
array.SetName(cuba.name)
for index, value in enumerate(temp.ravel()):
array.FillComponent(index, value)
self.data.AddArray(array)
def _append(self, data):
for cuba in self.keys:
default = default_cuba_value(cuba)
array = self[cuba]
value = data.get(cuba, default)
temp = numpy.asarray(value)
array.InsertNextTuple(temp.ravel())