Skip to content

Commit

Permalink
Merge b878b07 into 6963ffb
Browse files Browse the repository at this point in the history
  • Loading branch information
mpu-creare committed Apr 8, 2021
2 parents 6963ffb + b878b07 commit 7410bac
Show file tree
Hide file tree
Showing 84 changed files with 2,093 additions and 2,700 deletions.
2 changes: 1 addition & 1 deletion doc/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ Classes to manage interpolation
podpac.interpolators.Interpolator
podpac.interpolators.NearestNeighbor
podpac.interpolators.NearestPreview
podpac.interpolators.Rasterio
podpac.interpolators.RasterioInterpolator
podpac.interpolators.ScipyGrid
podpac.interpolators.ScipyPoint

Expand Down
2 changes: 1 addition & 1 deletion doc/source/interpolation.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ The first item in the list will be interpolated first. In this case, `lat`/`lon`
The list of available interpolators are as follows:
* `NearestNeighbor`: A custom implementation based on `scipy.cKDtree`, which handles nearly any combination of source and destination coordinates
* `XarrayInterpolator`: A light-weight wrapper around `xarray`'s `DataArray.interp` method, which is itself a wrapper around `scipy` interpolation functions, but with a clean `xarray` interface
* `Rasterio`: A wrapper around `rasterio`'s interpolation/reprojection routines. Appropriate for grid-to-grid interpolation.
* `RasterioInterpolator`: A wrapper around `rasterio`'s interpolation/reprojection routines. Appropriate for grid-to-grid interpolation.
* `ScipyGrid`: An optimized implementation for `grid` sources that uses `scipy`'s `RegularGridInterpolator`, or `RectBivariateSplit` interpolator depending on the method.
* `ScipyPoint`: An implementation based on `scipy.KDtree` capable of `nearest` interpolation for `point` sources
* `NearestPreview`: An approximate nearest-neighbor interpolator useful for rapidly viewing large files
Expand Down
3 changes: 1 addition & 2 deletions podpac/compositor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@
# REMINDER: update api docs (doc/source/user/api.rst) to reflect changes to this file

from podpac.core.compositor.ordered_compositor import OrderedCompositor
from podpac.core.compositor.tile_compositor import UniformTileCompositor, UniformTileMixin, TileCompositor
from podpac.core.compositor.data_compositor import DataCompositor
from podpac.core.compositor.tile_compositor import TileCompositor, TileCompositorRaw
60 changes: 27 additions & 33 deletions podpac/core/algorithm/algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,17 @@ class Algorithm(BaseAlgorithm):
Developers of new Algorithm nodes need to implement the `algorithm` method.
"""

def algorithm(self, inputs):
def algorithm(self, inputs, coordinates):
"""
Arguments
----------
inputs : dict
Evaluated outputs of the input nodes. The keys are the attribute names.
Raises
------
NotImplementedError
Description
Evaluated outputs of the input nodes. The keys are the attribute names. Each item is a `UnitsDataArray`.
coordinates : podpac.Coordinates
Requested coordinates.
Note that the ``inputs`` may contain different coordinates than the requested coordinates
"""

raise NotImplementedError

@common_doc(COMMON_DOC)
Expand Down Expand Up @@ -128,33 +127,28 @@ def f(node):
inputs[key] = node.eval(coordinates, output=output, _selector=_selector)
self._multi_threaded = False

# accumulate output coordinates
coords_list = [Coordinates.from_xarray(a.coords, crs=a.attrs.get("crs")) for a in inputs.values()]
output_coordinates = union([coordinates] + coords_list)

result = self.algorithm(inputs)
if isinstance(result, UnitsDataArray):
if output is None:
output = result
else:
output[:] = result.data[:]
elif isinstance(result, xr.DataArray):
if output is None:
output = self.create_output_array(
Coordinates.from_xarray(result.coords, crs=result.attrs.get("crs")), data=result.data
)
else:
output[:] = result.data
elif isinstance(result, np.ndarray):
if output is None:
output = self.create_output_array(output_coordinates, data=result)
else:
output.data[:] = result
else:
raise NodeException
result = self.algorithm(inputs, coordinates)

if "output" in output.dims and self.output is not None:
output = output.sel(output=self.output)
if not isinstance(result, xr.DataArray):
raise NodeException("algorithm returned unsupported type '%s'" % type(result))

if "output" in result.dims and self.output is not None:
result = result.sel(output=self.output)

if output is not None:
missing = [dim for dim in result.dims if dim not in output.dims]
if any(missing):
raise NodeException("provided output is missing dims %s" % missing)

output_dims = output.dims
output = output.transpose(..., *result.dims)
output[:] = result.data
output = output.transpose(*output_dims)
elif isinstance(result, UnitsDataArray):
output = result
else:
output_coordinates = Coordinates.from_xarray(result)
output = self.create_output_array(output_coordinates, data=result.data)

return output

Expand Down
64 changes: 54 additions & 10 deletions podpac/core/algorithm/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

ne = lazy_module("numexpr")

# Internal dependencies
from podpac import settings
from podpac import Coordinates
from podpac.core.node import Node
from podpac.core.utils import NodeTrait
from podpac.core.algorithm.algorithm import Algorithm
Expand Down Expand Up @@ -81,18 +81,21 @@ def init(self):

super(Arithmetic, self).init()

def algorithm(self, inputs):
def algorithm(self, inputs, coordinates):
"""Compute the algorithms equation
Attributes
----------
inputs : dict
Evaluated outputs of the input nodes. The keys are the attribute names.
coordinates : podpac.Coordinates
Requested coordinates.
Note that the ``inputs`` may contain with different coordinates.
Returns
-------
UnitsDataArray
Description
result : UnitsDataArray
Algorithm result.
"""

if not settings.allow_unsafe_eval:
Expand Down Expand Up @@ -154,7 +157,24 @@ def init(self):
)
super(Generic, self).init()

def algorithm(self, inputs):
def algorithm(self, inputs, coordinates):
"""
Run the generic code.
Attributes
----------
inputs : dict
Evaluated outputs of the input nodes. The keys are the attribute names.
coordinates : podpac.Coordinates
Requested coordinates.
Note that the ``inputs`` may contain with different coordinates.
Returns
-------
result : UnitsDataArray
Algorithm result.
"""

if not settings.allow_unsafe_eval:
raise PermissionError(
"Insecure evaluation of Python code using Generic node has not been allowed. If this "
Expand All @@ -167,7 +187,10 @@ def algorithm(self, inputs):


class Mask(Algorithm):
"""Masks the `source` based on a boolean expression involving the `mask` (i.e. source[mask <bool_op> <bool_val> ] = <masked_val>). For a normal boolean mask input, default values for `bool_op`, `bool_val` and `masked_val` can be used.
"""
Masks the `source` based on a boolean expression involving the `mask`
(i.e. source[mask <bool_op> <bool_val> ] = <masked_val>).
For a normal boolean mask input, default values for `bool_op`, `bool_val` and `masked_val` can be used.
Attributes
----------
Expand Down Expand Up @@ -213,8 +236,24 @@ class Mask(Algorithm):

_repr_keys = ["source", "mask"]

def algorithm(self, inputs):
"""Sets the values in inputs['source'] to self.masked_val using (inputs['mask'] <self.bool_op> <self.bool_val>)"""
def algorithm(self, inputs, coordinates):
"""
Sets the values in inputs['source'] to self.masked_val using (inputs['mask'] <self.bool_op> <self.bool_val>)
Attributes
----------
inputs : dict
Evaluated outputs of the input nodes. The keys are the attribute names.
coordinates : podpac.Coordinates
Requested coordinates.
Note that the ``inputs`` may contain with different coordinates.
Returns
-------
result : UnitsDataArray
Algorithm result.
"""

# shorter names
mask = inputs["mask"]
source = inputs["source"]
Expand Down Expand Up @@ -257,5 +296,10 @@ def _default_outputs(self):
input_keys = list(self.inputs.keys())
return input_keys

def algorithm(self, inputs):
return np.stack([inputs[key] for key in self.inputs], axis=-1)
def algorithm(self, inputs, coordinates):
cs = [Coordinates.from_xarray(x) for x in inputs.values()]
if any(c != cs[0] for c in cs):
raise NodeException("Cannot combine inputs with different coordinates")

data = np.stack([inputs[key] for key in self.inputs], axis=-1)
return self.create_output_array(cs[0], data=data)
23 changes: 10 additions & 13 deletions podpac/core/algorithm/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -938,19 +938,19 @@ class ResampleReduce(UnaryAlgorithm):
----------
custom_reduce_fn : function
required if reduce_fn is 'custom'.
resampleby : str
resample : str
datetime sub-accessor. Currently 'dayofyear' is the enabled option.
reduce_fn : str
builtin xarray groupby reduce function, or 'custom'.
source : podpac.Node
Source node
"""

_repr_keys = ["source", "resampleby", "reduce_fn"]
_repr_keys = ["source", "resample", "reduce_fn"]
coordinates_source = NodeTrait(allow_none=True).tag(attr=True)

# see https://github.com/pydata/xarray/blob/eeb109d9181c84dfb93356c5f14045d839ee64cb/xarray/core/accessors.py#L61
resample = tl.Unicode().tag(attr=True) # could add season, month, etc
resample = tl.Unicode().tag(attr=True)
reduce_fn = tl.CaselessStrEnum(_REDUCE_FUNCTIONS).tag(attr=True)
custom_reduce_fn = tl.Any(allow_none=True, default_value=None).tag(attr=True)

Expand Down Expand Up @@ -980,7 +980,7 @@ def _eval(self, coordinates, output=None, _selector=None):
Raises
------
ValueError
If source it not time-depended (required by this node).
If source it not time-dependent (required by this node).
"""

source_output = self.source.eval(coordinates, _selector=_selector)
Expand All @@ -996,11 +996,8 @@ def _eval(self, coordinates, output=None, _selector=None):
out = getattr(grouped, self.reduce_fn)()

if output is None:
coords = podpac.coordinates.merge_dims(
[coordinates.drop("time"), Coordinates([out.coords["time"]], ["time"])]
)
coords = coords.transpose(*out.dims)
output = self.create_output_array(coords, data=out.data)
output = podpac.UnitsDataArray(out)
output.attrs = source_output.attrs
else:
output.data[:] = out.data[:]

Expand Down Expand Up @@ -1080,7 +1077,7 @@ class DayOfYearWindow(Algorithm):
scale_float = tl.List(default_value=None, allow_none=True).tag(attr=True)
rescale = tl.Bool(False).tag(attr=True)

def algorithm(self, inputs):
def algorithm(self, inputs, coordinates):
win = self.window // 2
source = inputs["source"]

Expand All @@ -1106,12 +1103,12 @@ def algorithm(self, inputs):
source.data[(source.data < 0) | (source.data > 1)] = np.nan

# Make the output coordinates with day-of-year as time
coords = xr.Dataset({"time": self._requested_coordinates["time"].coordinates})
coords = xr.Dataset({"time": coordinates["time"].coordinates})
dsdoy = np.sort(np.unique(coords.time.dt.dayofyear))
latlon_coords = self._requested_coordinates.drop("time")
latlon_coords = coordinates.drop("time")
time_coords = podpac.Coordinates([dsdoy], ["time"])
coords = podpac.coordinates.merge_dims([latlon_coords, time_coords])
coords = coords.transpose(*self._requested_coordinates.dims)
coords = coords.transpose(*coordinates.dims)
output = self.create_output_array(coords)

# if all-nan input, no need to calculate
Expand Down

0 comments on commit 7410bac

Please sign in to comment.