Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Physrisk commercial real estate #1

Merged
merged 2 commits into from
Sep 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions docs/handbook/onboarding.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,43 @@ Probability bins can be obtained from the exceedance curve, by subtracting one c

Note that in this case - which is the standard case - linear interpolation between points of the exceedance curve is assumed which corresponds to flat probability density within a bin.

In code this can be done using the :code:`ExceedanceCurve`:
::
exceedance_curve = ExceedanceCurve(1.0 / return_periods, event_intensities)
intensity_bins, probs = exceedance_curve.get_probability_bins()

Vulnerability/Event Model
In code, this can be done using the :code:`ExceedanceCurve`:

.. code-block::

exceedance_curve = ExceedanceCurve(1.0 / return_periods, event_intensities)
intensity_bins, probs = exceedance_curve.get_probability_bins()

Vulnerability/Event Model
-------------------------
In general a Vulnerability/Event Model is responsible for obtaining for a particular asset instances of:
In general, a Vulnerability/Event Model is responsible for obtaining for a particular asset instances of:

#. :code:`HazardEventDistrib` that provides probabilities of hazard event intensentities for the asset, and
#. :code:`HazardEventDistrib` that provides probabilities of hazard event intensities for the asset, and
#. :code:`VulnerabilityDistrib` that provides conditional probabilities that given a hazard event of given intensity has occurred, a damage/disruption of a given level will occur.

The damage or disruption is sometimes referred to as the 'impact'.

The current implementation is non-parametric and based on discete bins - although continuous versions of :code:`HazardEventDistrib`/:code:`VulnerabilityDistrib` could certainly be added, based on particular parametric distributions.
The current implementation is non-parametric and based on discrete bins - although continuous versions of :code:`HazardEventDistrib`/:code:`VulnerabilityDistrib` could certainly be added, based on particular parametric distributions.

:code:`HazardEventDistrib` is in this non-parametric version a histogram of hazard event intensities: defines a set of intensity bins and the annual probability of occurrence.

:code:`VulnerabilityDistrib` is a matix that provides the probability that if an event occurs with intensity falling in a particular intensity bin, an impact in a particular impact bin occurs.
:code:`VulnerabilityDistrib` is a matrix that provides the probability that if an event occurs with intensity falling in a particular intensity bin, an impact in a particular impact bin occurs.

The Vulnerability/Event Model (henceforth 'model') is in general responsible for

* Defining its hazard event data requirements by implementing method :code:`get_event_data_requests`
* Using the data to construct instances of :code:`HazardEventDistrib` and :code:`VulnerabilityDistrib` that will be used in the impact calculation. This is done by implementing method :code:`get_distributions`

:code:`HazardEventDistrib` and :code:`VulnerabilityDistrib` can be constructed in a single method to ensure their alignment, although this is method is probably only required in most bespoke cases. :code:`get_event_data_requests` is done as a separate step for performance reasons: it is desirable that all models state their data requirements 'up-front' in order that requests can be batched for fast retrieval.
:code:`HazardEventDistrib` and :code:`VulnerabilityDistrib` can be constructed in a single method to ensure their alignment, although this method is probably only required in most bespoke cases. :code:`get_event_data_requests` is done as a separate step for performance reasons: it is desirable that all models state their data requirements 'up-front' in order that requests can be batched for fast retrieval.

The model applies to:

* A type of hazard event (Inundation, Wildfire, Drought, etc)
* A type of asset (residential property, power generating asset, etc)

Decorators are used to 'tag' a model, so that an appropriate model can be selected for a given asset and hazard type; configuration allows types of :code:`Model` to be used in preference to other candidates.

Specific types of model also exist for common modelling approaches. In particular, although in general it is desirable that a model has the flexibility to define its hazard event distribution and vulnerability distribution, in many cases the former will be sourced directly from a data set and it only remains to define the vulnerability distribution. The :code:`Model` class allows the general form of the Model to be implemented. The :code:`VulnerabilityModel` class is for cases where only the vulnerability is to be specified.
Specific types of model also exist for common modelling approaches. In particular, although in general it is desirable that a model has the flexibility to define its hazard event distribution and vulnerability distribution, in many cases the former will be sourced directly from a data set and it only remains to define the vulnerability distribution. The :code:`Model` class allows the general form of the model to be implemented. The :code:`VulnerabilityModel` class is for cases where only the vulnerability is to be specified.

On-boarding a model based on a damage/disruption curve
------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,47 +256,142 @@
{
"asset_type": "Buildings/Commercial",
"event_type": "RiverineInundation",
"impact_mean": [],
"impact_mean": [
0.0,
0.15,
0.3,
0.45,
0.55,
0.75,
0.9,
1.0,
1.0
],
"impact_std": [],
"impact_type": "Damage",
"intensity": [],
"intensity": [
0.0,
0.5,
1.0,
1.5,
2.0,
3.0,
4.0,
5.0,
6.0
],
"intensity_units": "m",
"location": "Europe"
},
{
"asset_type": "Buildings/Commercial",
"event_type": "RiverineInundation",
"impact_mean": [
0.0
],
"impact_std": [
0.0
0.0,
0.018404908,
0.239263804,
0.374233129,
0.466257669,
0.552147239,
0.687116564,
0.82208589,
0.90797546,
1.0
],
"impact_std": [],
"impact_type": "Damage",
"intensity": [
0.0,
0.01
0.01,
0.5,
1.0,
1.5,
2.0,
3.0,
4.0,
5.0,
6.0
],
"intensity_units": "m",
"location": "North America"
},
{
"asset_type": "Buildings/Commercial",
"event_type": "RiverineInundation",
"impact_mean": [],
"impact_std": [],
"impact_mean": [
0.0,
0.611477587,
0.839531094,
0.923588457,
0.991972477,
1.0,
1.0,
1.0,
1.0
],
"impact_std": [
0.0,
0.077023435,
0.035924027,
0.026876525,
0.016055046,
0.0,
0.0,
0.0,
0.0
],
"impact_type": "Damage",
"intensity": [],
"intensity": [
0.0,
0.5,
1.0,
1.5,
2.0,
3.0,
4.0,
5.0,
6.0
],
"intensity_units": "m",
"location": "South America"
},
{
"asset_type": "Buildings/Commercial",
"event_type": "RiverineInundation",
"impact_mean": [],
"impact_std": [],
"impact_mean": [
0.0,
0.376789623,
0.537681619,
0.659336684,
0.762845232,
0.883348656,
0.941854895,
0.98075938,
1.0
],
"impact_std": [
0.0,
0.240462285,
0.240596279,
0.243605156,
0.250253511,
0.171703625,
0.11240992,
0.052781064,
0.0
],
"impact_type": "Damage",
"intensity": [],
"intensity": [
0.0,
0.5,
1.0,
1.5,
2.0,
3.0,
4.0,
5.0,
6.0
],
"intensity_units": "m",
"location": "Asia"
},
Expand All @@ -306,27 +401,87 @@
"impact_mean": [],
"impact_std": [],
"impact_type": "Damage",
"intensity": [],
"intensity": [
0.0,
0.5,
1.0,
1.5,
2.0,
3.0,
4.0,
5.0,
6.0
],
"intensity_units": "m",
"location": "Africa"
},
{
"asset_type": "Buildings/Commercial",
"event_type": "RiverineInundation",
"impact_mean": [],
"impact_std": [],
"impact_mean": [
0.0,
0.238953575,
0.481199682,
0.673795091,
0.864583333,
1.0,
1.0,
1.0,
1.0
],
"impact_std": [
0.0,
0.142878204,
0.204113206,
0.190903594,
0.178000078,
0.0,
0.0,
0.0,
0.0
],
"impact_type": "Damage",
"intensity": [],
"intensity": [
0.0,
0.5,
1.0,
1.5,
2.0,
3.0,
4.0,
5.0,
6.0
],
"intensity_units": "m",
"location": "Oceania"
},
{
"asset_type": "Buildings/Commercial",
"event_type": "RiverineInundation",
"impact_mean": [],
"impact_mean": [
0.0,
0.323296918,
0.506529105,
0.63459558,
0.744309656,
0.864093044,
0.932788157,
0.977746968,
1.0
],
"impact_std": [],
"impact_type": "Damage",
"intensity": [],
"intensity": [
0.0,
0.5,
1.0,
1.5,
2.0,
3.0,
4.0,
5.0,
6.0
],
"intensity_units": "m",
"location": "Global"
},
Expand Down
4 changes: 1 addition & 3 deletions src/physrisk/kernel/impact.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,7 @@ def calculate_impacts( # noqa: C901
hazard_data = [responses[req] for req in get_iterable(requests)]
if isinstance(model, VulnerabilityModelAcuteBase):
impact, vul, event = model.get_impact_details(asset, hazard_data)
results[ImpactKey(asset, model.hazard_type)] = AssetImpactResult(
impact, vulnerability=vul, event=event, hazard_data=hazard_data
)
results[ImpactKey(asset, model.hazard_type)] = AssetImpactResult(impact, vulnerability=vul, event=event, hazard_data=hazard_data)
elif isinstance(model, VulnerabilityModelBase):
impact = model.get_impact(asset, hazard_data)
results[ImpactKey(asset, model.hazard_type)] = AssetImpactResult(impact, hazard_data=hazard_data)
Expand Down
2 changes: 1 addition & 1 deletion src/test/models/test_power_generating_asset_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
class TestPowerGeneratingAssetModels(TestWithCredentials):
"""Tests World Resource Institute (WRI) models for power generating assets."""

def test_innundation(self):
def test_inundation(self):
# exceedance curve
return_periods = np.array([2.0, 5.0, 10.0, 25.0, 50.0, 100.0, 250.0, 500.0, 1000.0])
base_depth = np.array(
Expand Down
Loading