Skip to content

Commit

Permalink
add ability to create a synthetic stormevent
Browse files Browse the repository at this point in the history
  • Loading branch information
zacharyburnett committed Jul 5, 2022
1 parent bda7df9 commit 0759960
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 5 deletions.
77 changes: 72 additions & 5 deletions stormevents/stormevent.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import pandas
import xarray
from pandas import Series
from shapely import ops
from shapely.geometry import MultiPolygon
from shapely.geometry import Polygon
Expand Down Expand Up @@ -49,12 +50,15 @@ def __init__(
year: int,
start_date: datetime = None,
end_date: datetime = None,
synthetic: bool = False,
**kwargs,
):
"""
:param name: storm name
:param year: storm year
:param start_date: starting time
:param end_date: ending time
:param synthetic: whether the storm actually exists; `True` will skip lookup in the storm table
>>> StormEvent('florence', 2018)
StormEvent(name='FLORENCE', year=2018, start_date=Timestamp('2018-08-30 06:00:00'), end_date=Timestamp('2018-09-18 12:00:00'))
Expand All @@ -72,17 +76,30 @@ def __init__(
StormEvent(name='IDA', year=2021, start_date=Timestamp('2021-08-27 18:00:00'), end_date=Timestamp('2021-08-29 18:00:00'))
"""

storms = nhc_storms(year=year)
storms = storms[storms["name"].str.contains(name.upper())]
if len(storms) > 0:
self.__entry = storms.iloc[0]
if not synthetic:
storms = nhc_storms(year=year)
storms = storms[storms["name"].str.contains(name.upper())]
if len(storms) > 0:
self.__entry = storms.iloc[0]
else:
raise ValueError(f'storm "{name} {year}" not found in NHC database')
else:
raise ValueError(f'storm "{name} {year}" not found in NHC database')
self.__entry = Series(
{
"name": name,
"year": year,
"start_date": start_date,
"end_date": end_date,
**kwargs,
},
index=None,
)

self.__usgs_id = None
self.__is_usgs_flood_event = True
self.__high_water_marks = None
self.__previous_configuration = {"name": self.name, "year": self.year}
self.__synthetic = synthetic

self.start_date = start_date
self.end_date = end_date
Expand Down Expand Up @@ -268,6 +285,10 @@ def status(self) -> StormStatus:
else:
return StormStatus.HISTORICAL

@property
def synthetic(self) -> bool:
return self.__synthetic

def track(
self,
start_date: datetime = None,
Expand Down Expand Up @@ -514,3 +535,49 @@ def __repr__(self) -> str:
f"end_date={repr(self.end_date)}"
f")"
)

def __copy__(self) -> "StormEvent":
return self.__class__(
self.name,
year=self.year,
start_date=self.start_date,
end_date=self.end_date,
)

def perturb(
self,
name: str = None,
year: int = None,
start_date: datetime = None,
end_date: datetime = None,
**kwargs,
) -> "StormEvent":
"""
:param name: storm name
:param year: storm year
:param start_date: starting time
:param end_date: ending time
:return: a new synthetic storm based on parameters from the current storm
"""

if name is None:
name = self.name
if year is None:
year = self.year
if start_date is None:
start_date = self.start_date
elif isinstance(start_date, timedelta):
start_date = self.start_date + start_date
if end_date is None:
end_date = self.end_date
elif isinstance(end_date, timedelta):
end_date = self.end_date + end_date

return self.__class__(
name=name,
year=year,
start_date=start_date,
end_date=end_date,
synthetic=True,
**kwargs,
)
32 changes: 32 additions & 0 deletions tests/test_stormevent.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,38 @@ def test_storm_event_lookup():
assert ida2021.end_date == datetime(2021, 9, 4, 18)


def test_synthetic_stormevent(florence2018):
synth_1 = StormEvent("synth_1", year=2018, synthetic=True)
synth_2 = StormEvent(
"synth_2",
start_date=datetime(2019, 10, 2),
end_date=datetime(2019, 10, 10),
year=2019,
synthetic=True,
)
synth_florence = florence2018.perturb(name="synth_florence")

assert synth_1.name == "synth_1"
assert synth_1.year == 2018
assert synth_1.nhc_code is None
assert synth_1.start_date is None
assert synth_1.end_date is None
assert synth_1.synthetic

assert synth_2.name == "synth_2"
assert synth_2.year == 2019
assert synth_2.nhc_code is None
assert synth_2.start_date == datetime(2019, 10, 2)
assert synth_2.end_date == datetime(2019, 10, 10)
assert synth_2.synthetic

assert synth_florence.name == "synth_florence"
assert synth_florence.year == 2018
assert synth_florence.start_date == florence2018.start_date
assert synth_florence.end_date == florence2018.end_date
assert synth_florence.synthetic


def test_storm_event_time_interval():
florence2018 = StormEvent("florence", 2018, start_date=timedelta(days=-2))
paine2016 = StormEvent.from_nhc_code("EP172016", end_date=timedelta(days=1))
Expand Down

0 comments on commit 0759960

Please sign in to comment.