def test_wmts(): # Find out what a WMTS has to offer. Service metadata: from owslib.wmts import WebMapTileService wmts = WebMapTileService(SERVICE_URL) assert wmts.identification.type == 'OGC WMTS' assert wmts.identification.version == '1.0.0' assert wmts.identification.title == 'NASA Global Imagery Browse Services for EOSDIS' bytearray(wmts.identification.abstract, 'utf-8') bytearray(b'Near real time imagery from multiple NASA instruments') assert wmts.identification.keywords == ['World', 'Global'] # Service Provider: assert wmts.provider.name == 'National Aeronautics and Space Administration' assert wmts.provider.url == 'https://earthdata.nasa.gov/' # Available Layers: assert len(wmts.contents.keys()) > 0 assert sorted(list(wmts.contents))[0] == 'AIRS_CO_Total_Column_Day' # Fetch a tile (using some defaults): tile = wmts.gettile(layer='MODIS_Terra_CorrectedReflectance_TrueColor', tilematrixset='EPSG4326_250m', tilematrix='0', row=0, column=0, format="image/jpeg") out = open(scratch_file('nasa_modis_terra_truecolour.jpg'), 'wb') bytes_written = out.write(tile.read()) out.close() # Test styles for several layers # TODO: fix dict order # assert wmts.contents['MLS_SO2_147hPa_Night'].styles == {'default': {'isDefault': True, 'title': 'default'}} assert wmts.contents['MLS_SO2_147hPa_Night'].styles['default'][ 'isDefault'] is True # assert wmts.contents['MLS_SO2_147hPa_Night'].styles == {'default': {'isDefault': True, 'title': 'default'}} assert wmts.contents['MLS_SO2_147hPa_Night'].styles['default'][ 'isDefault'] is True
def test_wmts_rest_only(): # ServiceMetadata wmts = WebMapTileService(SERVICE_URL) assert wmts.identification.type == 'OGC WMTS' assert wmts.identification.version == '1.0.0' assert wmts.identification.title == 'WMTS-Testserver DOP80' # Content assert sorted(list(wmts.contents)) == ['dop80'] # RESTful WMTS assert wmts.restonly resource = wmts.buildTileResource(layer='dop80', tilematrixset='webmercator', tilematrix='11', row='706', column='1089') assert resource == 'http://geoserv.weichand.de/mapproxy/wmts/dop80/webmercator/11/1089/706.png' tile = wmts.gettile(layer='dop80', tilematrixset='webmercator', tilematrix='11', row='706', column='1089') out = open(scratch_file('bvv_bayern_dop80.png'), 'wb') bytes_written = out.write(tile.read()) out.close()
def test_wmts(): # Find out what a WMTS has to offer. Service metadata: from owslib.wmts import WebMapTileService wmts = WebMapTileService(SERVICE_URL) assert wmts.identification.type == 'OGC WMTS' assert wmts.identification.version == '1.0.0' assert wmts.identification.title == 'NASA Global Imagery Browse Services for EOSDIS' bytearray(wmts.identification.abstract, 'utf-8') bytearray(b'Near real time imagery from multiple NASA instruments') assert wmts.identification.keywords == ['World', 'Global'] # Service Provider: assert wmts.provider.name == 'National Aeronautics and Space Administration' assert wmts.provider.url == 'https://earthdata.nasa.gov/' # Available Layers: assert len(wmts.contents.keys()) > 0 assert sorted(list(wmts.contents))[0] == 'AIRS_All_Sky_Outgoing_Longwave_Radiation_Daily_Day' # Fetch a tile (using some defaults): tile = wmts.gettile(layer='MODIS_Terra_CorrectedReflectance_TrueColor', tilematrixset='EPSG4326_250m', tilematrix='0', row=0, column=0, format="image/jpeg") out = open(scratch_file('nasa_modis_terra_truecolour.jpg'), 'wb') bytes_written = out.write(tile.read()) out.close() # Test styles for several layers # TODO: fix dict order # assert wmts.contents['MLS_SO2_147hPa_Night'].styles == {'default': {'isDefault': True, 'title': 'default'}} assert wmts.contents['MLS_SO2_147hPa_Night'].styles['default']['isDefault'] is True # assert wmts.contents['MLS_SO2_147hPa_Night'].styles == {'default': {'isDefault': True, 'title': 'default'}} assert wmts.contents['MLS_SO2_147hPa_Night'].styles['default']['isDefault'] is True
def wmtsRequest(self, layer='AGRICULTURE'): self.layer = layer ID = 'your ID' wmts_url = 'https://services.sentinel-hub.com/ogc/wmts/'+ID wmts = WebMapTileService(wmts_url) self.x, self.y = self.deg2num(self.lat_center, self.lon_center, self.zoom) self.wmtsOut = wmts.gettile(layer=self.layer, tilematrixset='PopularWebMercator256', tilematrix=self.zoom, row=self.y, column=self.x, format="image/png") self.imgArr = imread(io.BytesIO(wmtsOut.read())) self.lat_max, self.lon_min = self.num2deg(self.x, self.y, self.zoom) self.lat_min, self.lon_max = self.num2deg(self.x+1, self.y+1, self.zoom) imgurl = image_to_url(image=self.imgArr) self.map.add_layer(ImageOverlay(url=imgurl, bounds=[[self.lat_min, self.lon_min], [self.lat_max, self.lon_max]]))
def test_wmts_gettile_exception(ows_server): wmts = WebMapTileService(url=ows_server.url + "/wmts") contents = list(wmts.contents) test_layer_name = contents[0] try: # supplying an unsupported tilematrixset wmts.gettile(layer=test_layer_name, tilematrixset='WholeWorld_WebMercatorxxx', tilematrix='0', row=0, column=0, format="image/png") except ServiceException as e: assert 'Invalid Tile Matrix Set:' in str(e) else: assert False
def test_wmts_rest_only(): # Test a WMTS with REST only from owslib.wmts import WebMapTileService wmts = WebMapTileService(SERVICE_URL_REST) tile = wmts.gettile(layer="bmaporthofoto30cm", tilematrix="10", row=357, column=547) assert (tile.info()['Content-Type'] == 'image/jpeg')
def test_wmts_example_get_title(): """ Example for wmts.getTitle """ wmts = WebMapTileService(SERVICE_URL) img = wmts.gettile(layer='VIIRS_CityLights_2012', tilematrixset='EPSG4326_500m', tilematrix='6', row=4, column=4) out = open('tile.jpg', 'wb') bytes_written = out.write(img.read()) out.close()
def get_map(lon_min, lon_max, lat_min, lat_max, zoom=19): """ Get an ESRI World Imagery map of the selected region Args: lon_min: Minimum longitude (degrees) lon_max: Maximum longitude (degrees) lat_min: Minimum latitude (degrees) lat_max: Maximum latitude (degrees) zoom: Zoom level Returns: np.array: Numpy array which can be plotted with plt.imshow """ upperleft_tile = mercantile.tile(lon_min, lat_max, zoom) xmin, ymin = upperleft_tile.x, upperleft_tile.y lowerright_tile = mercantile.tile(lon_max, lat_min, zoom) xmax, ymax = lowerright_tile.x, lowerright_tile.y total_image = np.zeros([256 * (ymax - ymin + 1), 256 * (xmax - xmin + 1), 3], dtype='uint8') os.makedirs("tilecache", exist_ok=True) tile_min = mercantile.tile(lon_min, lat_min, zoom) tile_max = mercantile.tile(lon_max, lat_max, zoom) wmts = WebMapTileService("http://server.arcgisonline.com/arcgis/rest/" + "services/World_Imagery/MapServer/WMTS/1.0.0/WMTSCapabilities.xml") for x in range(tile_min.x, tile_max.x + 1): for y in range(tile_max.y, tile_min.y + 1): tilename = os.path.join("tilecache", f"World_Imagery_{zoom}_{x}_{y}.jpg") if not os.path.isfile(tilename): tile = wmts.gettile(layer="World_Imagery", tilematrix=str(zoom), row=y, column=x) out = open(tilename, "wb") out.write(tile.read()) out.close() tile_image = imread(tilename) total_image[(y - ymin) * 256: (y - ymin + 1) * 256, (x - xmin) * 256: (x - xmin + 1) * 256] = tile_image total_llmin = {'lon': mercantile.bounds(xmin, ymax, zoom).west, 'lat': mercantile.bounds(xmin, ymax, zoom).south} total_llmax = {'lon': mercantile.bounds(xmax, ymin, zoom).east, 'lat': mercantile.bounds(xmax, ymin, zoom).north} pix_xmin = int(round(np.interp(lon_min, [total_llmin['lon'], total_llmax['lon']], [0, total_image.shape[1]]))) pix_ymin = int(round(np.interp(lat_min, [total_llmin['lat'], total_llmax['lat']], [0, total_image.shape[0]]))) pix_xmax = int(round(np.interp(lon_max, [total_llmin['lon'], total_llmax['lon']], [0, total_image.shape[1]]))) pix_ymax = int(round(np.interp(lat_max, [total_llmin['lat'], total_llmax['lat']], [0, total_image.shape[0]]))) return total_image[total_image.shape[0] - pix_ymax: total_image.shape[0] - pix_ymin, pix_xmin: pix_xmax]
def test_wmts_gettile(ows_server): wmts = WebMapTileService(url=ows_server.url + "/wmts") contents = list(wmts.contents) test_layer_name = contents[0] tile = wmts.gettile(layer=test_layer_name, tilematrixset='WholeWorld_WebMercator', tilematrix='0', row=0, column=0, format="image/png") assert tile assert tile.info()['Content-Type'] == 'image/png'
def test_wmts_gettile_wkss(ows_server): wmts = WebMapTileService(url=ows_server.url + "/wmts") contents = list(wmts.contents) test_layer_name = contents[0] tile = wmts.gettile( layer=test_layer_name, tilematrixset="urn:ogc:def:wkss:OGC:1.0:GoogleMapsCompatible", tilematrix="0", row=0, column=0, format="image/png", ) assert tile assert tile.info()["Content-Type"] == "image/png"
class TileMatrix: """ See: 07-057r7_Web_Map_Tile_Service_Standard.pdf, pp. 8-9 + annex H. """ def __init__(self, url: str, layer: str, tile_system: str, tile_level: Union[str, int], format: str) -> None: """Creates a tile matrix (WMTS layer at fixed zoom level). Args: url: The URL to the Web Map Tile Service (WMTS). layer: The WMTS layer name. tile_system: Name of the tile system (should use the Rijksdriehoek coordinate system, or at least use 1-metre units). tile_level: The zoom level. format: The image format for tiles. Usually either `image/png` or `image/jpeg`. """ self.wmts = WebMapTileService(url) self.layer = layer self.tile_system = tile_system self.tile_level = str(tile_level) self.format = format assert layer in self.wmts.contents, \ 'Layer not found.' assert tile_system in self.wmts.tilematrixsets, \ 'Tile matrix set not found.' assert tile_system in self.wmts.contents[layer].tilematrixsetlinks, \ 'Tile system not found.' assert format in self.wmts.contents[layer].formats, \ 'Unsupported format.' # See: pdf, pp. 8-9 # (Top left corner is min x and max y.) # Note: Rijksdriehoek metric is in metres. This is relevant # because the scaling parameter has been omitted for this # reason. self.matrix = ( self.wmts.tilematrixsets[tile_system].tilematrix[str(tile_level)]) self.pixel_span = self.matrix.scaledenominator * 0.28 * 1e-3 self.span_x = self.matrix.tilewidth * self.pixel_span self.span_y = self.matrix.tileheight * self.pixel_span def bbox_tiles(self, bbox: BoundingBox) -> Iterator[TileIndex]: """Iterates over all tiles that intersect the bounding box. Yields `TileIndex` instances. """ def _rd_to_tile(xy: Rijksdriehoek) -> TileIndex: """Maps one RD coordinate to an unrounded (float) tile index. """ # See: pdf, annex H.1. return TileIndex((top_left_corner[1] - xy.y) / tile_span_y, (xy.x - top_left_corner[0]) / tile_span_x) matrix_height = self.matrix.matrixheight matrix_width = self.matrix.matrixwidth tile_span_x = self.span_x tile_span_y = self.span_y top_left_corner = self.matrix.topleftcorner # See: pdf, annex H.1. row_max, col_min = _rd_to_tile(bbox.lower) row_min, col_max = _rd_to_tile(bbox.upper) eps = 1e-6 row_min = max(floor(row_min + eps), 0) col_min = max(floor(col_min + eps), 0) row_max = min(floor(row_max - eps), matrix_height - 1) col_max = min(floor(col_max - eps), matrix_width - 1) return (TileIndex(row, col) for row in range(row_min, row_max + 1) for col in range(col_min, col_max + 1)) def fetch(self, bbox: BoundingBox) -> Iterator[Tile]: """Fetches all tiles in the bounding box. Iterates over the tiles (with pointers to the downloaded images). Deletes all images after iteration. """ dir_path = tempfile.mkdtemp() ext = self.format.split('/')[-1] for index in self.bbox_tiles(bbox): filename = joinpath(dir_path, f'{index.row}_{index.col}.{ext}') yield self.fetch_tile(index, filename) # Clean up. shutil.rmtree(dir_path) def fetch_tile(self, index: TileIndex, filename: str) -> Tile: """Fetches a tile by its tile index. Returns the index, image and bounding box. """ res = self.wmts.gettile(layer=self.layer, tilematrixset=self.tile_system, tilematrix=self.tile_level, row=index.row, column=index.col, format=self.format) with open(filename, 'wb') as f: f.write(res.read()) return Tile(index, filename, self.tile_bbox(index)) def tile_bbox(self, tile: TileIndex) -> BoundingBox: """Maps a tile index to its Rijksdriehoek bounding box. """ x_min = tile.col * self.span_x + self.matrix.topleftcorner[0] y_max = self.matrix.topleftcorner[1] - tile.row * self.span_y # See: pdf, annex H.2. lower = Rijksdriehoek(x_min, y_max - self.span_y) upper = Rijksdriehoek(x_min + self.span_x, y_max) return BoundingBox(lower, upper)
def download( wmts_url: str, layer_name: str, data_dir: Path, zoom: int): """ Download the Actueel_orth25 layer from the pdok WMTS. The following subdirectory will be created in `data_dir`: <data dir>/Actueel_orth25/<zoom level> Parameters --------- wmts_url : str The url to the WMTS. layer_name : str The layer name. data_dir : Path Directory in which the jpg's are saved. zoom : int The zoom level of the layer. Link ---- https://geodata.nationaalgeoregister.nl/luchtfoto/rgb/wmts """ logger = logging.getLogger(__name__) logger.info('scraping wmts: %s', wmts_url) logger.info('layer: %s', layer_name) logger.info('data_dir: %s', data_dir) logger.info('zoom: %s', zoom) layer_dir = data_dir / layer_name zoom_dir = layer_dir / f'{zoom:02d}' for d in data_dir, layer_dir, zoom_dir: mkdir_isdir(d) wmts = WebMapTileService(wmts_url, version='1.1.1') bbox = helpers.Bbox(*wmts.contents[layer_name].boundingBoxWGS84) # TODO: For now only download data around Amsterdam bbox = helpers.Bbox( xmin=100000, ymin=460000, xmax=140000, ymax=500000, ) cols, rows = zip(*[ helpers.wgs84_to_tile_number(*point, zoom) for point in bbox.rdnew_to_wgs84() ]) pbar = tqdm( ((col, row) for col in range(*cols) for row in range(*rows, -1)), total=(cols[1] - cols[0]) * (rows[0] - rows[1]), ) for col, row in pbar: logger.debug('col=%s, row=%s', col, row) pbar.set_postfix(row=row, col=col) tile_file = zoom_dir / f'{col}_{row}.jpg' if tile_file.exists(): continue try_ = 0 while try_ < 10: time.sleep(0.1) try: tile = wmts.gettile( layer=layer_name, tilematrixset='EPSG:3857', tilematrix=f'{zoom:02d}', row=row, column=col, format="image/png" ) except requests.exceptions.ReadTimeout: logger.info('Got timeout') try_ += 1 finally: tile_file.write_bytes(tile.read()) break
class WMTS: '''Web Map Tile Service wrapper''' def __init__(self, wmts, layer=None, tms=None, tm=None, fmt=None, pixel_size=_PIXEL_SIZE): # Web Map Tile Service self.wmts = WebMapTileService(wmts) if layer is None: layer = next(iter(self.wmts.contents)) self.layer = self.wmts.contents[layer] if tms is None: tms = next(iter(self.wmts.tilematrixsets)) self.tms = self.wmts.tilematrixsets[tms] if tm is None: tm = next(iter(self.tms.tilematrix)) self.tm = self.tms.tilematrix[tm] # CRS self.crs = pp.CRS.from_user_input(self.tms.crs) self.epsg = ':'.join(self.crs.to_authority()) self._from_wgs = pp.Transformer.from_crs(_WGS84, self.crs) self._to_wgs = pp.Transformer.from_crs(self.crs, _WGS84) self.unit = self.crs.coordinate_system.axis_list[0].unit_name self.ucf = self.crs.coordinate_system.axis_list[ 0].unit_conversion_factor # Tile span(s) self.pixel_size = pixel_size self.scale = self.tm.scaledenominator self.pixel_span = self.scale * self.pixel_size * self.ucf self.tile_width = self.tm.tilewidth self.tile_height = self.tm.tileheight self.tile_span_x = self.tile_width * self.pixel_span self.tile_span_y = self.tile_height * self.pixel_span # Domain self.matrix_width = self.tm.matrixwidth self.matrix_height = self.tm.matrixheight self.x_min, self.y_max = self.tm.topleftcorner self.x_max = self.x_min + self.matrix_width * self.tile_span_x self.y_min = self.y_max - self.matrix_height * self.tile_span_y # Format self.fmt = self.layer.formats[0] if fmt is None else fmt def get_tile(self, row, col): return self.wmts.gettile(layer=self.layer.id, tilematrixset=self.tms.identifier, tilematrix=self.tm.identifier, row=row, column=col, format=self.fmt) def tile_to_xy(self, row, col): x = self.x_min + col * self.tile_span_x y = self.y_max - row * self.tile_span_y return x, y def xy_to_tile(self, x, y, integer=True): col = (x - self.x_min) / self.tile_span_x row = (self.y_max - y) / self.tile_span_y if integer: row, col = int(row), int(col) return row, col def xy_to_wgs(self, x, y): return self._to_wgs.transform(x, y) def wgs_to_xy(self, lat, lon): return self._from_wgs.transform(lat, lon) def tile_to_wgs(self, row, col): return self.xy_to_wgs(*self.tile_to_xy(row, col)) def wgs_to_tile(self, lat, lon): return self.xy_to_tile(*self.wgs_to_xy(lat, lon)) @property def domain(self): return self.x_min, self.y_min, self.x_max, self.y_max
from owslib.wmts import WebMapTileService src="/myDigitalGlobe/getbrowse?featureId=2f70a09f987b84c003809ded0b84d72c&footprintwkt=POLYGON ((-61.03964250016393 10.001272499939741, -61.03964250016393 10.00007099993966, -60.98612400010362 10.000003499939657, -60.84463049994418 10.000183499939668, -60.846286499946046 10.905209999999997, -61.03848600016263 10.882696499998495, -61.03964250016393 10.001272499939741))&viewportwkt=POLYGON ((-60.96700251102447 10.340243409146554,-60.96443027257919 10.340243409146554,-60.96443027257919 10.339170796977305,-60.96700251102447 10.339170796977305,-60.96700251102447 10.340243409146554))&featureIdType=FINISHED_FEATURE&archiveType=null" wmts = WebMapTileService("https://evwhs.digitalglobe.com/earthservice/wmtsaccess?connectid=c19b1c96-cd25-453a-96ef-4cd223c6d2c0",username='******',password=passwd) wmts.contents wmts.contents['DigitalGlobe:ImageryTileService'].formats u = openURL("https://evwhs.digitalglobe.com/earthservice/wmtsaccess","service=WMTS&connectid=c19b1c96-cd25-453a-96ef-4cd223c6d2c0&request=GetCapabilities&version=1.1.1", method='Get', username='******',password=passwd) dir(wmts.contents['DigitalGlobe:ImageryTileService'].tilematrixsetlinks['EPSG:4326']) tile = wmts.gettile(layer='DigitalGlobe:ImageryTileService', tilematrixset='EPSG:3857', tilematrix='EPSG:3857:17', row=47785, column=47785, format="image/png") #tile = wmts.gettile(layer='DigitalGlobe:ImageryTileService', tilematrixset='EPSG:4326', tilematrix='EPSG:4326:17', column=47785, row=76367, format="image/png") f = open("stile.png","wb") f.write(tile.read()) f.close() src="https://evwhs.digitalglobe.com/tiles/earthservice/wmtsaccess?connectId=c19b1c96-cd25-453a-96ef-4cd223c6d2c0&cdnKey=st=1457626216~exp=1457799016~acl=%2ftiles%2fearthservice%2fwmtsaccess%3fconnectId%3dc19b1c96-cd25-453a-96ef-4cd223c6d2c0%2a~hmac=4089e046ff674c88d05a814b4afe848eab06760e5efdb43c236ab2dbbca04a08&dgToken=607974af7d39943ec1e950edc04390fab00790b780281756d4ec634b8dc1149f&SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&TileMatrixSet=EPSG:3857&LAYER=DigitalGlobe:ImageryTileService&FORMAT=image/jpeg&STYLE=&featureProfile=Global_Currency_Profile&TileMatrix=EPSG:3857:20&TILEROW=494005&TILECOL=346711" 756d4ec634b8dc1149f&FEATURECOLLECTION=6ba149dfe589f442e9325c9593425ab4&USECLOUDLESSGEOMETRY=false&SRS=EPSG%3A3857&BBOX=-6797392.0513441535,1164288.814839805,-6794946.066439027,1166734.7997449306" src="https://evwhs.digitalglobe.com/mapservice/wmsaccess?SERVICE=WMS&REQUEST=GetMap&VERSION=1.1.1&LAYERS=DigitalGlobe%3AImagery&STYLES=&FORMAT=image%2Fpng&TRANSPARENT=true&HEIGHT=256&WIDTH=256&BGCOLOR=0xFFFFFF&CONNECTID=c19b1c96-cd25-453a-96ef-4cd223c6d2c0&DGTOKEN=607974af7d39943ec1e950edc04390fab00790b780281756d4ec634b8dc1149f&FEATURECOLLECTION=2f70a09f987b84c003809ded0b84d72c&USECLOUDLESSGEOMETRY=false&SRS=EPSG%3A3857&BBOX=-6786690.867384229,1157294.8267517104,-6786652.648870086,1157333.045265852" src="https://evwhs.digitalglobe.com/mapservice/wmsaccess?SERVICE=WMS&REQUEST=GetMap&VERSION=1.1.1&LAYERS=DigitalGlobe%3AImagery&STYLES=&FORMAT=image%2Fpng&TRANSPARENT=true &HEIGHT=256&WIDTH=256&BGCOLOR=0xFFFFFF&CONNECTID=c19b1c96-cd25-453a-96ef-4cd223c6d2c0&DGTOKEN=607974af7d39943ec1e950edc04390fab00790b780281756d4ec634b8dc1149f& FEATURECOLLECTION=2f70a09f987b84c003809ded0b84d72c&USECLOUDLESSGEOMETRY=false&SRS=EPSG%3A3857&BBOX=-6786729.085898371,1157294.8267517104,-6786690.867384229,1157333.045265852"