Skip to content

Commit a047eac

Browse files
committed
Merge branch 'feature/snapshots' into feature/impact-computation-strategies
2 parents a4e0e0c + f334b8c commit a047eac

File tree

6 files changed

+187
-135
lines changed

6 files changed

+187
-135
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Code freeze date: YYYY-MM-DD
1717

1818
### Fixed
1919

20+
- Fixed asset count in impact logging message [#1195](https://github.com/CLIMADA-project/climada_python/pull/1195).
21+
2022
### Deprecated
2123

2224
### Removed

climada/engine/impact_calc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ def impact(
186186
return self._return_empty(save_mat)
187187
LOGGER.info(
188188
"Calculating impact for %s assets (>0) and %s events.",
189-
exp_gdf.size,
189+
len(exp_gdf),
190190
self.n_events,
191191
)
192192
imp_mat_gen = self.imp_mat_gen(exp_gdf, impf_col)

climada/engine/test/test_impact_calc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ def test_calc_insured_impact_no_insurance(self):
441441
self.assertEqual(
442442
logs.output,
443443
[
444-
"INFO:climada.engine.impact_calc:Calculating impact for 150 assets (>0) and 14450 events."
444+
"INFO:climada.engine.impact_calc:Calculating impact for 50 assets (>0) and 14450 events."
445445
],
446446
)
447447
self.assertEqual(icalc.n_events, len(impact.at_event))

climada/trajectories/snapshot.py

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
import copy
2727
import datetime
2828
import logging
29+
import warnings
30+
31+
import pandas as pd
2932

3033
from climada.entity.exposures import Exposures
3134
from climada.entity.impact_funcs import ImpactFuncSet
@@ -46,10 +49,9 @@ class Snapshot:
4649
exposure : Exposures
4750
hazard : Hazard
4851
impfset : ImpactFuncSet
49-
date : int | datetime.date | str
50-
The date of the Snapshot, it can be an integer representing a year,
51-
a datetime object or a string representation of a datetime object
52-
with format "YYYY-MM-DD".
52+
date : datetime.date | str | pd.Timestamp
53+
The date of the Snapshot, it can be an string representing a year,
54+
a datetime object or a string representation of a datetime object.
5355
ref_only : bool, default False
5456
Should the `Snapshot` contain deep copies of the Exposures, Hazard and Impfset (False)
5557
or references only (True).
@@ -81,14 +83,22 @@ def __init__(
8183
hazard: Hazard,
8284
impfset: ImpactFuncSet,
8385
measure: Measure | None,
84-
date: int | datetime.date | str,
86+
date: datetime.date | str | pd.Timestamp,
8587
ref_only: bool = False,
88+
_from_factory: bool = False,
8689
) -> None:
90+
if not _from_factory:
91+
warnings.warn(
92+
"Direct instantiation of 'Snapshot' is discouraged. "
93+
"Use 'Snapshot.from_triplet()' instead.",
94+
UserWarning,
95+
stacklevel=2,
96+
)
8797
self._exposure = exposure if ref_only else copy.deepcopy(exposure)
8898
self._hazard = hazard if ref_only else copy.deepcopy(hazard)
8999
self._impfset = impfset if ref_only else copy.deepcopy(impfset)
90-
self._measure = measure if ref_only else copy.deepcopy(impfset)
91-
self._date = self._convert_to_date(date)
100+
self._measure = measure if ref_only else copy.deepcopy(measure)
101+
self._date = self._convert_to_timestamp(date)
92102

93103
@classmethod
94104
def from_triplet(
@@ -97,7 +107,7 @@ def from_triplet(
97107
exposure: Exposures,
98108
hazard: Hazard,
99109
impfset: ImpactFuncSet,
100-
date: int | datetime.date | str,
110+
date: datetime.date | str | pd.Timestamp,
101111
ref_only: bool = False,
102112
) -> "Snapshot":
103113
"""Create a Snapshot from exposure, hazard and impact functions set
@@ -112,7 +122,7 @@ def from_triplet(
112122
exposure : Exposures
113123
hazard : Hazard
114124
impfset : ImpactFuncSet
115-
date : int | datetime.date | str
125+
date : datetime.date | str | pd.Timestamp
116126
ref_only : bool
117127
If true, uses references to the exposure, hazard and impact
118128
function objects. Note that modifying the original objects after
@@ -137,6 +147,7 @@ def from_triplet(
137147
measure=None,
138148
date=date,
139149
ref_only=ref_only,
150+
_from_factory=True,
140151
)
141152

142153
@property
@@ -160,7 +171,7 @@ def measure(self) -> Measure | None:
160171
return self._measure
161172

162173
@property
163-
def date(self) -> datetime.date:
174+
def date(self) -> pd.Timestamp:
164175
"""Date of the snapshot."""
165176
return self._date
166177

@@ -174,24 +185,22 @@ def impact_calc_data(self) -> dict:
174185
}
175186

176187
@staticmethod
177-
def _convert_to_date(date_arg) -> datetime.date:
178-
"""Convert date argument of type int or str to a datetime.date object."""
179-
if isinstance(date_arg, int):
180-
# Assume the integer represents a year
181-
return datetime.date(date_arg, 1, 1)
188+
def _convert_to_timestamp(date_arg) -> pd.Timestamp:
189+
"""Convert date argument of type str or datetime.date to pandas Timestamp object."""
182190
if isinstance(date_arg, str):
183191
# Try to parse the string as a date
184192
try:
185-
return datetime.datetime.strptime(date_arg, "%Y-%m-%d").date()
193+
return pd.Timestamp(date_arg)
186194
except ValueError as exc:
187195
raise ValueError("String must be in the format 'YYYY-MM-DD'") from exc
188196
if isinstance(date_arg, datetime.date):
189-
# Already a date object
197+
return pd.Timestamp(date_arg)
198+
if isinstance(date_arg, pd.Timestamp):
190199
return date_arg
191200

192-
raise TypeError("date_arg must be an int, str, or datetime.date")
201+
raise TypeError("date_arg must be an str, datetime.date or pandas.Timestamp")
193202

194-
def apply_measure(self, measure: Measure, ref_only: bool = False) -> "Snapshot":
203+
def apply_measure(self, measure: Measure) -> "Snapshot":
195204
"""Create a new snapshot by applying a Measure object.
196205
197206
This method creates a new `Snapshot` object by applying a measure on
@@ -216,6 +225,7 @@ def apply_measure(self, measure: Measure, ref_only: bool = False) -> "Snapshot":
216225
impfset=impfset,
217226
date=self.date,
218227
measure=measure,
219-
ref_only=ref_only,
228+
ref_only=True, # Avoid unecessary copies of new objects
229+
_from_factory=True,
220230
)
221231
return snap

0 commit comments

Comments
 (0)