Beispiel #1
0
    def __init__(self, area, wind_speed, wind_dir, world=None):
        """Abstract class providing access to the main properties of the environment

        :param area: ((x_min, x_max), (y_min, y_max))
        :param wind_speed: mean wind speed in km/h
        :param wind_dir: mean wind direction in radians
        """
        self._wind_speed = wind_speed  # type: float
        self._wind_dir = wind_dir  # type: float
        self._area = area  # type: ((float, float), (float, float))
        self._world = world  # type: World
        if world is None:
            self._world = World()
        elevation = self._world.get_elevation(area)
        slope = self._world.get_slope(area)
        wind = self._world.get_wind(area,
                                    domain_average=(wind_speed, wind_dir))
        # When output resolution doesn't match the internal simulation res.
        # then the final raster is a bit bigger than the initial one. Just crop it
        wind.data = wind.data[:elevation.data.shape[0], :elevation.data.
                              shape[1], ...]
        moisture = slope.clone(fill_value=env.get_moisture_scenario_id('D1L1'),
                               dtype=[('moisture', 'int32')])
        fuel = self._world.get_fuel_type(area)
        # type: GeoData
        self.raster = slope.combine(wind).combine(moisture).combine(
            fuel).combine(elevation)
        self._clustering = None
 def test_geodata_conversion(self):
     from fire_rs.geodata.environment import World
     world = World()
     gd = world.get_elevation([[475060.0, 485060], [6200074.0, 6210074]])
     raster = gd.as_cpp_raster()
     print(raster)
     gd2 = GeoData.from_cpp_raster(raster, "elevation_cpp")
     print(gd2[10, 10][0])
     self.assertAlmostEqual(gd[10, 10][0], gd2[10, 10][0])
     self.assertAlmostEqual(gd.x_offset, gd2.x_offset)
     self.assertAlmostEqual(gd.y_offset, gd2.y_offset)
     self.assertEqual(gd.data.shape, gd2.data.shape)
     print(gd2)
    def test_get_wind_elevation_on_area(self):
        world = World()
        area = [[475060.0, 476060.0], [6200074.0, 6200174.0]]
        elevation_data = world.get_elevation(area)
        wind_data = world.get_wind(area, domain_average=(3.11, np.pi / 2))
        self.assertEqual(elevation_data.data.shape, wind_data.data.shape)
        self.assertEqual(elevation_data.x_offset, wind_data.x_offset)
        self.assertEqual(elevation_data.y_offset, wind_data.y_offset)
        self.assertEqual(elevation_data.cell_width, wind_data.cell_width)
        self.assertEqual(elevation_data.cell_height, wind_data.cell_height)

        elev_wind = elevation_data.combine(wind_data)
        self.assertEqual(elevation_data.data.shape, elev_wind.data.shape)
        self.assertEqual(elevation_data.x_offset, elev_wind.x_offset)
        self.assertEqual(elevation_data.y_offset, elev_wind.y_offset)
        self.assertEqual(elevation_data.cell_width, elev_wind.cell_width)
        self.assertEqual(elevation_data.cell_height, elev_wind.cell_height)
Beispiel #4
0
def _main():
    area = [[530000.0, 535000.0], [6230000.0, 6235000.0]]
    area_wind = (10, np.pi)

    world = World()

    elev = world.get_elevation(area)
    clustered = regular_partition_clustering(
        elev, 30)  # cluster with a 30 meters margin
    elev.plot()
    clustered.plot()

    wind = world.get_wind(area, domain_average=area_wind)
    clustered = cluster_multi_layer(wind, {
        'wind_angle': 0.2,
        'wind_velocity': 2
    })
    clustered.plot()

    pyplot.show()  # blocking until all plot windows are closed
 def test_get_fuel_type_on_area(self):
     world = World()
     res = world.get_fuel_type([[475060.0, 485060], [6200074.0, 6210074]],
                               CORINELANDCOVER_TO_FUELMODEL_REMAP)
 def test_get_fuel_type(self):
     world = World()
     res = world.get_fuel_type([475060.0, 6200074.0],
                               CORINELANDCOVER_TO_FUELMODEL_REMAP)
 def test_get_landcover_class_on_area(self):
     world = World()
     res = world.get_landcover_class([[475060.0, 485060],
                                      [6200074.0, 6210074]])
 def test_get_landcover_class(self):
     world = World()
     res = world.get_landcover_class([475060.0, 6200074.0])
 def test_get_slope_on_area(self):
     world = World()
     res = world.get_slope([[475060.0, 476060.0], [6200074.0, 6200174.0]])
 def test_get_wind_on_area(self):
     world = World()
     res = world.get_wind([[475060.0, 476160.0], [6200074.0, 6201174.0]],
                          domain_average=(3.11, np.pi))
 def test_get_wind(self):
     world = World()
     ret = world.get_wind([475060.0, 6200074.0],
                          domain_average=(3.11, np.pi / 2))
 def test_get_elevation_on_area(self):
     world = World()
     world.get_elevation([[475060.0, 485060], [6200074.0, 6210074]])
 def test_get_elevation(self):
     world = World()
     world.get_elevation([475060.0, 6200074.0])
Beispiel #14
0
class Environment:
    def __init__(self, area, wind_speed, wind_dir, world=None):
        """Abstract class providing access to the main properties of the environment

        :param area: ((x_min, x_max), (y_min, y_max))
        :param wind_speed: mean wind speed in km/h
        :param wind_dir: mean wind direction in radians
        """
        self._wind_speed = wind_speed  # type: float
        self._wind_dir = wind_dir  # type: float
        self._area = area  # type: ((float, float), (float, float))
        self._world = world  # type: World
        if world is None:
            self._world = World()
        elevation = self._world.get_elevation(area)
        slope = self._world.get_slope(area)
        wind = self._world.get_wind(area,
                                    domain_average=(wind_speed, wind_dir))
        # When output resolution doesn't match the internal simulation res.
        # then the final raster is a bit bigger than the initial one. Just crop it
        wind.data = wind.data[:elevation.data.shape[0], :elevation.data.
                              shape[1], ...]
        moisture = slope.clone(fill_value=env.get_moisture_scenario_id('D1L1'),
                               dtype=[('moisture', 'int32')])
        fuel = self._world.get_fuel_type(area)
        # type: GeoData
        self.raster = slope.combine(wind).combine(moisture).combine(
            fuel).combine(elevation)
        self._clustering = None

    @property
    def area(self) -> Tuple[Tuple[float, float], Tuple[float, float]]:
        return self._area

    @property
    def area_wind(self) -> Tuple[float, float]:
        return self._wind_speed, self._wind_dir

    @property
    @deprecated
    def clustering(self):
        if self._clustering is None:
            base_for_clustering = self.raster.slice(
                ['wind_angle', 'wind_velocity', 'fuel', 'moisture'])
            self._clustering = cluster_multi_layer(
                base_for_clustering,
                err_by_layer={
                    'wind_angle': 0.2,
                    'wind_velocity': 2
                },
                already_clustered=['fuel', 'moisture'])
        return self._clustering

    def update_area_wind(self, wind_speed, wind_dir):
        new_wind = self._world.get_wind(self._area,
                                        domain_average=(wind_speed, wind_dir))
        self.raster.data['wind_velocity'] = new_wind['wind_velocity']
        self.raster.data['wind_angle'] = new_wind['wind_angle']

    def get_fuel_type(self, x, y):
        """Returns the fuel type (e.g. 'SH5') in (x,y)"""
        return env.get_fuel_model_name(int(self.raster.data[x, y]['fuel']))

    def get_wind(self, x, y):
        """Returns a tuple (wind_speed [km/h], wind_angle [rad]) in (x,y)"""
        tmp = self.raster.data[x, y]
        wind_vel = tmp['wind_velocity']
        wind_angle = tmp['wind_angle']
        return wind_vel, wind_angle

    def get_moisture(self, x, y):
        """Returns the moisture scenario (e.g. 'D1L3') in (x,y)"""
        return env.get_moisture_scenario_name(
            int(self.raster.data[x, y]['moisture']))

    def get_slope(self, x, y):
        tmp = self.raster.data[x, y]
        return tmp['slope'], tmp['raise_dir']

    def get_spread_parameters(self, x, y):
        """Computes the three parameters dictating the spread of the fire.
         - ros: Rate of Spread [m/s] in main direction
         - effective wind angle: main direction of the fire spread, accounting for wind and slope
         - effective wind speed: wind equivalent [km/h] that takes into account wind and slope
        """
        fuel_type = self.get_fuel_type(x, y)
        moisture = self.get_moisture(x, y)
        slope_percent, slope_dir = self.get_slope(x, y)
        wind_speed, wind_dir = self.get_wind(x, y)
        summary = rothermel.ros(fuel_type, moisture, wind_speed, slope_percent)
        ros = summary.ros
        if np.isnan(ros):
            logger.warning(
                "RoS is NaN from fuel_type:%s moisture:%s slope:%s wind_speed:%s wind_dir:%s",
                fuel_type, moisture, slope_percent, wind_speed, wind_dir)
        slope_equivalent = summary.equivalent_slope
        x_w_eff = wind_speed * np.cos(wind_dir) + slope_equivalent * np.cos(
            slope_dir)
        y_w_eff = wind_speed * np.sin(wind_dir) + slope_equivalent * np.sin(
            slope_dir)
        angle_w_eff = np.arctan2(y_w_eff, x_w_eff)
        speed_w_eff = np.sqrt(x_w_eff**2 + y_w_eff**2)
        return ros, angle_w_eff, speed_w_eff

    def get_propagation_shape(self, x, y):
        ros, wind_angle, wind_speed = self.get_spread_parameters(x, y)
        return fireshapes.get_fire_shape(wind_speed, wind_angle, ros)