Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hook up Caching #175

Merged
merged 26 commits into from
Nov 30, 2018
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c902a6b
initial node_eval / node output caching decorator
jmilloy Nov 26, 2018
403c455
Renaming cache_output to node_eval and adding imports.
mpu-creare Nov 27, 2018
4d90ca2
BUGFIX: Fixing typos and missing imports.
mpu-creare Nov 27, 2018
fbe7183
Merge branch 'develop' into feature/eval_decorator
mpu-creare Nov 27, 2018
38445bb
BUGFIX: transform --> transpose. Also adding DEBUG to settings.py.
mpu-creare Nov 27, 2018
26d59c0
BUGFIX: Fixing typos and wrong syntax.
mpu-creare Nov 27, 2018
9268a76
BUGFIX: Removing the 'method' parameter'
mpu-creare Nov 27, 2018
6625025
BUGFIXES: Removed a few more methods. Had to rework part of the algor…
mpu-creare Nov 27, 2018
ef975a7
ENH: Making the ROOT_PATH for podpac storage to be ~/.podpac
mpu-creare Nov 27, 2018
6646db5
ENH: Initial caching working.
mpu-creare Nov 27, 2018
ae709ed
BUGFIX: Moving around where the utf-8 encoding happens so that None c…
mpu-creare Nov 27, 2018
be5125d
TESTFIX: hashlib doesn't hash None
mpu-creare Nov 27, 2018
64c1043
BUGFIX: makedirs still throwing an error for the settings file. This …
mpu-creare Nov 27, 2018
3f72aab
BUGFIX: Typo on previous commit. Brackets.
mpu-creare Nov 27, 2018
bc7aa97
BUGFIX: Fixing Python 2 with usage of os.makedirs(ok_exist) parameter.
mpu-creare Nov 27, 2018
b4965b2
ENH: Further stabilizing hashes for caching using hashlib instead of …
mpu-creare Nov 27, 2018
b373cee
ENH: Making SMAP robust to offline usage.
mpu-creare Nov 27, 2018
8874dfe
BUG: Fixing various bugs for the downscaling demo.
mpu-creare Nov 29, 2018
5b4af0f
ENH: Removing Deprecated caching methods from Node.
mpu-creare Nov 29, 2018
be9ed01
ENH: Making SMAP_BASE_URL checking lazy, so we don't get a warning at…
mpu-creare Nov 29, 2018
ab36032
BUGFIX: cache_dir has been removed. So WCS and S3 nodes now have to u…
mpu-creare Nov 29, 2018
19554a3
BUGFIX: Indentation error from last commit.
mpu-creare Nov 29, 2018
96b2e2a
BUGFIX: podpac.settings --> settings. Trying to fix things too rapidl…
mpu-creare Nov 29, 2018
cdb6764
ENH: renaming decorator. Fixing filepath sanitization.
mpu-creare Nov 30, 2018
093809e
BUG: Fixing file path sanitization again.
mpu-creare Nov 30, 2018
0cd6257
TESTFIX: Fixing unit tests with renamed decorator.
mpu-creare Nov 30, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions podpac/core/algorithm/algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from podpac.core.units import UnitsDataArray
from podpac.core.node import Node
from podpac.core.node import COMMON_NODE_DOC
from podpac.core.node import node_eval
from podpac.core.utils import common_doc

COMMON_DOC = COMMON_NODE_DOC.copy()
Expand Down Expand Up @@ -51,6 +52,7 @@ def _inputs(self):
}

@common_doc(COMMON_DOC)
@node_eval
def eval(self, coordinates, output=None):
"""Evalutes this nodes using the supplied coordinates.

Expand Down Expand Up @@ -79,16 +81,15 @@ def eval(self, coordinates, output=None):
result = self.algorithm(inputs)
if isinstance(result, np.ndarray):
if output is None:
output = self.create_output_array(output_coordinates)
output.data[:] = result
output = self.create_output_array(output_coordinates, data=result)
else:
output.data[:] = result
else:
if output is None:
output_coordinates = Coordinates.from_xarray(result.coords)
output = self.create_output_array(output_coordinates)
output[:] = result
output = output.transpose(*[dim for dim in coordinates.dims if dim in result.dims])
output = result
else:
output[:] = result

self._output = output
return output

def find_coordinates(self):
Expand Down
38 changes: 14 additions & 24 deletions podpac/core/algorithm/coord_select.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,6 @@ class ModifyCoordinates(Algorithm):
@tl.default('coordinates_source')
def _default_coordinates_source(self):
return self.source

def algorithm(self, inputs):
"""Passthrough of the source data

Arguments
----------
inputs : dict
Evaluated output of the input nodes. The keys are the attribute names.

Returns
-------
UnitDataArray
Source evaluated at the expanded coordinates
"""
return inputs['source']

@common_doc(COMMON_DOC)
def eval(self, coordinates, output=None):
Expand All @@ -79,18 +64,23 @@ def eval(self, coordinates, output=None):
"""

self._requested_coordinates = coordinates

modified_coordinates = Coordinates(
self.outputs = {}
self._modified_coordinates = Coordinates(
[self.get_modified_coordinates1d(coordinates, dim) for dim in coordinates.dims])
for dim in modified_coordinates.udims:
if modified_coordinates[dim].size == 0:

for dim in self._modified_coordinates.udims:
if self._modified_coordinates[dim].size == 0:
raise ValueError("Modified coordinates do not intersect with source data (dim '%s')" % dim)
output = super(ModifyCoordinates, self).eval(modified_coordinates, output=output)

# debugging
self._modified_coordinates = modified_coordinates
self._output = output
self.outputs['source'] = self.source.eval(self._modified_coordinates, output=output, method=method)

if output is None:
output = self.outputs['source']
else:
output[:] = self.outputs['source']

if self.debug:
self._output = output
return output

class ExpandCoordinates(ModifyCoordinates):
Expand Down Expand Up @@ -207,4 +197,4 @@ def get_modified_coordinates1d(self, coords, dim):
else:
raise ValueError("Invalid selection attrs for '%s'" % dim)

return coords1d
return coords1d
50 changes: 18 additions & 32 deletions podpac/core/algorithm/signal.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from podpac.core.node import Node
from podpac.core.algorithm.algorithm import Algorithm
from podpac.core.utils import common_doc
from podpac.core.node import COMMON_NODE_DOC
from podpac.core.node import COMMON_NODE_DOC, node_eval

COMMON_DOC = COMMON_NODE_DOC.copy()
COMMON_DOC['full_kernel'] = '''Kernel that contains all the dimensions of the input source, in the correct order.
Expand Down Expand Up @@ -77,6 +77,7 @@ class Convolution(Algorithm):
_full_kernel = tl.Instance(np.ndarray)

@common_doc(COMMON_DOC)
@node_eval
def eval(self, coordinates, output=None):
"""Evaluates this nodes using the supplied coordinates.

Expand All @@ -91,20 +92,18 @@ def eval(self, coordinates, output=None):
-------
{eval_return}
"""
self._requested_coordinates = coordinates

# This should be aligned with coordinates' dimension order
# The size of this kernel is used to figure out the expanded size
self._full_kernel = self.get_full_kernel(coordinates)
shape = self._full_kernel.shape

if len(shape) != len(coordinates.shape):
raise ValueError("Kernel shape does not match source data shape")
if len(self._full_kernel.shape) != len(coordinates.shape):
raise ValueError("shape mismatch, kernel does not match source data (%s != %s)" % (
self._full_kernel.shape, coordinates.shape))

# expand the coordinates
exp_coords = []
exp_slice = []
for dim, s in zip(coordinates.dims, shape):
for dim, s in zip(coordinates.dims, self._full_kernel.shape):
coord = coordinates[dim]
if s == 1 or not isinstance(coord, UniformCoordinates1d):
exp_coords.append(coord)
Expand All @@ -121,8 +120,19 @@ def eval(self, coordinates, output=None):
coord.step,
**coord.properties))
exp_slice.append(slice(-s_start, -s_end))
exp_coords = Coordinates(exp_coords)
exp_slice = tuple(exp_slice)
self._expanded_coordinates = Coordinates(exp_coords)

# evaluate source using expanded coordinates, convolve, and then slice out original coordinates
self.outputs['source'] = self.source.eval(self._expanded_coordinates, method=method)

if np.isnan(np.max(self.outputs['source'])):
method = 'direct'
else:
method = 'auto'

result = scipy.signal.convolve(self.outputs['source'], self._full_kernel, mode='same', method=method)
result = result[exp_slice]

# evaluate using expanded coordinates and then reduce down to originally requested coordinates
out = super(Convolution, self).eval(exp_coords)
Expand All @@ -132,10 +142,6 @@ def eval(self, coordinates, output=None):
else:
output[:] = result

# debugging
self._expanded_coordinates = exp_coords
self._output = output

return output

@tl.default('kernel')
Expand Down Expand Up @@ -163,26 +169,6 @@ def get_full_kernel(self, coordinates):
"""
return self.kernel

def algorithm(self, inputs):
"""Computes the convolution of the source and the kernel

Arguments
----------
inputs : dict
evaluated outputs of the input nodes. The keys are the attribute names.

Returns
-------
np.ndarray
Resultant array.
"""
if np.isnan(np.max(inputs['source'])):
method = 'direct'
else:
method = 'auto'
res = scipy.signal.convolve(inputs['source'], self._full_kernel, mode='same', method=method)
return res


class TimeConvolution(Convolution):
"""Compute a temporal convolution over a source node.
Expand Down
8 changes: 4 additions & 4 deletions podpac/core/algorithm/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from podpac.core.node import Node
from podpac.core.algorithm.algorithm import Algorithm
from podpac.core.utils import common_doc
from podpac.core.node import COMMON_NODE_DOC
from podpac.core.node import COMMON_NODE_DOC, node_eval

COMMON_DOC = COMMON_NODE_DOC.copy()

Expand Down Expand Up @@ -162,6 +162,7 @@ def iteroutputs(self, coordinates):
yield self.source.eval(chunk)

@common_doc(COMMON_DOC)
@node_eval
def eval(self, coordinates, output=None):
"""Evaluates this nodes using the supplied coordinates.

Expand Down Expand Up @@ -204,7 +205,6 @@ def eval(self, coordinates, output=None):
else:
output[:] = result

self._output = output
return output

def reduce(self, x):
Expand Down Expand Up @@ -907,6 +907,7 @@ def _get_source_coordinates(self, requested_coordinates):
return coords

@common_doc(COMMON_DOC)
@node_eval
def eval(self, coordinates, output=None):
"""Evaluates this nodes using the supplied coordinates.

Expand All @@ -926,7 +927,7 @@ def eval(self, coordinates, output=None):
ValueError
If source it not time-depended (required by this node).
"""
self._requested_coordinates = coordinates

self._source_coordinates = self._get_source_coordinates(coordinates)

if output is None:
Expand All @@ -950,7 +951,6 @@ def eval(self, coordinates, output=None):
out = out.sel(**{self.groupby:E}).rename({self.groupby: 'time'})
output[:] = out.transpose(*output.dims).data

self._output = output
return output

def base_ref(self):
Expand Down
5 changes: 3 additions & 2 deletions podpac/core/compositor.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from podpac.core.coordinates import Coordinates, merge_dims
from podpac.core.node import Node
from podpac.core.utils import common_doc
from podpac.core.node import COMMON_NODE_DOC
from podpac.core.node import node_eval
from podpac.core.data.datasource import COMMON_DATA_DOC
from podpac.core.data.interpolate import interpolation_trait
from podpac.core.utils import trait_is_defined
Expand Down Expand Up @@ -200,6 +202,7 @@ def f(src):
yield output
output[:] = np.nan

@node_eval
@common_doc(COMMON_COMPOSITOR_DOC)
def eval(self, coordinates, output=None):
"""Evaluates this nodes using the supplied coordinates.
Expand All @@ -220,8 +223,6 @@ def eval(self, coordinates, output=None):

outputs = self.iteroutputs(coordinates)
output = self.composite(outputs, output)

self._output = output
return output

def find_coordinates(self):
Expand Down
12 changes: 9 additions & 3 deletions podpac/core/data/datasource.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from podpac.core.node import Node, NodeException
from podpac.core.utils import common_doc, trait_is_defined
from podpac.core.node import COMMON_NODE_DOC
from podpac.core.node import node_eval
from podpac.core.data.interpolate import Interpolation, interpolation_trait

DATA_DOC = {
Expand Down Expand Up @@ -166,7 +167,7 @@ class DataSource(Node):
# privates
_interpolation = tl.Instance(Interpolation)

_evaluated_coordinates = tl.Instance(Coordinates, allow_none=True)
_original_requested_coordinates = tl.Instance(Coordinates, allow_none=True)
_requested_source_coordinates = tl.Instance(Coordinates)
_requested_source_coordinates_index = tl.List()
_requested_source_data = tl.Instance(UnitsDataArray)
Expand Down Expand Up @@ -272,6 +273,10 @@ def eval(self, coordinates, output=None):
if self.coordinate_index_type != 'numpy':
warnings.warn('Coordinates index type {} is not yet supported.'.format(self.coordinate_index_type) +
'`coordinate_index_type` is set to `numpy`', UserWarning)

# store requested coordinates for debugging
if self.debug:
self._original_requested_coordinates = coordinates

# check for missing dimensions
for c in self.native_coordinates.values():
Expand All @@ -296,7 +301,10 @@ def eval(self, coordinates, output=None):
# set input coordinates to evaluated coordinates
# TODO move this if WCS can be updated to support
self._evaluated_coordinates = coordinates
return self._eval(coordinates, output=output, method=None)

@node_eval
def _eval(self, coordinates, output=None):
# intersect the native coordinates with requested coordinates
# to get native coordinates within requested coordinates bounds
# TODO: support coordinate_index_type parameter to define other index types
Expand All @@ -309,8 +317,6 @@ def eval(self, coordinates, output=None):
output = self.create_output_array(coordinates)
else:
output[:] = np.nan

self._output = output
return output

# reset interpolation
Expand Down
8 changes: 4 additions & 4 deletions podpac/core/data/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -804,14 +804,14 @@ def native_coordinates(self):
data wrangling for us...
"""

# TODO update so that we don't rely on _evaluated_coordinates
if not self._evaluated_coordinates:
# TODO update so that we don't rely on _requested_coordinates if possible
if not self._requested_coordinates:
return self.wcs_coordinates

cs = []
for dim in self.wcs_coordinates.dims:
if dim in self._evaluated_coordinates.dims:
c = self._evaluated_coordinates[dim]
if dim in self._requested_coordinates.dims:
c = self._requested_coordinates[dim]
if c.size == 1:
cs.append(ArrayCoordinates1d(c.coordinates[0], name=dim))
elif isinstance(c, UniformCoordinates1d):
Expand Down
Loading