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:
dictofSuitabilityCriteriawhere 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()
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()
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()