Skip to content

Commit

Permalink
Merge pull request #38 from mitrefireline/37-historicallayer-cannot-h…
Browse files Browse the repository at this point in the history
…andle-all-available-burnmd-time-formats

Minor updates to HistoricalLayer and usage of BurnMD data
  • Loading branch information
doyled-it authored Nov 19, 2024
2 parents 5d76a16 + cf929d4 commit 04905b1
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 12 deletions.
1 change: 0 additions & 1 deletion configs/historical_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ operational:
year: 2020

historical:
default: true
path: '../burnmd/BurnMD'
year: 2020
state: "California"
Expand Down
31 changes: 25 additions & 6 deletions simfire/utils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ def __post_init__(self) -> None:

@dataclasses.dataclass
class HistoricalConfig:
default: bool
path: Union[Path, str]
year: int
state: str
Expand Down Expand Up @@ -228,12 +227,32 @@ def __init__(
# operational to functional
self.original_screen_size = self.yaml_data["area"]["screen_size"]

if (
self.yaml_data["terrain"]["topography"]["type"] == "historical"
or self.yaml_data["terrain"]["fuel"]["type"] == "historical"
):
# If using 'historical', BOTH topo and fuel must be 'historical'!
# The only use case I can imagine is using 'functional' for one and
# 'historical' for the other. I don't see how that would be useful,
# so we will force FULL usage of historical data, when specified. Otherwise,
# raise an error!
topo_type = self.yaml_data["terrain"]["topography"]["type"]
fuel_type = self.yaml_data["terrain"]["fuel"]["type"]

if topo_type == "historical" and fuel_type != "historical":
log.error(f"Invalid config: historical topography, but {fuel_type} fuel.")
raise ConfigError(
"If using 'historical' data for topography type, the fuel type must "
"also be 'historical'!"
)
elif fuel_type == "historical" and topo_type != "historical":
log.error(f"Invalid config: historical fuel, but {topo_type} topography.")
raise ConfigError(
"If using 'historical' data for fuel type, the topography type must "
"also be 'historical'!"
)

# Load the historical data layers, if necessary.
if topo_type == "historical" and fuel_type == "historical":
self.historical = self._load_historical()
self.historical_layer = self._create_historical_layer()

# This can take up to 30 seconds to pull LandFire data directly from source
self.landfire_lat_long_box = self._make_lat_long_box()

Expand Down Expand Up @@ -794,7 +813,7 @@ def _load_fire(self, pos: Optional[Tuple[int, int]] = None) -> FireConfig:
return FireConfig((pos_x, pos_y), diagonal_spread, max_fire_duration, seed)
elif fire_init_pos_type == "historical":
return FireConfig(
(self.historical_layer.fire_start_y, self.historical_layer.fire_start_x),
(self.historical_layer.fire_start_x, self.historical_layer.fire_start_y),
diagonal_spread,
max_fire_duration,
None,
Expand Down
25 changes: 21 additions & 4 deletions simfire/utils/layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@

log = create_logger(__name__)

BURNMD_STRPTIME_FORMATS = [
"%Y/%m/%d %H:%M:%S.%f",
"%Y/%m/%d",
"%Y-%m-%d",
"%m/%d/%Y %H:%M:%S.%f",
]


class LandFireLatLongBox:
"""
Expand Down Expand Up @@ -818,7 +825,7 @@ def __init__(
self.width = width

# Format to convert BurnMD timestamp to datetime object
self.strptime_fmt = "%Y/%m/%d %H:%M:%S.%f"
self.strptime_fmt_options = BURNMD_STRPTIME_FORMATS
# set the path
self.fire_path = f"{self.state.title()}/{self.year}/fires/{self.fire.title()}"
# get available geopandas dataframes
Expand Down Expand Up @@ -1076,12 +1083,22 @@ def convert_to_datetime(self, bmd_time: str) -> datetime.datetime:
"""Convert a BurnMD dataset time to a Python datetime.datetime object
Arguments:
bmd_time: The BurmMD time string
bmd_time: The BurnMD time string
Returns:
A Python datetime.datetime object of the input BurnMD time
A Python datetime.datetime object of the input BurnMD time, or None if the
input is None.
"""
return datetime.datetime.strptime(bmd_time, self.strptime_fmt)
if bmd_time is None:
return None

for fmt in self.strptime_fmt_options:
try:
return datetime.datetime.strptime(bmd_time, fmt)
except ValueError:
continue

raise ValueError(f"Time data '{bmd_time}' does not match any known format.")

def _make_perimeters_image(self) -> np.ndarray:
"""
Expand Down
2 changes: 1 addition & 1 deletion tests/historical_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from simfire.sim.simulation import FireSimulation
from simfire.utils.config import Config

config = Config("configs/historical_config.yml")
config = Config(path="configs/historical_config.yml")
sim = FireSimulation(config)

sim.rendering = True
Expand Down

0 comments on commit 04905b1

Please sign in to comment.