https://colab.research.google.com/assets/colab-badge.svg

Elliptical Time Density (ETD)#

Setup#

Ecoscope#

[ ]:
ECOSCOPE_RAW = "https://raw.githubusercontent.com/wildlife-dynamics/ecoscope/master"

# !pip install ecoscope
[ ]:
import os
import sys

import geopandas as gpd
import numpy as np
import pandas as pd

import ecoscope

ecoscope.init()

Google Drive setup#

[ ]:
output_dir = "Ecoscope-Outputs"

if "google.colab" in sys.modules:
    from google.colab import drive

    drive.mount("/content/drive/", force_remount=True)
    output_dir = os.path.join("/content/drive/MyDrive/", output_dir)

os.makedirs(output_dir, exist_ok=True)

Create Relocations#

[ ]:
ecoscope.io.download_file(
    f"{ECOSCOPE_RAW}/tests/sample_data/vector/movbank_data.csv",
    os.path.join(output_dir, "movbank_data.csv"),
)

df = pd.read_csv(os.path.join(output_dir, "movbank_data.csv"), index_col=0)
gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df["location-long"], df["location-lat"]), crs=4326)

relocs = ecoscope.base.Relocations.from_gdf(gdf, groupby_col="individual-local-identifier", time_col="timestamp")
relocs

Create Trajectory from Relocations#

[ ]:
traj = ecoscope.base.Trajectory.from_relocations(relocs)
traj

Count unique Subjects in the data:

[ ]:
traj["groupby_col"].nunique()

Filter the segments:

[ ]:
traj_seg_filter = ecoscope.base.TrajSegFilter(
    min_length_meters=0.0,
    max_length_meters=float("inf"),
    min_time_secs=0.0,
    max_time_secs=4 * 60 * 60,
    min_speed_kmhr=0.0,
    max_speed_kmhr=8.0,
)
traj.apply_traj_filter(traj_seg_filter, inplace=True)
[ ]:
traj.remove_filtered(inplace=True)

Calculate Individual ETD Ranges#

View maximum speed:

[ ]:
traj.speed_kmhr.max()

Define RasterProfile#

[ ]:
raster_profile = ecoscope.io.raster.RasterProfile(
    pixel_size=250.0,  # may need to reduce grid size if you receive a warning
    crs="ESRI:102022",  # Albers Africa Equal Area Conic
    nodata_value=np.nan,
    band_count=1,
)

Compute ETD#

[ ]:
def f(trajectory_gdf):
    output_path = os.path.join(output_dir, f"{trajectory_gdf.name}.tif")

    ecoscope.analysis.UD.calculate_etd_range(
        trajectory_gdf=trajectory_gdf,
        output_path=output_path,
        max_speed_kmhr=1.05 * trajectory_gdf.speed_kmhr.max(),  # Choose a value above the max recorded segment speed
        raster_profile=raster_profile,
        expansion_factor=1.3,
    )
    return output_path


etd = traj.groupby("groupby_col").apply(f)

Calculate ETD Percentiles#

[ ]:
percentiles = pd.concat(
    [
        ecoscope.analysis.get_percentile_area(percentile_levels=[50, 99.9, 100.0], raster_path=v, subject_id=k)
        for k, v in etd.iteritems()
    ]
).reset_index(drop=True)

percentiles

Export#

[ ]:
percentiles.to_file(os.path.join(output_dir, "percentiles.gpkg"))
[ ]:
percentiles.to_csv(os.path.join(output_dir, "percentiles.csv"))

Visualize Percentiles#

[ ]:
salif = ecoscope.analysis.get_percentile_area(
    percentile_levels=[50, 60, 70, 80, 90, 99.9], raster_path=etd.at["Salif Keita"], subject_id="Salif Keita"
)
[ ]:
m = ecoscope.mapping.EcoMap(width=800, height=600)
m.add_gdf(salif, column="percentile", cmap="RdYlGn")
m.zoom_to_gdf(salif.geometry)
m