From 56209e1638e314404362553504add6e7fc9b97fa Mon Sep 17 00:00:00 2001 From: Aidan Fennelly Date: Tue, 19 Nov 2024 15:56:57 -0500 Subject: [PATCH 1/5] Remove default field HistoricalConfig class --- configs/historical_config.yml | 1 - simfire/utils/config.py | 1 - 2 files changed, 2 deletions(-) diff --git a/configs/historical_config.yml b/configs/historical_config.yml index 460d8c1..0babae1 100644 --- a/configs/historical_config.yml +++ b/configs/historical_config.yml @@ -33,7 +33,6 @@ operational: year: 2020 historical: - default: true path: '../burnmd/BurnMD' year: 2020 state: "California" diff --git a/simfire/utils/config.py b/simfire/utils/config.py index 608917a..cf0ab6f 100644 --- a/simfire/utils/config.py +++ b/simfire/utils/config.py @@ -146,7 +146,6 @@ def __post_init__(self) -> None: @dataclasses.dataclass class HistoricalConfig: - default: bool path: Union[Path, str] year: int state: str From 8f8f1c2627a11d55c506d2663f33c8d6cb4c713e Mon Sep 17 00:00:00 2001 From: Aidan Fennelly Date: Tue, 19 Nov 2024 15:57:44 -0500 Subject: [PATCH 2/5] Fix bug in historical_test.py script. --- tests/historical_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/historical_test.py b/tests/historical_test.py index babeb75..6b31348 100644 --- a/tests/historical_test.py +++ b/tests/historical_test.py @@ -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 From a23d49c87907c3c5e8fcaeb5fd6091d1028c7b17 Mon Sep 17 00:00:00 2001 From: Aidan Fennelly Date: Tue, 19 Nov 2024 15:59:07 -0500 Subject: [PATCH 3/5] Add new time formats to handle variety in BurnMD. --- simfire/utils/layers.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/simfire/utils/layers.py b/simfire/utils/layers.py index 8b817f7..bcd7f97 100644 --- a/simfire/utils/layers.py +++ b/simfire/utils/layers.py @@ -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: """ @@ -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 @@ -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: """ From 2984b2c6b045db3b35aebca104ecbeac9af3ba01 Mon Sep 17 00:00:00 2001 From: Aidan Fennelly Date: Tue, 19 Nov 2024 15:59:45 -0500 Subject: [PATCH 4/5] Enforce consistency in historical data usage for topography and fuel types --- simfire/utils/config.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/simfire/utils/config.py b/simfire/utils/config.py index cf0ab6f..7e563ef 100644 --- a/simfire/utils/config.py +++ b/simfire/utils/config.py @@ -227,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() From cf929d4c4d620c62acfe0bde4aac4ade9dcacb1d Mon Sep 17 00:00:00 2001 From: Aidan Fennelly Date: Tue, 19 Nov 2024 16:01:07 -0500 Subject: [PATCH 5/5] Fix: incorrect start pos tuple was passed to FireConfig. - Note that in simulation.py, we do 'x, y = fire_pos', so we need to ensure this matches when setting the pos for type == 'historical'! --- simfire/utils/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simfire/utils/config.py b/simfire/utils/config.py index 7e563ef..444ffe4 100644 --- a/simfire/utils/config.py +++ b/simfire/utils/config.py @@ -813,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,