Skip to content

Commit

Permalink
Merge pull request #141 from Deltares/#137-allow-to-use-different-nam…
Browse files Browse the repository at this point in the history
…es-for-the-spatial-exposure-data

#137-allow-to-use-different-names-for-the-spatial-exposure-data
  • Loading branch information
frederique-hub authored Sep 28, 2023
2 parents 4d5b37b + e609e0a commit 686d08a
Show file tree
Hide file tree
Showing 27 changed files with 525 additions and 325 deletions.
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def write_nested_dropdown(name, data_cat, note="", categories=[]):
"github_url": "https://github.com", # or your GitHub Enterprise interprise
"github_user": "Deltares",
"github_repo": "hydromt_fiat",
"github_version": "main",
"github_version": "main",
"doc_path": "docs",
"default_mode": "light",
}
Expand Down Expand Up @@ -324,4 +324,4 @@ def write_nested_dropdown(name, data_cat, note="", categories=[]):
"""

# Allow errors in notebooks
# nbsphinx_allow_errors = True
# nbsphinx_allow_errors = True
2 changes: 1 addition & 1 deletion examples/data/hydromt_fiat_catalog_global.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jrc_vulnerability_curves:
paper_doi: https://dx.doi.org/10.2760/16510

jrc_vulnerability_curves_linking:
path: damage_functions/flooding/JRC_damage_functions_linking.csv
path: vulnerability_linking/JRC_damage_functions_linking.csv
data_type: DataFrame
driver: csv
meta:
Expand Down
4 changes: 1 addition & 3 deletions hydromt_fiat/api/exposure_vm.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ def set_asset_locations_source(
self.exposure_model.occupancy_type = input_source
self.exposure_model.max_potential_damage = input_source
self.exposure_model.ground_floor_height = 1 # TODO: make flexible
self.exposure_model.unit = (
Units.ft.value
) # TODO: make flexible
self.exposure_model.unit = Units.ft.value # TODO: make flexible

# Download NSI from the database
region = self.data_catalog.get_geodataframe("area_of_interest")
Expand Down
30 changes: 30 additions & 0 deletions hydromt_fiat/data/hydromt_fiat_catalog_global.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

jrc_vulnerability_curves:
path: damage_functions/flooding/JRC_damage_functions.csv
data_type: DataFrame
driver: csv
meta:
category: vulnerability
description: JRC depth-damage functions for flooding, processed into a handy format for HydroMT-FIAT.
source_url: https://publications.jrc.ec.europa.eu/repository/handle/JRC105688
paper_ref: Huizinga, J., De Moel, H. and Szewczyk, W., Global flood depth-damage functions - Methodology and the database with guidelines, EUR 28552 EN, Publications Office of the European Union, Luxembourg, 2017, ISBN 978-92-79-67781-6, doi:10.2760/16510, JRC105688.
paper_doi: https://dx.doi.org/10.2760/16510

jrc_vulnerability_curves_linking:
path: vulnerability_linking/JRC_damage_functions_linking.csv
data_type: DataFrame
driver: csv
meta:
category: vulnerability
description: Default linking table for the JRC damage functions (e.g., the residential damage function links to residential buildings).

jrc_damage_values:
path: max_potential_damages/JRC_base_damage_values.csv
data_type: DataFrame
driver: csv
meta:
category: vulnerability
description: Base damage values from the JRC publicated Excel from the tab "MaxDamage-Data", processed into a handy format for HydroMT-FIAT.
source_url: https://publications.jrc.ec.europa.eu/repository/handle/JRC105688
paper_ref: Huizinga, J., De Moel, H. and Szewczyk, W., Global flood depth-damage functions - Methodology and the database with guidelines, EUR 28552 EN, Publications Office of the European Union, Luxembourg, 2017, ISBN 978-92-79-67781-6, doi:10.2760/16510, JRC105688.
paper_doi: https://dx.doi.org/10.2760/16510
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Name,Link,Damage Type,type
FIAT Damage Function Name,Exposure Link,Damage Type,type
residential,residential,total,residential
commercial,commercial,total,commercial
industrial,industrial,total,industrial
4 changes: 1 addition & 3 deletions hydromt_fiat/data_apis/open_street_maps.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@ def get_assets_from_osm(polygon: Polygon):

def get_landuse_from_osm(polygon: Polygon):
tags = {"landuse": True} # this is the tag we use to find the correct OSM data
landuse = ox.features.features_from_polygon(
polygon, tags
) # then we query the data
landuse = ox.features.features_from_polygon(polygon, tags) # then we query the data

if landuse.empty:
logging.warning("No land use data found from OSM")
Expand Down
45 changes: 16 additions & 29 deletions hydromt_fiat/fiat.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,13 +278,13 @@ def setup_exposure_vector(
if asset_locations == occupancy_type == max_potential_damage:
# The source for the asset locations, occupancy type and maximum potential
# damage is the same, use one source to create the exposure data.
self.exposure.setup_from_single_source(
self.exposure.setup_buildings_from_single_source(
asset_locations, ground_floor_height, extraction_method
)
else:
# The source for the asset locations, occupancy type and maximum potential
# damage is different, use three sources to create the exposure data.
self.exposure.setup_from_multiple_sources(
self.exposure.setup_buildings_from_multiple_sources(
asset_locations,
occupancy_type,
max_potential_damage,
Expand Down Expand Up @@ -313,7 +313,6 @@ def setup_exposure_vector(
self.set_config("exposure.geom.crs", self.exposure.crs)
self.set_config("exposure.geom.unit", unit)


def setup_exposure_raster(self):
"""Setup raster exposure data for Delft-FIAT.
This function will be implemented at a later stage.
Expand Down Expand Up @@ -581,25 +580,15 @@ def setup_social_vulnerability_index(
# Link the SVI score to the exposure data
exposure_data = self.exposure.get_full_gdf(self.exposure.exposure_db)
exposure_data.sort_values("Object ID")

if svi.svi_data_shp.crs != exposure_data.crs:
svi.svi_data_shp.to_crs(crs=exposure_data.crs, inplace = True)
svi.svi_data_shp.to_crs(crs=exposure_data.crs, inplace=True)

svi_exp_joined = gpd.sjoin(
exposure_data, svi.svi_data_shp, how="left"
)
svi_exp_joined.drop(columns=['geometry'], inplace=True)
svi_exp_joined = gpd.sjoin(exposure_data, svi.svi_data_shp, how="left")
svi_exp_joined.drop(columns=["geometry"], inplace=True)
svi_exp_joined = pd.DataFrame(svi_exp_joined)
self.exposure.exposure_db = svi_exp_joined

# exposure opnieuw opslaan in self._tables

# TODO: geometries toevoegen aan de dataset met API
# we now use the shape download function by the census, the user needs to download their own shape data. They can download this from: https://www.census.gov/cgi-bin/geo/shapefiles/index.php
# #wfs python get request -> geometries

# this link can be used: https://github.com/datamade/census

# Update functions
def update_all(self):
self.logger.info("Updating all data objects...")
Expand All @@ -623,12 +612,16 @@ def update_tables(self):
def update_geoms(self):
# Update the exposure data geoms
if self.exposure and "exposure" in self._tables:
for i, geom in enumerate(self.exposure.exposure_geoms):
file_suffix = i if i > 0 else ""
self.set_geoms(geom=geom, name=f"exposure{file_suffix}")
for i, geom_and_name in enumerate(
zip(self.exposure.exposure_geoms, self.exposure.geom_names)
):
geom = geom_and_name[0]
name = geom_and_name[1]

self.set_geoms(geom=geom, name=name)
self.set_config(
f"exposure.geom.file{str(i+1)}",
f"./exposure/exposure{file_suffix}.gpkg",
f"./exposure/{name}.gpkg",
)

if not self.region.empty:
Expand All @@ -639,7 +632,8 @@ def update_maps(self):

# I/O
def read(self):
"""Method to read the complete model schematization and configuration from file."""
"""Method to read the complete model schematization and configuration from
file."""
self.logger.info(f"Reading model data from {self.root}")

# Read the configuration file
Expand All @@ -661,13 +655,6 @@ def _configread(self, fn):
config = Config()
return config.load_file(fn)

def check_path_exists(self, fn):
"""TODO: decide to use this or another function (check_file_exist in py)"""
path = Path(fn)
self.logger.debug(f"Reading file {str(path.name)}")
if not fn.is_file():
logging.warning(f"File {fn} does not exist!")

def read_tables(self):
"""Read the model tables for vulnerability and exposure data."""
if not self._write:
Expand Down
34 changes: 19 additions & 15 deletions hydromt_fiat/validation.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from pathlib import Path


def check_dir_exist(dir, name=None):
""" """

if not isinstance(dir, Path):
raise TypeError(
f"The directory indicated by the '{name}' parameter does not exist."
)



def check_file_exist(root, param_lst, name=None):
root = Path(root)
param_lst = [Path(p) for p in param_lst]
Expand Down Expand Up @@ -38,12 +40,13 @@ def check_file_exist(root, param_lst, name=None):
else:
assert isinstance(param_lst[param_idx], Path)
except AssertionError:
raise TypeError(
f"The file indicated by the '{name}' parameter does not"
f" exist in the directory '{root}'."
)

#TODO: Improve this tool without calling model.get_congif(input_dir)
raise TypeError(
f"The file indicated by the '{name}' parameter does not"
f" exist in the directory '{root}'."
)


# TODO: Improve this tool without calling model.get_congif(input_dir)
# def check_file_exist(get_config, root, param_lst, name=None, input_dir=None):
# root = Path(root)
# param_lst = [Path(p) for p in param_lst]
Expand Down Expand Up @@ -96,24 +99,23 @@ def check_file_exist(root, param_lst, name=None):
# f"'{get_config(input_dir)}'."
# )

def check_uniqueness(map_name_lst):

def check_uniqueness(map_name_lst):
def check_duplicates(lst):
unique_elements = set()
for element in lst:
if element in unique_elements:
return True # Found a duplicate
unique_elements.add(element)
return False # No duplicates found

check = check_duplicates(map_name_lst)

if check:
raise ValueError(
f"The filenames of the hazard maps should be unique."
)
if check:
raise ValueError(f"The filenames of the hazard maps should be unique.")


#TODO: Improve this tool without calling model. Just checking the maps names
# TODO: Improve this tool without calling model. Just checking the maps names
# def check_uniqueness(model, *args, file_type=None, filename=None):
# """ """

Expand All @@ -136,6 +138,7 @@ def check_duplicates(lst):
# ):
# raise ValueError(f"Each model input layers must be unique.")


def check_param_type(param, name=None, types=None):
""" """

Expand All @@ -155,6 +158,7 @@ def check_param_type(param, name=None, types=None):
f"{type(i)} instead."
)


def get_param(param_lst, map_fn_lst, file_type, filename, i, param_name):
""" """

Expand All @@ -166,4 +170,4 @@ def get_param(param_lst, map_fn_lst, file_type, filename, i, param_name):
raise IndexError(
f"Could not derive the {param_name} parameter for {file_type} "
f"map: {filename}."
)
)
1 change: 1 addition & 0 deletions hydromt_fiat/workflows/exposure_raster.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

logger = logging.getLogger(__name__)


### TO BE UPDATED ###
class ExposureRaster(Exposure):
def setup_buildings_value(
Expand Down
36 changes: 32 additions & 4 deletions hydromt_fiat/workflows/exposure_vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ def __init__(
)
self.exposure_db = pd.DataFrame()
self.exposure_geoms = list() # A list of GeoDataFrames
self.source = gpd.GeoDataFrame()
self.unit = unit
self._geom_names = list() # A list of (original) names of the geometry (files)

def read_table(self, fn: Union[str, Path]):
"""Read the Delft-FIAT exposure data.
Expand All @@ -102,9 +102,10 @@ def read_geoms(self, fn: Union[List[str], List[Path], str, Path]):
fn = [fn]

for f in fn:
self.set_geom_names(Path(f).stem)
self.set_exposure_geoms(gpd.read_file(f, engine="pyogrio"))

def setup_from_single_source(
def setup_buildings_from_single_source(
self,
source: Union[str, Path],
ground_floor_height: Union[int, float, str, Path, None],
Expand Down Expand Up @@ -178,7 +179,10 @@ def setup_from_single_source(
# Set the geoms from the X and Y coordinates
self.set_exposure_geoms_from_xy()

def setup_from_multiple_sources(
# Set the name to the geom_names
self.set_geom_names("buildings")

def setup_buildings_from_multiple_sources(
self,
asset_locations: Union[str, Path],
occupancy_source: Union[str, Path],
Expand Down Expand Up @@ -235,7 +239,28 @@ def setup_asset_locations(self, asset_locations: str) -> None:
assets["Object ID"] = range(1, len(assets.index) + 1)

# Set the asset locations to the geometry variable (self.exposure_geoms)
# and set the geom name
self.set_exposure_geoms(assets)
self.set_geom_names("buildings")

def set_geom_names(self, name: str) -> None:
"""Append a name to the list of geometry names `geom_names`."""
self.logger.info(f"Setting geometry name to {name}...")
self._geom_names.append(name)

@property
def geom_names(self) -> List[str]:
"""Returns a list with the geom names."""
if len(self._geom_names) > 0 and len(self.exposure_geoms) > 0:
return self._geom_names
elif len(self._geom_names) == 0 and len(self.exposure_geoms) == 1:
return ["exposure"]
else:
self.logger.warning(
"No geometry names found, returning a list with the default names "
"'exposure_X'."
)
return [f"exposure_{i}" for i in range(len(self.exposure_geoms))]

def set_exposure_geoms(self, gdf: gpd.GeoDataFrame) -> None:
"""Append a GeoDataFrame to the exposure geometries `exposure_geoms`."""
Expand Down Expand Up @@ -856,7 +881,10 @@ def link_exposure_vulnerability(
damage_types: Optional[List[str]] = ["Structure", "Content"],
):
linking_dict = dict(
zip(exposure_linking_table["Exposure Link"], exposure_linking_table["FIAT Damage Function Name"])
zip(
exposure_linking_table["Exposure Link"],
exposure_linking_table["FIAT Damage Function Name"],
)
)

# Find the column to link the exposure data to the vulnerability data
Expand Down
2 changes: 2 additions & 0 deletions hydromt_fiat/workflows/hazard.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ def read_floodmaps(

return da_map_fn, da_name, da_type


def load_floodmaps(
data_catalog: DataCatalog,
region: gpd.GeoDataFrame,
Expand Down Expand Up @@ -316,6 +317,7 @@ def load_floodmaps(

return da


# def load_floodmaps(
# data_catalog: DataCatalog,
# region: gpd.GeoDataFrame,
Expand Down
Loading

0 comments on commit 686d08a

Please sign in to comment.