Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…into fiat_adapter
  • Loading branch information
panosatha committed Jan 17, 2025
2 parents f7004dd + 11b2462 commit cf03679
Show file tree
Hide file tree
Showing 60 changed files with 1,074 additions and 963 deletions.
20 changes: 15 additions & 5 deletions .github/workflows/publish-to-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,16 @@ name: release
# 1. In github settings:
# - Create an environment called `release`
# - Setup the permissions (https://github.com/<ORGANIZATION>/<REPO_NAME>/settings/environments)
# - Add the following variables:
# - PACKAGE_NAME: the name of your package on pypi
# - PYTHON_VERSION: the version of Python you want to use

# 2. On PyPi:
# - Create the project and add a trusted publisher (https://pypi.org/manage/project/<PACKAGE_NAME>/settings/publishing/ or https://pypi.org/manage/account/publishing if the project is not on pypi yet)
# - Ensure the publisher is configured to use:
# - the filename of this workflow yml (in this case: publish-to-pypi.yml)

# 3. In this file:
# - Add the following variables to the `env` section:
# - PACKAGE_NAME: the name of your package on pypi
# - PYTHON_VERSION: the version of Python you want to use
# - In the `setup_and_build` job:
# - Update the the shell commands to install your package

Expand All @@ -36,6 +37,11 @@ on:
- v[0-9]+\.[0-9]+\.[0-9]+
# https://peps.python.org/pep-0440/


env:
PACKAGE_NAME: "flood-adapt"
PYTHON_VERSION: "3.10"

jobs:
details:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -95,10 +101,13 @@ jobs:
- uses: conda-incubator/setup-miniconda@v3
with:
auto-update-conda: true
activate-environment: publish
python-version: ${{ env.PYTHON_VERSION }}
channels: conda-forge

- name: Create environment
shell: bash -el {0}
run: |
conda create -n publish python=${{ env.PYTHON_VERSION }}
- name: Install Build tools
shell: bash -el {0}
run: |
Expand All @@ -107,6 +116,7 @@ jobs:
- name: Install dependencies
shell: bash -el {0}
run: |
conda install -n publish gdal basemap cftime fiona netCDF4 pygeos pyproj rasterio rtree shapely --channel conda-forge
conda run -n publish pip install .
- name: Build source and wheel distribution
Expand Down
6 changes: 3 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
// Python settings
"python.analysis.typeEvaluation.strictDictionaryInference": true,
"python.analysis.typeEvaluation.strictListInference": true,
"python.analysis.typeEvaluation.strictSetInference": true,
"python.analysis.typeEvaluation.strictDictionaryInference": false,
"python.analysis.typeEvaluation.strictListInference": false,
"python.analysis.typeEvaluation.strictSetInference": false,
"python.missingPackage.severity": "Error",

"debug.console.closeOnEnd": true,
Expand Down
1 change: 0 additions & 1 deletion docs/_quarto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ quartodoc:
- name: object_model.benefit.Benefit
- name: adapter.impacts_integrator.Impacts
- name: object_model.scenario.Scenario
- name: object_model.interface.site.Site
- name: object_model.strategy.Strategy
- name: misc.log.FloodAdaptLogging
- name: misc.config.Settings
Expand Down
24 changes: 12 additions & 12 deletions flood_adapt/adapter/fiat_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,9 +422,9 @@ def apply_economic_growth(
]

# Get objects that are buildings (using site info)
buildings_rows = ~self._model.exposure.exposure_db["Primary Object Type"].isin(
self._site.attrs.fiat.non_building_names
)
buildings_rows = ~self.fiat_model.exposure.exposure_db[
"Primary Object Type"
].isin(self.site.attrs.fiat.config.non_building_names)

# If ids are given use that as an additional filter
if ids:
Expand Down Expand Up @@ -466,9 +466,9 @@ def apply_population_growth_existing(
]

# Get objects that are buildings (using site info)
buildings_rows = ~self._model.exposure.exposure_db["Primary Object Type"].isin(
self._site.attrs.fiat.non_building_names
)
buildings_rows = ~self.fiat_model.exposure.exposure_db[
"Primary Object Type"
].isin(self.site.attrs.fiat.config.non_building_names)

# If ids are given use that as an additional filter
if ids:
Expand Down Expand Up @@ -614,9 +614,9 @@ def buyout_properties(self, buyout: Buyout, ids: Optional[list[str]] = []):
]

# Get objects that are buildings (using site info)
buildings_rows = ~self._model.exposure.exposure_db["Primary Object Type"].isin(
self._site.attrs.fiat.non_building_names
)
buildings_rows = ~self.fiat_model.exposure.exposure_db[
"Primary Object Type"
].isin(self.site.attrs.fiat.config.non_building_names)

# Get rows that are affected
objectids = get_object_ids(buyout, self._model)
Expand Down Expand Up @@ -671,7 +671,7 @@ def get_buildings(self) -> gpd.GeoDataFrame:
)
return self._model.exposure.select_objects(
primary_object_type="ALL",
non_building_names=self._site.attrs.fiat.non_building_names,
non_building_names=self.site.attrs.fiat.config.non_building_names,
return_gdf=True,
)

Expand All @@ -686,7 +686,7 @@ def get_property_types(self) -> list:
raise ValueError("No property types found in the FIAT model.")
types.append("all") # Add "all" type for using as identifier

names = self._site.attrs.fiat.non_building_names
names = self.site.attrs.fiat.config.non_building_names
if names:
for name in names:
if name in types:
Expand Down Expand Up @@ -725,7 +725,7 @@ def get_object_ids(
ids = self._model.exposure.get_object_ids(
selection_type=measure.attrs.selection_type,
property_type=measure.attrs.property_type,
non_building_names=self._site.attrs.fiat.non_building_names,
non_building_names=self.site.attrs.fiat.config.non_building_names,
aggregation=measure.attrs.aggregation_area_type,
aggregation_area_name=measure.attrs.aggregation_area_name,
polygon_file=str(polygon_file),
Expand Down
8 changes: 4 additions & 4 deletions flood_adapt/adapter/impacts_integrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,19 +169,19 @@ def preprocess_fiat(self):
dem = (
self.database.static_path
/ "dem"
/ self.site_info.attrs.dem.filename
/ self.site_info.attrs.sfincs.dem.filename
)
aggregation_areas = [
self.database.static_path / aggr.file
for aggr in self.site_info.attrs.fiat.aggregation
for aggr in self.site_info.attrs.fiat.config.aggregation
]
attribute_names = [
aggr.field_name
for aggr in self.site_info.attrs.fiat.aggregation
for aggr in self.site_info.attrs.fiat.config.aggregation
]
label_names = [
f"Aggregation Label: {aggr.name}"
for aggr in self.site_info.attrs.fiat.aggregation
for aggr in self.site_info.attrs.fiat.config.aggregation
]

fa.apply_population_growth_new(
Expand Down
57 changes: 31 additions & 26 deletions flood_adapt/adapter/sfincs_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
GreenInfrastructure,
)
from flood_adapt.object_model.hazard.measure.pump import Pump
from flood_adapt.object_model.interface.config.site import Site
from flood_adapt.object_model.interface.measures import IMeasure
from flood_adapt.object_model.interface.path_builder import (
ObjectDir,
Expand All @@ -80,7 +81,6 @@
PhysicalProjectionModel,
)
from flood_adapt.object_model.interface.scenarios import IScenario
from flood_adapt.object_model.interface.site import Site
from flood_adapt.object_model.io import unit_system as us
from flood_adapt.object_model.utils import cd, resolve_filepath

Expand Down Expand Up @@ -500,7 +500,9 @@ def write_floodmap_geotiff(
):
results_path = self._get_result_path(scenario)
sim_path = sim_path or self._get_simulation_paths(scenario)[0]
demfile = self.database.static_path / "dem" / self.site.attrs.dem.filename
demfile = (
self.database.static_path / "dem" / self.site.attrs.sfincs.dem.filename
)

# read SFINCS model
with SfincsAdapter(model_root=sim_path) as model:
Expand Down Expand Up @@ -568,7 +570,7 @@ def plot_wl_obs(
with SfincsAdapter(model_root=sim_path) as model:
df, gdf = model._get_zs_points()

gui_units = us.UnitTypesLength(self.site.attrs.gui.default_length_units)
gui_units = us.UnitTypesLength(self.site.attrs.gui.units.default_length_units)
conversion_factor = us.UnitfulLength(
value=1.0, units=us.UnitTypesLength("meters")
).convert(gui_units)
Expand All @@ -577,21 +579,21 @@ def plot_wl_obs(
# Plot actual thing
fig = px.line(
df[col] * conversion_factor
+ self.site.attrs.water_level.localdatum.height.convert(
+ self.site.attrs.sfincs.water_level.localdatum.height.convert(
gui_units
) # convert to reference datum for plotting
)

# plot reference water levels
fig.add_hline(
y=self.site.attrs.water_level.msl.height.convert(gui_units),
y=self.site.attrs.sfincs.water_level.msl.height.convert(gui_units),
line_dash="dash",
line_color="#000000",
annotation_text=self.site.attrs.water_level.msl.name,
annotation_text=self.site.attrs.sfincs.water_level.msl.name,
annotation_position="bottom right",
)
if self.site.attrs.water_level.other:
for wl_ref in self.site.attrs.water_level.other:
if self.site.attrs.sfincs.water_level.other:
for wl_ref in self.site.attrs.sfincs.water_level.other:
fig.add_hline(
y=wl_ref.height.convert(gui_units),
line_dash="dash",
Expand Down Expand Up @@ -621,10 +623,10 @@ def plot_wl_obs(

# check if event is historic
if isinstance(event, HistoricalEvent):
if self.site.attrs.tide_gauge is None:
if self.site.attrs.sfincs.tide_gauge is None:
continue
df_gauge = TideGauge(
attrs=self.site.attrs.tide_gauge
attrs=self.site.attrs.sfincs.tide_gauge
).get_waterlevels_in_time_frame(
time=TimeModel(
start_time=event.attrs.time.start_time,
Expand All @@ -636,7 +638,7 @@ def plot_wl_obs(
if df_gauge is not None:
waterlevel = df_gauge.iloc[
:, 0
] + self.site.attrs.water_level.msl.height.convert(gui_units)
] + self.site.attrs.sfincs.water_level.msl.height.convert(gui_units)

# If data is available, add to plot
fig.add_trace(
Expand All @@ -657,10 +659,10 @@ def plot_wl_obs(

def add_obs_points(self):
"""Add observation points provided in the site toml to SFINCS model."""
if self.site.attrs.obs_point is not None:
if self.site.attrs.sfincs.obs_point is not None:
self.logger.info("Adding observation points to the overland flood model...")

obs_points = self.site.attrs.obs_point
obs_points = self.site.attrs.sfincs.obs_point
names = []
lat = []
lon = []
Expand Down Expand Up @@ -716,7 +718,7 @@ def calculate_rp_floodmaps(self, scenario: IScenario):

phys_proj = scenario.projection.get_physical_projection()

floodmap_rp = self.site.attrs.risk.return_periods
floodmap_rp = self.site.attrs.fiat.risk.return_periods
frequencies = scenario.event.attrs.frequency

# adjust storm frequency for hurricane events
Expand Down Expand Up @@ -816,7 +818,9 @@ def calculate_rp_floodmaps(self, scenario: IScenario):

# write geotiff
# dem file for high resolution flood depth map
demfile = self.database.static_path / "dem" / self.site.attrs.dem.filename
demfile = (
self.database.static_path / "dem" / self.site.attrs.sfincs.dem.filename
)

# writing the geotiff to the scenario results folder
with SfincsAdapter(model_root=sim_paths[0]) as dummymodel:
Expand Down Expand Up @@ -1021,13 +1025,13 @@ def _add_forcing_waterlevels(self, forcing: IWaterlevel):
df_ts *= conversion
self._set_waterlevel_forcing(df_ts)
elif isinstance(forcing, WaterlevelGauged):
if self.site.attrs.tide_gauge is None:
if self.site.attrs.sfincs.tide_gauge is None:
raise ValueError("No tide gauge defined for this site.")
df_ts = TideGauge(self.site.attrs.tide_gauge).get_waterlevels_in_time_frame(
time=time_frame
)
df_ts = TideGauge(
self.site.attrs.sfincs.tide_gauge
).get_waterlevels_in_time_frame(time=time_frame)
conversion = us.UnitfulLength(
value=1.0, units=self.site.attrs.tide_gauge.units
value=1.0, units=self.site.attrs.sfincs.tide_gauge.units
).convert(us.UnitTypesLength.meters)
df_ts *= conversion
self._set_waterlevel_forcing(df_ts)
Expand Down Expand Up @@ -1097,7 +1101,7 @@ def _add_measure_floodwall(self, floodwall: FloodWall):
float(
us.UnitfulLength(
value=float(height),
units=self.site.attrs.gui.default_length_units,
units=self.site.attrs.gui.units.default_length_units,
).convert(us.UnitTypesLength("meters"))
)
for height in gdf_floodwall["z"]
Expand Down Expand Up @@ -1363,7 +1367,7 @@ def _get_simulation_paths(self, scenario: IScenario) -> List[Path]:
base_path = (
self._get_result_path(scenario)
/ "simulations"
/ self.site.attrs.sfincs.overland_model
/ self.site.attrs.sfincs.config.overland_model
)

if isinstance(scenario.event, EventSet):
Expand All @@ -1383,7 +1387,7 @@ def _get_simulation_path_offshore(self, scenario: IScenario) -> List[Path]:
base_path = (
self._get_result_path(scenario)
/ "simulations"
/ self.site.attrs.sfincs.offshore_model
/ self.site.attrs.sfincs.config.offshore_model
)
if isinstance(scenario.event, EventSet):
return [
Expand Down Expand Up @@ -1430,8 +1434,8 @@ def _get_zs_points(self):
names = []
descriptions = []
# get station names from site.toml
if self.site.attrs.obs_point is not None:
obs_points = self.site.attrs.obs_point
if self.site.attrs.sfincs.obs_point is not None:
obs_points = self.site.attrs.sfincs.obs_point
for pt in obs_points:
names.append(pt.name)
descriptions.append(pt.description)
Expand All @@ -1447,11 +1451,12 @@ def _get_zs_points(self):
# @gundula do we keep this func, its not used anywhere?
def _downscale_hmax(self, zsmax, demfile: Path):
# read DEM and convert units to metric units used by SFINCS
demfile_units = self.site.attrs.dem.units
demfile_units = self.site.attrs.sfincs.dem.units
dem_conversion = us.UnitfulLength(value=1.0, units=demfile_units).convert(
us.UnitTypesLength("meters")
)
dem = dem_conversion * self._model.data_catalog.get_rasterdataset(demfile)
dem = dem.rio.reproject(self.sf_model.crs)

# determine conversion factor for output floodmap
floodmap_units = self.site.attrs.sfincs.floodmap_units
Expand Down
9 changes: 5 additions & 4 deletions flood_adapt/api/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
CSVTimeseries,
SyntheticTimeseriesModel,
)
from flood_adapt.object_model.hazard.forcing.waterlevels import SurgeModel, TideModel
from flood_adapt.object_model.hazard.interface.events import (
IEvent,
IEventModel,
Expand All @@ -45,6 +46,7 @@
ShapeType,
)
from flood_adapt.object_model.hazard.interface.models import TimeModel
from flood_adapt.object_model.interface.config.sfincs import RiverModel
from flood_adapt.object_model.io import unit_system as us

# Ensure all objects are imported and available for use if this module is imported
Expand Down Expand Up @@ -78,6 +80,9 @@
"CSVTimeseries",
"SyntheticTimeseriesModel",
"DischargeConstant",
"RiverModel",
"SurgeModel",
"TideModel",
]


Expand Down Expand Up @@ -148,10 +153,6 @@ def create_event(attrs: dict[str, Any] | IEventModel) -> IEvent | EventSet:
return EventFactory.load_dict(attrs)


def list_forcing_types() -> list[str]:
return ForcingFactory.list_forcing_types()


def list_forcings() -> list[Type[IForcing]]:
return ForcingFactory.list_forcings()

Expand Down
Loading

0 comments on commit cf03679

Please sign in to comment.