From a370d57473d7a0c54c38ef59fa3f6fc7b68e7796 Mon Sep 17 00:00:00 2001 From: atmorling Date: Thu, 19 Dec 2024 11:25:30 +0200 Subject: [PATCH] remove SpeedDataframe and Speedmap (#294) --- ecoscope/analysis/__init__.py | 1 - ecoscope/analysis/speed.py | 100 ---------------------------------- ecoscope/mapping/map.py | 39 +------------ tests/test_speed.py | 9 --- 4 files changed, 1 insertion(+), 148 deletions(-) delete mode 100644 ecoscope/analysis/speed.py delete mode 100644 tests/test_speed.py diff --git a/ecoscope/analysis/__init__.py b/ecoscope/analysis/__init__.py index 76b816e9..1b335172 100644 --- a/ecoscope/analysis/__init__.py +++ b/ecoscope/analysis/__init__.py @@ -1,6 +1,5 @@ __all__ = [ "ecograph", - "speed", "UD", "astronomy", "classifier", diff --git a/ecoscope/analysis/speed.py b/ecoscope/analysis/speed.py deleted file mode 100644 index 529830fc..00000000 --- a/ecoscope/analysis/speed.py +++ /dev/null @@ -1,100 +0,0 @@ -import typing - -import geopandas as gpd -import pandas as pd -import shapely - -import ecoscope.base - -try: - import mapclassify -except ModuleNotFoundError: - raise ModuleNotFoundError( - 'Missing optional dependencies required by this module. \ - Please run pip install ecoscope["analysis"]' - ) - - -class SpeedDataFrame(ecoscope.base.EcoDataFrame): - @classmethod - def from_trajectory( - cls, - trajectory: ecoscope.base.Trajectory, - classification_method: str = "equal_interval", - num_classes: int = 6, - bins: typing.List = None, - speed_colors: typing.List = None, - ): - if not bins: - bins = apply_classification(trajectory.speed_kmhr, num_classes, cls_method=classification_method) - - if not speed_colors: - speed_colors = default_speed_colors - - speed_colors = speed_colors[: len(bins) - 1] - - speed_df = cls( - geometry=gpd.GeoSeries( - trajectory.geometry.values, - index=pd.Index( - pd.cut(x=trajectory.speed_kmhr, bins=bins, labels=speed_colors, include_lowest=True), - name="speed_colour", - ), - ) - .groupby(level=0) - .apply(lambda gs: shapely.multilinestrings(gs)), - crs=trajectory.crs, - ) - speed_df.reset_index(drop=False, inplace=True) - speed_df["label"] = _speedmap_labels(bins) - speed_df.sort_values("speed_colour", inplace=True) - - return speed_df - - -def _speedmap_labels(bins): - return [f"{bins[i]:.1f} - {bins[i + 1]:.1f} km/hr" for i in range(len(bins) - 1)] - - -def apply_classification(x, k, cls_method="natural_breaks", multiples=[-2, -1, 1, 2]): - """ - Function to select which classifier to apply to the speed distributed data. - - Parameters - ---------- - x : np.ndarray - The input array to be classified. Must be 1-dimensional - k : int - Number of classes required. - cls_method : str - Classification method - multiples : Listlike - The multiples of the standard deviation to add/subtract from the sample mean to define the bins. defaults= - """ - - classifier = classification_methods.get(cls_method) - if not classifier: - return - - map_classifier = classifier(x, multiples) if cls_method == "std_mean" else classifier(x, k) - edges, _, _ = mapclassify.classifiers._format_intervals(map_classifier, fmt="{:.2f}") - return [float(i) for i in edges] - - -default_speed_colors = [ - "#1a9850", - "#91cf60", - "#d9ef8b", - "#fee08b", - "#fc8d59", - "#d73027", -] - -classification_methods = { - "equal_interval": mapclassify.EqualInterval, - "natural_breaks": mapclassify.NaturalBreaks, - "quantile": mapclassify.Quantiles, - "std_mean": mapclassify.StdMean, - "max_breaks": mapclassify.MaximumBreaks, - "fisher_jenks": mapclassify.FisherJenks, -} diff --git a/ecoscope/mapping/map.py b/ecoscope/mapping/map.py index 12bd21cf..25a8f6a6 100644 --- a/ecoscope/mapping/map.py +++ b/ecoscope/mapping/map.py @@ -14,13 +14,11 @@ try: import matplotlib as mpl - from ecoscope.analysis.speed import SpeedDataFrame from lonboard import Map from lonboard.types.layer import PathLayerKwargs, PolygonLayerKwargs, ScatterplotLayerKwargs from lonboard._geoarrow.ops.bbox import Bbox from lonboard._viewport import compute_view, bbox_to_zoom_level from lonboard._viz import viz_layer - from lonboard.colormap import apply_categorical_cmap from lonboard._layer import ( BaseLayer, BitmapLayer, @@ -46,42 +44,7 @@ ) -class EcoMapMixin: - def add_speedmap( - self, - trajectory: gpd.GeoDataFrame, - classification_method: str = "equal_interval", - num_classes: int = 6, - speed_colors: List = None, - bins: List = None, - legend: bool = True, - ): - - speed_df = SpeedDataFrame.from_trajectory( - trajectory=trajectory, - classification_method=classification_method, - num_classes=num_classes, - speed_colors=speed_colors, - bins=bins, - ) - - colors = speed_df["speed_colour"].to_list() - rgb = [] - for i, color in enumerate(colors): - color = color.strip("#") - rgb.append(list(int(color[i : i + 2], 16) for i in (0, 2, 4))) - - cmap = apply_categorical_cmap(values=speed_df.index.to_series(), cmap=rgb) - path_kwargs = {"get_color": cmap, "pickable": False} - self.add_gdf(speed_df, path_kwargs=path_kwargs) - - if legend: - self.add_legend(labels=speed_df.label.to_list(), colors=speed_df.speed_colour.to_list()) - - return speed_df - - -class EcoMap(EcoMapMixin, Map): +class EcoMap(Map): def __init__(self, static=False, default_widgets=True, *args, **kwargs): kwargs["height"] = kwargs.get("height", 600) diff --git a/tests/test_speed.py b/tests/test_speed.py deleted file mode 100644 index 801730dd..00000000 --- a/tests/test_speed.py +++ /dev/null @@ -1,9 +0,0 @@ -import ecoscope -from ecoscope.analysis import speed - - -def test_speed_geoseries(movebank_relocations): - trajectory = ecoscope.base.Trajectory.from_relocations(movebank_relocations) - sdf = speed.SpeedDataFrame.from_trajectory(trajectory) - assert not sdf.geometry.is_empty.any() - assert not sdf.geometry.isna().any()