Source code for podpac.core.compositor.ordered_compositor

from __future__ import division, unicode_literals, print_function, absolute_import

import numpy as np
import traitlets as tl

from podpac.core.node import NodeException
from podpac.core.units import UnitsDataArray
from podpac.core.utils import common_doc
from podpac.core.compositor.compositor import COMMON_COMPOSITOR_DOC, BaseCompositor


[docs]@common_doc(COMMON_COMPOSITOR_DOC) class OrderedCompositor(BaseCompositor): """Compositor that combines sources based on their order in self.sources. The sources should generally be interpolated before being composited (i.e. not raw datasources). Attributes ---------- sources : list Source nodes, in order of preference. Later sources are only used where earlier sources do not provide data. source_coordinates : :class:`podpac.Coordinates` Coordinates that make each source unique. Must the same size as ``sources`` and single-dimensional. Optional. multithreading : bool, optional Default is True. If True, will always evaluate the compositor in serial, ignoring any MULTITHREADING settings """ multithreading = tl.Bool(False)
[docs] @common_doc(COMMON_COMPOSITOR_DOC) def composite(self, coordinates, data_arrays, result=None): """Composites data_arrays in order that they appear. Once a request contains no nans, the result is returned. Parameters ---------- coordinates : :class:`podpac.Coordinates` {requested_coordinates} data_arrays : generator Evaluated source data, in the same order as the sources. result : podpac.UnitsDataArray, optional {eval_output} Returns ------- {eval_return} This composites the sources together until there are no nans or no more sources. """ if result is None: result = self.create_output_array(coordinates) else: result[:] = np.nan mask = UnitsDataArray.create(coordinates, outputs=self.outputs, data=0, dtype=bool) for data in data_arrays: if self.outputs is None: try: data = data.transpose(*result.dims) except ValueError: raise NodeException( "Cannot evaluate compositor with requested dims %s. " "The compositor source dims are %s. " "Specify the compositor 'dims' attribute to ignore extra requested dims." % (coordinates.dims, data.dims) ) self._composite(result, data, mask) else: for name in data["output"]: self._composite(result.sel(output=name), data.sel(output=name), mask.sel(output=name)) # stop if the results are full if np.all(mask): break return result
@staticmethod def _composite(result, data, mask): source_mask = np.isfinite(data.data) b = ~mask & source_mask result.data[b.data] = data.data[b.data] mask |= source_mask