Skip to content

Commit 32095df

Browse files
authored
Merge pull request #46 from descarteslabs/feat/shapes
Breaks API, renames shapes/places/locations/geoms.
2 parents 1ba6d46 + 0f2f09f commit 32095df

File tree

6 files changed

+102
-51
lines changed

6 files changed

+102
-51
lines changed

descarteslabs/scripts/metadata

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ if __name__ == "__main__":
3030
parser.add_argument('argument', nargs='?')
3131

3232
parser.add_argument('-url', help='The url of the service')
33-
parser.add_argument('-shape', help='A slug for a named shape')
33+
parser.add_argument('-place', help='A slug for a named place')
3434
parser.add_argument('-const_id', default=None, help='Constellation ID', nargs='+')
3535
parser.add_argument('-start_time', help='Start of valid date/time range (inclusive)')
3636
parser.add_argument('-end_time', help='End of valid date/time range (inclusive)')
@@ -58,8 +58,8 @@ if __name__ == "__main__":
5858

5959
if args.command == 'summary':
6060

61-
if args.shape:
62-
kwargs['shape'] = args.shape
61+
if args.place:
62+
kwargs['place'] = args.place
6363
if args.const_id:
6464
kwargs['const_id'] = args.const_id
6565
if args.start_time:
@@ -79,8 +79,8 @@ if __name__ == "__main__":
7979

8080
if args.command == 'search':
8181

82-
if args.shape:
83-
kwargs['shape'] = args.shape
82+
if args.place:
83+
kwargs['place'] = args.place
8484
if args.const_id:
8585
kwargs['const_id'] = args.const_id
8686
if args.start_time:
@@ -104,8 +104,8 @@ if __name__ == "__main__":
104104

105105
if args.command == 'keys':
106106

107-
if args.shape:
108-
kwargs['shape'] = args.shape
107+
if args.place:
108+
kwargs['place'] = args.place
109109
if args.const_id:
110110
kwargs['const_id'] = args.const_id
111111
if args.start_time:

descarteslabs/scripts/places

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ if __name__ == "__main__":
2424

2525
parser = argparse.ArgumentParser()
2626

27-
parser.add_argument('command', choices=['find', 'shape', 'prefix', 'placetypes'],
27+
parser.add_argument('command', choices=['find', 'place', 'prefix', 'placetypes'],
2828
help='The action to take.')
2929
parser.add_argument('argument', nargs='?')
3030

descarteslabs/services/metadata.py

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ def sources(self):
4949

5050
return r.json()
5151

52-
def summary(self, const_id=None, date='acquired', part='day', shape=None, geom=None, start_time=None, end_time=None,
52+
def summary(self, const_id=None, date='acquired', part='day', place=None, geom=None, start_time=None, end_time=None,
5353
params=None, bbox=False, direct=False):
5454
"""Get a summary of the results for the specified spatio-temporal query.
5555
5656
:param list(str) const_id: Constellation identifier(s).
5757
:param str date: The date field to use for search (e.g. `acquired`).
5858
:param str part: Part of the date to aggregate over (e.g. `day`).
59-
:param str shape: A slug identifier to be used as a region of interest.
59+
:param str place: A slug identifier to be used as a region of interest.
6060
:param str geom: A GeoJSON or WKT region of interest.
6161
:param str start_time: Desired starting date and time (inclusive).
6262
:param str end_time: Desired ending date and time (inclusive).
@@ -65,7 +65,7 @@ def summary(self, const_id=None, date='acquired', part='day', shape=None, geom=N
6565
6666
Example usage::
6767
68-
>>> metadata.summary(shape='north-america_united-states_iowa',
68+
>>> metadata.summary(place='north-america_united-states_iowa',
6969
const_id=['L8'], part='year')
7070
7171
[{'bytes': 187707322653,
@@ -93,11 +93,15 @@ def summary(self, const_id=None, date='acquired', part='day', shape=None, geom=N
9393
'pixels': 18087390976}],
9494
'pixels': 367993294400}]
9595
"""
96-
if shape:
97-
waldo = Places()
98-
shape = waldo.shape(shape, geom='low')
96+
if place:
97+
places = Places()
98+
places.auth = self.auth
99+
shape = places.shape(place, geom='low')
99100
geom = json.dumps(shape['geometry'])
100101

102+
if isinstance(geom, dict):
103+
geom = json.dumps(geom)
104+
101105
kwargs = {}
102106

103107
if date:
@@ -143,14 +147,14 @@ def f(x):
143147

144148
return result
145149

146-
def search(self, const_id=None, date='acquired', shape=None, geom=None, start_time=None, end_time=None, params=None,
150+
def search(self, const_id=None, date='acquired', place=None, geom=None, start_time=None, end_time=None, params=None,
147151
limit=100, offset=0, bbox=False, direct=False):
148152
"""Search metadata given a spatio-temporal query. All parameters are
149153
optional. Results are paged using limit/offset.
150154
151155
:param list(str) const_id: Constellation identifier(s).
152156
:param str date: The date field to use for search (e.g. `acquired`).
153-
:param str shape: A slug identifier to be used as a region of interest.
157+
:param str place: A slug identifier to be used as a region of interest.
154158
:param str geom: A GeoJSON or WKT region of interest.
155159
:param str start_time: Desired starting date and time (inclusive).
156160
:param str end_time: Desired ending date and time (inclusive).
@@ -163,19 +167,21 @@ def search(self, const_id=None, date='acquired', shape=None, geom=None, start_ti
163167
164168
Example::
165169
166-
>>> scenes = metadata.search(shape='north-america_united-states_iowa', const_id=['L8'],
170+
>>> scenes = metadata.search(place='north-america_united-states_iowa', const_id=['L8'],
167171
start_time='2016-07-01', end_time='2016-07-31 23:59:59')
168172
len(scenes['features'])
169173
170174
34
171175
"""
172-
if shape:
173-
waldo = Places()
174-
175-
shape = waldo.shape(shape, geom='low')
176-
176+
if place:
177+
places = Places()
178+
places.auth = self.auth
179+
shape = places.shape(place, geom='low')
177180
geom = json.dumps(shape['geometry'])
178181

182+
if isinstance(geom, dict):
183+
geom = json.dumps(geom)
184+
179185
kwargs = {}
180186

181187
kwargs['limit'] = limit
@@ -215,14 +221,14 @@ def f(x):
215221

216222
return result
217223

218-
def keys(self, const_id=None, date='acquired', shape=None, geom=None, start_time=None, end_time=None, params=None,
224+
def keys(self, const_id=None, date='acquired', place=None, geom=None, start_time=None, end_time=None, params=None,
219225
limit=100, offset=0, bbox=False, direct=False):
220226
"""Search metadata given a spatio-temporal query. All parameters are
221227
optional. Results are paged using limit/offset.
222228
223229
:param list(str) const_id: Constellation identifier(s).
224230
:param str date: The date field to use for search (e.g. `acquired`).
225-
:param str shape: A slug identifier to be used as a region of interest.
231+
:param str place: A slug identifier to be used as a region of interest.
226232
:param str geom: A GeoJSON or WKT region of interest.
227233
:param str start_time: Desired starting date and time (inclusive).
228234
:param str end_time: Desired ending date and time (inclusive).
@@ -235,7 +241,7 @@ def keys(self, const_id=None, date='acquired', shape=None, geom=None, start_time
235241
236242
Example::
237243
238-
>>> metadata.keys(shape='north-america_united-states_iowa', const_id=['L8'],
244+
>>> metadata.keys(place='north-america_united-states_iowa', const_id=['L8'],
239245
start_time='2016-07-01', end_time='2016-07-31 23:59:59')
240246
241247
[
@@ -245,19 +251,19 @@ def keys(self, const_id=None, date='acquired', shape=None, geom=None, start_time
245251
...
246252
]
247253
"""
248-
result = self.search(const_id, date, shape, geom, start_time, end_time, params, limit, offset, bbox, direct)
254+
result = self.search(const_id, date, place, geom, start_time, end_time, params, limit, offset, bbox, direct)
249255

250256
return [feature['id'] for feature in result['features'][:limit]]
251257

252-
def features(self, const_id=None, date='acquired', shape=None, geom=None, start_time=None, end_time=None,
258+
def features(self, const_id=None, date='acquired', place=None, geom=None, start_time=None, end_time=None,
253259
params=None, limit=100, bbox=False, direct=False):
254260
"""Generator that combines summary and search to page through results.
255261
256262
:param int limit: Number of features to fetch per request.
257263
258264
:return: Generator of GeoJSON ``Feature`` objects.
259265
"""
260-
result = self.summary(const_id=const_id, date=date, shape=shape, geom=geom, start_time=start_time,
266+
result = self.summary(const_id=const_id, date=date, place=place, geom=geom, start_time=start_time,
261267
end_time=end_time, params=params, bbox=bbox, direct=direct)
262268

263269
for summary in result:
@@ -269,7 +275,7 @@ def features(self, const_id=None, date='acquired', shape=None, geom=None, start_
269275

270276
while offset < count:
271277

272-
features = self.search(const_id=[const_id], date=date, shape=shape, geom=geom, start_time=start_time,
278+
features = self.search(const_id=[const_id], date=date, place=place, geom=geom, start_time=start_time,
273279
end_time=end_time, params=params, limit=limit, offset=offset, bbox=bbox,
274280
direct=direct)
275281

descarteslabs/services/raster.py

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ def raster(
105105
resolution=None,
106106
bounds=None,
107107
bounds_srs=None,
108-
shape=None,
109-
location=None,
108+
cutline=None,
109+
place=None,
110110
align_pixels=False,
111111
resampler=None,
112112
):
@@ -125,21 +125,22 @@ def raster(
125125
:param str srs: Output spatial reference system definition understood by GDAL.
126126
:param float resolution: Desired resolution in output SRS units.
127127
:param tuple outsize: Desired output (width, height) in pixels.
128-
:param str shape: A GeoJSON feature to be used as a cutline.
129-
:param str location: A slug identifier to be used as a cutline.
128+
:param str cutline: A GeoJSON feature or geometry to be used as a cutline.
129+
:param str place: A slug identifier to be used as a cutline.
130130
:param tuple bounds: ``(min_x, min_y, max_x, max_y)`` in target SRS.
131131
:param str bounds_srs: Override the coordinate system in which bounds are expressed.
132132
:param bool align_pixels: Align pixels to the target coordinate system.
133133
:param str resampler: Resampling algorithm to be used during warping (``near``,
134134
``bilinear``, ``cubic``, ``cubicsplice``, ``lanczos``, ``average``, ``mode``,
135135
``max``, ``min``, ``med``, ``q1``, ``q3``).
136136
"""
137-
shape = as_json_string(shape)
137+
cutline = as_json_string(cutline)
138138

139-
if location:
139+
if place:
140140
places = Places()
141-
shape = places.shape(location, geom='low')
142-
shape = json.dumps(shape['geometry'])
141+
places.auth = self.auth
142+
shape = places.shape(place, geom='low')
143+
cutline = json.dumps(shape['geometry'])
143144

144145
params = {
145146
'keys': inputs,
@@ -149,7 +150,7 @@ def raster(
149150
'of': output_format,
150151
'srs': srs,
151152
'resolution': resolution,
152-
'shape': shape,
153+
'shape': cutline,
153154
'outputBounds': bounds,
154155
'outputBoundsSRS': bounds_srs,
155156
'outsize': dimensions,
@@ -178,8 +179,8 @@ def ndarray(
178179
srs=None,
179180
resolution=None,
180181
dimensions=None,
181-
shape=None,
182-
location=None,
182+
cutline=None,
183+
place=None,
183184
bounds=None,
184185
bounds_srs=None,
185186
align_pixels=False,
@@ -194,12 +195,13 @@ def ndarray(
194195
``(row, column, band)`` while `gdal` returns arrays as ``(band, row, column)``.
195196
196197
"""
197-
shape = as_json_string(shape)
198+
cutline = as_json_string(cutline)
198199

199-
if location is not None:
200+
if place is not None:
200201
places = Places()
201-
shape = places.shape(location, geom='low')
202-
shape = json.dumps(shape['geometry'])
202+
places.auth = self.auth
203+
shape = places.shape(place, geom='low')
204+
cutline = json.dumps(shape['geometry'])
203205

204206
params = {
205207
'keys': inputs,
@@ -208,7 +210,7 @@ def ndarray(
208210
'ot': data_type,
209211
'srs': srs,
210212
'resolution': resolution,
211-
'shape': shape,
213+
'shape': cutline,
212214
'outputBounds': bounds,
213215
'outputBoundsSRS': bounds_srs,
214216
'outsize': dimensions,

descarteslabs/tests/test_metadata.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from .helpers import is_external_user
1919

2020

21-
class TestRuncible(unittest.TestCase):
21+
class TestMetadata(unittest.TestCase):
2222
instance = None
2323

2424
@classmethod
@@ -47,9 +47,9 @@ def test_multiple_const_id(self):
4747
r = self.instance.search(start_time='2016-09-01', end_time='2016-09-02', const_id=['L8', 'L7'])
4848
self.assertGreater(len(r['features']), 0)
4949

50-
@unittest.skip("search by shape name not currently supported")
51-
def test_shape(self):
52-
r = self.instance.search(shape='north-america_united-states_iowa', limit=1)
50+
@unittest.skipIf(is_external_user(), "currently requires internal user")
51+
def test_place(self):
52+
r = self.instance.search(const_id=['L8'], place='north-america_united-states_iowa', limit=1)
5353
self.assertEqual(1, len(r['features']))
5454

5555
def test_summary(self):

descarteslabs/tests/test_raster.py

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
# limitations under the License.
1414

1515
import unittest
16+
import json
1617

1718
import descarteslabs as dl
1819
from descarteslabs.addons import numpy as np
19-
from .helpers import is_external_user
20+
from descarteslabs.tests.helpers import is_external_user
2021

2122

2223
class TestRaster(unittest.TestCase):
@@ -68,6 +69,48 @@ def test_ndarray_single_band(self):
6869
except ImportError:
6970
pass
7071

72+
@unittest.skipIf(is_external_user(), "currently requires internal user")
73+
def test_cutline_dict(self):
74+
shape = {"geometry":
75+
{"type": "Polygon",
76+
"coordinates": [[[-95.2989209, 42.7999878], [-93.1167728, 42.3858464],
77+
[-93.7138666, 40.703737], [-95.8364984, 41.1150618],
78+
[-95.2989209, 42.7999878]]]
79+
}
80+
}
81+
try:
82+
data, metadata = self.raster.ndarray(
83+
inputs=['meta_LC80270312016188_v1'],
84+
bands=['red'],
85+
resolution=960,
86+
cutline=shape,
87+
)
88+
self.assertEqual(data.shape, (245, 238))
89+
self.assertEqual(data.dtype, np.uint16)
90+
self.assertEqual(len(metadata['bands']), 1)
91+
except ImportError:
92+
pass
93+
94+
@unittest.skipIf(is_external_user(), "currently requires internal user")
95+
def test_cutline_str(self):
96+
shape = {"geometry":
97+
{"type": "Polygon",
98+
"coordinates": [[[-95.2989209, 42.7999878], [-93.1167728, 42.3858464],
99+
[-93.7138666, 40.703737], [-95.8364984, 41.1150618],
100+
[-95.2989209, 42.7999878]]]}}
101+
try:
102+
data, metadata = self.raster.ndarray(
103+
inputs=['meta_LC80270312016188_v1'],
104+
bands=['red'],
105+
resolution=960,
106+
cutline=json.dumps(shape),
107+
)
108+
self.assertEqual(data.shape, (245, 238))
109+
self.assertEqual(data.dtype, np.uint16)
110+
self.assertEqual(len(metadata['bands']), 1)
111+
except ImportError:
112+
pass
113+
71114
@unittest.skipIf(is_external_user(), "currently requires internal user")
72115
def test_thumbnail(self):
73116
r = self.raster.raster(
@@ -96,7 +139,7 @@ def test_landsat8_bands(self):
96139
self.assertTrue(band in r)
97140

98141
@unittest.skipIf(is_external_user(), "currently requires internal user")
99-
def test_dlkeys_from_shape(self):
142+
def test_dlkeys_from_place(self):
100143
iowa = self.places.shape('north-america_united-states_iowa', geom='low')
101144
iowa_geom = iowa['geometry']
102145
dlkeys_geojson = self.raster.dlkeys_from_shape(30.0, 2048, 16, iowa_geom)

0 commit comments

Comments
 (0)