Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
AleksMat committed Oct 23, 2018
2 parents a07a88e + 0cbe21b commit 7b2ba31
Show file tree
Hide file tree
Showing 14 changed files with 485 additions and 125 deletions.
6 changes: 6 additions & 0 deletions docs/source/geopedia.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,11 @@ geopedia
.. module:: sentinelhub.geopedia
.. autoclass:: GeopediaService
:members:
.. autoclass:: GeopediaSession
:members:
.. autoclass:: GeopediaWmsService
:members:
.. autoclass:: GeopediaImageService
:members:
.. autoclass:: GeopediaFeatureIterator
:members:
4 changes: 3 additions & 1 deletion sentinelhub/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
This module lists all externally useful classes and functions
"""

from .data_request import WmsRequest, WcsRequest, AwsTileRequest, AwsProductRequest, GeopediaWmsRequest, \
from .data_request import WmsRequest, WcsRequest, AwsTileRequest, AwsProductRequest, \
GeopediaWmsRequest, GeopediaImageRequest, \
get_safe_format, download_safe_format

from .aws import AwsProduct, AwsTile
Expand All @@ -11,6 +12,7 @@
from .areas import BBoxSplitter, OsmSplitter, TileSplitter

from .ogc import WebFeatureService
from .geopedia import GeopediaFeatureIterator, GeopediaSession

from .common import BBox
from .constants import DataSource, CustomUrlParam, CRS, MimeType, OgcConstants, AwsConstants, ServiceType
Expand Down
2 changes: 1 addition & 1 deletion sentinelhub/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
Version of sentinelhub package
"""

__version__ = "2.4.3"
__version__ = "2.4.4"
2 changes: 1 addition & 1 deletion sentinelhub/aws.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def get_base_url(self, force_http=False):
:return: base url string
:rtype: str
"""
base_url = SHConfig().aws_metadata_base_url.rstrip('/') if force_http else 's3:/'
base_url = SHConfig().aws_metadata_url.rstrip('/') if force_http else 's3:/'
aws_bucket = SHConfig().aws_s3_l1c_bucket if self.data_source is DataSource.SENTINEL2_L1C else \
SHConfig().aws_s3_l2a_bucket

Expand Down
7 changes: 4 additions & 3 deletions sentinelhub/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
"aws_access_key_id": "",
"aws_secret_access_key": "",
"ogc_base_url": "https://services.sentinel-hub.com/ogc/",
"gpd_base_url": "http://service.geopedia.world/",
"aws_metadata_base_url": "https://roda.sentinel-hub.com/",
"geopedia_wms_url": "http://service.geopedia.world/",
"geopedia_rest_url": "https://www.geopedia.world/rest/",
"aws_metadata_url": "https://roda.sentinel-hub.com/",
"aws_s3_l1c_bucket": "sentinel-s2-l1c",
"aws_s3_l2a_bucket": "sentinel-s2-l2a",
"opensearch_url": "http://opensearch.sentinel-hub.com/resto/api/collections/Sentinel2/",
Expand All @@ -14,4 +15,4 @@
"max_download_attempts": 4,
"download_sleep_time": 5,
"download_timeout_seconds": 120
}
}
12 changes: 7 additions & 5 deletions sentinelhub/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ class SHConfig:
of specifying it explicitly every time he/she creates new ogc request.
- `aws_access_key_id`: Access key for AWS Requester Pays buckets.
- `aws_secret_access_key`: Secret access key for AWS Requester Pays buckets.
- `ogc_base_url`: Base url for Sentinel Hub's services (should not be changed by the user).
- `gpd_base_url`: Base url for Geopedia's services (should not be changed by the user).
- `aws_metadata_base_url`: Base url for publicly available metadata files
- `ogc_base_url`: Base url for Sentinel Hub's services.
- `geopedia_wms_url`: Base url for Geopedia WMS services.
- `geopedia_rest_url`: Base url for Geopedia REST services.
- `aws_metadata_url`: Base url for publicly available metadata files
- `aws_s3_l1c_bucket`: Name of Sentinel-2 L1C bucket at AWS s3 service.
- `aws_s3_l2a_bucket`: Name of Sentinel-2 L2A bucket at AWS s3 service.
- `opensearch_url`: Base url for Sentinelhub Opensearch service.
Expand All @@ -46,8 +47,9 @@ class _SHConfig:
('aws_access_key_id', ''),
('aws_secret_access_key', ''),
('ogc_base_url', 'https://services.sentinel-hub.com/ogc/'),
('gpd_base_url', 'http://service.geopedia.world/'),
('aws_metadata_base_url', 'https://roda.sentinel-hub.com/'),
('geopedia_wms_url', 'http://service.geopedia.world/'),
('geopedia_rest_url', 'https://www.geopedia.world/rest/'),
('aws_metadata_url', 'https://roda.sentinel-hub.com/'),
('aws_s3_l1c_bucket', 'sentinel-s2-l1c'),
('aws_s3_l2a_bucket', 'sentinel-s2-l2a'),
('opensearch_url', 'http://opensearch.sentinel-hub.com/resto/api/collections/Sentinel2/'),
Expand Down
10 changes: 9 additions & 1 deletion sentinelhub/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ def get_version():
class ServiceType(Enum):
""" Enum constant class for type of service
Supported types are WMS, WCS, WFS, AWS
Supported types are WMS, WCS, WFS, AWS, IMAGE
"""
WMS = 'wms'
WCS = 'wcs'
WFS = 'wfs'
AWS = 'aws'
IMAGE = 'image'


class _DataSourceMeta(EnumMeta):
Expand Down Expand Up @@ -510,6 +511,13 @@ def get_expected_max_value(self):
except IndexError:
raise ValueError('Type {} is not supported by this method'.format(self))

@staticmethod
def from_string(mime_type_str):
if mime_type_str == 'jpeg':
return MimeType.JPG

return MimeType(mime_type_str)


class RequestType(Enum):
""" Enum constant class for GET/POST request type """
Expand Down
162 changes: 105 additions & 57 deletions sentinelhub/data_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from copy import deepcopy

from .ogc import OgcImageService
from .geopedia import GeopediaImageService
from .geopedia import GeopediaWmsService, GeopediaImageService
from .aws import AwsProduct, AwsTile
from .aws_safe import SafeProduct, SafeTile
from .download import download_data, ImageDecodingError, DownloadFailedException
Expand All @@ -38,10 +38,10 @@ def __init__(self, *, data_folder=None):

self.download_list = []
self.folder_list = []
self.create_request()
self._create_request()

@abstractmethod
def create_request(self):
def _create_request(self):
raise NotImplementedError

def get_download_list(self):
Expand Down Expand Up @@ -314,7 +314,7 @@ def _check_custom_url_parameters(self):
if param not in CustomUrlParam:
raise ValueError('Parameter %s is not a valid custom url parameter. Please check and fix.' % param)

def create_request(self):
def _create_request(self):
"""Set download requests
Create a list of DownloadRequests for all Sentinel-2 acquisitions within request's time interval and
Expand Down Expand Up @@ -472,96 +472,144 @@ def __init__(self, *, resx='10m', resy='10m', **kwargs):


class GeopediaRequest(DataRequest):
""" The base class for Geopedia's OGC-type requests (WMS and WCS) where all common parameters are
defined.
""" The base class for Geopedia requests where all common parameters are defined.
:param service_type: type of OGC service (WMS or WCS)
:param layer: Geopedia layer which contains requested data
:type layer: str
:param service_type: Type of the service, supported are ``ServiceType.WMS`` and ``ServiceType.IMAGE``
:type service_type: constants.ServiceType
:param size_x: number of pixels in x or resolution in x (i.e. ``512`` or ``10m``)
:type size_x: int or str
:param size_y: number of pixels in x or resolution in y (i.e. ``512`` or ``10m``)
:type size_y: int or str
:param bbox: Bounding box of the requested image. Coordinates must be in the specified coordinate reference system.
:param bbox: Bounding box of the requested data
:type bbox: common.BBox
:param layer: the preconfigured layer (image) to be returned as comma separated layer names. Required.
:type layer: str
:param theme: Geopedia's theme for which the layer is defined.
:type theme: str
:param custom_url_params: dictionary of CustomUrlParameters and their values supported by Geopedia's WMS services.
At the moment only the transparancy is supported (CustomUrlParam.TRANSPARENT).
:type custom_url_params: dictionary of CustomUrlParameter enum and its value, i.e.
``{constants.CustomUrlParam.TRANSPARENT:True}``
:param image_format: format of the returned image by the Sentinel Hub's WMS getMap service. Default is PNG, but
in some cases 32-bit TIFF is required, i.e. if requesting unprocessed raw bands.
Default is ``constants.MimeType.PNG``.
:param image_format: Format of the returned image by the Sentinel Hub's WMS getMap service. Default is
``constants.MimeType.PNG``.
:type image_format: constants.MimeType
:param data_folder: location of the directory where the fetched data will be saved.
:param data_folder: Location of the directory where the fetched data will be saved.
:type data_folder: str
"""
def __init__(self, layer, bbox, theme, *, service_type=None, size_x=None, size_y=None, custom_url_params=None,
image_format=MimeType.PNG, **kwargs):
def __init__(self, layer, service_type, *, bbox=None, theme=None, image_format=MimeType.PNG, **kwargs):
self.layer = layer
self.theme = theme
self.service_type = service_type

self.bbox = bbox
if bbox.crs is not CRS.POP_WEB:
raise ValueError('Geopedia Request at the moment supports only bounding boxes with coordinates in '
'{}'.format(CRS.POP_WEB))

self.theme = theme
self.image_format = MimeType(image_format)
self.service_type = service_type
self.size_x = size_x
self.size_y = size_y

super().__init__(**kwargs)

@abstractmethod
def _create_request(self):
raise NotImplementedError


class GeopediaWmsRequest(GeopediaRequest):
""" Web Map Service request class for Geopedia
Creates an instance of Geopedia's WMS (Web Map Service) GetMap request, which provides access to WMS layers in
Geopedia.
:param width: width (number of columns) of the returned image (array)
:type width: int or None
:param height: height (number of rows) of the returned image (array)
:type height: int or None
:param custom_url_params: dictionary of CustomUrlParameters and their values supported by Geopedia's WMS services.
At the moment only the transparency is supported (CustomUrlParam.TRANSPARENT).
:type custom_url_params: dictionary of CustomUrlParameter enum and its value, i.e.
``{constants.CustomUrlParam.TRANSPARENT:True}``
:param layer: Geopedia layer which contains requested data
:type layer: str
:param bbox: Bounding box of the requested data
:type bbox: common.BBox
:param theme: Geopedia's theme for which the layer is defined.
:type theme: str
:param image_format: Format of the returned image by the Sentinel Hub's WMS getMap service. Default is
``constants.MimeType.PNG``.
:type image_format: constants.MimeType
:param data_folder: Location of the directory where the fetched data will be saved.
:type data_folder: str
"""
def __init__(self, *, width=None, height=None, custom_url_params=None, **kwargs):
self.size_x = width
self.size_y = height

self.custom_url_params = custom_url_params

if self.custom_url_params is not None:
self._check_custom_url_parameters()

if bbox.crs is not CRS.POP_WEB:
raise ValueError('Geopedia Request at the moment supports only CRS = {}'.format(CRS.POP_WEB))

super().__init__(**kwargs)
super().__init__(service_type=ServiceType.WMS, **kwargs)

def _check_custom_url_parameters(self):
"""Checks if custom url parameters are valid parameters.
Throws ValueError if the provided parameter is not a valid parameter.
"""
for param in self.custom_url_params.keys():
if param not in [CustomUrlParam.TRANSPARENT]:
raise ValueError('Parameter %s is not a valid custom url parameter. Please check and fix.' % param)
if param is not CustomUrlParam.TRANSPARENT:
raise ValueError('Parameter {} is currently not supported.'.format(param))

def create_request(self):
def _create_request(self):
"""Set download requests
Create a list of DownloadRequests for all Sentinel-2 acquisitions within request's time interval and
acceptable cloud coverage.
"""
gpd_service = GeopediaImageService()
gpd_service = GeopediaWmsService()
self.download_list = gpd_service.get_request(self)


class GeopediaWmsRequest(GeopediaRequest):
""" Web Map Service request class for Geopedia
Creates an instance of Geopedia's WMS (Web Map Service) GetMap request,
which provides access to various layers in Geopedia.
class GeopediaImageRequest(GeopediaRequest):
"""Request to access data in a Geopedia vector / raster layer.
:param width: width (number of columns) of the returned image (array)
:type width: int or None
:param height: height (number of rows) of the returned image (array)
:type height: int or None
:param data_source: Source of requested satellite data. Default is Sentinel-2 L1C data.
:type data_source: constants.DataSource
:param bbox: Bounding box of the requested image. Coordinates must be in the specified coordinate reference system.
:type bbox: common.BBox
:param layer: the preconfigured layer (image) to be returned. Required.
:param image_field_name: Name of the field in the data table which holds images
:type image_field_name: str
:param keep_image_names: If ``True`` images will be saved with the same names as in Geopedia otherwise Geopedia
hashes will be used as names. If there are multiple images with the same names in the Geopedia layer this
parameter should be set to ``False`` to prevent images being overwritten.
:type keep_image_names: bool
:param layer: Geopedia layer which contains requested data
:type layer: str
:param bbox: Bounding box of the requested data
:type bbox: common.BBox
:param theme: Geopedia's theme for which the layer is defined.
:type theme: str
:param image_format: format of the returned image by the Geopedia WMS getMap service. Default is PNG.
:param image_format: Format of the returned image by the Sentinel Hub's WMS getMap service. Default is
``constants.MimeType.PNG``.
:type image_format: constants.MimeType
:param data_folder: location of the directory where the fetched data will be saved.
:param data_folder: Location of the directory where the fetched data will be saved.
:type data_folder: str
"""
def __init__(self, *, width=None, height=None, **kwargs):
super().__init__(service_type=ServiceType.WMS, size_x=width, size_y=height, **kwargs)
def __init__(self, *, image_field_name, keep_image_names=True, **kwargs):
self.image_field_name = image_field_name
self.keep_image_names = keep_image_names

self.gpd_iterator = None

super().__init__(service_type=ServiceType.IMAGE, **kwargs)

def _create_request(self):
"""Set a list of download requests
Set a list of DownloadRequests for all images that are under the
given property of the Geopedia's Vector layer.
"""
gpd_service = GeopediaImageService()
self.download_list = gpd_service.get_request(self)
self.gpd_iterator = gpd_service.get_gpd_iterator()

def get_items(self):
"""Returns iterator over info about data used for this request
:return: Iterator of dictionaries containing info about data used in
this request.
:rtype: Iterator[dict] or None
"""
return self.gpd_iterator


class AwsRequest(DataRequest):
Expand Down Expand Up @@ -592,7 +640,7 @@ def __init__(self, *, bands=None, metafiles=None, safe_format=False, **kwargs):
super().__init__(**kwargs)

@abstractmethod
def create_request(self):
def _create_request(self):
raise NotImplementedError

def get_aws_service(self):
Expand Down Expand Up @@ -632,7 +680,7 @@ def __init__(self, product_id, *, tile_list=None, **kwargs):

super().__init__(**kwargs)

def create_request(self):
def _create_request(self):
if self.safe_format:
self.aws_service = SafeProduct(self.product_id, tile_list=self.tile_list, bands=self.bands,
metafiles=self.metafiles)
Expand Down Expand Up @@ -680,7 +728,7 @@ def __init__(self, *, tile=None, time=None, aws_index=None, data_source=DataSour

super().__init__(**kwargs)

def create_request(self):
def _create_request(self):
if self.safe_format:
self.aws_service = SafeTile(self.tile, self.time, self.aws_index, bands=self.bands,
metafiles=self.metafiles, data_source=self.data_source)
Expand Down

0 comments on commit 7b2ba31

Please sign in to comment.