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

Remove all uses of Tag from climada/engine #743

Merged
merged 9 commits into from
Jul 10, 2023
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
peanutfun marked this conversation as resolved.
Show resolved Hide resolved
├─ 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