Skip to content

Commit

Permalink
feat(sbr-b): allow multi building validation
Browse files Browse the repository at this point in the history
  • Loading branch information
RDWimmers committed Jun 6, 2024
1 parent dd769a6 commit 2c5334a
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 31 deletions.
58 changes: 52 additions & 6 deletions notebooks/NBxxxxx_SBR.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -622,25 +622,71 @@
" result = client.call_endpoint(\n",
" \"VibraCore\", f\"/{methode.lower()}/validation/single\", schema=single_payload\n",
" )\n",
" cfc = CFC_FACTOR_FLOORS[installation_type][\n",
" buildings.loc[buildings[\"name\"] == name][\"material\"].item()\n",
" ][\"Cfc\"]\n",
"\n",
" fig = map_nuisance(\n",
" buildings,\n",
" source_location=location,\n",
" building_name=name,\n",
" response_dict=result,\n",
" cfc=cfc,\n",
" u_eff=0.54,\n",
" vibration_type=vibration_type,\n",
" installation_type=installation_type,\n",
" period=period,\n",
" settings={\n",
" \"source_location\": {\"label\": \"Trillingsbron\", \"color\": \"blue\"},\n",
" \"levels\": [\n",
" {\n",
" \"label\": \"<= 1 day\",\n",
" \"color\": \"darkred\",\n",
" },\n",
" {\n",
" \"label\": \">= 6 days; <26 days\",\n",
" \"color\": \"orange\",\n",
" },\n",
" {\n",
" \"label\": \">= 26 days; <78 days\",\n",
" \"color\": \"green\",\n",
" },\n",
" {\n",
" \"label\": \"Unlimited\",\n",
" \"color\": \"black\",\n",
" },\n",
" ],\n",
" },\n",
" )\n",
"\n",
" # add basemap\n",
" ctx.add_basemap(\n",
" fig.axes[0], crs=\"EPSG:28992\", source=ctx.providers.Esri.WorldTopoMap\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f3db0419-ccb6-46bd-8959-67a5fd771790",
"metadata": {},
"outputs": [],
"source": [
"# create a dataframe for all buildings\n",
"_df_list = []\n",
"for name in buildings[\"name\"]:\n",
" single_payload = create_single_payload(multi_vibration_payload, name=name)\n",
" result = client.call_endpoint(\n",
" \"VibraCore\", f\"/{methode.lower()}/validation/single\", schema=single_payload\n",
" )\n",
"\n",
" _df_list.append(\n",
" df_nuisance(\n",
" buildings,\n",
" building_name=name,\n",
" response_dict=result,\n",
" vibration_type=vibration_type,\n",
" installation_type=installation_type,\n",
" period=period,\n",
" )\n",
" )\n",
"\n",
" print(df_nuisance(response_dict=result, cfc=cfc, u_eff=0.54, period=period))"
"pd.concat(_df_list, axis=1)"
]
},
{
Expand Down
122 changes: 97 additions & 25 deletions src/pyvibracore/results/nuisance.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
from __future__ import annotations

from typing import Any, List, Sequence, Tuple
from copy import deepcopy
from typing import Any, List, Literal, Sequence, Tuple

import geopandas as gpd
import matplotlib.patches as patches
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from numpy.typing import NDArray
from scipy.interpolate import interpolate
from scipy.interpolate import interp1d
from shapely.geometry import LineString, Point, Polygon

from pyvibracore.results.plot_utils import _north_arrow, _scalebar
Expand All @@ -34,9 +35,46 @@
"5 days": [0.48, 6, 0.32],
">= 6 days; <26 days": [0.4, 6, 0.3],
">= 26 days; <78 days": [0.3, 6, 0.2],
"Unlimited": {
"short-term": {
"woonfunctie": [0.2, 0.8, 0.1],
"gezondheidsfunctie": [0.2, 0.8, 0.1],
"onderwijsfunctie": [0.3, 1.2, 0.15],
},
"repeated-short-term": {
"woonfunctie": [0.2, 0.8, 0.1],
"gezondheidsfunctie": [0.2, 0.8, 0.1],
"onderwijsfunctie": [0.3, 1.2, 0.15],
},
"continuous": {
"woonfunctie": [0.1, 0.4, 0.05],
"gezondheidsfunctie": [0.1, 0.4, 0.05],
"onderwijsfunctie": [0.15, 0.6, 0.07],
},
},
}


def _get_target_value(
vibration_type: Literal["short-term", "repeated-short-term", "continuous"],
building_function: str,
) -> dict:
if "woonfunctie" in building_function:
_building_function = "woonfunctie"
elif "gezondheidsfunctie" in building_function:
_building_function = "gezondheidsfunctie"
elif "onderwijsfunctie" in building_function:
_building_function = "onderwijsfunctie"
else:
_building_function = "other"

_body = deepcopy(TARGET_VALUE)
_body["Unlimited"] = TARGET_VALUE["Unlimited"][vibration_type].get( # type: ignore
_building_function, [np.nan, np.nan, np.nan]
)
return _body


def _nuisance_prediction(
target_value_one: List[float] | NDArray | Sequence,
target_value_two: List[float] | NDArray | Sequence,
Expand Down Expand Up @@ -77,21 +115,21 @@ def _nuisance_prediction(
).drop_duplicates(subset=["vibrationVelocity_per", "vibrationVelocity_eff"])

# interpolate and predict
f_eff = interpolate.interp1d(
f_eff = interp1d(
df["vibrationVelocity_eff"],
df["distance"],
kind="cubic",
kind="linear",
assume_sorted=False,
fill_value="extrapolate",
)
target_value_one_spaces = f_eff(target_value_one)
target_value_two_spaces = f_eff(target_value_two)

# interpolate and predict
f_per = interpolate.interp1d(
f_per = interp1d(
df["vibrationVelocity_per"],
df["distance"],
kind="cubic",
kind="linear",
assume_sorted=False,
fill_value="extrapolate",
)
Expand All @@ -107,31 +145,53 @@ def _nuisance_prediction(


def df_nuisance(
buildings: gpd.GeoDataFrame,
response_dict: dict,
cfc: float,
u_eff: float,
period: float,
building_name: str,
vibration_type: Literal[
"short-term", "repeated-short-term", "continuous"
] = "continuous",
installation_type: Literal["vibrate", "driving"] = "vibrate",
period: float = 10,
) -> pd.DataFrame:
"""
Get a DataFrame that holds the distance of the different durations
Parameters
----------
buildings:
GeoDataFrame of the input buildings
response_dict:
response of the single prepal or cur166 endpoint.
u_eff:
Vibration transfer to part of a building (u_eff) CUR 166-1997 page 514 [-]
cfc:
Vibration transfer to part of a building (Cfc) CUR 166-1997 table 5.20 or 5.21 [-]
building_name:
name of the building
vibration_type
Based on the SBR A table 10.4.
installation_type
Based on CUR 166 3rd edition table 5.20 or 5.21
period:
Operating period of the building code [hours]
period:
Operating period of the building code [hours]
Returns
-------
dataframe
"""
building = buildings.get(buildings["name"] == building_name)
if building.empty:
raise ValueError(f"No buildings with name {building_name}.")

levels = _get_target_value(
vibration_type,
building_function=building["gebruiksdoel"].item(),
).values()
arr = np.array(response_dict["data"]["vibrationVelocity"])
a_one, a_two, a_three = [*zip(*TARGET_VALUE.values())]
a_one, a_two, a_three = [*zip(*levels)]

# safety factors
cfc = CFC_FACTOR_FLOORS[installation_type][building["material"].item()]["Cfc"]
u_eff = 0.64 if vibration_type == "continuous" else 0.42

distances = _nuisance_prediction(
target_value_one=a_one,
Expand All @@ -144,9 +204,9 @@ def df_nuisance(

return pd.DataFrame(
{
"labels": TARGET_VALUE.keys(),
"distance": distances,
}
building_name: distances,
},
index=list(TARGET_VALUE.keys()),
)


Expand All @@ -155,9 +215,11 @@ def map_nuisance(
source_location: Point | LineString | Polygon,
building_name: str,
response_dict: dict,
cfc: float,
u_eff: float,
period: float,
vibration_type: Literal[
"short-term", "repeated-short-term", "continuous"
] = "continuous",
installation_type: Literal["vibrate", "driving"] = "vibrate",
period: float = 10,
title: str = "Legend:",
figsize: Tuple[float, float] = (10.0, 12.0),
settings: dict | None = None,
Expand All @@ -176,10 +238,10 @@ def map_nuisance(
location of the vibration source
building_name:
name of the building
u_eff:
Vibration transfer to part of a building (u_eff) CUR 166-1997 page 514 [-]
cfc:
Vibration transfer to part of a building (Cfc) CUR 166-1997 table 5.20 or 5.21 [-]
vibration_type
Based on the SBR A table 10.4.
installation_type
Based on CUR 166 3rd edition table 5.20 or 5.21
period:
Operating period of the building code [hours]
title:
Expand Down Expand Up @@ -259,10 +321,20 @@ def map_nuisance(
)

# plot contour
levels = [TARGET_VALUE[values["label"]] for values in settings["levels"]]
levels = [
_get_target_value(
vibration_type,
building_function=building["gebruiksdoel"].item(),
)[values["label"]]
for values in settings["levels"]
]
arr = np.array(response_dict["data"]["vibrationVelocity"])
a_one, a_two, a_three = [*zip(*levels)]

# safety factors
cfc = CFC_FACTOR_FLOORS[installation_type][building["material"].item()]["Cfc"]
u_eff = 0.64 if vibration_type == "continuous" else 0.42

distances = _nuisance_prediction(
target_value_one=a_one,
target_value_two=a_two,
Expand Down

0 comments on commit 2c5334a

Please sign in to comment.