sentinelhub 3.11.0__py3-none-any.whl → 3.11.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sentinelhub/__init__.py +0 -7
- sentinelhub/_version.py +1 -1
- sentinelhub/api/__init__.py +0 -6
- sentinelhub/api/batch/__init__.py +1 -4
- sentinelhub/api/batch/base.py +1 -4
- sentinelhub/api/batch/process.py +159 -410
- sentinelhub/api/batch/process_v2.py +9 -320
- sentinelhub/api/batch/utils.py +3 -130
- sentinelhub/areas.py +2 -78
- sentinelhub/config.py +2 -2
- {sentinelhub-3.11.0.dist-info → sentinelhub-3.11.2.dist-info}/METADATA +3 -5
- {sentinelhub-3.11.0.dist-info → sentinelhub-3.11.2.dist-info}/RECORD +15 -15
- {sentinelhub-3.11.0.dist-info → sentinelhub-3.11.2.dist-info}/WHEEL +1 -1
- {sentinelhub-3.11.0.dist-info → sentinelhub-3.11.2.dist-info}/entry_points.txt +0 -0
- {sentinelhub-3.11.0.dist-info → sentinelhub-3.11.2.dist-info}/licenses/LICENSE.md +0 -0
sentinelhub/api/batch/process.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Module implementing an interface with
|
|
3
|
-
`
|
|
3
|
+
`Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
# ruff: noqa: FA100
|
|
@@ -8,80 +8,73 @@ Module implementing an interface with
|
|
|
8
8
|
import datetime as dt
|
|
9
9
|
import logging
|
|
10
10
|
from dataclasses import dataclass, field
|
|
11
|
-
from
|
|
12
|
-
from typing import Any, Dict, Iterator, List, Optional, Tuple, Union
|
|
11
|
+
from typing import Any, Dict, Iterator, Optional, Union
|
|
13
12
|
|
|
14
13
|
from dataclasses_json import CatchAll, LetterCase, Undefined, dataclass_json
|
|
15
14
|
from dataclasses_json import config as dataclass_config
|
|
15
|
+
from typing_extensions import Literal
|
|
16
16
|
|
|
17
17
|
from ...constants import RequestType
|
|
18
|
-
from ...data_collections import DataCollection
|
|
19
|
-
from ...geometry import CRS, BBox, Geometry
|
|
20
18
|
from ...types import Json, JsonDict
|
|
21
|
-
from ..base import
|
|
19
|
+
from ..base import SentinelHubFeatureIterator
|
|
22
20
|
from ..process import SentinelHubRequest
|
|
23
|
-
from ..utils import datetime_config, enum_config, remove_undefined
|
|
24
|
-
from .base import BaseBatchClient, BaseBatchRequest, BatchRequestStatus, BatchUserAction
|
|
21
|
+
from ..utils import AccessSpecification, datetime_config, enum_config, remove_undefined, s3_specification
|
|
22
|
+
from .base import BaseBatchClient, BaseBatchRequest, BatchRequestStatus, BatchUserAction, StoppedStatusReason
|
|
25
23
|
|
|
26
24
|
LOGGER = logging.getLogger(__name__)
|
|
27
25
|
|
|
28
|
-
BatchRequestType = Union[str, dict, "
|
|
29
|
-
BatchCollectionType = Union[str, dict, "BatchCollection"]
|
|
26
|
+
BatchRequestType = Union[str, dict, "BatchProcessRequest"]
|
|
30
27
|
|
|
31
28
|
|
|
32
|
-
class
|
|
33
|
-
"""An
|
|
29
|
+
class BatchProcessClient(BaseBatchClient):
|
|
30
|
+
"""An interface class for Sentinel Hub Batch API version 2.
|
|
34
31
|
|
|
35
|
-
|
|
36
|
-
SCHEDULED = "SCHEDULED"
|
|
37
|
-
QUEUED = "QUEUED"
|
|
38
|
-
PROCESSING = "PROCESSING"
|
|
39
|
-
PROCESSED = "PROCESSED"
|
|
40
|
-
FAILED = "FAILED"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
class SentinelHubBatch(BaseBatchClient):
|
|
44
|
-
"""An interface class for Sentinel Hub Batch API
|
|
45
|
-
|
|
46
|
-
For more info check `Batch API reference <https://docs.sentinel-hub.com/api/latest/reference/#tag/batch_process>`__.
|
|
32
|
+
`Batch Process API <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
|
|
47
33
|
"""
|
|
48
34
|
|
|
35
|
+
s3_specification = staticmethod(s3_specification)
|
|
36
|
+
|
|
49
37
|
# pylint: disable=too-many-public-methods
|
|
50
38
|
@staticmethod
|
|
51
39
|
def _get_service_url(base_url: str) -> str:
|
|
52
40
|
"""Provides URL to Catalog API"""
|
|
53
|
-
return f"{base_url}/api/
|
|
41
|
+
return f"{base_url}/api/v2/batch"
|
|
42
|
+
|
|
43
|
+
def _get_processing_url(self, request_id: Optional[str] = None) -> str:
|
|
44
|
+
"""Creates a URL for process endpoint"""
|
|
45
|
+
url = f"{self.service_url}/process"
|
|
46
|
+
if request_id is None:
|
|
47
|
+
return url
|
|
48
|
+
return f"{url}/{request_id}"
|
|
54
49
|
|
|
55
50
|
def create(
|
|
56
51
|
self,
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
output:
|
|
60
|
-
|
|
52
|
+
process_request: Union[SentinelHubRequest, JsonDict],
|
|
53
|
+
input: Dict[str, Any], # noqa: A002 #pylint: disable=redefined-builtin
|
|
54
|
+
output: Dict[str, Any],
|
|
55
|
+
instance_type: Literal["normal", "large"] = "normal",
|
|
61
56
|
description: Optional[str] = None,
|
|
62
57
|
**kwargs: Any,
|
|
63
|
-
) -> "
|
|
58
|
+
) -> "BatchProcessRequest":
|
|
64
59
|
"""Create a new batch request
|
|
65
60
|
|
|
66
|
-
`Batch
|
|
67
|
-
<https://docs.sentinel-hub.com/api/latest/reference/#operation/createNewBatchProcessingRequest>`__
|
|
61
|
+
`Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
|
|
68
62
|
|
|
69
|
-
:param
|
|
63
|
+
:param process_request: An instance of SentinelHubRequest class containing all request parameters.
|
|
70
64
|
Alternatively, it can also be just a payload dictionary for Process API request
|
|
71
|
-
:param
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
65
|
+
:param input: A dictionary with input parameters. It can be built with `tiling_grid_input` or `geopackage_input`
|
|
66
|
+
methods.
|
|
67
|
+
:param output: A dictionary with output parameters. It can be built with `raster_output` or `zarr_output`
|
|
68
|
+
methods.
|
|
69
|
+
:param instance_type": Specifies which size of instances to use for the request.
|
|
76
70
|
:param description: A description of a batch request
|
|
77
71
|
:param kwargs: Any other arguments to be added to a dictionary of parameters.
|
|
78
|
-
:return: An instance of `SentinelHubBatch` object that represents a newly created batch request.
|
|
79
72
|
"""
|
|
80
73
|
|
|
81
|
-
if isinstance(
|
|
82
|
-
request_dict =
|
|
74
|
+
if isinstance(process_request, SentinelHubRequest):
|
|
75
|
+
request_dict = process_request.download_list[0].post_values
|
|
83
76
|
else:
|
|
84
|
-
request_dict =
|
|
77
|
+
request_dict = process_request
|
|
85
78
|
|
|
86
79
|
if not isinstance(request_dict, dict):
|
|
87
80
|
raise ValueError(
|
|
@@ -89,116 +82,133 @@ class SentinelHubBatch(BaseBatchClient):
|
|
|
89
82
|
"dictionary with a request payload"
|
|
90
83
|
)
|
|
91
84
|
|
|
92
|
-
payload =
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
85
|
+
payload = remove_undefined(
|
|
86
|
+
{
|
|
87
|
+
"processRequest": request_dict,
|
|
88
|
+
"input": input,
|
|
89
|
+
"output": output,
|
|
90
|
+
"instance_type": instance_type,
|
|
91
|
+
"description": description,
|
|
92
|
+
**kwargs,
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
request_info = self.client.get_json_dict(self._get_processing_url(), post_values=payload, use_session=True)
|
|
101
97
|
|
|
102
|
-
|
|
103
|
-
request_info = self.client.get_json_dict(url, post_values=payload, use_session=True)
|
|
98
|
+
return BatchProcessRequest.from_dict(request_info)
|
|
104
99
|
|
|
105
|
-
|
|
100
|
+
@staticmethod
|
|
101
|
+
def geopackage_input(geopackage_specification: AccessSpecification) -> JsonDict:
|
|
102
|
+
"""A helper method to build a suitable dictionary for the `input` field.
|
|
103
|
+
|
|
104
|
+
:param geopackage_specification: A specification of the S3 path for the Geopackage. Can be built using the
|
|
105
|
+
`s3_specification` helper method.
|
|
106
|
+
"""
|
|
107
|
+
return {"type": "geopackage", "features": geopackage_specification}
|
|
106
108
|
|
|
107
109
|
@staticmethod
|
|
108
|
-
def
|
|
109
|
-
grid_id: int, resolution: float,
|
|
110
|
+
def tiling_grid_input(
|
|
111
|
+
grid_id: int, resolution: float, buffer_x: Optional[int] = None, buffer_y: Optional[int] = None, **kwargs: Any
|
|
110
112
|
) -> JsonDict:
|
|
111
|
-
"""A helper method to build a dictionary with tiling grid parameters
|
|
113
|
+
"""A helper method to build a dictionary with tiling grid parameters for the `input` field.
|
|
112
114
|
|
|
113
115
|
:param grid_id: An ID of a tiling grid
|
|
114
116
|
:param resolution: A grid resolution
|
|
115
|
-
:param
|
|
116
|
-
|
|
117
|
+
:param buffer_x: Will expand each output tile horizontally (left and right) by specified number of pixels.
|
|
118
|
+
:param buffer_y: Will expand each output tile vertically (up and down) by specified number of pixels.
|
|
117
119
|
:param kwargs: Any other arguments to be added to a dictionary of parameters
|
|
118
|
-
:return: A dictionary with parameters
|
|
119
120
|
"""
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
return remove_undefined(
|
|
122
|
+
{
|
|
123
|
+
"type": "tiling-grid",
|
|
124
|
+
"id": grid_id,
|
|
125
|
+
"resolution": resolution,
|
|
126
|
+
"bufferX": buffer_x,
|
|
127
|
+
"bufferY": buffer_y,
|
|
128
|
+
**kwargs,
|
|
129
|
+
}
|
|
130
|
+
)
|
|
124
131
|
|
|
125
132
|
@staticmethod
|
|
126
|
-
def
|
|
133
|
+
def raster_output(
|
|
134
|
+
delivery: AccessSpecification,
|
|
127
135
|
*,
|
|
128
|
-
default_tile_path: Optional[str] = None,
|
|
129
136
|
overwrite: Optional[bool] = None,
|
|
130
137
|
skip_existing: Optional[bool] = None,
|
|
131
138
|
cog_output: Optional[bool] = None,
|
|
132
139
|
cog_parameters: Optional[Dict[str, Any]] = None,
|
|
133
140
|
create_collection: Optional[bool] = None,
|
|
134
141
|
collection_id: Optional[str] = None,
|
|
135
|
-
responses: Optional[List[str]] = None,
|
|
136
142
|
**kwargs: Any,
|
|
137
143
|
) -> Dict[str, Any]:
|
|
138
|
-
"""A helper method to build a dictionary
|
|
144
|
+
"""A helper method to build a dictionary specifying raster output
|
|
139
145
|
|
|
140
|
-
:param
|
|
141
|
-
|
|
146
|
+
:param delivery: An S3 access specification containing a path or a template on an s3 bucket where to store
|
|
147
|
+
results. You can use the `s3_specification` method for construction. For more information on templates see
|
|
148
|
+
documentation.
|
|
142
149
|
:param overwrite: A flag specifying if a request should overwrite existing outputs without failing
|
|
143
150
|
:param skip_existing: A flag specifying if existing outputs should be overwritten
|
|
144
|
-
:param cog_output: A flag specifying if outputs should be written in COGs (cloud-optimized GeoTIFFs
|
|
151
|
+
:param cog_output: A flag specifying if outputs should be written in COGs (cloud-optimized GeoTIFFs) or
|
|
145
152
|
normal GeoTIFFs
|
|
146
|
-
:param cog_parameters: A dictionary specifying COG creation parameters
|
|
153
|
+
:param cog_parameters: A dictionary specifying COG creation parameters. See documentation for more info.
|
|
147
154
|
:param create_collection: If True the results will be written in COGs and a batch collection will be created
|
|
148
155
|
:param collection_id: If True results will be added to an existing collection
|
|
149
|
-
:param responses: Specification of path template for individual outputs/responses
|
|
150
156
|
:param kwargs: Any other arguments to be added to a dictionary of parameters
|
|
151
|
-
:return: A dictionary of output parameters
|
|
152
157
|
"""
|
|
153
158
|
return remove_undefined(
|
|
154
159
|
{
|
|
155
|
-
"
|
|
160
|
+
"type": "raster",
|
|
161
|
+
"delivery": delivery,
|
|
156
162
|
"overwrite": overwrite,
|
|
157
163
|
"skipExisting": skip_existing,
|
|
158
164
|
"cogOutput": cog_output,
|
|
159
165
|
"cogParameters": cog_parameters,
|
|
160
166
|
"createCollection": create_collection,
|
|
161
167
|
"collectionId": collection_id,
|
|
162
|
-
"responses": responses,
|
|
163
168
|
**kwargs,
|
|
164
169
|
}
|
|
165
170
|
)
|
|
166
171
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
:
|
|
174
|
-
:
|
|
172
|
+
@staticmethod
|
|
173
|
+
def zarr_output(
|
|
174
|
+
delivery: AccessSpecification,
|
|
175
|
+
*,
|
|
176
|
+
group: Optional[Dict[str, Any]] = None,
|
|
177
|
+
array_parameters: Optional[Dict[str, Any]] = None,
|
|
178
|
+
array_overrides: Optional[Dict[str, Any]] = None,
|
|
179
|
+
**kwargs: Any,
|
|
180
|
+
) -> JsonDict:
|
|
181
|
+
"""A helper method to build a dictionary specifying Zarr output. See documentation for more information on
|
|
182
|
+
each parameter.
|
|
183
|
+
|
|
184
|
+
`Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
|
|
185
|
+
|
|
186
|
+
:param delivery: An S3 access specification containing a path or a template on an s3 bucket where to store
|
|
187
|
+
results. You can use the `s3_specification` method for construction. For more information on templates see
|
|
188
|
+
documentation.
|
|
189
|
+
:param group: Zarr group level parameters
|
|
190
|
+
:param array_parameters: Parameters that will be used for all output arrays, except where overriden with
|
|
191
|
+
`array_overrides`. Required unless `array_overrides` includes all required fields for all output arrays.
|
|
192
|
+
:param array_overrides: Overrides the values of `array_arameters` for individual arrays.
|
|
193
|
+
:param kwargs: Any other arguments to be added to a dictionary of parameters
|
|
175
194
|
"""
|
|
176
|
-
return
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
195
|
+
return remove_undefined(
|
|
196
|
+
{
|
|
197
|
+
"type": "zarr",
|
|
198
|
+
"delivery": delivery,
|
|
199
|
+
"group": group,
|
|
200
|
+
"arrayParameter": array_parameters,
|
|
201
|
+
"arrayOverrides": array_overrides,
|
|
202
|
+
**kwargs,
|
|
203
|
+
}
|
|
181
204
|
)
|
|
182
205
|
|
|
183
|
-
def get_tiling_grid(self, grid_id: Union[int, str]) -> JsonDict:
|
|
184
|
-
"""Provides a single tiling grid
|
|
185
|
-
|
|
186
|
-
`Batch API reference
|
|
187
|
-
<https://docs.sentinel-hub.com/api/latest/reference/#operation/getBatchTilingGridProperties>`__
|
|
188
|
-
|
|
189
|
-
:param grid_id: An ID of a requested tiling grid
|
|
190
|
-
:return: A tiling grid definition
|
|
191
|
-
"""
|
|
192
|
-
url = self._get_tiling_grids_url(grid_id)
|
|
193
|
-
return self.client.get_json_dict(url=url, use_session=True)
|
|
194
|
-
|
|
195
206
|
def iter_requests(
|
|
196
207
|
self, user_id: Optional[str] = None, search: Optional[str] = None, sort: Optional[str] = None, **kwargs: Any
|
|
197
|
-
) -> Iterator["
|
|
208
|
+
) -> Iterator["BatchProcessRequest"]:
|
|
198
209
|
"""Iterate existing batch requests
|
|
199
210
|
|
|
200
|
-
`Batch
|
|
201
|
-
<https://docs.sentinel-hub.com/api/latest/reference/#operation/getAllBatchProcessRequests>`__
|
|
211
|
+
`Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
|
|
202
212
|
|
|
203
213
|
:param user_id: Filter requests by a user id who defined a request
|
|
204
214
|
:param search: A search query to filter requests
|
|
@@ -211,366 +221,105 @@ class SentinelHubBatch(BaseBatchClient):
|
|
|
211
221
|
client=self.client, url=self._get_processing_url(), params=params, exception_message="No requests found"
|
|
212
222
|
)
|
|
213
223
|
for request_info in feature_iterator:
|
|
214
|
-
yield
|
|
224
|
+
yield BatchProcessRequest.from_dict(request_info)
|
|
215
225
|
|
|
216
|
-
def
|
|
217
|
-
"""
|
|
226
|
+
def get_request(self, batch_request: BatchRequestType) -> "BatchProcessRequest":
|
|
227
|
+
"""Collects information about a single batch request.
|
|
218
228
|
|
|
219
|
-
|
|
220
|
-
"""
|
|
221
|
-
latest_request_iter = self.iter_requests(sort="created:desc", count=1)
|
|
222
|
-
try:
|
|
223
|
-
return next(latest_request_iter)
|
|
224
|
-
except StopIteration as exception:
|
|
225
|
-
raise ValueError("No batch request is available") from exception
|
|
226
|
-
|
|
227
|
-
def get_request(self, batch_request: BatchRequestType) -> "BatchRequest":
|
|
228
|
-
"""Collects information about a single batch request
|
|
229
|
-
|
|
230
|
-
`Batch API reference
|
|
231
|
-
<https://docs.sentinel-hub.com/api/latest/reference/#operation/getSingleBatchProcessRequestById>`__
|
|
232
|
-
|
|
233
|
-
:return: Batch request info
|
|
229
|
+
`Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
|
|
234
230
|
"""
|
|
235
231
|
request_id = self._parse_request_id(batch_request)
|
|
236
232
|
request_info = self.client.get_json_dict(url=self._get_processing_url(request_id), use_session=True)
|
|
237
|
-
return
|
|
238
|
-
|
|
239
|
-
def update_request(
|
|
240
|
-
self,
|
|
241
|
-
batch_request: BatchRequestType,
|
|
242
|
-
output: Optional[Dict[str, Any]] = None,
|
|
243
|
-
description: Optional[str] = None,
|
|
244
|
-
**kwargs: Any,
|
|
245
|
-
) -> Json:
|
|
246
|
-
"""Update batch job request parameters
|
|
233
|
+
return BatchProcessRequest.from_dict(request_info)
|
|
247
234
|
|
|
248
|
-
|
|
249
|
-
|
|
235
|
+
def update_request(self, batch_request: BatchRequestType, description: str) -> Json:
|
|
236
|
+
"""Update certain batch job request parameters. Can only update requests that are not currently being processed.
|
|
250
237
|
|
|
251
|
-
|
|
252
|
-
`SentinelHubBatch`.
|
|
238
|
+
`Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
|
|
253
239
|
|
|
254
|
-
:param batch_request:
|
|
255
|
-
request ID.
|
|
256
|
-
:param output: A dictionary with output parameters to be updated.
|
|
240
|
+
:param batch_request: Batch request ID, a dictionary containing an "ID" field, or a BatchProcessRequest.
|
|
257
241
|
:param description: A description of a batch request to be updated.
|
|
258
|
-
:param kwargs: Any other arguments to be added to a dictionary of parameters.
|
|
259
242
|
"""
|
|
260
243
|
request_id = self._parse_request_id(batch_request)
|
|
261
|
-
|
|
244
|
+
|
|
262
245
|
return self.client.get_json(
|
|
263
246
|
url=self._get_processing_url(request_id),
|
|
264
|
-
post_values=
|
|
247
|
+
post_values={"description": description},
|
|
265
248
|
request_type=RequestType.PUT,
|
|
266
249
|
use_session=True,
|
|
267
250
|
)
|
|
268
251
|
|
|
269
|
-
def delete_request(self, batch_request: BatchRequestType) -> Json:
|
|
270
|
-
"""Delete a batch job request
|
|
271
|
-
|
|
272
|
-
`Batch API reference
|
|
273
|
-
<https://docs.sentinel-hub.com/api/latest/reference/#operation/deleteBatchProcessRequest>`__
|
|
274
|
-
|
|
275
|
-
:param batch_request: It could be a batch request object, a raw batch request payload or only a batch
|
|
276
|
-
request ID.
|
|
277
|
-
"""
|
|
278
|
-
request_id = self._parse_request_id(batch_request)
|
|
279
|
-
return self.client.get_json(
|
|
280
|
-
url=self._get_processing_url(request_id), request_type=RequestType.DELETE, use_session=True
|
|
281
|
-
)
|
|
282
|
-
|
|
283
252
|
def start_analysis(self, batch_request: BatchRequestType) -> Json:
|
|
284
253
|
"""Starts analysis of a batch job request
|
|
285
254
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
:param batch_request: It could be a batch request object, a raw batch request payload or only a batch
|
|
289
|
-
request ID.
|
|
255
|
+
:param batch_request: Batch request ID, a dictionary containing an "ID" field, or a BatchProcessRequest.
|
|
290
256
|
"""
|
|
291
257
|
return self._call_job(batch_request, "analyse")
|
|
292
258
|
|
|
293
259
|
def start_job(self, batch_request: BatchRequestType) -> Json:
|
|
294
260
|
"""Starts running a batch job
|
|
295
261
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
:param batch_request: It could be a batch request object, a raw batch request payload or only a batch
|
|
299
|
-
request ID.
|
|
262
|
+
:param batch_request: Batch request ID, a dictionary containing an "ID" field, or a BatchProcessRequest.
|
|
300
263
|
"""
|
|
301
264
|
return self._call_job(batch_request, "start")
|
|
302
265
|
|
|
303
|
-
def
|
|
304
|
-
"""
|
|
305
|
-
|
|
306
|
-
`Batch API reference
|
|
307
|
-
<https://docs.sentinel-hub.com/api/latest/reference/#operation/batchCancelProcessRequest>`__
|
|
308
|
-
|
|
309
|
-
:param batch_request: It could be a batch request object, a raw batch request payload or only a batch
|
|
310
|
-
request ID.
|
|
311
|
-
"""
|
|
312
|
-
return self._call_job(batch_request, "cancel")
|
|
313
|
-
|
|
314
|
-
def restart_job(self, batch_request: BatchRequestType) -> Json:
|
|
315
|
-
"""Restarts only those parts of a job that failed
|
|
316
|
-
|
|
317
|
-
`Batch API reference
|
|
318
|
-
<https://docs.sentinel-hub.com/api/latest/reference/#operation/batchRestartPartialProcessRequest>`__
|
|
319
|
-
|
|
320
|
-
:param batch_request: It could be a batch request object, a raw batch request payload or only a batch
|
|
321
|
-
request ID.
|
|
322
|
-
"""
|
|
323
|
-
return self._call_job(batch_request, "restartpartial")
|
|
324
|
-
|
|
325
|
-
def iter_tiles(
|
|
326
|
-
self, batch_request: BatchRequestType, status: Union[None, "BatchTileStatus", str] = None, **kwargs: Any
|
|
327
|
-
) -> SentinelHubFeatureIterator:
|
|
328
|
-
"""Iterate over info about batch request tiles
|
|
329
|
-
|
|
330
|
-
`Batch API reference <https://docs.sentinel-hub.com/api/latest/reference/#operation/getAllBatchProcessTiles>`__
|
|
331
|
-
|
|
332
|
-
:param batch_request: It could be a batch request object, a raw batch request payload or only a batch
|
|
333
|
-
request ID.
|
|
334
|
-
:param status: A filter to obtain only tiles with a certain status
|
|
335
|
-
:param kwargs: Any additional parameters to include in a request query
|
|
336
|
-
:return: An iterator over information about each tile
|
|
337
|
-
"""
|
|
338
|
-
request_id = self._parse_request_id(batch_request)
|
|
339
|
-
if isinstance(status, BatchTileStatus):
|
|
340
|
-
status = status.value
|
|
341
|
-
|
|
342
|
-
return SentinelHubFeatureIterator(
|
|
343
|
-
client=self.client,
|
|
344
|
-
url=self._get_tiles_url(request_id),
|
|
345
|
-
params={"status": status, **kwargs},
|
|
346
|
-
exception_message="No tiles found, please run analysis on batch request before calling this method",
|
|
347
|
-
)
|
|
348
|
-
|
|
349
|
-
def get_tile(self, batch_request: BatchRequestType, tile_id: Optional[int]) -> JsonDict:
|
|
350
|
-
"""Provides information about a single batch request tile
|
|
266
|
+
def stop_job(self, batch_request: BatchRequestType) -> Json:
|
|
267
|
+
"""Stops a batch job
|
|
351
268
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
:param batch_request: It could be a batch request object, a raw batch request payload or only a batch
|
|
355
|
-
request ID.
|
|
356
|
-
:param tile_id: An ID of a tile
|
|
357
|
-
:return: Information about a tile
|
|
269
|
+
:param batch_request: Batch request ID, a dictionary containing an "ID" field, or a BatchProcessRequest.
|
|
358
270
|
"""
|
|
359
|
-
|
|
360
|
-
url = self._get_tiles_url(request_id, tile_id=tile_id)
|
|
361
|
-
return self.client.get_json_dict(url, use_session=True)
|
|
271
|
+
return self._call_job(batch_request, "stop")
|
|
362
272
|
|
|
363
|
-
def
|
|
364
|
-
"""
|
|
273
|
+
def iter_tiling_grids(self, **kwargs: Any) -> SentinelHubFeatureIterator:
|
|
274
|
+
"""An iterator over tiling grids
|
|
365
275
|
|
|
366
|
-
`Batch
|
|
276
|
+
`Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
|
|
367
277
|
|
|
368
|
-
:param
|
|
369
|
-
:
|
|
370
|
-
:return: An iterator over existing batch collections
|
|
278
|
+
:param kwargs: Any other request query parameters
|
|
279
|
+
:return: An iterator over tiling grid definitions
|
|
371
280
|
"""
|
|
372
281
|
return SentinelHubFeatureIterator(
|
|
373
282
|
client=self.client,
|
|
374
|
-
url=self.
|
|
375
|
-
params=
|
|
376
|
-
exception_message="Failed to obtain information about available
|
|
377
|
-
)
|
|
378
|
-
|
|
379
|
-
def get_collection(self, collection_id: str) -> JsonDict:
|
|
380
|
-
"""Get batch collection by its id
|
|
381
|
-
|
|
382
|
-
`Batch API reference
|
|
383
|
-
<https://docs.sentinel-hub.com/api/latest/reference/#operation/getSingleBatchCollectionById>`__
|
|
384
|
-
|
|
385
|
-
:param collection_id: A batch collection id
|
|
386
|
-
:return: A dictionary of the collection parameters
|
|
387
|
-
"""
|
|
388
|
-
url = self._get_collections_url(collection_id)
|
|
389
|
-
return self.client.get_json_dict(url=url, use_session=True, extract_key="data")
|
|
390
|
-
|
|
391
|
-
def create_collection(self, collection: Union["BatchCollection", dict]) -> JsonDict:
|
|
392
|
-
"""Create a new batch collection
|
|
393
|
-
|
|
394
|
-
`Batch API reference <https://docs.sentinel-hub.com/api/latest/reference/#operation/createNewBatchCollection>`__
|
|
395
|
-
|
|
396
|
-
:param collection: Batch collection definition
|
|
397
|
-
:return: A dictionary of a newly created collection
|
|
398
|
-
"""
|
|
399
|
-
collection_payload = self._parse_collection_to_dict(collection)
|
|
400
|
-
url = self._get_collections_url()
|
|
401
|
-
return self.client.get_json_dict(url=url, post_values=collection_payload, use_session=True, extract_key="data")
|
|
402
|
-
|
|
403
|
-
def update_collection(self, collection: Union["BatchCollection", dict]) -> Json:
|
|
404
|
-
"""Update an existing batch collection
|
|
405
|
-
|
|
406
|
-
`Batch API reference <https://docs.sentinel-hub.com/api/latest/reference/#operation/updateBatchCollection>`__
|
|
407
|
-
|
|
408
|
-
:param collection: Batch collection definition
|
|
409
|
-
"""
|
|
410
|
-
collection_id = self._parse_collection_id(collection)
|
|
411
|
-
return self.client.get_json(
|
|
412
|
-
url=self._get_collections_url(collection_id),
|
|
413
|
-
post_values=self._parse_collection_to_dict(collection),
|
|
414
|
-
request_type=RequestType.PUT,
|
|
415
|
-
use_session=True,
|
|
283
|
+
url=f"{self.service_url}/tilinggrids",
|
|
284
|
+
params=remove_undefined(kwargs),
|
|
285
|
+
exception_message="Failed to obtain information about available tiling grids",
|
|
416
286
|
)
|
|
417
287
|
|
|
418
|
-
def
|
|
419
|
-
"""
|
|
288
|
+
def get_tiling_grid(self, grid_id: int) -> JsonDict:
|
|
289
|
+
"""Provides a single tiling grid
|
|
420
290
|
|
|
421
|
-
`Batch
|
|
291
|
+
`Batch Process V2 <https://docs.sentinel-hub.com/api/latest/api/batchv2/>`__
|
|
422
292
|
|
|
423
|
-
:param
|
|
293
|
+
:param grid_id: An ID of a requested tiling grid
|
|
294
|
+
:return: A tiling grid definition
|
|
424
295
|
"""
|
|
425
|
-
|
|
426
|
-
return self.client.
|
|
427
|
-
url=self._get_collections_url(collection_id), request_type=RequestType.DELETE, use_session=True
|
|
428
|
-
)
|
|
429
|
-
|
|
430
|
-
def _get_processing_url(self, request_id: Optional[str] = None) -> str:
|
|
431
|
-
"""Creates a URL for process endpoint"""
|
|
432
|
-
url = f"{self.service_url}/process"
|
|
433
|
-
if request_id is None:
|
|
434
|
-
return url
|
|
435
|
-
return f"{url}/{request_id}"
|
|
436
|
-
|
|
437
|
-
def _get_tiles_url(self, request_id: str, tile_id: Union[None, str, int] = None) -> str:
|
|
438
|
-
"""Creates a URL for tiles endpoint"""
|
|
439
|
-
url = f"{self._get_processing_url(request_id)}/tiles"
|
|
440
|
-
if tile_id is None:
|
|
441
|
-
return url
|
|
442
|
-
return f"{url}/{tile_id}"
|
|
443
|
-
|
|
444
|
-
def _get_tiling_grids_url(self, grid_id: Union[None, str, int] = None) -> str:
|
|
445
|
-
"""Creates a URL for tiling grids endpoint"""
|
|
446
|
-
url = f"{self.service_url}/tilinggrids"
|
|
447
|
-
if grid_id is None:
|
|
448
|
-
return url
|
|
449
|
-
return f"{url}/{grid_id}"
|
|
450
|
-
|
|
451
|
-
def _get_collections_url(self, collection_id: Optional[str] = None) -> str:
|
|
452
|
-
"""Creates a URL for batch collections endpoint"""
|
|
453
|
-
url = f"{self.service_url}/collections"
|
|
454
|
-
if collection_id is None:
|
|
455
|
-
return url
|
|
456
|
-
return f"{url}/{collection_id}"
|
|
457
|
-
|
|
458
|
-
@staticmethod
|
|
459
|
-
def _parse_collection_id(data: BatchCollectionType) -> Optional[str]:
|
|
460
|
-
"""Parses batch collection id from multiple possible inputs"""
|
|
461
|
-
if isinstance(data, (BatchCollection, DataCollection)):
|
|
462
|
-
return data.collection_id
|
|
463
|
-
if isinstance(data, dict):
|
|
464
|
-
return data["id"]
|
|
465
|
-
if isinstance(data, str):
|
|
466
|
-
return data
|
|
467
|
-
raise ValueError(f"Expected a BatchCollection dataclass, dictionary or a string, got {data}.")
|
|
468
|
-
|
|
469
|
-
@staticmethod
|
|
470
|
-
def _parse_collection_to_dict(data: Union["BatchCollection", dict]) -> dict:
|
|
471
|
-
"""Constructs a dictionary from given object"""
|
|
472
|
-
if isinstance(data, BatchCollection):
|
|
473
|
-
return data.to_dict() # type: ignore[attr-defined]
|
|
474
|
-
if isinstance(data, dict):
|
|
475
|
-
return data
|
|
476
|
-
raise ValueError(f"Expected either a BatchCollection or a dict, got {data}.")
|
|
296
|
+
url = f"{self.service_url}/tilinggrids/{grid_id}"
|
|
297
|
+
return self.client.get_json_dict(url=url, use_session=True)
|
|
477
298
|
|
|
478
299
|
|
|
479
300
|
@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.INCLUDE)
|
|
480
301
|
@dataclass(repr=False)
|
|
481
|
-
class
|
|
302
|
+
class BatchProcessRequest(BaseBatchRequest): # pylint: disable=abstract-method
|
|
482
303
|
"""A dataclass object that holds information about a batch request"""
|
|
483
304
|
|
|
484
305
|
# dataclass_json doesn't handle parameter inheritance correctly
|
|
485
|
-
# pylint: disable=
|
|
306
|
+
# pylint: disable=invalid-name
|
|
486
307
|
|
|
487
308
|
request_id: str = field(metadata=dataclass_config(field_name="id"))
|
|
488
|
-
|
|
489
|
-
|
|
309
|
+
request: dict
|
|
310
|
+
domain_account_id: str
|
|
490
311
|
status: BatchRequestStatus = field(metadata=enum_config(BatchRequestStatus))
|
|
491
|
-
user_id: Optional[str] = None
|
|
492
|
-
created: Optional[dt.datetime] = field(metadata=datetime_config, default=None)
|
|
493
|
-
tiling_grid: dict = field(default_factory=dict)
|
|
494
|
-
output: dict = field(default_factory=dict)
|
|
495
|
-
bucket_name: Optional[str] = None
|
|
496
|
-
description: Optional[str] = None
|
|
497
|
-
value_estimate: Optional[float] = None
|
|
498
|
-
tile_width_px: Optional[int] = None
|
|
499
|
-
tile_height_px: Optional[int] = None
|
|
500
|
-
user_action: Optional[BatchUserAction] = field(metadata=enum_config(BatchUserAction), default=None)
|
|
501
|
-
user_action_updated: Optional[str] = field(metadata=datetime_config, default=None)
|
|
502
312
|
error: Optional[str] = None
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
"user_action",
|
|
512
|
-
"value_estimate",
|
|
513
|
-
"tile_count",
|
|
313
|
+
user_action: Optional[BatchUserAction] = field(metadata=enum_config(BatchUserAction), default=None)
|
|
314
|
+
user_action_updated: Optional[dt.datetime] = field(metadata=datetime_config, default=None)
|
|
315
|
+
created: Optional[dt.datetime] = field(metadata=datetime_config, default=None)
|
|
316
|
+
completion_percentage: float = 0
|
|
317
|
+
last_updated: Optional[dt.datetime] = field(metadata=datetime_config, default=None)
|
|
318
|
+
cost_PU: Optional[float] = field(metadata=dataclass_config(field_name="costPU"), default=None) # noqa: N815
|
|
319
|
+
stopped_status_reason: Optional[StoppedStatusReason] = field(
|
|
320
|
+
metadata=enum_config(StoppedStatusReason), default=None
|
|
514
321
|
)
|
|
515
322
|
|
|
516
|
-
@property
|
|
517
|
-
def evalscript(self) -> str:
|
|
518
|
-
"""Provides an evalscript used by a batch request
|
|
519
|
-
|
|
520
|
-
:return: An evalscript
|
|
521
|
-
"""
|
|
522
|
-
return self.process_request["evalscript"]
|
|
523
|
-
|
|
524
|
-
@property
|
|
525
|
-
def bbox(self) -> Optional[BBox]:
|
|
526
|
-
"""Provides a bounding box used by a batch request
|
|
527
|
-
|
|
528
|
-
:return: An area bounding box together with CRS
|
|
529
|
-
:raises: ValueError
|
|
530
|
-
"""
|
|
531
|
-
bbox, _, crs = self._parse_bounds_payload()
|
|
532
|
-
return None if bbox is None else BBox(bbox, crs) # type: ignore[arg-type]
|
|
533
|
-
|
|
534
|
-
@property
|
|
535
|
-
def geometry(self) -> Optional[Geometry]:
|
|
536
|
-
"""Provides a geometry used by a batch request
|
|
537
|
-
|
|
538
|
-
:return: An area geometry together with CRS
|
|
539
|
-
:raises: ValueError
|
|
540
|
-
"""
|
|
541
|
-
_, geometry, crs = self._parse_bounds_payload()
|
|
542
|
-
return None if geometry is None else Geometry(geometry, crs)
|
|
543
|
-
|
|
544
|
-
def _parse_bounds_payload(self) -> Tuple[Optional[List[float]], Optional[list], CRS]:
|
|
545
|
-
"""Parses bbox, geometry and crs from batch request payload. If bbox or geometry don't exist it returns None
|
|
546
|
-
instead.
|
|
547
|
-
"""
|
|
548
|
-
bounds_definition = self.process_request["input"]["bounds"]
|
|
549
|
-
crs = CRS(bounds_definition["properties"]["crs"].rsplit("/", 1)[-1])
|
|
550
|
-
|
|
551
|
-
return bounds_definition.get("bbox"), bounds_definition.get("geometry"), crs
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.INCLUDE)
|
|
555
|
-
@dataclass
|
|
556
|
-
class BatchCollectionBatchData:
|
|
557
|
-
"""Dataclass to hold batch collection batchData part of the payload"""
|
|
558
|
-
|
|
559
|
-
tiling_grid_id: Optional[int] = None
|
|
560
|
-
other_data: CatchAll = field(default_factory=dict)
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
@dataclass_json(letter_case=LetterCase.CAMEL, undefined=Undefined.INCLUDE)
|
|
564
|
-
@dataclass
|
|
565
|
-
class BatchCollectionAdditionalData:
|
|
566
|
-
"""Dataclass to hold batch collection additionalData part of the payload"""
|
|
567
|
-
|
|
568
|
-
bands: Optional[Dict[str, Any]] = None
|
|
569
323
|
other_data: CatchAll = field(default_factory=dict)
|
|
570
324
|
|
|
571
|
-
|
|
572
|
-
class BatchCollection(BaseCollection):
|
|
573
|
-
"""Dataclass for batch collections"""
|
|
574
|
-
|
|
575
|
-
batch_data: Optional[BatchCollectionBatchData] = None
|
|
576
|
-
additional_data: Optional[BatchCollectionAdditionalData] = None
|
|
325
|
+
_REPR_PARAM_NAMES = ("request_id", "created", "status", "completion_percentage", "user_action", "cost_PU")
|