# Import packages
import contextily as cx
import geopandas as gpd
import rasterio
import rasterio.plot
from datetime import datetime
from pathlib import Path
from IPython.display import HTML
from flood_adapt.objects import forcing as f
from flood_adapt.objects import (
HurricaneEvent,
TimeFrame,
Elevate,
FloodProof,
FloodWall,
GreenInfrastructure,
SelectionType,
MeasureType,
Projection,
PhysicalProjection,
SocioEconomicChange,
Scenario,
Strategy,
)
from flood_adapt.objects.events.hurricane import TranslationModel
from flood_adapt import FloodAdapt, Settings
from flood_adapt import unit_system as us
π Example: Advanced Scenario
In this notebook we demonstrate the workflow on how you can build an advanced FloodAdapt scenario in Charleston, USA, using the API.
In this notebook we will cover the following steps:
- Create a synthetic event
- Create a projection - Sea level rise (SLR)
- Create a measure and strategy - Seawall
- Create and run a scenario
- Investigate the output
Import libraries
π Step 1. Reading-in the FloodAdapt database
Letβs start with initiating the database and FloodAdapt class. 1. Initiate the database class Settings
by defining the DATABASE_ROOT
and DATABASE_NAME
. 2. Initiate the FloodAdapt
class by parsing the Settings().database_path
.
# Define the static data folder
= Path("../../_data/examples/static-data/5_Advanced_Scenario").resolve()
STATIC_DATA_DIR = Path("../../_data/system/win-64/sfincs/sfincs.exe").resolve()
SFINCS_BIN_PATH = Path("../../_data/system/win-64/fiat/fiat.exe").resolve()
FIAT_BIN_PATH
# Set up the settings for the database
= Settings(
settings =Path("../../_data/examples").resolve(),
DATABASE_ROOT="charleston_test",
DATABASE_NAME=FIAT_BIN_PATH,
FIAT_BIN_PATH=SFINCS_BIN_PATH,
SFINCS_BIN_PATH=True,
VALIDATE_BINARIES
)
# Create the FloodAdapt instance
= FloodAdapt(settings.database_path) fa
π Step 2. Events - Create a synthetic Event
Events in FloodAdapt are categorized into different forcings: 1. Wind 2. Rainfall 3. Discharge 4. Water Level
If you want to learn more about the individual forcings in FloodAdapt, please go and read the section on Events in the FloodAdapt documentation.
When creating an event, we need to create an Event
object. Depending on which type of event we create, we select a different class. In this example we create a synthetic event, therefore we use the SyntheticEvent
class.
To create the SyntheticEvent
object we use the time
attribute to define the event duration. This should be parsed as a TimeFrame
object. In the forcings
attribute we aggregated the different forcing objects in a dictionary.
In this event example we will create an event with the following forcings
:
π¬οΈ WindConstant
: Define a value for a constant wind speed (mps) and direction (degrees)
π§οΈ RainfallConstant
: Define a value for a constant rainfall (mm/hr)
π¦ DischargeConstant
: Define the x and y coordinates of the discharge point of the Cooper River and a value for a constant mean discharge (cfs) in the River- and Discharge model (same value)
π WaterlevelSynthetic SurgeModel
: Define a peak time (h), peak value in (m) and duration (d)
βοΈοΈ WaterlevelSynthetic TideModel
: Define the harmonic amplitude (m), harmonic period (h) and harmonic phase (h)
For a complete guide on all the possible event options and inputs check out the notebook specifically on events.
Step 2.1: Create a Historical Hurricane Event
In FloodAdapt we can re-create and edit historical hurricanes and explore their impacts with altered parameters to answer community questions e.g. what would have happened if the hurrican made landfall further south/north? To create a hurricane we need to do he following steps: 1. Set a time frame 2. Define the waterlevel 3. Obtain the hurricane track 4. Add rainfall 5. Add wind 6. Add River discharge
For a detailed description on how to create a hurricane event go to the event notebook.
# Create an time frame for the simulation
= datetime(year=2025, month=1, day=1)
start_time = datetime(year=2025, month=1, day=2)
end_time = TimeFrame(start_time=start_time, end_time=end_time)
time_frame
# Define Water Level Forcing
= f.WaterlevelModel()
water_levels
# Obtain a hurricane track
## Get the cyclone database
= fa.database.static.get_cyclone_track_database()
cyclone_db = cyclone_db.list_names().index("IAN")
ian_index
## Not all cyclone tracks have names, in addition to duplicate names existing, so it is better to use the index
= fa.get_cyclone_track_by_index(index=ian_index)
track = STATIC_DATA_DIR / "IAN.cyc"
track_file =track_file, fmt="ddb_cyc")
track.write_track(filename
## Optionally translate the cyclone track from what is defined in the file
= TranslationModel(
translation =us.UnitfulLength(value=3000, units=us.UnitTypesLength.meters),
eastwest_translation=us.UnitfulLength(value=5000, units=us.UnitTypesLength.meters),
northsouth_translation
)
# We want to include the rainfall and wind from the hurricane track
= f.RainfallTrack(path=track_file)
rainfall = f.WindTrack(path=track_file)
wind
# The available rivers are defined in the hazard model when creating the database.
# You cannot add new rivers to the model in an event, you can only set the discharge of each given river.
= fa.database.site.sfincs.river[0]
river
= f.DischargeConstant(
discharge =river,
river=us.UnitfulDischarge(value=100, units=us.UnitTypesDischarge.cms)
discharge
)
# Inspect
= discharge.to_dataframe(time_frame=time_frame)
df ="Constant Discharge River", xlabel="Time", ylabel="Discharge (cms)", legend=True, figsize=(5, 2)) df.plot(title
πͺοΈπ Letβs put the forcings together and create the HurricaneEvent
object.
# Create a hurricaneEvent with the forcings and time frame
= HurricaneEvent(
event ="ian_hurricane_event",
name=time_frame,
time= {
forcings # The keys of the dictionary are the forcing types, and the values are lists of the corresponding forcing objects.
f.ForcingType.WATERLEVEL: [water_levels],
f.ForcingType.RAINFALL: [rainfall],
f.ForcingType.WIND: [wind],
f.ForcingType.DISCHARGE: [discharge],
},=track.name,
track_name=translation,
hurricane_translation )
πΎ Step 2.1. Saving the event to the database
# Save the event to the database
fa.save_event(event)
π Step 3. Projections - Create a projection
Projections in FloodAdapt allow us to adjust our model to future conditions such as sea level rise or/and population growth. If you want to learn more about projections in FlooAdapt, please go to the section Projections in the FloodAdapt documentation.
The projections can be divided into two categories: 1. π Physical Projections: Sea level rise, intensified precipitation, increased storm frequency 2. π° Socio economic change: Population growth (existing built area, new development area), economic growth
When creating a projection we need to create a Projection
object. The PhysicalProjection
attribute is parsed as a PhysicalProjection
object which captures the physical projection such as sea lvel rise. The SocioEconomicChange
attribute is parsed as a SocioEconomicChange
object which captures the socioeconomic projection such as population growth. Itβs not mandatory to parse both projections. If we only want to use one of the two types of projections we can leave the other one blank ().
The attributes of the PhysicalProjection
or SocioEconomicChange
object define the projection. In this case we parse the attribute sea_level_rise
to the PhysicalProjection
object and define the value in UnitfulLength
and the unit in UnitTypesLength
.
To get a deeper understanding for all the possible projections and their inputs go to the notebook specifically about projections.
In this example we will make use of sea level rise scenarios for a PhysicalProjection
and explore population growth as SocioEconomicChange
.
First, letβs get the sea level rise scenarios from the database.
A FloodAdapt database can include sea level rise scenarios, describing a timeline of future sea level rise relative to a reference year. If these scenarios are available in the database the get_slr_scn_names() method will return a list of the available scenarios. To get a deeper understanding on how you can create different Projections read the projectionblablab notebook.
# Get the Scenarios
fa.get_slr_scn_names()
# Interpolate until 2050
="ssp585", year=2060) fa.interp_slr(slr_scenario
0.85
Use that projection to create the Projection
object.
= Projection(
projection ="proj_2060",
name="2060 projection",
description= PhysicalProjection(
physical_projection=us.UnitfulLength(value=fa.interp_slr(slr_scenario="ssp585", year=2060),
sea_level_rise=us.UnitTypesLength.meters)
units
),
) projection
Projection(name='proj_2060', description='2060 projection', physical_projection=PhysicalProjection(sea_level_rise=UnitfulLength(value=0.85, units=UnitTypesLength.meters), subsidence=UnitfulLength(value=0.0, units=UnitTypesLength.meters), rainfall_multiplier=1.0, storm_frequency_increase=0.0), socio_economic_change=SocioEconomicChange(population_growth_existing=0.0, economic_growth=0.0, population_growth_new=0.0, new_development_elevation=None, new_development_shapefile=None))
Now we can create the population growth projection. To capture population growth, we will create a new development area and pass the population_growth_existing
and population_growth_new
. You find a detailed explanation of these input attributes in the FloodAdapt User Guide.
We can have a quick look at the new development area.
= gpd.read_file(STATIC_DATA_DIR / "new_dev.gpkg")
new_dev new_dev.explore()
Now we can create the SocioEconomicChange
object as part of the Projection
object we created above. Then we are ready to save the projection.
# Create new development area
= SocioEconomicChange(
projection.socio_economic_change =10,
population_growth_existing=0,
economic_growth=5,
population_growth_new=str(STATIC_DATA_DIR / "new_dev.gpkg"),
new_development_shapefile=us.UnitfulLengthRefValue(
new_development_elevation=0.5,
value=us.UnitTypesLength.meters,
unitstype=us.VerticalReference.datum
) )
πΎ Step 3.1. Saving the projection to the database
# Save projection
fa.save_projection(projection)
π§± Step 4. Measures - Create a measure
Measures in FloodAdapt enable the user to mititgate the event impacts and investigate their efficiency on the fly.
Measures can be: 1. π¦ Hydraulic measures on the hazard level 2. π± Green infrastructure measures on the hazard level 3. π Impact measures on the building level.
You can read more about measures in the section Measures in the FloodAdapt documentation.
π¦ Hydraulic measures
In this example we will create two hydraulic measures, a sea wall of 12ft and a water square.
π§± To create a measure we need to create a Measure
object. In the attributes we define the measure type
object, in the first example a FloodWall
object. Additionally to the other attributes, we need to add the elevation
value as UnitfulLength
and the unit as UnitTypesLength
of the sea wall.
# Create a measure object for a seawall
= FloodWall(
seawall ="seawall_16ft",
name="16ft Seawall",
description=SelectionType.polyline,
selection_type=str(STATIC_DATA_DIR / "seawall.geojson"),
polygon_file=us.UnitfulLength(value=16, units=us.UnitTypesLength.feet)
elevation )
π¦ Next, we create the GreenInfrastructure
water square object. Instead of the elevation
attribute we need to define the volume
of the total storage capacity of the water square. We use the UnitfulVolume
object to define the value and unit
of the storage capacity. Optionally we can add the height
of the water square to validate the total storage volume.
# Create a measure object for a water square
= GreenInfrastructure(
water_square ="water_square",
name="Water Square",
descriptiontype=MeasureType.water_square,
=SelectionType.polygon,
selection_type=str(STATIC_DATA_DIR / "water_square.geojson"),
polygon_file=us.UnitfulVolume(value=43975190.31512848, units=us.UnitTypesVolume.cf),
volume=us.UnitfulHeight(value=3, units = us.UnitTypesLength.feet)
height )
π Impact Measure
Letβs add two more measures on the impact level. We can for example flood proof and elevate buildings in a specific area to mititgate the impact on these assets.
β¬οΈ When elevating buildings we need to create a Elevate
object. To specify which buildings should be elevated we choose a selection_type
and then either provide a spatial file with the boundaries of the area or select a whole aggregation area from our model. We can also specify which building types we want the measure to be applied on by defining the property type
attribute. we need to use the property type (e.g. residential, commercial, ALLβ¦) that is used in our Delft-FIAT Model.
To capture the magnitude of elevation of the buildings we define the elevation
attribute. Here we provide the value, unit of type UnitTypesLength
, and vertical reference of type VerticalReference
as part of the UnitfulLengthRefValue
object.
# Create a measure object for elevating buildings
= Elevate(
elevate ="elevated_homes_1ft",
name="Elevate residential buildings",
description=SelectionType.polygon,
selection_type=str(STATIC_DATA_DIR / "raise_property_polygon.geojson"),
polygon_file="ALL",
property_type=us.UnitfulLengthRefValue(value=1, units=us.UnitTypesLength.feet, type=us.VerticalReference.floodmap)
elevation )
π¦Ί When we flood proof buildings we follow similar steps as when we elevate buildings. We create a FloodProof
object where we define the same attributes as in the Elevate
object. The only difference is here is, that we do not need to provide a vertical_reference
for the elevation
attribute.
# Create a measure object for flood proofing commercial buildings
= FloodProof(
flood_proof ="floodproof_all_commercial",
name="Floodproofing all commercial buildings.",
description=SelectionType.all,
selection_type="commercial",
property_type=us.UnitfulLength(value=2, units=us.UnitTypesLength.feet)
elevation )
πΎ Step 4.1. Saving the measure to the database
# Save the measure
fa.save_measure(seawall)
fa.save_measure(water_square)
fa.save_measure(elevate) fa.save_measure(flood_proof)
π§© Step 5. Strategies - Create a strategy
Strategies are combinations measures. They allow us to run an test multiple measures in a single model run.
To create a strategy we need to create a Strategy
object. In the measures
attribute we parse a list of all the names of the measures that we want to apply in that strategy.
In this example we will create a strategy with the measures we created above, a sea wall of 12ft, a water square, elevating buildings 2ft above the floodmap reference in a specific area and flood proofing commercial buildings up to 1 ft.
# Create a strategy object
= Strategy(
strategy ="seawall_greening_elev_build_floodproof_com",
name="Strategy with a seawall, water square, elevation of buildings and floodp proofing commercial buildings",
description=[seawall.name, water_square.name, elevate.name, flood_proof.name],
measures )
πΎ Step 5.1. Saving the strategy to the database
# Save the strategy
fa.save_strategy(strategy)
πΊοΈ Step 6. Create a scenario
We reached the final step where we can put all the building blocks together to create a complete scenario!
A scenario is composed of:
1. Event
2. Projection
3. Strategy (Measures)
If you want to read more about the composition of scenarios, go read the Scenario-section of the FloodAdapt documentation.
When creating a scenario we need to create a Scenario
object in which we parse the name of the event
, projection
and strategy
as attributes.
# Create a scenario object
= Scenario(
scenario ="slr_pop_growth_seawall_water_square_elev_floodproof_build",
name="Nearshore event with SLR and population growth projection. Strategy with a seawall, water square, elevation of buildings and floodp proofing commercial buildings.",
description=event.name,
event=projection.name,
projection=strategy.name,
strategy )
πΎ Step 6.1. Saving the scenario to the database
# Save the scenario
fa.save_scenario(scenario)
πββοΈ Final step: Run a scenario
We are ready to run the scenario! Simply parse the scenario.name
into the function run_scenario
.
# Run the scenario
fa.run_scenario(scenario.name)
The provided timeseries does not cover the entire model time period.
2025-06-12 04:57:19 PM - FloodAdapt.SfincsAdapter - WARNING - Failed to add event rainfall multiplier, no rainfall forcing found in the model.
Downloading file 'v0.0.9/data_catalog.yml' from 'https://raw.githubusercontent.com/Deltares/hydromt/main/data/catalogs/artifact_data/v0.0.9/data_catalog.yml' to 'C:\Users\runneradmin\.hydromt_data\artifact_data'.
Downloading data from 'https://github.com/DirkEilander/hydromt-artifacts/releases/download/v0.0.9/data.tar.gz' to file 'C:\Users\runneradmin\.hydromt_data\artifact_data\v0.0.9\data.tar.gz'.
SHA256 hash of downloaded file: 32de5b95c171628547f303d7f65d53cbb1b9da9af4834717c8efff93fe55aad4
Use this value as the 'known_hash' argument of 'pooch.retrieve' to ensure that the file hasn't changed if it is downloaded again in the future.
Untarring contents of 'C:\Users\runneradmin\.hydromt_data\artifact_data\v0.0.9\data.tar.gz' to 'C:\Users\runneradmin\.hydromt_data\artifact_data\v0.0.9\data.tar'
GeoDataFrame : CRS from data catalog does not match CRS of data. The original CRS will be used. Please check your data catalog.
2025-06-12 04:57:22 PM - FloodAdapt.SfincsAdapter - WARNING - Could not use height data from file due to missing `z` column or missing values therein. Using uniform height of 16.0 feet instead.
GeoDataFrame : CRS from data catalog does not match CRS of data. The original CRS will be used. Please check your data catalog.
2025-06-12 04:57:23 PM - FloodAdapt.SfincsAdapter - WARNING - Failed to add projected rainfall multiplier, no rainfall forcing found in the model.
Replacing geom: obs
Model dir already exists and files might be overwritten: C:\a\FloodAdapt\FloodAdapt\docs\_data\examples\charleston_test\output\scenarios\slr_pop_growth_seawall_water_square_elev_floodproof_build\Flooding\simulations\overland\gis.
Finished!
Congratulations you created and ran your first FloodAdapt scenario!
Output: π΅οΈββοΈ Letβs inspect the output
1. Output files
In your scenario output folder you should see the following files: - Flooding: Folder - Impacts: Folder - finished.txt: text file - Infometrics_βscenario_nameβ.csv: csv file of the overall infometrics - Infometrics_βscenario_nameββaggregation_layerβ.csv: csv file of the aggregated areas. You have one file per aggregation level. In this example we have two files. - logfileβscenario_nameβ.log: The log of the scenario run - **βscenario_nameβ_metrics.html**: A metric file of your scenario output
The figure below presents a visual overview of all the output files that should be in your database after running the scenario2. Floodmap - Inspect the floodmap
We can open and inspect the floodmap geotiff.
# Plot max wwater level map
= fa.get_max_water_level_map(scenario.name)
max_water_level ="Max water level map", cmap="Blues")
rasterio.plot.show(max_water_level, title
# Plot floodmap geotiff
= fa.get_flood_map_geotiff(scenario.name)
geotiff_file = rasterio.open(geotiff_file)
tiff ="GeoTiff Floodmap", cmap="Blues") rasterio.plot.show(tiff, title
3. Economic Impacts - Inspect the economic impacts on the building level and aggregated
We can plot the economic impacts on the building level and on the aggregated level.
## Building Impacts
# Open building impacts
= fa.get_building_footprint_impacts(scenario.name).to_crs(epsg=3857)
gdf_impacts_buildings
# Plot building impacts
= gdf_impacts_buildings.plot(
ax =(10, 10),
figsize="Total Damage",
column="Reds",
cmap=True,
legend=0,
vmin=60000,
vmax={"label": "Total Damages ($) Buildings", "orientation": "horizontal"}
legend_kwds
)
cx.add_basemap(ax)
ax.plot()
## Aggregated Impacts
= fa.get_aggregated_impacts(scenario.name)
impacts = impacts["aggr_lvl_1"].to_crs(epsg=3857)
gdf_impacts_aggr_lvl1
# Plot aggregated impacts
= gdf_impacts_aggr_lvl1.plot(
ax =(10, 10),
figsize="TotalDamageEvent",
column="Reds",
cmap=True,
legend=0,
vmin=10000000,
vmax="k",
edgecolor={"label": "Total Damages ($) per aggregatetion area", "orientation": "horizontal"}
legend_kwds
)
cx.add_basemap(ax) ax.plot()
4. Infometrics & Infographics
Which infometrics and infographics to generate can be defined in the infometrics and infographics and configuration file in your database ../Database charleston_full/static/templates/infometrics/, ../Database/charleston_full/static/templates/infographics/"xyzβ.toml, respectively.
The figure below shows the infographics of the scenario we created above.
# Display HTML infographics
= fa.get_infographic(scenario.name)
fn =fn) HTML(filename