Land Suitability Analysis#

NOTE: If you are new to LSAPy, we recommand you start with the Suitability Functions and Suitability Criteria tutorials.

To perform a LSA, we use LandSuitabilityAnalysis that allows to compute the overall suitability of several criteria and that has the following attributes:

  • land_use: a name for the land use.

  • criteria: dict of SuitabilityCriteria where the keys is the name of the criteria.

  • short_name (optional): a short name for the land suitability analysis (LSA).

  • long_name (optional): a long name for the LSA.

  • description (optional): additional information about the LSA.

  • comment (optional): miscellaneous information about the LSA.

First we have to define the criteria. Here, we use three criteria: the potential rooting depth and water requirement already used above and a third one corresponding to the soil draingage class (discrete). We are going to split criteria in two categories, soil and climate, and change the weight of each of them.

[15]:
import matplotlib.pyplot as plt
from xclim.indicators.atmos import precip_accumulation

from lsapy import LandSuitabilityAnalysis, SuitabilityCriteria, SuitabilityFunction
from lsapy.utils import load_climate_data, load_soil_data

soil_data = load_soil_data()
clim_data = load_climate_data().interp_like(
    soil_data, method="nearest"
)  # resample climate data to soil data resolution

lsa = LandSuitabilityAnalysis(
    land_use="your_land_use",
    long_name="My First Land Suitability Analysis",
    criteria={
        "potential_root_depth": SuitabilityCriteria(
            name="potential_root_depth",
            long_name="Potential Rooting Depth Suitability",
            weight=2,
            category="soil",
            indicator=soil_data["PRD"],  # indicator as xr.DataArray
            func=SuitabilityFunction(name="vetharaniam2022_eq5", params={"a": -11.98, "b": 0.459}),
        ),
        "drainage_class": SuitabilityCriteria(
            name="drainage_class",
            weight=1,
            category="soil",
            long_name="Drainage Class Suitability",
            indicator=soil_data["DRC"],
            func=SuitabilityFunction(name="discrete", params={"rules": {"1": 0, "2": 0.1, "3": 0.5, "4": 0.9, "5": 1}}),
        ),
        "water_requirements": SuitabilityCriteria(
            name="water_requirements",
            weight=0.5,
            category="climate",
            long_name="Annual Rainfall Requirement Suitability",
            indicator=precip_accumulation(clim_data["pr"], freq="YS"),  # indicator as xr.DataArray
            func=SuitabilityFunction(name="vetharaniam2022_eq5", params={"a": 0.876, "b": 1248}),
        ),
    },
)

Then, we can compute the suitability starting with the criteria.

[16]:
lsa.run(suitability_type="criteria", inplace=True)
lsa.data
[16]:
<xarray.Dataset> Size: 482kB
Dimensions:               (lon: 100, lat: 100, time: 10)
Coordinates:
  * lon                   (lon) float64 800B 170.0 170.1 170.1 ... 174.9 175.0
  * lat                   (lat) float64 800B -43.98 -43.92 ... -39.08 -39.02
  * time                  (time) datetime64[ns] 80B 2000-01-01 ... 2009-01-01
Data variables:
    potential_root_depth  (lat, lon) float32 40kB 0.2833 0.2076 ... 0.9426
    drainage_class        (lat, lon) float32 40kB 1.0 nan 1.0 ... 1.0 1.0 0.9
    water_requirements    (time, lat, lon) float32 400kB nan nan nan ... nan nan
Attributes:
    land_use:   your_land_use
    criteria:   ['potential_root_depth', 'drainage_class', 'water_requirements']
    long_name:  My First Land Suitability Analysis
[17]:
fig, ax = plt.subplots(1, 3, figsize=(12, 4))
lsa.data["potential_root_depth"].plot(ax=ax[0], vmin=0, vmax=1)
lsa.data["drainage_class"].plot(ax=ax[1], vmin=0, vmax=1)
lsa.data["water_requirements"].isel(time=2).plot(ax=ax[2], vmin=0, vmax=1)
plt.show()
../_images/notebooks_lsa_4_0.png

Now, we can compute the suitability of categories. There are several method implemented to aggregate criteria (e.g., mean, weighted mean, geometric mean, weighted geometric mean, and limiting factor). Here, we are going to use a simple weighted mean.

[18]:
lsa.run(suitability_type="category", agg_methods="weighted_mean", keep_vars=True, inplace=True)
lsa.data
C:\Users\Baptiste\AppData\Local\Temp\ipykernel_3644\2314572650.py:1: UserWarning: Existing data found and will be overwritten.
  lsa.run(suitability_type="category", agg_methods="weighted_mean", keep_vars=True, inplace=True)
[18]:
<xarray.Dataset> Size: 922kB
Dimensions:               (lon: 100, lat: 100, time: 10)
Coordinates:
  * lon                   (lon) float64 800B 170.0 170.1 170.1 ... 174.9 175.0
  * lat                   (lat) float64 800B -43.98 -43.92 ... -39.08 -39.02
  * time                  (time) datetime64[ns] 80B 2000-01-01 ... 2009-01-01
Data variables:
    potential_root_depth  (lat, lon) float32 40kB 0.2833 0.2076 ... 0.9426
    drainage_class        (lat, lon) float32 40kB 1.0 nan 1.0 ... 1.0 1.0 0.9
    water_requirements    (time, lat, lon) float32 400kB nan nan nan ... nan nan
    soil                  (lat, lon) float32 40kB 0.5222 nan ... 0.9593 0.9284
    climate               (time, lat, lon) float32 400kB nan nan nan ... nan nan
Attributes:
    land_use:   your_land_use
    criteria:   ['potential_root_depth', 'drainage_class', 'water_requirements']
    long_name:  My First Land Suitability Analysis
[19]:
fig, ax = plt.subplots(1, 2, figsize=(12, 4))
lsa.data["soil"].plot(ax=ax[0], vmin=0, vmax=1)
ax[0].set_title("Soil Suitability")
lsa.data["climate"].isel(time=2).plot(ax=ax[1], vmin=0, vmax=1)
ax[1].set_title("Climate Suitability")
plt.show()
../_images/notebooks_lsa_7_0.png

Finally, we can compute the overall suitability.

[20]:
lsa.run(suitability_type="overall", agg_methods="weighted_mean", by_category=True, inplace=True)
# lsa.compute_suitability(method="weighted_mean", by_category=True, inplace=True, keep_all=True)
lsa.data
C:\Users\Baptiste\AppData\Local\Temp\ipykernel_3644\1861411689.py:1: UserWarning: Existing data found and will be overwritten.
  lsa.run(suitability_type="overall", agg_methods="weighted_mean", by_category=True, inplace=True)
[20]:
<xarray.Dataset> Size: 1MB
Dimensions:               (lon: 100, lat: 100, time: 10)
Coordinates:
  * lon                   (lon) float64 800B 170.0 170.1 170.1 ... 174.9 175.0
  * lat                   (lat) float64 800B -43.98 -43.92 ... -39.08 -39.02
  * time                  (time) datetime64[ns] 80B 2000-01-01 ... 2009-01-01
Data variables:
    potential_root_depth  (lat, lon) float32 40kB 0.2833 0.2076 ... 0.9426
    drainage_class        (lat, lon) float32 40kB 1.0 nan 1.0 ... 1.0 1.0 0.9
    water_requirements    (time, lat, lon) float32 400kB nan nan nan ... nan nan
    soil                  (lat, lon) float32 40kB 0.5222 nan ... 0.9593 0.9284
    climate               (time, lat, lon) float32 400kB nan nan nan ... nan nan
    suitability           (lat, lon, time) float32 400kB nan nan nan ... nan nan
Attributes:
    land_use:   your_land_use
    criteria:   ['potential_root_depth', 'drainage_class', 'water_requirements']
    long_name:  My First Land Suitability Analysis
[21]:
fig, ax = plt.subplots(1, 3, figsize=(18, 4))
lsa.data["soil"].plot(ax=ax[0], vmin=0, vmax=1)
ax[0].set_title("Soil Suitability")
lsa.data["climate"].isel(time=2).plot(ax=ax[1], vmin=0, vmax=1)
ax[1].set_title("Climate Suitability")
lsa.data["suitability"].isel(time=2).plot(ax=ax[2], vmin=0, vmax=1)
ax[2].set_title("Land Suitability")
plt.show()
../_images/notebooks_lsa_10_0.png