Skip to content

Commit aa46644

Browse files
committed
Add vulnerability functions.
We add vulnerability functions with the aim of replicating the paper: 'Climate change-related statistical indicators' Statistics Paper Series No 48 from the European Central Bank. https://www.ecb.europa.eu/pub/pdf/scpsps/ecb.sps48~e3fd21dd5a.en.pdf?4826f6ee77d3ac7a681916b6d419b751 Co-authored-by: Víctor de Luna <vdeluna@arfima.com> Co-authored-by: Arfima Dev <dev@arfima.com> Signed-off-by: Virginia Morales <vmorales@arfima.com>
1 parent c7cdb15 commit aa46644

21 files changed

+1966
-225
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,5 +181,5 @@ quote-style = "double"
181181
indent-style = "space"
182182
skip-magic-trailing-comma = false
183183
line-ending = "auto"
184-
#docstring-code-format = false
184+
docstring-code-format = true
185185
docstring-code-line-length = "dynamic"

src/physrisk/api/v1/common.py

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
from enum import Enum
12
from typing import Dict, List, Optional, Union
23

34
import numpy as np
4-
from pydantic import BaseModel, Field
5+
from pydantic import BaseModel, ConfigDict, Field
56

67

78
class TypedArray(np.ndarray):
@@ -23,13 +24,17 @@ class Array(np.ndarray, metaclass=ArrayMeta):
2324
pass
2425

2526

26-
class Asset(BaseModel, extra="allow"):
27-
"""Defines an asset. An asset is identified first by its asset_class and then by its type within the class.
27+
class Asset(BaseModel):
28+
"""Defines an asset.
29+
30+
An asset is identified first by its asset_class and then by its type within the class.
2831
An asset's value may be impacted through damage or through disruption
2932
disruption being reduction of an asset's ability to generate cashflows
3033
(or equivalent value, e.g. by reducing expenses or increasing sales).
3134
"""
3235

36+
model_config = ConfigDict(extra="allow")
37+
3338
asset_class: str = Field(
3439
description="name of asset class; corresponds to physrisk class names, e.g. PowerGeneratingAsset"
3540
)
@@ -104,30 +109,27 @@ class IntensityCurve(BaseModel):
104109
class ExceedanceCurve(BaseModel):
105110
"""General exceedance curve (e.g. hazazrd, impact)."""
106111

112+
model_config = ConfigDict(arbitrary_types_allowed=True)
107113
values: np.ndarray = Field(default_factory=lambda: np.zeros(10), description="")
108114
exceed_probabilities: np.ndarray = Field(
109115
default_factory=lambda: np.zeros(10), description=""
110116
)
111117

112-
class Config:
113-
arbitrary_types_allowed = True
114-
115118

116119
class Distribution(BaseModel):
117120
"""General exceedance curve (e.g. hazazrd, impact)."""
118121

122+
model_config = ConfigDict(arbitrary_types_allowed=True)
119123
bin_edges: np.ndarray = Field(default_factory=lambda: np.zeros(11), description="")
120124
probabilities: np.ndarray = Field(
121125
default_factory=lambda: np.zeros(10), description=""
122126
)
123127

124-
class Config:
125-
arbitrary_types_allowed = True
126-
127128

128129
class HazardEventDistrib(BaseModel):
129130
"""Intensity curve of an acute hazard."""
130131

132+
model_config = ConfigDict(arbitrary_types_allowed=True)
131133
intensity_bin_edges: np.ndarray = Field(
132134
default_factory=lambda: np.zeros(10), description=""
133135
)
@@ -136,13 +138,11 @@ class HazardEventDistrib(BaseModel):
136138
)
137139
path: List[str] = Field([], description="Path to the hazard indicator data source.")
138140

139-
class Config:
140-
arbitrary_types_allowed = True
141-
142141

143142
class VulnerabilityCurve(BaseModel):
144143
"""Defines a damage or disruption curve."""
145144

145+
model_config = ConfigDict(arbitrary_types_allowed=True)
146146
asset_type: str = Field(...)
147147
location: str = Field(...)
148148
event_type: str = Field(description="hazard event type, e.g. RiverineInundation")
@@ -156,9 +156,6 @@ class VulnerabilityCurve(BaseModel):
156156
description="standard deviation of impact (damage or disruption)"
157157
)
158158

159-
class Config:
160-
arbitrary_types_allowed = True
161-
162159

163160
class VulnerabilityCurves(BaseModel):
164161
"""List of VulnerabilityCurve."""
@@ -169,6 +166,7 @@ class VulnerabilityCurves(BaseModel):
169166
class VulnerabilityDistrib(BaseModel):
170167
"""Defines a vulnerability matrix."""
171168

169+
model_config = ConfigDict(arbitrary_types_allowed=True)
172170
intensity_bin_edges: np.ndarray = Field(
173171
default_factory=lambda: np.zeros(10), description=""
174172
)
@@ -178,6 +176,3 @@ class VulnerabilityDistrib(BaseModel):
178176
prob_matrix: np.ndarray = Field(
179177
default_factory=lambda: np.zeros(10), description=""
180178
)
181-
182-
class Config:
183-
arbitrary_types_allowed = True

src/physrisk/api/v1/impact_req_resp.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from enum import Enum
22
from typing import Dict, List, NamedTuple, Optional, Sequence
33

4-
from pydantic import BaseModel, Field, computed_field
4+
from pydantic import BaseModel, ConfigDict, Field, computed_field
55

66
from physrisk.api.v1.common import (
77
Assets,
@@ -37,8 +37,10 @@ class AssetImpactRequest(BaseModel):
3737
True, description="If true, include impact calculation details."
3838
)
3939
use_case_id: str = Field(
40-
"",
41-
description="Identifier for 'use case' used in the risk measures calculation.",
40+
"DEFAULT",
41+
description=(
42+
"Identifier for 'use case' used in vulnerability models and risk measures calculations."
43+
),
4244
)
4345
provider_max_requests: Dict[str, int] = Field(
4446
{},
@@ -70,6 +72,8 @@ class Category(int, Enum):
7072
HIGH = 3
7173
REDFLAG = 4
7274

75+
NORISK = -1
76+
7377

7478
class RiskMeasureDefinition(BaseModel):
7579
measure_id: str = Field(None, description="Identifier for the risk measure.")
@@ -95,7 +99,7 @@ class RiskScoreValue(BaseModel):
9599
)
96100

97101

98-
class ScoreBasedRiskMeasureDefinition(BaseModel, frozen=True):
102+
class ScoreBasedRiskMeasureDefinition(BaseModel):
99103
hazard_types: List[str] = Field(
100104
[], description="Defines the hazards that the measure is used for."
101105
)
@@ -111,7 +115,7 @@ class ScoreBasedRiskMeasureDefinition(BaseModel, frozen=True):
111115
# [], description="The identifiers of the underlying risk measures from which the scores are inferred."
112116
# )
113117

114-
# should be sufficient to pass frozen=True, but does not seem to work (pydantic docs says feature in beta)
118+
# It is not enough to pass frozen=True, since not all attributes are hashable
115119
def __hash__(self):
116120
return id(self)
117121

@@ -166,6 +170,7 @@ class ImpactKey(BaseModel):
166170
class AssetSingleImpact(BaseModel):
167171
"""Impact at level of single asset and single type of hazard."""
168172

173+
model_config = ConfigDict(arbitrary_types_allowed=True)
169174
key: ImpactKey
170175

171176
@computed_field # deprecated: use key instead
@@ -191,9 +196,6 @@ def year(self) -> str:
191196
description="""Details of impact calculation for acute hazard calculations.""",
192197
)
193198

194-
class Config:
195-
arbitrary_types_allowed = True
196-
197199

198200
class AssetLevelImpact(BaseModel):
199201
"""Impact at asset level. Each asset can have impacts for multiple hazard types."""

src/physrisk/container.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,14 @@
22

33
from dependency_injector import containers, providers
44

5+
from physrisk.kernel import calculation as calc
56
from physrisk.data.hazard_data_provider import SourcePath
67
from physrisk.data.inventory import EmbeddedInventory
78
from physrisk.data.inventory_reader import InventoryReader
89
from physrisk.data.pregenerated_hazard_model import ZarrHazardModel
910
from physrisk.data.zarr_reader import ZarrReader
10-
from physrisk.kernel import calculation as calc
1111
from physrisk.kernel.hazard_model import HazardModelFactory
12-
from physrisk.kernel.vulnerability_model import (
13-
DictBasedVulnerabilityModels,
14-
VulnerabilityModels,
15-
VulnerabilityModelsFactory,
16-
)
12+
from physrisk.kernel.vulnerability_model import DictBasedVulnerabilityModelsFactory
1713
from physrisk.requests import Requester, _create_inventory, create_source_paths
1814

1915

@@ -41,11 +37,6 @@ def hazard_model(
4137
)
4238

4339

44-
class DictBasedVulnerabilityModelsFactory(VulnerabilityModelsFactory):
45-
def vulnerability_models(self) -> VulnerabilityModels:
46-
return DictBasedVulnerabilityModels(calc.get_default_vulnerability_models())
47-
48-
4940
class Container(containers.DeclarativeContainer):
5041
config = providers.Configuration(default={"zarr_sources": ["embedded", "hazard"]})
5142

src/physrisk/data/inventory.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@
99

1010
import physrisk.data.colormap_provider as colormap_provider
1111
import physrisk.data.static.hazard
12+
from physrisk.api.v1.hazard_data import HazardResource, Period
1213
from physrisk.data.inventory_reader import HazardModels
1314

14-
from ..api.v1.hazard_data import HazardResource, Period
15-
1615
# from physrisk.kernel.hazards import ChronicHeat
1716

1817

0 commit comments

Comments
 (0)