{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# TrajectoryCollection aggregation (flow maps)\n", "\n", "\n", "\n", "[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/movingpandas/movingpandas/main?filepath=tutorials/3-generalization-and-aggregation.ipynb)\n", "\n", "**

This notebook demonstrates the current development version of MovingPandas.

**\n", "\n", "For tutorials using the latest release visit https://github.com/movingpandas/movingpandas-examples.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import urllib\n", "import os\n", "import numpy as np\n", "import pandas as pd\n", "from geopandas import GeoDataFrame, read_file\n", "from shapely.geometry import Point, LineString, Polygon, MultiPoint\n", "from datetime import datetime, timedelta\n", "from holoviews import opts, dim\n", "\n", "import sys\n", "sys.path.append(\"..\")\n", "import movingpandas as mpd\n", "mpd.show_versions()\n", "\n", "import warnings\n", "warnings.simplefilter(\"ignore\")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Ship movements (AIS data)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df = read_file('data/demodata_ais.gpkg')\n", "df['t'] = pd.to_datetime(df['Timestamp'], format='%d/%m/%Y %H:%M:%S')\n", "df = df[df.SOG>0]\n", "len(df)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "MIN_LENGTH = 100 # meters\n", "traj_collection = mpd.TrajectoryCollection(df, 'MMSI', min_length=MIN_LENGTH, t='t')\n", "print(\"Finished creating {} trajectories\".format(len(traj_collection)))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "trips = mpd.ObservationGapSplitter(traj_collection).split(gap=timedelta(minutes=5))\n", "print(\"Extracted {} individual trips from {} continuous vessel tracks\".format(len(trips), len(traj_collection)))" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Generalizing the trip trajectories significantly speeds up the following aggregation step." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%time\n", "generalized = mpd.MinDistanceGeneralizer(trips).generalize(tolerance=100)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%time\n", "aggregator = mpd.TrajectoryCollectionAggregator(generalized, max_distance=1000, min_distance=100, min_stop_duration=timedelta(minutes=5))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from hvplot import pandas\n", "pts = aggregator.get_significant_points_gdf()\n", "clusters = aggregator.get_clusters_gdf()\n", "( pts.hvplot(geo=True, tiles='OSM', frame_width=800) * \n", " clusters.hvplot(geo=True, color='red') )" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "flows = aggregator.get_flows_gdf()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "( #trips.hvplot(color='gray') *\n", " flows.hvplot(geo=True, hover_cols=['weight'], line_width=dim('weight')*0.3, alpha=0.5, color='#1f77b3', tiles='OSM') * \n", " clusters.hvplot(geo=True, color='red', size='n') )" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Comparison of generalized vs. original trajectories" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%time\n", "aggregator_original = mpd.TrajectoryCollectionAggregator(trips, max_distance=1000, min_distance=100, min_stop_duration=timedelta(minutes=5))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "( aggregator_original.get_flows_gdf().hvplot(title='Original', geo=True, tiles='OSM', hover_cols=['weight'], line_width=dim('weight')*0.3, alpha=0.5, color='#1f77b3', frame_height=400, frame_width=400) * \n", " aggregator_original.get_clusters_gdf().hvplot(geo=True, color='red', size='n') +\n", " flows.hvplot(title='Generalized', geo=True, tiles='OSM', hover_cols=['weight'], line_width=dim('weight')*0.3, alpha=0.5, color='#1f77b3', frame_height=400, frame_width=400) * \n", " clusters.hvplot(geo=True, color='red', size='n') \n", ")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Bird migration data" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df = read_file('data/demodata_gulls.gpkg')\n", "len(df)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "traj_collection = mpd.TrajectoryCollection(df, 'individual-local-identifier', min_length=MIN_LENGTH, t='timestamp') \n", "print(\"Finished creating {} trajectories\".format(len(traj_collection)))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "trips = mpd.TemporalSplitter(traj_collection).split(mode='month')\n", "print(\"Extracted {} individual trips from {} continuous tracks\".format(len(trips), len(traj_collection)))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "generalized = mpd.MinTimeDeltaGeneralizer(trips).generalize(tolerance=timedelta(days=1))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%time\n", "aggregator = mpd.TrajectoryCollectionAggregator(generalized, max_distance=1000000, min_distance=100000, min_stop_duration=timedelta(minutes=5))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "flows = aggregator.get_flows_gdf()\n", "clusters = aggregator.get_clusters_gdf()\n", "\n", "( flows.hvplot(geo=True, hover_cols=['weight'], line_width=dim('weight')*0.8, alpha=0.5, color='#1f77b3', tiles='OSM', frame_height=600, frame_width=400) * \n", " clusters.hvplot(geo=True, color='red', size='n') )" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%%time\n", "aggregator_original = mpd.TrajectoryCollectionAggregator(trips, max_distance=1000000, min_distance=100000, min_stop_duration=timedelta(minutes=5))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "( aggregator_original.get_flows_gdf().hvplot(title='Original', geo=True, tiles='OSM', hover_cols=['weight'], line_width=dim('weight')*0.8, alpha=0.5, color='#1f77b3', frame_height=600, frame_width=400) * \n", " aggregator_original.get_clusters_gdf().hvplot(geo=True, color='red', size='n') +\n", " flows.hvplot(title='Generalized', geo=True, tiles='OSM', hover_cols=['weight'], line_width=dim('weight')*0.8, alpha=0.5, color='#1f77b3', frame_height=600, frame_width=400) * \n", " clusters.hvplot(geo=True, color='red', size='n') \n", ")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Continue exploring MovingPandas\n", "\n", "1. [Getting started](1-getting-started.ipynb)\n", "1. [Handling trajectory data files (reading & writing)](2-reading-data-from-files.ipynb)\n", "1. [TrajectoryCollection aggregation (flow maps)](3-generalization-and-aggregation.ipynb)\n", "1. [Stop detection](4-stop-detection.ipynb)\n", "1. [Working with local coordinates](5-local-coordinates.ipynb)" ] } ], "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.10.8" }, "vscode": { "interpreter": { "hash": "e083ffb052fc3090335b68330fa2108e4b62c90ad12f6dc729a484d53ff96ca7" } } }, "nbformat": 4, "nbformat_minor": 4 }