lofarimaging/lofarimaging/maputil.py

105 lines
4.1 KiB
Python
Raw Normal View History

2020-02-28 05:42:39 -07:00
"""Functions for working with LOFAR single station data"""
import os
import folium
import numpy as np
from matplotlib.pyplot import imread
2020-03-04 06:36:39 -07:00
from owslib.wmts import WebMapTileService
import mercantile
2020-02-28 05:42:39 -07:00
__all__ = ["get_map", "make_leaflet_map"]
__version__ = "1.5.0"
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')
2020-03-02 10:30:28 -07:00
os.makedirs("tilecache", exist_ok=True)
2020-02-28 05:42:39 -07:00
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 make_leaflet_map(overlay_array: np.array, lon_center: float, lat_center: float, lon_min: float, lat_min: float,
2020-03-04 06:36:39 -07:00
lon_max: float, lat_max: float, opacity=0.7):
2020-02-28 05:42:39 -07:00
"""
Show an image in a leaflet map, using Folium
Args:
overlay_array: array with values to be used as overlay
lon_center: Longitude of center, in degrees
lat_center: Latitude of center, in degrees
lon_min: Longitude of lower left corner, in degrees
lat_min: Latitude of lower left corner, in degrees
lon_max: Longitude of top right corner, in degrees
lat_max: Latitude of top right corner, in degrees
opacity: Opacity of overlay
Returns:
An interactive map object that will render nicely in a Jupyter notebook.
"""
m = folium.Map(location=[lat_center, lon_center], zoom_start=19,
tiles='http://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/MapServer/' +
'tile/{z}/{y}/{x}',
attr='ESRI')
folium.TileLayer(tiles="OpenStreetMap").add_to(m)
folium.raster_layers.ImageOverlay(
2020-03-14 15:38:09 -06:00
name='Near field image',
image=overlay_array,
bounds=[[lat_min, lon_min], [lat_max, lon_max]],
opacity=opacity,
interactive=True,
cross_origin=False,
zindex=1
2020-02-28 05:42:39 -07:00
).add_to(m)
folium.LayerControl().add_to(m)
return m