Skip to content

Commit 7804bd9

Browse files
committed
define meta attribute in exposures
1 parent 54d2c6a commit 7804bd9

File tree

5 files changed

+58
-24
lines changed

5 files changed

+58
-24
lines changed

climada/entity/exposures/base.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ class Exposures(GeoDataFrame):
8787
If not provided, set to default 'if_' with ids 1 in check().
8888
geometry (pd.Series, optional): geometry of type Point of each instance.
8989
Computed in method set_geometry_points().
90+
meta (dict): dictionary containing corresponding raster properties (if any):
91+
width, height, crs and transform must be present at least (transform needs
92+
to contain upper left corner!). Exposures might not contain all the points
93+
of the corresponding raster.
9094
deductible (pd.Series, optional): deductible value for each exposure
9195
cover (pd.Series, optional): cover value for each exposure
9296
category_id (pd.Series, optional): category id for each exposure
@@ -95,7 +99,8 @@ class Exposures(GeoDataFrame):
9599
TC. There might be different hazards defined: centr_TC, centr_FL, ...
96100
Computed in method assign_centroids().
97101
"""
98-
_metadata = GeoDataFrame._metadata + ['tag', 'ref_year', 'value_unit']
102+
_metadata = GeoDataFrame._metadata + ['tag', 'ref_year', 'value_unit',
103+
'meta']
99104

100105
vars_oblig = ['value', 'latitude', 'longitude']
101106
"""Name of the variables needed to compute the impact."""
@@ -139,6 +144,8 @@ def check(self):
139144
self.ref_year = DEF_REF_YEAR
140145
elif var == 'value_unit':
141146
self.value_unit = DEF_VALUE_UNIT
147+
elif var == 'meta':
148+
self.meta = None
142149
LOGGER.info('%s metadata set to default value: %s', var, self.__dict__[var])
143150

144151
for var in self.vars_oblig:
@@ -215,14 +222,14 @@ def assign_centroids(self, hazard, method='NN', distance='haversine',
215222
self[INDICATOR_CENTR + hazard.tag.haz_type] = assigned
216223

217224
def set_geometry_points(self, scheduler=None):
218-
""" Set geometry attribute of GeoDataFrame from latitude and longitude
219-
attributes.
225+
""" Set geometry attribute of GeoDataFrame with Points from latitude and
226+
longitude attributes.
220227
221228
Parameter:
222229
scheduler (str): used for dask map_partitions. “threads”,
223230
“synchronous” or “processes”
224231
"""
225-
LOGGER.info('Setting geometry attribute.')
232+
LOGGER.info('Setting geometry points.')
226233
def apply_point(df_exp):
227234
return df_exp.apply((lambda row: Point(row.longitude, row.latitude)), axis=1)
228235
if not scheduler:
@@ -244,7 +251,7 @@ def set_lat_lon(self):
244251
def set_from_raster(self, file_name, band=1, src_crs=None, window=False,
245252
geometry=False, dst_crs=False, transform=None,
246253
width=None, height=None, resampling=Resampling.nearest):
247-
""" Read raster data and set latitude, longitude and value
254+
""" Read raster data and set latitude, longitude, value and meta
248255
249256
Parameters:
250257
file_name (str): file name containing values
@@ -259,9 +266,6 @@ def set_from_raster(self, file_name, band=1, src_crs=None, window=False,
259266
height (float): number of lats for transform
260267
resampling (rasterio.warp,.Resampling optional): resampling
261268
function used for reprojection to dst_crs
262-
263-
Returns:
264-
dict (meta raster information)
265269
"""
266270
self.__init__()
267271
self.tag = Tag()
@@ -281,7 +285,7 @@ def set_from_raster(self, file_name, band=1, src_crs=None, window=False,
281285
self['longitude'] = x_grid.flatten()
282286
self['latitude'] = y_grid.flatten()
283287
self['value'] = value.reshape(-1)
284-
return meta
288+
self.meta = meta
285289

286290
def plot_scatter(self, mask=None, ignore_zero=False, pop_name=True,
287291
buffer=0.0, extend='neither', **kwargs):

climada/entity/exposures/black_marble.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@
3434

3535
from climada.entity.tag import Tag
3636
from climada.entity.exposures.base import Exposures, INDICATOR_IF
37-
from climada.util.constants import SYSTEM_DIR
37+
from climada.util.constants import SYSTEM_DIR, DEF_CRS
3838
from climada.entity.exposures import nightlight as nl_utils
3939
from climada.util.finance import gdp, income_group
40+
from climada.util.coordinates import points_to_raster
4041

4142
LOGGER = logging.getLogger(__name__)
4243

@@ -104,15 +105,18 @@ def set_countries(self, countries, ref_year=2016, res_km=None, from_hr=None,
104105
tag.description += ("{} {:d} GDP: {:.3e} income group: {:d} \n").\
105106
format(cntry_val[1], cntry_val[3], cntry_val[4], cntry_val[5])
106107

107-
Exposures.__init__(self, gpd.GeoDataFrame(pd.concat(bkmrbl_list,
108-
ignore_index=True)))
108+
Exposures.__init__(self, gpd.GeoDataFrame(pd.concat(bkmrbl_list, \
109+
ignore_index=True)), crs=DEF_CRS)
109110

110111
# set metadata
111112
self.ref_year = ref_year
112113
self.tag = tag
113114
self.tag.file_name = fn_nl
114115
self.value_unit = 'USD'
115-
self.crs = {'init': 'epsg:4326'}
116+
rows, cols, ras_trans = points_to_raster((self.longitude.min(), \
117+
self.latitude.min(), self.longitude.max(), self.latitude.max()), \
118+
coord_nl[0, 1])
119+
self.meta = {'width':cols, 'height':rows, 'crs':self.crs, 'transform':ras_trans}
116120

117121
@staticmethod
118122
def _set_one_country(cntry_info, nightlight, coord_nl, res_fact,

climada/entity/exposures/litpop.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@
3838
from climada.entity.exposures.base import Exposures, INDICATOR_IF
3939
from climada.entity.exposures import gpw_import
4040
from climada.util.finance import gdp, income_group, wealth2gdp, world_bank_wealth_account
41-
from climada.util.constants import SYSTEM_DIR
41+
from climada.util.constants import SYSTEM_DIR, DEF_CRS
42+
from climada.util.coordinates import points_to_raster, get_resolution
4243

4344
logging.root.setLevel(logging.DEBUG)
4445
LOGGER = logging.getLogger(__name__)
@@ -261,11 +262,15 @@ def set_country(self, countries, **args):
261262
min(GPW_YEARS, key=lambda x:abs(x-reference_year)), \
262263
min(BM_YEARS, key=lambda x:abs(x-reference_year)), \
263264
exponents[0], exponents[1])
264-
Exposures.__init__(self, gpd.GeoDataFrame(pd.concat(lp_cntry,
265-
ignore_index=True)))
265+
Exposures.__init__(self, gpd.GeoDataFrame(pd.concat(lp_cntry, \
266+
ignore_index=True)), crs=DEF_CRS)
266267
self.ref_year = reference_year
267268
self.tag = tag
268269
self.value_unit = 'USD'
270+
rows, cols, ras_trans = points_to_raster((self.longitude.min(), \
271+
self.latitude.min(), self.longitude.max(), self.latitude.max()), \
272+
min(get_resolution(self.latitude, self.longitude)))
273+
self.meta = {'width':cols, 'height':rows, 'crs':self.crs, 'transform':ras_trans}
269274

270275
if check_plot == 1:
271276
self.plot_log(admin1_plot=0)
@@ -1875,11 +1880,11 @@ def exposure_set_admin1(exposure):
18751880
"""
18761881
Input:
18771882
exposure: exposure instance
1878-
1883+
18791884
Returns:
18801885
exposure: exposure instance with 2 extra columns: admin1 & admin1_ID
18811886
"""
1882-
1887+
18831888
exposure['admin1'] = pd.Series()
18841889
exposure['admin1_ID'] = pd.Series()
18851890
count = 0

climada/test/test_LitPop.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from climada.entity.exposures import litpop as lp
2626
from climada.entity.exposures import gpw_import
2727
from climada.util.finance import world_bank_wealth_account
28+
from climada.util.coordinates import equal_crs
2829

2930
# ---------------------
3031
class TestLitPopExposure(unittest.TestCase):
@@ -48,6 +49,16 @@ def test_switzerland300_pass(self):
4849
self.assertIn('GPW-year=2015', ent.tag.description)
4950
self.assertIn('BM-year=2016', ent.tag.description)
5051
self.assertIn('exp=[1, 1]', ent.tag.description)
52+
self.assertTrue(equal_crs(ent.crs['init'], {'init': 'epsg:4326'}))
53+
self.assertEqual(ent.meta['width'], 54)
54+
self.assertEqual(ent.meta['height'], 23)
55+
self.assertTrue(equal_crs(ent.meta['crs'], {'init': 'epsg:4326'}))
56+
self.assertAlmostEqual(ent.meta['transform'][0], 0.08333333333333333)
57+
self.assertAlmostEqual(ent.meta['transform'][1], 0)
58+
self.assertAlmostEqual(ent.meta['transform'][2], 5.9166666666666)
59+
self.assertAlmostEqual(ent.meta['transform'][3], 0)
60+
self.assertAlmostEqual(ent.meta['transform'][4], -0.08333333333333333)
61+
self.assertAlmostEqual(ent.meta['transform'][5], 47.7499999999999)
5162

5263
def test_switzerland30normPop_pass(self):
5364
"""Create LitPop entity for Switzerland on 30 arcsec:"""

climada/test/test_blackmarble.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from climada.entity.exposures.nightlight import load_nightlight_nasa, \
2929
load_nightlight_noaa, NOAA_BORDER, cut_nl_nasa
3030
from climada.entity.exposures import nightlight as nl_utils
31+
from climada.util.coordinates import equal_crs
3132

3233
class Test2013(unittest.TestCase):
3334
"""Test black marble of previous in 2013."""
@@ -46,7 +47,16 @@ def test_spain_pass(self):
4647
self.assertIn("Processing country Spain.", cm.output[1])
4748
self.assertIn("Generating resolution of approx 1 km.", cm.output[2])
4849
self.assertTrue(np.isclose(ent.value.sum(), 1.362e+12*(4+1), 4))
49-
self.assertEqual(ent.crs, {'init': 'epsg:4326'})
50+
self.assertTrue(equal_crs(ent.crs['init'], {'init': 'epsg:4326'}))
51+
self.assertEqual(ent.meta['width'], 2699)
52+
self.assertEqual(ent.meta['height'], 1938)
53+
self.assertTrue(equal_crs(ent.meta['crs'], {'init': 'epsg:4326'}))
54+
self.assertAlmostEqual(ent.meta['transform'][0], 0.008333333333333333)
55+
self.assertAlmostEqual(ent.meta['transform'][1], 0)
56+
self.assertAlmostEqual(ent.meta['transform'][2], -18.1625000000000)
57+
self.assertAlmostEqual(ent.meta['transform'][3], 0)
58+
self.assertAlmostEqual(ent.meta['transform'][4], -0.008333333333333333)
59+
self.assertAlmostEqual(ent.meta['transform'][5], 43.79583333333333)
5060

5161
def test_sint_maarten_pass(self):
5262
country_name = ['Sint Maarten']
@@ -55,15 +65,15 @@ def test_sint_maarten_pass(self):
5565
ent.set_countries(country_name, 2013, res_km=0.2)
5666
self.assertIn('GDP SXM 2014: 3.658e+08.', cm.output[0])
5767
self.assertIn('Income group SXM 2013: 4.', cm.output[1])
58-
self.assertEqual(ent.crs, {'init': 'epsg:4326'})
68+
self.assertTrue(equal_crs(ent.crs['init'], {'init': 'epsg:4326'}))
5969

6070
with self.assertLogs('climada.entity.exposures.black_marble', level='INFO') as cm:
6171
ent.set_countries(country_name, 2013, res_km=0.2)
6272
self.assertIn("Nightlights from NOAA's earth observation group for year 2013.", cm.output[0])
6373
self.assertIn("Processing country Sint Maarten.", cm.output[1])
6474
self.assertIn("Generating resolution of approx 0.2 km.", cm.output[2])
6575
self.assertAlmostEqual(ent.value.sum(), 3.658e+08*(4+1))
66-
self.assertEqual(ent.crs, {'init': 'epsg:4326'})
76+
self.assertTrue(equal_crs(ent.crs['init'], {'init': 'epsg:4326'}))
6777

6878
def test_anguilla_pass(self):
6979
country_name = ['Anguilla']
@@ -72,7 +82,7 @@ def test_anguilla_pass(self):
7282
self.assertEqual(ent.ref_year, 2013)
7383
self.assertIn("Anguilla 2013 GDP: 1.754e+08 income group: 3", ent.tag.description)
7484
self.assertAlmostEqual(ent.value.sum(), 1.754e+08*(3+1))
75-
self.assertEqual(ent.crs, {'init': 'epsg:4326'})
85+
self.assertTrue(equal_crs(ent.crs['init'], {'init': 'epsg:4326'}))
7686

7787
class Test1968(unittest.TestCase):
7888
"""Test black marble of previous years to 1992."""
@@ -90,7 +100,7 @@ def test_switzerland_pass(self):
90100
self.assertTrue("Processing country Switzerland." in cm.output[-2])
91101
self.assertTrue("Generating resolution of approx 0.5 km." in cm.output[-1])
92102
self.assertTrue(np.isclose(ent.value.sum(), 1.894e+10*(4+1), 4))
93-
self.assertEqual(ent.crs, {'init': 'epsg:4326'})
103+
self.assertTrue(equal_crs(ent.crs['init'], {'init': 'epsg:4326'}))
94104

95105
class Test2012(unittest.TestCase):
96106
"""Test year 2012 flags."""
@@ -126,7 +136,7 @@ def test_from_hr_flag_pass(self):
126136
self.assertTrue(np.isclose(ent.value.sum(), 8.740e+11*(3+1), 4))
127137
size3 = ent.value.size
128138
self.assertEqual(size1, size3)
129-
self.assertEqual(ent.crs, {'init': 'epsg:4326'})
139+
self.assertTrue(equal_crs(ent.crs['init'], {'init': 'epsg:4326'}))
130140

131141
class BMFuncs(unittest.TestCase):
132142
"""Test plot functions."""

0 commit comments

Comments
 (0)