Skip to content

Commit 6bf3416

Browse files
committed
Initial data
1 parent 6d3c41a commit 6bf3416

1 file changed

Lines changed: 210 additions & 0 deletions

File tree

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
"""
2+
This file is part of CLIMADA.
3+
4+
Copyright (C) 2017 ETH Zurich, CLIMADA contributors listed in AUTHORS.
5+
6+
CLIMADA is free software: you can redistribute it and/or modify it under the
7+
terms of the GNU General Public License as published by the Free
8+
Software Foundation, version 3.
9+
10+
CLIMADA is distributed in the hope that it will be useful, but WITHOUT ANY
11+
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
12+
PARTICULAR PURPOSE. See the GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License along
15+
with CLIMADA. If not, see <https://www.gnu.org/licenses/>.
16+
---
17+
18+
A set of reusable objects for testing purpose.
19+
20+
The objective of this file is to provide minimalistic, understandable and consistent
21+
default objects for unit and integration testing.
22+
23+
"""
24+
25+
import copy
26+
from unittest import TestCase
27+
28+
import geopandas as gpd
29+
import numpy as np
30+
import pandas as pd
31+
from scipy.sparse import csr_matrix
32+
from shapely.geometry import Point
33+
34+
from climada.entity import Exposures, ImpactFunc, ImpactFuncSet, ImpfTropCyclone
35+
from climada.hazard import Centroids, Hazard
36+
from climada.trajectories import InterpolatedRiskTrajectory, StaticRiskTrajectory
37+
from climada.trajectories.snapshot import Snapshot
38+
39+
# ---------------------------------------------------------------------------
40+
# Coordinate system and metadata
41+
# ---------------------------------------------------------------------------
42+
CRS_WGS84 = "EPSG:4326"
43+
44+
# ---------------------------------------------------------------------------
45+
# Exposure attributes
46+
# ---------------------------------------------------------------------------
47+
EXP_DESC = "Test exposure dataset"
48+
EXP_DESC_LATLON = "Test exposure dataset (lat/lon)"
49+
EXPOSURE_REF_YEAR = 2020
50+
EXPOSURE_VALUE_UNIT = "USD"
51+
VALUES = np.array([0, 1000, 2000, 3000])
52+
REGIONS = np.array(["A", "A", "B", "B"])
53+
CATEGORIES = np.array([1, 1, 2, 1])
54+
55+
# Exposure coordinates
56+
EXP_LONS = np.array([4, 4.5, 4, 4.5])
57+
EXP_LATS = np.array([45, 45, 45.5, 45.5])
58+
59+
# ---------------------------------------------------------------------------
60+
# Hazard definition
61+
# ---------------------------------------------------------------------------
62+
HAZARD_TYPE = "TEST_HAZARD_TYPE"
63+
HAZARD_UNIT = "TEST_HAZARD_UNIT"
64+
65+
# Hazard centroid positions
66+
HAZ_JITTER = 0.1 # To test centroid matching
67+
HAZ_LONS = EXP_LONS + HAZ_JITTER
68+
HAZ_LATS = EXP_LATS + HAZ_JITTER
69+
70+
# Hazard events
71+
EVENT_IDS = np.array([1, 2, 3, 4])
72+
EVENT_NAMES = ["ev1", "ev2", "ev3", "ev4"]
73+
DATES = np.array([1, 2, 3, 4])
74+
75+
# Frequency are choosen so that they cumulate nicely
76+
# to correspond to 100, 50, and 20y return periods (for impacts)
77+
FREQUENCY = np.array([0.1, 0.03, 0.01, 0.01])
78+
FREQUENCY_UNIT = "1/year"
79+
80+
# Hazard maximum intensity
81+
# 100 to match 0 to 100% idea
82+
# also in line with linear 1:1 impact function
83+
# for easy mental calculus
84+
HAZARD_MAX_INTENSITY = 100
85+
86+
# ---------------------------------------------------------------------------
87+
# Impact function
88+
# ---------------------------------------------------------------------------
89+
IMPF_ID = 1
90+
IMPF_NAME = "IMPF_1"
91+
92+
# ---------------------------------------------------------------------------
93+
# Future years
94+
# ---------------------------------------------------------------------------
95+
EXPOSURE_FUTURE_YEAR = 2040
96+
97+
98+
def reusable_minimal_exposures(
99+
values=VALUES,
100+
regions=REGIONS,
101+
group_id=None,
102+
lon=EXP_LONS,
103+
lat=EXP_LATS,
104+
crs=CRS_WGS84,
105+
desc=EXP_DESC,
106+
ref_year=EXPOSURE_REF_YEAR,
107+
value_unit=EXPOSURE_VALUE_UNIT,
108+
assign_impf=IMPF_ID,
109+
increase_value_factor=1,
110+
) -> Exposures:
111+
data = gpd.GeoDataFrame(
112+
{
113+
"value": values * increase_value_factor,
114+
"region_id": regions,
115+
f"impf_{HAZARD_TYPE}": assign_impf,
116+
"geometry": [Point(lon, lat) for lon, lat in zip(lon, lat)],
117+
},
118+
crs=crs,
119+
)
120+
if group_id is not None:
121+
data["group_id"] = group_id
122+
return Exposures(
123+
data=data,
124+
description=desc,
125+
ref_year=ref_year,
126+
value_unit=value_unit,
127+
)
128+
129+
130+
def reusable_intensity_mat(max_intensity=HAZARD_MAX_INTENSITY):
131+
# Choosen such that:
132+
# - 1st event has 0 intensity
133+
# - 2nd event has max intensity in first exposure point (defaulting to 0 value)
134+
# - 3rd event has 1/2* of max intensity in second centroid
135+
# - 4th event has 1/4* of max intensity everywhere
136+
# *: So that you can double intensity of the hazard and expect double impacts
137+
return csr_matrix(
138+
[
139+
[0, 0, 0, 0],
140+
[max_intensity, 0, 0, 0],
141+
[0, max_intensity / 2, 0, 0],
142+
[
143+
max_intensity / 4,
144+
max_intensity / 4,
145+
max_intensity / 4,
146+
max_intensity / 4,
147+
],
148+
]
149+
)
150+
151+
152+
def reusable_minimal_hazard(
153+
haz_type=HAZARD_TYPE,
154+
units=HAZARD_UNIT,
155+
lat=HAZ_LATS,
156+
lon=HAZ_LONS,
157+
crs=CRS_WGS84,
158+
event_id=EVENT_IDS,
159+
event_name=EVENT_NAMES,
160+
date=DATES,
161+
frequency=FREQUENCY,
162+
frequency_unit=FREQUENCY_UNIT,
163+
intensity=None,
164+
intensity_factor=1,
165+
) -> Hazard:
166+
intensity = reusable_intensity_mat() if intensity is None else intensity
167+
intensity *= intensity_factor
168+
return Hazard(
169+
haz_type=haz_type,
170+
units=units,
171+
centroids=Centroids(lat=lat, lon=lon, crs=crs),
172+
event_id=event_id,
173+
event_name=event_name,
174+
date=date,
175+
frequency=frequency,
176+
frequency_unit=frequency_unit,
177+
intensity=intensity,
178+
)
179+
180+
181+
def reusable_minimal_impfset(
182+
hazard=None, name=IMPF_NAME, impf_id=IMPF_ID, max_intensity=HAZARD_MAX_INTENSITY
183+
):
184+
hazard = reusable_minimal_hazard() if hazard is None else hazard
185+
return ImpactFuncSet(
186+
[
187+
ImpactFunc(
188+
haz_type=hazard.haz_type,
189+
intensity_unit=hazard.units,
190+
name=name,
191+
intensity=np.array([0, max_intensity / 2, max_intensity]),
192+
mdd=np.array([0, 0.5, 1]),
193+
paa=np.array([1, 1, 1]),
194+
id=impf_id,
195+
)
196+
]
197+
)
198+
199+
200+
def reusable_snapshot(
201+
hazard_intensity_increase_factor=1,
202+
exposure_value_increase_factor=1,
203+
date=EXPOSURE_REF_YEAR,
204+
):
205+
exposures = reusable_minimal_exposures(
206+
increase_value_factor=exposure_value_increase_factor
207+
)
208+
hazard = reusable_minimal_hazard(intensity_factor=hazard_intensity_increase_factor)
209+
impfset = reusable_minimal_impfset()
210+
return Snapshot(exposure=exposures, hazard=hazard, impfset=impfset, date=date)

0 commit comments

Comments
 (0)