-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #87 from kleok/dev
CPU support, visualization, vector results
- Loading branch information
Showing
5 changed files
with
227 additions
and
258 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import geopandas as gpd | ||
import rasterio as rio | ||
import rasterio.mask | ||
import os | ||
import pandas as pd | ||
import xarray as xr | ||
import numpy as np | ||
|
||
# plotting functionalities | ||
import matplotlib.pyplot as plt | ||
import folium | ||
import matplotlib | ||
from branca.element import Template, MacroElement | ||
import branca.colormap as cm | ||
from folium.plugins import MeasureControl, Draw | ||
from xyzservices.lib import TileProvider | ||
|
||
# FLOODPY libraries | ||
from floodpy.utils.folium_categorical_legend import get_folium_categorical_template | ||
|
||
def plot_interactive_map(Floodpy_app): | ||
|
||
# Read AOI | ||
aoi = gpd.read_file(Floodpy_app.geojson_bbox) | ||
|
||
# AOI bounds | ||
left, bottom, right, top = aoi.total_bounds | ||
|
||
# Define map bounds | ||
map_bounds = [[bottom, left], [top, right]] | ||
|
||
# Create a map located to the AOI | ||
m = folium.Map(location=[aoi.centroid.y[0], aoi.centroid.x[0]], tiles="openstreetmap", zoom_start=13) | ||
|
||
folium.TileLayer("openstreetmap").add_to(m) | ||
folium.TileLayer('cartodbdark_matter').add_to(m) | ||
|
||
# measuring funcs | ||
MeasureControl('bottomleft').add_to(m) | ||
|
||
# drawing funcs | ||
draw = Draw(export = True, | ||
filename=os.path.join(Floodpy_app.projectfolder,'myJson.json'), | ||
position='topleft').add_to(m) | ||
|
||
# add geojson AOI | ||
folium.GeoJson(aoi["geometry"], | ||
show = False, | ||
name='Area of Interest').add_to(m) | ||
|
||
#------------------------------------------------------------------------------ | ||
# ESA worldcover | ||
|
||
with rio.open(Floodpy_app.lc_mosaic_filename) as src: | ||
LC_cover, out_transform = rasterio.mask.mask(src, aoi.geometry, crop=True) | ||
LC_cover = LC_cover[0,:,:] | ||
|
||
LC_map = folium.raster_layers.ImageOverlay(image = LC_cover, | ||
name = 'ESA Worldcover 2021', | ||
opacity = 1, | ||
bounds = map_bounds, | ||
show = False, | ||
colormap = lambda x: Floodpy_app.LC_COLORBAR[x]) | ||
|
||
m.add_child(LC_map) | ||
|
||
legend_categories = {Floodpy_app.LC_CATEGORIES[x]: Floodpy_app.LC_COLORBAR[x] for x in np.unique(LC_cover)} | ||
|
||
template = get_folium_categorical_template(legend_categories) | ||
macro = MacroElement() | ||
macro._template = Template(template) | ||
m.get_root().add_child(macro) | ||
|
||
#------------------------------------------------------------------------------ | ||
# S1 VV backscatter Flood image | ||
|
||
S1_stack_dB = xr.open_dataset(Floodpy_app.S1_stack_filename)['VV_dB'] | ||
Flood_data = S1_stack_dB.sel(time = pd.to_datetime(Floodpy_app.flood_datetime_str)).values | ||
|
||
vmin = np.nanquantile(Flood_data, 0.01) | ||
vmax = np.nanquantile(Flood_data, 0.99) | ||
|
||
S1_data = np.clip(Flood_data, vmin, vmax) | ||
|
||
cmap = cm.LinearColormap(['black', 'white'], | ||
index=[vmin, vmax], | ||
vmin=vmin, vmax=vmax) | ||
|
||
cmap.caption = "Backscatter coefficient VV (dB)" | ||
cmap_func = lambda x: matplotlib.colors.to_rgba(cmap(x)) if ~np.isnan(x) else (0,0,0,0) | ||
|
||
folium.raster_layers.ImageOverlay(image = S1_data, | ||
name = "Sentinel-1 ({})".format(Floodpy_app.flood_datetime_str), | ||
opacity = 1, | ||
bounds = map_bounds, | ||
colormap = cmap_func).add_to(m) | ||
m.add_child(cmap) | ||
|
||
#------------------------------------------------------------------------------ | ||
# Flood binary mask | ||
|
||
Flood_map_dataset = xr.open_dataset(Floodpy_app.Flood_map_dataset_filename) | ||
flooded_regions = Flood_map_dataset.flooded_regions.data.astype(np.int32) | ||
|
||
raster_to_coloridx = {1: (0.0, 0.0, 1.0, 0.8), | ||
0: (0.0, 0.0, 0.0, 0.0)} | ||
|
||
m.add_child(folium.raster_layers.ImageOverlay(image = flooded_regions, | ||
name = 'Flooded Regions {} (UTC)'.format(Floodpy_app.flood_datetime_str), | ||
bounds = map_bounds, | ||
colormap = lambda x: raster_to_coloridx[x])) | ||
|
||
folium.LayerControl('bottomleft', collapsed=False).add_to(m) | ||
|
||
return m |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,28 @@ | ||
from shapely.geometry import Polygon | ||
import geopandas as gpd | ||
from rasterio.features import shapes | ||
from shapely.geometry import shape | ||
import rasterio | ||
import numpy as np | ||
|
||
def create_polygon(coordinates): | ||
return Polygon(coordinates['coordinates'][0]) | ||
return Polygon(coordinates['coordinates'][0]) | ||
|
||
|
||
def convert_to_vector(Floodpy_app): | ||
with rasterio.open(Floodpy_app.Flood_map_dataset_filename) as src: | ||
data = src.read(1).astype(np.int16) | ||
|
||
# Use a generator instead of a list | ||
shape_gen = ((shape(s), v) for s, v in shapes(data, transform=src.transform)) | ||
|
||
# either build a pd.DataFrame | ||
# df = DataFrame(shape_gen, columns=['geometry', 'class']) | ||
# gdf = GeoDataFrame(df["class"], geometry=df.geometry, crs=src.crs) | ||
|
||
# or build a dict from unpacked shapes | ||
gdf = gpd.GeoDataFrame(dict(zip(["geometry", "flooded_regions"], zip(*shape_gen))), crs=src.crs) | ||
gdf = gdf.loc[gdf.flooded_regions == 1,:] | ||
gdf.datetime = Floodpy_app.flood_datetime_str | ||
|
||
gdf.to_file(Floodpy_app.Flood_map_vector_dataset_filename, driver='GeoJSON') |