Skip to content

Commit 939de78

Browse files
authored
Merge pull request #190 from sentinel-hub/feat/sh-py-proc-api-update
Use the SentinelHubRequest for issuing Processing API requests
2 parents 85ee15f + 0a4d95a commit 939de78

File tree

12 files changed

+61
-72
lines changed

12 files changed

+61
-72
lines changed

.travis.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,11 @@ notifications:
55
email: false
66

77
python:
8-
- "3.5"
98
- "3.6"
109
- "3.7"
1110
- "3.8"
1211

1312
before_install:
14-
- sudo add-apt-repository -y ppa:jonathonf/backports
15-
- sudo apt-get -qq update
1613
- sudo apt-get install -y libgdal-dev
1714
- sudo apt-get install graphviz
1815
- sudo apt-get install proj-bin
@@ -26,6 +23,7 @@ install:
2623
else
2724
python install_all.py;
2825
fi
26+
- pip install geopandas==0.6.3 # This is temporal fix
2927

3028
script:
3129
- sentinelhub.config --instance_id $INSTANCE_ID

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
## [Unreleased]
1+
## [Version 0.7.2] - 2019-02-17
2+
- Support additional data in the Processing API input task (such as sunAzimuthAngles, sunZenithAngles, viewAzimuthMean, viewZenithMean)
3+
- Compatibility with the `sentinelhub-py` 3.0
4+
- Removed support for python 3.5
5+
- Multiprocessing Log filtering
26

37
## [Version 0.7.1] - 2019-02-05
48
### Fixed

core/eolearn/core/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@
1818
from .utilities import deep_eq, negate_mask, constant_pad, get_common_timestamps, bgr_to_rgb, FeatureParser
1919

2020

21-
__version__ = '0.7.1'
21+
__version__ = '0.7.2'

core/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ attrs>=18.2.0
22
python-dateutil
33
numpy>=1.16
44
geopandas
5-
sentinelhub==3.0.0b1
5+
sentinelhub>=3.0.0
66
tqdm>=4.27
77
boto3
88
fs

geometry/eolearn/geometry/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@
77
from .superpixel import SuperpixelSegmentation, FelzenszwalbSegmentation, SlicSegmentation, MarkSegmentationBoundaries
88
from .transformations import VectorToRaster, RasterToVector
99

10-
__version__ = '0.7.0'
10+
__version__ = '0.7.2'

geometry/eolearn/geometry/transformations.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ def execute(self, eopatch):
384384

385385
affine_transform = rasterio.transform.from_bounds(*eopatch.bbox, width=width, height=height)
386386

387-
crs = eopatch.bbox.get_crs()
387+
crs = eopatch.bbox.crs
388388

389389
if raster_ft.is_timeless():
390390
eopatch[vector_ft][vector_fn] = self._vectorize_single_raster(raster, affine_transform, crs)

geometry/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def get_version():
2828

2929
setup(
3030
name='eo-learn-geometry',
31-
python_requires='>=3.5',
31+
python_requires='>=3.6',
3232
version=get_version(),
3333
description='A collection of geometry utilities and EOTasks',
3434
long_description=get_long_description(),

io/eolearn/io/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@
99
from .local_io import ExportToTiff, ImportFromTiff
1010
from .processing_api import SentinelHubInputTask, SentinelHubDemTask
1111

12-
__version__ = '0.7.1'
12+
__version__ = '0.7.2'

io/eolearn/io/geopedia.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import rasterio.transform
1717
import rasterio.warp
1818

19-
from sentinelhub import MimeType, CustomUrlParam, CRS, GeopediaWmsRequest, transform_bbox
19+
from sentinelhub import MimeType, CustomUrlParam, CRS, GeopediaWmsRequest
2020

2121
from eolearn.core import EOTask, FeatureType
2222

@@ -55,7 +55,7 @@ def _get_wms_request(self, bbox, size_x, size_y):
5555
"""
5656
Returns WMS request.
5757
"""
58-
bbox_3857 = transform_bbox(bbox, CRS.POP_WEB)
58+
bbox_3857 = bbox.transform(CRS.POP_WEB)
5959

6060
return GeopediaWmsRequest(layer=self.layer,
6161
theme=self.theme,
@@ -79,7 +79,7 @@ def _reproject(self, eopatch, src_raster):
7979

8080
dst_raster = np.ones((height, width), dtype=self.raster_dtype)
8181

82-
src_bbox = transform_bbox(eopatch.bbox, CRS.POP_WEB)
82+
src_bbox = eopatch.bbox.transform(CRS.POP_WEB)
8383
src_transform = rasterio.transform.from_bounds(*src_bbox, width=width, height=height)
8484

8585
dst_bbox = eopatch.bbox

io/eolearn/io/processing_api.py

Lines changed: 40 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@
66
import datetime as dt
77
import numpy as np
88

9-
from sentinelhub import WebFeatureService, MimeType, SentinelHubDownloadClient, DownloadRequest, SHConfig,\
9+
from sentinelhub import SentinelHubRequest, WebFeatureService, MimeType, SentinelHubDownloadClient, SHConfig, \
1010
bbox_to_dimensions, parse_time_interval, DataSource
11-
import sentinelhub.sentinelhub_request as shr
1211
from sentinelhub.time_utils import iso_to_datetime
1312

1413
from eolearn.core import EOPatch, EOTask, FeatureType
@@ -43,15 +42,7 @@ def __init__(self, data_source, size=None, resolution=None, cache_folder=None, c
4342
self.config = config or SHConfig()
4443
self.max_threads = max_threads
4544
self.data_source = data_source
46-
47-
self.request_args = dict(
48-
url=self.config.get_sh_processing_api_url(),
49-
headers={"accept": "application/tar", 'content-type': 'application/json'},
50-
data_folder=cache_folder,
51-
hash_save=bool(cache_folder),
52-
request_type='POST',
53-
data_type=MimeType.TAR
54-
)
45+
self.cache_folder = cache_folder
5546

5647
def execute(self, eopatch=None, bbox=None, time_interval=None):
5748
""" Main execute method for the Processing API tasks
@@ -80,8 +71,8 @@ def execute(self, eopatch=None, bbox=None, time_interval=None):
8071
elif timestamp:
8172
eopatch.timestamp = timestamp
8273

83-
payloads = self._build_payloads(bbox, size_x, size_y, timestamp, time_interval)
84-
requests = [DownloadRequest(post_values=payload, **self.request_args) for payload in payloads]
74+
requests = self._build_requests(bbox, size_x, size_y, timestamp, time_interval)
75+
requests = [request.download_list[0] for request in requests]
8576

8677
LOGGER.debug('Downloading %d requests of type %s', len(requests), str(self.data_source))
8778
client = SentinelHubDownloadClient(config=self.config)
@@ -118,10 +109,10 @@ def _extract_data(self, eopatch, images, shape):
118109
"""
119110
raise NotImplementedError("The _extract_data method should be implemented by the subclass.")
120111

121-
def _build_payloads(self, bbox, size_x, size_y, timestamp, time_interval):
122-
""" Build payloads for the requests to the service
112+
def _build_requests(self, bbox, size_x, size_y, timestamp, time_interval):
113+
""" Build requests
123114
"""
124-
raise NotImplementedError("The _build_payloads method should be implemented by the subclass.")
115+
raise NotImplementedError("The _build_requests method should be implemented by the subclass.")
125116

126117
def _get_timestamp(self, time_interval, bbox):
127118
""" Get the timestamp array needed as a parameter for downloading the images
@@ -318,39 +309,36 @@ def _get_timestamp(self, time_interval, bbox):
318309

319310
return [dates[0]] + [d2 for d1, d2 in zip(dates[:-1], dates[1:]) if d2 - d1 > self.time_difference]
320311

321-
def _build_payloads(self, bbox, size_x, size_y, timestamp, time_interval):
322-
""" Build payloads for the requests to the service
312+
def _build_requests(self, bbox, size_x, size_y, timestamp, time_interval):
313+
""" Build requests
323314
"""
324315
if self.single_scene:
325316
dates = [(iso_to_datetime(time_interval[0]), iso_to_datetime(time_interval[1]))]
326317
else:
327318
dates = [(date - self.time_difference, date + self.time_difference) for date in timestamp]
328319

329-
return [self._request_payload(date1, date2, bbox, size_x, size_y) for date1, date2 in dates]
320+
return [self._create_sh_request(date1, date2, bbox, size_x, size_y) for date1, date2 in dates]
330321

331-
def _request_payload(self, date_from, date_to, bbox, size_x, size_y):
332-
""" Build the payload dictionary for the request
322+
def _create_sh_request(self, date_from, date_to, bbox, size_x, size_y):
323+
""" Create an instance of SentinelHubRequest
333324
"""
334-
time_from, time_to = date_from.isoformat() + 'Z', date_to.isoformat() + 'Z'
335-
336-
responses = [shr.response(btype.id, 'image/tiff') for btype in self.requested_bands]
337-
338-
responses.append(shr.response('userdata', 'application/json'))
339-
340-
data_type = 'CUSTOM' if self.data_source.is_custom() else self.data_source.api_identifier()
341-
342-
data = shr.data(time_from=time_from, time_to=time_to, data_type=data_type)
343-
data['dataFilter']['maxCloudCoverage'] = int(self.maxcc * 100)
344-
data['dataFilter']['mosaickingOrder'] = self.mosaicking_order
345-
346-
if data_type == 'CUSTOM':
347-
data['dataFilter']['collectionId'] = self.data_source.value
348-
349-
return shr.body(
350-
request_bounds=shr.bounds(crs=bbox.crs.opengis_string, bbox=list(bbox)),
351-
request_data=[data],
352-
request_output=shr.output(size_x=size_x, size_y=size_y, responses=responses),
353-
evalscript=self.generate_evalscript()
325+
responses = [SentinelHubRequest.output_response(btype.id, MimeType.TIFF) for btype in self.requested_bands]
326+
responses.append(SentinelHubRequest.output_response('userdata', MimeType.JSON))
327+
328+
return SentinelHubRequest(
329+
evalscript=self.generate_evalscript(),
330+
input_data=[
331+
SentinelHubRequest.input_data(
332+
data_source=self.data_source,
333+
time_interval=(date_from, date_to),
334+
mosaicking_order=self.mosaicking_order,
335+
maxcc=self.maxcc
336+
)
337+
],
338+
responses=responses,
339+
bbox=bbox,
340+
size=(size_x, size_y),
341+
data_folder=self.cache_folder
354342
)
355343

356344
def _extract_data(self, eopatch, images, shape):
@@ -440,8 +428,8 @@ def __init__(self, dem_feature, size=None, resolution=None, cache_folder=None, c
440428

441429
self.dem_feature = next(feature_parser())
442430

443-
def _build_payloads(self, bbox, size_x, size_y, timestamp, time_interval):
444-
""" Build payloads for the requests to the service
431+
def _build_requests(self, bbox, size_x, size_y, timestamp, time_interval):
432+
""" Build requests
445433
"""
446434
evalscript = """
447435
//VERSION=3
@@ -462,19 +450,19 @@ def _build_payloads(self, bbox, size_x, size_y, timestamp, time_interval):
462450
}
463451
"""
464452

465-
responses = [shr.response('default', 'image/tiff'), shr.response('userdata', 'application/json')]
466-
request_body = shr.body(
467-
request_bounds=shr.bounds(crs=bbox.crs.opengis_string, bbox=list(bbox)),
468-
request_data=[{"type": "DEM"}],
469-
request_output=shr.output(size_x=size_x, size_y=size_y, responses=responses),
470-
evalscript=evalscript
453+
request = SentinelHubRequest(
454+
evalscript=evalscript,
455+
input_data=[SentinelHubRequest.input_data(data_source=self.data_source)],
456+
responses=[SentinelHubRequest.output_response('default', MimeType.TIFF)],
457+
bbox=bbox,
458+
size=(size_x, size_y),
459+
data_folder=self.cache_folder
471460
)
472461

473-
return [request_body]
462+
return [request]
474463

475464
def _extract_data(self, eopatch, images, shape):
476465
""" Extract data from the received images and assign them to eopatch features
477466
"""
478-
tif = images[0]['default.tif']
479-
467+
tif = images[0]
480468
eopatch[self.dem_feature] = tif[..., np.newaxis].astype(np.int16)

0 commit comments

Comments
 (0)