""" YFilters pass an additional data array on filter instantenation that is used to modify the RGBA array Since we do not know, however, the order or subset of items """ import numpy as np from .filters import ColorFilter from .models import color_model from .utils import color, rgb class YFilter(ColorFilter): """ Class to modify data color array before returning based separate data array provided on initialisation. The filter takes as call arguments RGBA normalized to 0...1. When used as a _filter function, parameters must be passes by keyword. """ _filter = None def __init__(self, *args, **kwargs): kw = kwargs.copy() self._data = kwargs.pop('data') self._ndim = kwargs.pop('ndim', max(0, self._data.ndim - 2)) index = kw.get('index', None) if isinstance(index, np.ndarray): assert index.shape == self._data.shape[:self._ndim] else: self._index = np.arange(self._data.size, dtype=int64) if isinstance(index, list): index.append(self._index) elif isinstance(index, dict): index['index'] = self._index else: raise AttributeError('unknown index type') func = kw.pop('func', lambda x: x) if np.isscalar(func): self._func = lambda x : np.tile(func, x.shape) else: self._func = func self._data_func = kw.pop('data_func', lambda x: x) super().__init__(*args, **kw) @property def index(self): return self._index def _yfilter(self, rgba): """ take rgba, filter, replace data in place, return modified array """ raise NotImplementedError() def __call__(self, *args, **kwargs): # use as _yfilter print('[yfilter]', args[0].shape, self._data.shape) if (self._color is None and len(args) == 2 and len(kwargs) == 0 and isinstance(args[0], np.ndarray) and isinstance(self._data, np.ndarray) and len(args[0].shape) == 3 and args[0].shape[-1] == 4 and np.allclose(args[0].shape[:-1], self._data.shape[:2])): data = self._data_func(args[1]) return self._yfilter(*args), data print('[yfilter] Error: did not run.') return super().__call__(*args, **kwargs) class FuncAlphaYFilter(YFilter): """ set alpha based on data array """ def _yfilter(self, rgba): ii = (0 <= self._data) & (self._data <= 1) breakpoint() rgba[ii, 3] = np.clip(self._func(self._data[ii]), 0, 1) return rgba class FuncShadeYFilter(YFilter): """ Shade colors according to scalar data processed by function (default=identity) """ def _yfilter(self, rgba, data): print('xxx') breakpoint() ii = (0 <= self._data) & (self._data <= 1) rgba[ii, 0:3] = np.clip(rgba[ii, 0:3] * self._func(self._data[ii, np.newaxis]), 0, 1) return rgba