Skip to content
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ Removed:
### Removed

- `Centroids.set_raster_from_pix_bounds` [#721](https://github.com/CLIMADA-project/climada_python/pull/721)

- `requirements/env_developer.yml` environment specs. Use 'extra' requirements when installing the Python package instead [#712](https://github.com/CLIMADA-project/climada_python/pull/712)
- `Impact.tag` attribute. This change is not backwards-compatible with respect to the files written and read by the `Impact` class [#743](https://github.com/CLIMADA-project/climada_python/pull/743)

## v3.3.2

Expand Down
125 changes: 28 additions & 97 deletions climada/engine/impact.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

__all__ = ['ImpactFreqCurve', 'Impact']

from dataclasses import dataclass, field
from dataclasses import dataclass
import logging
import copy
import csv
Expand Down Expand Up @@ -51,7 +51,6 @@
import climada.util.dates_times as u_dt
import climada.util.plot as u_plot
from climada.util.select import get_attributes_with_matching_dimension
from climada.util.tag import Tag

LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -88,9 +87,6 @@ class Impact():
imp_mat : sparse.csr_matrix
matrix num_events x num_exp with impacts.
only filled if save_mat is True in calc()
tag : dict
dictionary of tags of exposures, impact functions set and
hazard: {'exp': Tag(), 'impf_set': Tag(), 'haz': Tag()}
haz_type : str
the hazard type of the hazard
"""
Expand All @@ -109,7 +105,6 @@ def __init__(self,
aai_agg=0,
unit='',
imp_mat=None,
tag=None,
haz_type=''):
"""
Init Impact object
Expand Down Expand Up @@ -145,15 +140,11 @@ def __init__(self,
value unit used (given by exposures unit)
imp_mat : sparse.csr_matrix, optional
matrix num_events x num_exp with impacts.
tag : dict, optional
dictionary of tags of exposures, impact functions set and
hazard: {'exp': Tag(), 'impf_set': Tag(), 'haz': Tag()}
haz_type : str, optional
the hazard type
"""

self.haz_type = haz_type
self.tag = tag or {}
self.event_id = np.array([], int) if event_id is None else event_id
self.event_name = [] if event_name is None else event_name
self.date = np.array([], int) if date is None else date
Expand Down Expand Up @@ -216,11 +207,13 @@ def calc(self, exposures, impact_funcs, hazard, save_mat=False, assign_centroids

#TODO: new name
@classmethod
def from_eih(cls, exposures, impfset, hazard,
at_event, eai_exp, aai_agg, imp_mat=None):
def from_eih(cls, exposures, hazard, at_event, eai_exp, aai_agg, imp_mat=None):
"""
Set Impact attributes from precalculated impact metrics.

.. versionchanged:: 3.3
The ``impfset`` argument was removed.

Parameters
----------
exposures : climada.entity.Exposures
Expand Down Expand Up @@ -260,10 +253,6 @@ def from_eih(cls, exposures, impfset, hazard,
at_event = at_event,
aai_agg = aai_agg,
imp_mat = imp_mat if imp_mat is not None else sparse.csr_matrix((0, 0)),
tag = {'exp': exposures.tag,
'impf_set': impfset.tag,
'haz': hazard.tag
},
haz_type = hazard.haz_type,
)

Expand Down Expand Up @@ -543,7 +532,6 @@ def calc_freq_curve(self, return_per=None):
ifc_impact = interp_imp

return ImpactFreqCurve(
tag=self.tag,
return_per=ifc_return_per,
impact=ifc_impact,
unit=self.unit,
Expand Down Expand Up @@ -885,14 +873,10 @@ def write_csv(self, file_name):
LOGGER.info('Writing %s', file_name)
with open(file_name, "w", encoding='utf-8') as imp_file:
imp_wr = csv.writer(imp_file)
imp_wr.writerow(["tag_hazard", "tag_exposure", "tag_impact_func",
"unit", "tot_value", "aai_agg", "event_id",
imp_wr.writerow(["haz_type", "unit", "tot_value", "aai_agg", "event_id",
"event_name", "event_date", "event_frequency", "frequency_unit",
"at_event", "eai_exp", "exp_lat", "exp_lon", "exp_crs"])
csv_data = [[[self.haz_type], [self.tag['haz'].file_name],
[self.tag['haz'].description]],
[[self.tag['exp'].file_name], [self.tag['exp'].description]],
[[self.tag['impf_set'].file_name], [self.tag['impf_set'].description]],
csv_data = [[self.haz_type],
[self.unit], [self._tot_value], [self.aai_agg],
self.event_id, self.event_name, self.date,
self.frequency, [self.frequency_unit], self.at_event,
Expand Down Expand Up @@ -920,32 +904,26 @@ def write_col(i_col, imp_ws, xls_data):
imp_wb = xlsxwriter.Workbook(file_name)
imp_ws = imp_wb.add_worksheet()

header = ["tag_hazard", "tag_exposure", "tag_impact_func",
"unit", "tot_value", "aai_agg", "event_id",
header = ["haz_type", "unit", "tot_value", "aai_agg", "event_id",
"event_name", "event_date", "event_frequency", "frequency_unit",
"at_event", "eai_exp", "exp_lat", "exp_lon", "exp_crs"]
for icol, head_dat in enumerate(header):
imp_ws.write(0, icol, head_dat)
data = [str(self.haz_type), str(self.tag['haz'].file_name),
str(self.tag['haz'].description)]
data = [str(self.haz_type)]
write_col(0, imp_ws, data)
data = [str(self.tag['exp'].file_name), str(self.tag['exp'].description)]
write_col(1, imp_ws, data)
data = [str(self.tag['impf_set'].file_name), str(self.tag['impf_set'].description)]
write_col(2, imp_ws, data)
write_col(3, imp_ws, [self.unit])
write_col(4, imp_ws, [self._tot_value])
write_col(5, imp_ws, [self.aai_agg])
write_col(6, imp_ws, self.event_id)
write_col(7, imp_ws, self.event_name)
write_col(8, imp_ws, self.date)
write_col(9, imp_ws, self.frequency)
write_col(10, imp_ws, [self.frequency_unit])
write_col(11, imp_ws, self.at_event)
write_col(12, imp_ws, self.eai_exp)
write_col(13, imp_ws, self.coord_exp[:, 0])
write_col(14, imp_ws, self.coord_exp[:, 1])
write_col(15, imp_ws, [str(self.crs)])
write_col(1, imp_ws, [self.unit])
write_col(2, imp_ws, [self._tot_value])
write_col(3, imp_ws, [self.aai_agg])
write_col(4, imp_ws, self.event_id)
write_col(5, imp_ws, self.event_name)
write_col(6, imp_ws, self.date)
write_col(7, imp_ws, self.frequency)
write_col(8, imp_ws, [self.frequency_unit])
write_col(9, imp_ws, self.at_event)
write_col(10, imp_ws, self.eai_exp)
write_col(11, imp_ws, self.coord_exp[:, 0])
write_col(12, imp_ws, self.coord_exp[:, 1])
write_col(13, imp_ws, [str(self.crs)])

imp_wb.close()

Expand Down Expand Up @@ -1023,11 +1001,6 @@ def write_dict(group, name, value):
for key, val in value.items():
write(group, key, val)

def write_tag(group, name, value):
"""Write a tag object using the dict writer"""
group = group.create_group(name) # name is 'exp', 'haz', 'impf_set'
value.to_hdf5(group) # value is a Tag

def _write_csr_dense(group, name, value):
"""Write a CSR Matrix in dense format"""
group.create_dataset(name, data=value.toarray())
Expand All @@ -1052,7 +1025,6 @@ def write_csr(group, name, value):
# 2) Anything is 'object', so this serves as fallback/default.
type_writers = {
str: write_attribute,
Tag: write_tag,
dict: write_dict,
sparse.csr_matrix: write_csr,
Collection: write_dataset,
Expand Down Expand Up @@ -1107,7 +1079,7 @@ def from_csv(cls, file_name):
# pylint: disable=no-member
LOGGER.info('Reading %s', file_name)
imp_df = pd.read_csv(file_name)
imp = cls(haz_type=str(imp_df.tag_hazard[0]))
imp = cls(haz_type=imp_df.haz_type[0])
imp.unit = imp_df.unit[0]
imp.tot_value = imp_df.tot_value[0]
imp.aai_agg = imp_df.aai_agg[0]
Expand All @@ -1128,12 +1100,7 @@ def from_csv(cls, file_name):
imp.crs = u_coord.to_crs_user_input(imp_df.exp_crs.values[0])
except AttributeError:
imp.crs = DEF_CRS
imp.tag['haz'] = Tag(str(imp_df.tag_hazard[1]),
str(imp_df.tag_hazard[2]))
imp.tag['exp'] = Tag(str(imp_df.tag_exposure[0]),
str(imp_df.tag_exposure[1]))
imp.tag['impf_set'] = Tag(str(imp_df.tag_impact_func[0]),
str(imp_df.tag_impact_func[1]))

return imp

def read_csv(self, *args, **kwargs):
Expand All @@ -1158,16 +1125,7 @@ def from_excel(cls, file_name):
"""
LOGGER.info('Reading %s', file_name)
dfr = pd.read_excel(file_name)
imp = cls(haz_type=str(dfr['tag_hazard'][0]))
imp.tag['haz'] = Tag(
file_name = dfr['tag_hazard'][1],
description = dfr['tag_hazard'][2])
imp.tag['exp'] = Tag()
imp.tag['exp'].file_name = dfr['tag_exposure'][0]
imp.tag['exp'].description = dfr['tag_exposure'][1]
imp.tag['impf_set'] = Tag()
imp.tag['impf_set'].file_name = dfr['tag_impact_func'][0]
imp.tag['impf_set'].description = dfr['tag_impact_func'][1]
imp = cls(haz_type=str(dfr['haz_type'][0]))

imp.unit = dfr.unit[0]
imp.tot_value = dfr.tot_value[0]
Expand Down Expand Up @@ -1215,24 +1173,11 @@ def from_hdf5(cls, file_path: Union[str, Path]):
├─ event_name
├─ frequency
├─ imp_mat
├─ tag/
│ ├─ exp/
│ │ ├─ .attrs/
│ │ │ ├─ file_name
│ │ │ ├─ description
│ ├─ haz/
│ │ ├─ .attrs/
│ │ │ ├─ haz_type
│ │ │ ├─ file_name
│ │ │ ├─ description
│ ├─ impf_set/
│ │ ├─ .attrs/
│ │ │ ├─ file_name
│ │ │ ├─ description
├─ .attrs/
│ ├─ aai_agg
│ ├─ crs
│ ├─ frequency_unit
│ ├─ haz_type
│ ├─ tot_value
│ ├─ unit

Expand Down Expand Up @@ -1300,13 +1245,6 @@ def from_hdf5(cls, file_path: Union[str, Path]):
# pylint: disable=no-member
kwargs["event_name"] = list(file["event_name"].asstr()[:])

# Tags
if "tag" in file:
tag_group = file["tag"]
# the tag group has tags for 'exp', 'haz' and 'impf_set'
tag_kwargs = {tag: Tag.from_hdf5(tag_group[tag]) for tag in tag_group.keys()}

kwargs["tag"] = tag_kwargs
# Create the impact object
return cls(**kwargs)

Expand Down Expand Up @@ -1476,7 +1414,6 @@ def _build_exp(self):
crs=self.crs,
value_unit=self.unit,
ref_year=0,
tag=Tag(),
meta=None
)

Expand All @@ -1498,7 +1435,6 @@ def _build_exp_event(self, event_id):
crs=self.crs,
value_unit=self.unit,
ref_year=0,
tag=Tag(),
meta=None
)

Expand Down Expand Up @@ -1719,8 +1655,8 @@ def concat(cls, imp_list: Iterable, reset_event_ids: bool = False):
``frequency``, ``imp_mat``, ``at_event``,
- sums up the values of attributes ``eai_exp``, ``aai_exp``
- and takes the following attributes from the first impact object in the passed
impact list: ``coord_exp``, ``crs``, ``unit``, ``tot_value``, ``tag``,
``frequency_unit``
impact list: ``coord_exp``, ``crs``, ``unit``, ``tot_value``,
``frequency_unit``, ``haz_type``

If event ids are not unique among the passed impact objects an error is raised.
In this case, the user can set ``reset_event_ids=True`` to create unique event ids
Expand Down Expand Up @@ -1806,7 +1742,6 @@ def stack_attribute(attr_name: str) -> np.ndarray:
eai_exp=np.nansum([imp.eai_exp for imp in imp_list], axis=0),
aai_agg=np.nansum([imp.aai_agg for imp in imp_list]),
imp_mat=imp_mat,
tag=first_imp.tag,
haz_type=first_imp.haz_type,
frequency_unit=first_imp.frequency_unit,
**kwargs,
Expand Down Expand Up @@ -1850,10 +1785,6 @@ class ImpactFreqCurve():
"""Impact exceedence frequency curve.
"""

tag : dict = field(default_factory=dict)
"""dictionary of tags of exposures, impact functions set and
hazard: {'exp': Tag(), 'impf_set': Tag(), 'haz': Tag()}"""

return_per : np.array = np.array([])
"""return period"""

Expand Down
10 changes: 5 additions & 5 deletions climada/engine/impact_calc.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,8 @@ def _return_impact(self, imp_mat_gen, save_mat):
imp_mat = None
at_event, eai_exp, aai_agg = self.stitch_risk_metrics(imp_mat_gen)
return Impact.from_eih(
self.exposures, self.impfset, self.hazard,
at_event, eai_exp, aai_agg, imp_mat
)
self.exposures, self.hazard, at_event, eai_exp, aai_agg, imp_mat
)

def _return_empty(self, save_mat):
"""
Expand All @@ -202,8 +201,9 @@ def _return_empty(self, save_mat):
)
else:
imp_mat = None
return Impact.from_eih(self.exposures, self.impfset, self.hazard,
at_event, eai_exp, aai_agg, imp_mat)
return Impact.from_eih(
self.exposures, self.hazard, at_event, eai_exp, aai_agg, imp_mat
)

def minimal_exp_gdf(self, impf_col, assign_centroids, ignore_cover, ignore_deductible):
"""Get minimal exposures geodataframe for impact computation
Expand Down
9 changes: 0 additions & 9 deletions climada/engine/impact_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
from climada.util.constants import DEF_CRS
import climada.util.coordinates as u_coord
from climada.engine import Impact
from climada.util.tag import Tag

LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -956,14 +955,6 @@ def emdat_to_impact(emdat_file_csv, hazard_type_climada, year_range=None, countr
# Inititate Impact-instance:
impact_instance = Impact(haz_type=hazard_type_climada)

impact_instance.tag = dict()
impact_instance.tag['haz'] = Tag(file_name=emdat_file_csv,
description='EM-DAT impact, direct import')
impact_instance.tag['exp'] = Tag(file_name=emdat_file_csv,
description='EM-DAT impact, direct import')
impact_instance.tag['impf_set'] = Tag(file_name=None, description=None)


# Load EM-DAT impact data by event:
em_data = emdat_impact_event(emdat_file_csv, countries=countries, hazard=hazard_type_emdat,
year_range=year_range, reference_year=reference_year,
Expand Down
Loading