Skip to content

Commit

Permalink
Merge pull request #142 from descarteslabs/feat/values
Browse files Browse the repository at this point in the history
Feat/values
  • Loading branch information
samskillman authored Aug 11, 2017
2 parents 78cea85 + ffc57ec commit 4c8760f
Show file tree
Hide file tree
Showing 2 changed files with 222 additions and 1 deletion.
185 changes: 184 additions & 1 deletion descarteslabs/services/places.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
from cachetools import TTLCache, cachedmethod
from cachetools.keys import hashkey
from .service import Service
from six import string_types


class Places(Service):
TIMEOUT = (9.5, 120)
TIMEOUT = (9.5, 360)
"""Places and statistics service https://iam.descarteslabs.com/service/waldo"""

def __init__(self, url=None, token=None, maxsize=10, ttl=600):
Expand All @@ -47,6 +48,29 @@ def placetypes(self):
r = self.session.get('/placetypes')
return r.json()

def random(self, geom='low', placetype=None):
"""Get a random location
geom: string
Resolution for the shape [low (default), medium, high]
return: geojson
"""
params = {}

if geom:
params['geom'] = geom

if placetype:
params['placetype'] = placetype

r = self.session.get('%s/random' % self.url, params=params)

if r.status_code != 200:
raise RuntimeError("%s: %s" % (r.status_code, r.text))

return r.json()

@cachedmethod(operator.attrgetter('cache'), key=partial(hashkey, 'find'))
def find(self, path, **kwargs):
"""Find candidate slugs based on full or partial path.
Expand All @@ -70,6 +94,45 @@ def find(self, path, **kwargs):
r = self.session.get('/find/%s' % path, params=kwargs)
return r.json()

def search(self, q, country=None, region=None, placetype=None):
"""Search for shapes
:param q: A query string.
:param str country: Restrict search to a specific country
:param str region: Restrict search to a specific region
:param str placetype: Restrict search to a specific placetype
:return: list of candidates
Example::
>>> import descarteslabs as dl
>>> from pprint import pprint
>>> results = dl.places.search('texas')
>>> pprint(results[0])
{'bbox': [-106.645584, 25.837395, -93.508039, 36.50035],
'id': 85688753,
'name': 'Texas',
'placetype': 'region',
'slug': 'north-america_united-states_texas'}
"""
params = {}

if q:
params['q'] = q

if country:
params['country'] = country

if region:
params['region'] = region

if placetype:
params['placetype'] = placetype

r = self.session.get('/search', params=params, timeout=self.TIMEOUT)

return r.json()

@cachedmethod(operator.attrgetter('cache'), key=partial(hashkey, 'shape'))
def shape(self, slug, output='geojson', geom='low'):
"""Get the geometry for a specific slug
Expand Down Expand Up @@ -126,3 +189,123 @@ def prefix(self, slug, output='geojson', placetype=None, geom='low'):
r = self.session.get('/prefix/%s.%s' % (slug, output), params=params)

return r.json()

def sources(self):
"""Get a list of sources
"""
r = self.session.get('/sources', timeout=self.TIMEOUT)

return r.json()

def categories(self):
"""Get a list of categories
"""
r = self.session.get('/categories', timeout=self.TIMEOUT)

return r.json()

def metrics(self):
"""Get a list of metrics
"""
r = self.session.get('/metrics', timeout=self.TIMEOUT)

return r.json()

def data(self, slug, source=None, category=None, metric=None, date=None, placetype='county'):
"""Get all values for a prefix search and point in time
:param str slug: Slug identifier (or shape id).
:param str source: Source
:param str category: Category
:param str metric: Metric
:param str date: Date
:param str placetype: Restrict results to a particular place type.
"""
params = {}

if source:
params['source'] = source

if category:
params['category'] = category

if metric:
params['metric'] = metric

if date:
params['date'] = date

if placetype:
params['placetype'] = placetype

r = self.session.get('/data/%s' % (slug),
params=params, timeout=self.TIMEOUT)

return r.json()

def statistics(self, slug, source=None, category=None, metric=None):
"""Get a time series for a specific place
:param str slug: Slug identifier (or shape id).
:param str slug: Slug identifier (or shape id).
:param str source: Source
:param str category: Category
:param str metric: Metric
"""
params = {}

if source:
params['source'] = source

if category:
params['category'] = category

if metric:
params['metric'] = metric

r = self.session.get('/statistics/%s' % (slug),
params=params, timeout=self.TIMEOUT)

return r.json()

def value(self, slug, source=None, category=None, metric=None, date=None):
"""Get point values for a specific place
:param str slug: Slug identifier (or shape id).
:param list(str) source: Source(s)
:param list(str) category: Category(s)
:param list(str) metric: Metric(s)
:param str date: Date
"""
params = {}

if source:

if isinstance(source, string_types):
source = [source]

params['source'] = source

if category:

if isinstance(category, string_types):
category = [category]

params['category'] = category

if metric:

if isinstance(metric, string_types):
metric = [metric]

params['metric'] = metric

if date:
params['date'] = date

r = self.session.get('/value/%s' % (slug),
params=params, timeout=self.TIMEOUT)

return r.json()
38 changes: 38 additions & 0 deletions descarteslabs/tests/test_places.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,19 @@ def test_find(self):
r = self.instance.find('united-states_iowa')
self.assertEqual(1, len(r))

def test_search(self):
r = self.instance.search('texas')
self.assertEqual(8, len(r))

r = self.instance.search('texas', country='united-states')
self.assertEqual(7, len(r))

r = self.instance.search('texas', country='united-states', placetype='county')
self.assertEqual(2, len(r))

r = self.instance.search('texas', country='united-states', region='oklahoma', placetype='county')
self.assertEqual(1, len(r))

def test_shape(self):
r = self.instance.shape('north-america_united-states_iowa')
self.assertEqual(85688713, r['id'])
Expand All @@ -44,6 +57,31 @@ def test_prefix(self):
r = self.instance.prefix('north-america_united-states_iowa', placetype='district')
self.assertEqual(9, len(r['features']))

def test_sources(self):
r = self.instance.sources()
self.assertIn('nass', r)

def test_categories(self):
r = self.instance.categories()
self.assertIn('corn', r)

def test_metrics(self):
r = self.instance.metrics()
self.assertIn('yield', r)

def test_value(self):
r = self.instance.value('north-america_united-states', source='nass', category='corn', metric='yield')
self.assertEqual(1, len(r))

def test_statistics(self):
r = self.instance.statistics('north-america_united-states', source='nass', category='corn', metric='yield')
self.assertEqual(36, len(r))

def test_data(self):
r = self.instance.data('north-america_united-states', source='nass', category='corn', metric='yield',
date='2015-01-01')
self.assertEqual(1439, len(r))


if __name__ == '__main__':
unittest.main()

0 comments on commit 4c8760f

Please sign in to comment.