Local Flood Mapping#
In the context of this notebook we referred to “local flood mapping” as performing the computation on you own machine, as opposed to remote processing which will be explained in the next notebook.
We will begin by loading the flood
module from the dask_flood_mapper
. You could use the default Dask settings, but it is often good to fine tune te settings to you machine’s specifications. We can do this by setting the Dask scheduler through the Client
of dask.distributed
.
from importlib.resources import files
import hvplot.xarray # noqa
import xarray as xr
from dask.distributed import Client
from dask_flood_mapper import flood
Here we set the Dask Scheduler with the Client
, where we avoid inter-worker communication which is common for working with numpy
and xarray
in this case.
client = Client(processes=False, threads_per_worker=2, n_workers=1, memory_limit="12GB")
client
Client
Client-dce5c823-5bfe-11f0-88ac-6045bd4c942d
Connection method: Cluster object | Cluster type: distributed.LocalCluster |
Dashboard: http://10.1.0.247:8787/status |
Cluster Info
LocalCluster
958352d8
Dashboard: http://10.1.0.247:8787/status | Workers: 1 |
Total threads: 2 | Total memory: 11.18 GiB |
Status: running | Using processes: False |
Scheduler Info
Scheduler
Scheduler-d289547f-c196-43ae-a3d8-0293dad01821
Comm: inproc://10.1.0.247/2220/1 | Workers: 1 |
Dashboard: http://10.1.0.247:8787/status | Total threads: 2 |
Started: Just now | Total memory: 11.18 GiB |
Workers
Worker: 0
Comm: inproc://10.1.0.247/2220/4 | Total threads: 2 |
Dashboard: http://10.1.0.247:46335/status | Memory: 11.18 GiB |
Nanny: None | |
Local directory: /tmp/dask-scratch-space/worker-m8i0ys7n |
No we are ready to map a flood. As an example we use here storm Babet which hit the Danish and Northern coast of Germany at the 20th of October 2023 Wikipedia. We target an area around Zingst at the Baltic coast of Northern Germany.
time_range = "2023-10-11/2023-10-25"
bbox = [12.3, 54.3, 13.1, 54.6]
fd = flood.decision(bbox=bbox, datetime=time_range).compute()
fd
sigma naught datacube processed
harmonic parameter datacube processed
projected local incidence angle processed
<xarray.DataArray 'reproject-7e5439c8f4ad45e9bac1d4d7f67c22b1' (time: 9, latitude: 1232, longitude: 3283)> Size: 291MB array([[[nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [ 0., 0., 0., ..., nan, nan, nan], ..., [nan, nan, 0., ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan]], [[nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., 0., nan, nan], ..., [nan, nan, nan, ..., 0., 0., 0.], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan]], [[nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., 0., nan, nan], ..., ... ..., [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan]], [[nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [ 0., 0., 0., ..., nan, nan, nan], ..., [nan, nan, 0., ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan], [nan, nan, 0., ..., nan, nan, nan]], [[nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., 0., nan, nan], ..., [nan, nan, nan, ..., 0., 0., 0.], [nan, nan, nan, ..., nan, nan, nan], [nan, nan, nan, ..., nan, nan, nan]]]) Coordinates: * time (time) datetime64[ns] 72B 2023-10-11T05:33:18 ... 2023-10-25... * latitude (latitude) float64 10kB 54.6 54.6 54.6 54.6 ... 54.3 54.3 54.3 * longitude (longitude) float64 26kB 12.3 12.3 12.3 12.3 ... 13.1 13.1 13.1 spatial_ref int64 8B 0
Since flood.decision
does not make a distinction between Sentinel-1 observations over land or over sea, we need to mask pixels over water. For the example here we will load a mask distributed along with this package. But in general this step is left to the user’s own discretion.
data_text = files("dask_flood_mapper.data").joinpath("wcover.nc")
wcover = xr.open_dataarray(data_text, decode_coords="all")
Then we can mask water bodies, like so:
fd = fd.where(wcover != 80)
Now we are ready to view our results. We use here hvplot
to create an animation of the flood’s extent over time.
fd.hvplot.image(
x="longitude",
y="latitude",
rasterize=True,
geo=True,
tiles=True,
project=True,
cmap=["rgba(0, 0, 1, 0.1)", "darkred"],
cticks=[(0, "non-flood"), (1, "flood")],
frame_height=400,
)
client.close()