Elliptical Time Density (ETD)#
Setup#
Ecoscope#
[ ]:
ECOSCOPE_RAW = "https://raw.githubusercontent.com/wildlife-dynamics/ecoscope/master"
%pip install \
'ecoscope[analysis,mapping,plotting] @ git+https://github.com/wildlife-dynamics/ecoscope@v1.8.21' &> /dev/null
[ ]:
import os
import sys
import geopandas as gpd
import numpy as np
import pandas as pd
import ecoscope
from ecoscope.analysis.UD import calculate_etd_range
from ecoscope.analysis.percentile import get_percentile_area
from ecoscope.io.raster import RasterData
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/movebank_data.csv",
os.path.join(output_dir, "movebank_data.csv"),
)
df = pd.read_csv(os.path.join(output_dir, "movebank_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")
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(
[
get_percentile_area(
percentile_levels=[50, 99.9, 100.0], raster_data=RasterData.from_raster_file(v), subject_id=k
)
for k, v in etd.items()
]
).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"))
Percentiles#
[ ]:
salif = get_percentile_area(
percentile_levels=[50, 60, 70, 80, 90, 99.9],
raster_data=RasterData.from_raster_file(etd.at["Salif Keita"]),
subject_id="Salif Keita",
)