{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Elliptical Time Density (ETD)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ecoscope" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ECOSCOPE_RAW = \"https://raw.githubusercontent.com/wildlife-dynamics/ecoscope/master\"\n", "\n", "!pip install 'ecoscope[analysis,mapping,plotting] @ git+https://github.com/wildlife-dynamics/ecoscope@v1.8.12' &> /dev/null" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import os\n", "import sys\n", "\n", "import geopandas as gpd\n", "import numpy as np\n", "import pandas as pd\n", "\n", "import ecoscope\n", "from ecoscope.analysis.UD import calculate_etd_range\n", "from ecoscope.analysis.percentile import get_percentile_area\n", "\n", "ecoscope.init()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Google Drive setup" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "output_dir = \"Ecoscope-Outputs\"\n", "\n", "if \"google.colab\" in sys.modules:\n", " from google.colab import drive\n", "\n", " drive.mount(\"/content/drive/\", force_remount=True)\n", " output_dir = os.path.join(\"/content/drive/MyDrive/\", output_dir)\n", "\n", "os.makedirs(output_dir, exist_ok=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Create Relocations " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ecoscope.io.download_file(\n", " f\"{ECOSCOPE_RAW}/tests/sample_data/vector/movebank_data.csv\",\n", " os.path.join(output_dir, \"movebank_data.csv\"),\n", ")\n", "\n", "df = pd.read_csv(os.path.join(output_dir, \"movebank_data.csv\"), index_col=0)\n", "gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df[\"location-long\"], df[\"location-lat\"]), crs=4326)\n", "\n", "relocs = ecoscope.base.Relocations.from_gdf(gdf, groupby_col=\"individual-local-identifier\", time_col=\"timestamp\")\n", "relocs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Create Trajectory from Relocations" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "traj = ecoscope.base.Trajectory.from_relocations(relocs)\n", "traj" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Count unique Subjects in the data:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "traj[\"groupby_col\"].nunique()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Filter the segments:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "traj_seg_filter = ecoscope.base.TrajSegFilter(\n", " min_length_meters=0.0,\n", " max_length_meters=float(\"inf\"),\n", " min_time_secs=0.0,\n", " max_time_secs=4 * 60 * 60,\n", " min_speed_kmhr=0.0,\n", " max_speed_kmhr=8.0,\n", ")\n", "traj.apply_traj_filter(traj_seg_filter, inplace=True)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "traj.remove_filtered(inplace=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Calculate Individual ETD Ranges" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "View maximum speed:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "traj.speed_kmhr.max()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Define RasterProfile" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "raster_profile = ecoscope.io.raster.RasterProfile(\n", " pixel_size=250.0, # may need to reduce grid size if you receive a warning\n", " crs=\"ESRI:102022\", # Albers Africa Equal Area Conic\n", " nodata_value=np.nan,\n", " band_count=1,\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Compute ETD" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def f(trajectory_gdf):\n", " output_path = os.path.join(output_dir, f\"{trajectory_gdf.name}.tif\")\n", "\n", " calculate_etd_range(\n", " trajectory_gdf=trajectory_gdf,\n", " output_path=output_path,\n", " max_speed_kmhr=1.05 * trajectory_gdf.speed_kmhr.max(), # Choose a value above the max recorded segment speed\n", " raster_profile=raster_profile,\n", " expansion_factor=1.3,\n", " )\n", " return output_path\n", "\n", "\n", "etd = traj.groupby(\"groupby_col\").apply(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Calculate ETD Percentiles" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "percentiles = pd.concat(\n", " [get_percentile_area(percentile_levels=[50, 99.9, 100.0], raster_path=v, subject_id=k) for k, v in etd.items()]\n", ").reset_index(drop=True)\n", "\n", "percentiles" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Export" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "percentiles.to_file(os.path.join(output_dir, \"percentiles.gpkg\"))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "percentiles.to_csv(os.path.join(output_dir, \"percentiles.csv\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Percentiles" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "salif = get_percentile_area(\n", " percentile_levels=[50, 60, 70, 80, 90, 99.9], raster_path=etd.at[\"Salif Keita\"], subject_id=\"Salif Keita\"\n", ")" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "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.12.3" } }, "nbformat": 4, "nbformat_minor": 4 }