{ "cells": [ { "cell_type": "markdown", "id": "0", "metadata": {}, "source": [ "# Overview of pylandstats" ] }, { "cell_type": "code", "execution_count": null, "id": "1", "metadata": {}, "outputs": [], "source": [ "import swisslandstats as sls\n", "\n", "import pylandstats as pls" ] }, { "cell_type": "markdown", "id": "2", "metadata": {}, "source": [ "The data used in this notebook ships with the docs in the `data` directory, namely:\n", "- the land use/land cover (LULC) data (see [A03-swisslandstats-preprocessing.ipynb](https://github.com/martibosch/pylandstats-notebooks/blob/main/notebooks/A03-swisslandstats-preprocessing.ipynb) for how it is derived from the raw SLS data).\n", "- the elevation zones vector data (see [A04-elevation-zones.ipynb](https://github.com/martibosch/pylandstats-notebooks/blob/main/notebooks/A04-elevation-zones.ipynb) for more details)." ] }, { "cell_type": "markdown", "id": "3", "metadata": {}, "source": [ "## Landscape analysis\n", "\n", "We can load landscapes from raster files and compute pandas data frames of patch, class and landscape level. See the notebook [01-landscape-analysis.ipynb](https://github.com/martibosch/pylandstats-notebooks/blob/main/notebooks/01-landscape-analysis.ipynb) for more thorough demonstration." ] }, { "cell_type": "code", "execution_count": null, "id": "4", "metadata": {}, "outputs": [], "source": [ "URBAN_CLASS_VAL = 1\n", "input_filepath = \"data/veveyse/LU18_4.tif\"" ] }, { "cell_type": "code", "execution_count": null, "id": "5", "metadata": {}, "outputs": [], "source": [ "ls = pls.Landscape(input_filepath)\n", "ls.plot_landscape(cmap=sls.noas04_4_cmap, norm=sls.noas04_4_norm, legend=True)" ] }, { "cell_type": "code", "execution_count": null, "id": "6", "metadata": {}, "outputs": [], "source": [ "patch_metrics_df = ls.compute_patch_metrics_df()\n", "patch_metrics_df.head()" ] }, { "cell_type": "code", "execution_count": null, "id": "7", "metadata": {}, "outputs": [], "source": [ "class_metrics_df = ls.compute_class_metrics_df()\n", "class_metrics_df" ] }, { "cell_type": "code", "execution_count": null, "id": "8", "metadata": {}, "outputs": [], "source": [ "landscape_metrics_df = ls.compute_landscape_metrics_df()\n", "landscape_metrics_df" ] }, { "cell_type": "markdown", "id": "9", "metadata": {}, "source": [ "(spatiotemporal-analysis)=\n", "## Spatio-temporal analysis\n", "\n", "Given a temporally-ordered sequence of landscape snapshots, we can also analyze the spatio-temporal patterns of landscape change. To that end, pylandstats can compute pandas dataframes with the evolution of the metrics and plot them, both at the class and landscape level. See the notebook [02-spatiotemporal-analysis.ipynb](https://github.com/martibosch/pylandstats-notebooks/blob/main/notebooks/02-spatiotemporal-analysis.ipynb) for a more thorough demonstration." ] }, { "cell_type": "code", "execution_count": null, "id": "10", "metadata": {}, "outputs": [], "source": [ "input_filepaths = [\n", " \"data/veveyse/LU85_4.tif\",\n", " \"data/veveyse/LU97_4.tif\",\n", " \"data/veveyse/LU09_4.tif\",\n", " \"data/veveyse/LU18_4.tif\",\n", "]\n", "years = [\"1980\", \"1992\", \"2004\", \"2013\"]" ] }, { "cell_type": "code", "execution_count": null, "id": "11", "metadata": {}, "outputs": [], "source": [ "sta = pls.SpatioTemporalAnalysis(input_filepaths, dates=years)" ] }, { "cell_type": "code", "execution_count": null, "id": "12", "metadata": {}, "outputs": [], "source": [ "sta.compute_class_metrics_df()" ] }, { "cell_type": "code", "execution_count": null, "id": "13", "metadata": {}, "outputs": [], "source": [ "sta.compute_landscape_metrics_df()" ] }, { "cell_type": "markdown", "id": "14", "metadata": {}, "source": [ "We can also plot the time series of metrics at the class level, e.g., the evolution of the proportion of landscape occupied by the land use class value `1` (urban):" ] }, { "cell_type": "code", "execution_count": null, "id": "15", "metadata": {}, "outputs": [], "source": [ "sta.plot_metric(\"proportion_of_landscape\", class_val=URBAN_CLASS_VAL)" ] }, { "cell_type": "markdown", "id": "16", "metadata": {}, "source": [ "or we can also plot at the landscape level by not providing any `class_val` argument, e.g., the evolution of the area-weighted mean fractal dimension of all the patches of the landscape:" ] }, { "cell_type": "code", "execution_count": null, "id": "17", "metadata": {}, "outputs": [], "source": [ "sta.plot_metric(\"fractal_dimension_am\")" ] }, { "cell_type": "markdown", "id": "18", "metadata": {}, "source": [ "(zonal-analysis)=\n", "## Zonal analysis\n", "\n", "Zonal analysis is a common procedure to compute statistics for a set of specified spatial zones. PyLandStats features three classes to perform zonal analysis, `ZonalAnalysis`, `BufferAnalysis` and `ZonalGridAnalysis`. The first allows user to fully customize how the zones are defined, while `BufferAnalysis` and `ZonalGriAnalysis` provide a convenient way to instantiate specific cases of zonal analysis, i.e., adding buffers around a feature of interest or as a regular rectangular grid over the landscape, respectively. See the notebook [03-zonal-analysis.ipynb](https://github.com/martibosch/pylandstats-notebooks/blob/main/notebooks/03-zonal-analysis.ipynb) for a thorough demonstration of the use cases described above.\n", "\n", "To define the zones of a `ZonalAnalysis`, we can use - among other options - any geographic data file that can be read by [geopandas.read_file](https://geopandas.org/en/stable/docs/reference/api/geopandas.read_file.html#geopandas.read_file). For instance, we can use a geopackage file defining three elevation zones in our landscape:" ] }, { "cell_type": "code", "execution_count": null, "id": "19", "metadata": {}, "outputs": [], "source": [ "elev_zones_filepath = \"data/elev-zones.gpkg\"\n", "\n", "za = pls.ZonalAnalysis(input_filepath, elev_zones_filepath, zone_index=\"elev-zone\")\n", "# plot the landscapes of each zone\n", "fig = za.plot_landscapes(\n", " cmap=sls.noas04_4_cmap, show_kwargs=dict(norm=sls.noas04_4_norm)\n", ")" ] }, { "cell_type": "markdown", "id": "20", "metadata": {}, "source": [ "Analogously to the spatio-temporal analysis, we can use the `compute_class_metrics_df` and `compute_landscape_metrics_df` methods to compute the metrics for each zone:" ] }, { "cell_type": "code", "execution_count": null, "id": "21", "metadata": {}, "outputs": [], "source": [ "za.compute_class_metrics_df()" ] }, { "cell_type": "code", "execution_count": null, "id": "22", "metadata": {}, "outputs": [], "source": [ "za.compute_landscape_metrics_df()" ] }, { "cell_type": "markdown", "id": "23", "metadata": {}, "source": [ "We can also use the `plot_metric` method to plot the metrics computed for each zone, e.g., how the proportion of landscape occupied by the land use class value `1` (urban) changes across elevation zones" ] }, { "cell_type": "code", "execution_count": null, "id": "24", "metadata": {}, "outputs": [], "source": [ "za.plot_metric(\"proportion_of_landscape\", class_val=URBAN_CLASS_VAL)" ] }, { "cell_type": "markdown", "id": "25", "metadata": {}, "source": [ "Like in the spatio-temporal analysis, the plots at the landscape level can obtained by not providing any `class_val` argument.\n", "\n", "In order to visualize such information in space, the zonal statistics can be computed in the form of a geo-data frame with the `compute_zonal_statistics_gdf` method as in:" ] }, { "cell_type": "code", "execution_count": null, "id": "26", "metadata": {}, "outputs": [], "source": [ "metrics = [\"proportion_of_landscape\", \"edge_density\"]\n", "zonal_statistics_gdf = za.compute_zonal_statistics_gdf(\n", " metrics=metrics, class_val=URBAN_CLASS_VAL\n", ")\n", "\n", "zonal_statistics_gdf.head()" ] }, { "cell_type": "markdown", "id": "27", "metadata": {}, "source": [ "the computed metrics are essentially the same as those obtained using the `compute_class_metrics_df` or `compute_landscape_metrics_df` (depending on whether a `class_val` argument is provided or not), with an additional column featuring the vector geometry of each zone. This actually corresponds to a geopandas geo-data frame, and as such, we can use [its `geopandas.GeoDataFrame.explore` method](https://geopandas.org/en/stable/docs/reference/api/geopandas.GeoDataFrame.explore.html) to obtain an interactive map as in:" ] }, { "cell_type": "code", "execution_count": null, "id": "28", "metadata": {}, "outputs": [], "source": [ "zonal_statistics_gdf.explore()" ] }, { "cell_type": "markdown", "id": "29", "metadata": {}, "source": [ "## Spatio-temporal zonal analysis\n", "\n", "We might also be interested in performing the same zonal analysis at different points in time. This is why pylandstats features an additional `SpatioTemporalZonalAnalysis` analysis class - as well as `SpatioTemporalBufferAnalysis` and `SpatioTemporalZonalGridAnalysis`. See the notebook [04-spatiotemporal-zonal-analysis.ipynb](https://github.com/martibosch/pylandstats-notebooks/blob/main/notebooks/04-spatiotemporal-zonal-analysis.ipynb) for a more thorough demonstration.\n", "\n", "Let us take the sequence of landscapes `input_filepaths` from [the spatio-temporal analysis above](#spatiotemporal-analysis) and let us use again the `dates` argument to specify the dates that correspond to each landscape.\n", "Let us also take the latitude and longitude of the center of Lausanne as well as the elevation zones from [the zonal analysis above](#zonal-analysis). Now we can construct our `SpatioTemporalZonalAnalysis` instance and evaluate the sensitive of our spatio-temporal analysis to the extent of the map:" ] }, { "cell_type": "code", "execution_count": null, "id": "30", "metadata": {}, "outputs": [], "source": [ "stza = pls.SpatioTemporalZonalAnalysis(\n", " input_filepaths, elev_zones_filepath, dates=years, zone_index=\"elev-zone\"\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "31", "metadata": {}, "outputs": [], "source": [ "stza.compute_class_metrics_df()" ] }, { "cell_type": "code", "execution_count": null, "id": "32", "metadata": {}, "outputs": [], "source": [ "stza.plot_metric(\"proportion_of_landscape\", class_val=URBAN_CLASS_VAL)" ] } ], "metadata": { "kernelspec": { "display_name": "Python (Pixi)", "language": "python", "name": "pixi-kernel-python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.14.7" }, "pixi-kernel": { "environment": "user-guide" } }, "nbformat": 4, "nbformat_minor": 5 }