Skip to content

Commit

Permalink
lazy load of expensive / niche imports
Browse files Browse the repository at this point in the history
  • Loading branch information
atmorling committed May 28, 2024
1 parent 2d1bed5 commit aabdce5
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 23 deletions.
14 changes: 6 additions & 8 deletions ecoscope/analysis/ecograph.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import geopandas as gpd
import igraph
import sklearn
import networkx as nx
import numpy as np
import pandas as pd
Expand All @@ -10,7 +11,7 @@
from shapely.geometry import shape
from skimage.draw import line

import ecoscope
from ecoscope.io.raster import RasterExtent, RasterProfile, RasterPy


class Ecograph:
Expand Down Expand Up @@ -118,7 +119,6 @@ def to_geotiff(self, feature, output_path, individual="all", interpolation=None,
transform : sklearn.base.TransformerMixin or None
A feature transform method (Default : None)
"""
from sklearn.base import TransformerMixin

if feature in self.features:
if individual == "all":
Expand All @@ -130,22 +130,20 @@ def to_geotiff(self, feature, output_path, individual="all", interpolation=None,
else:
raise ValueError("This feature was not computed by EcoGraph")

if isinstance(transform, TransformerMixin):
if isinstance(transform, sklearn.base.TransformerMixin):
nan_mask = ~np.isnan(feature_ndarray)
feature_ndarray[nan_mask] = transform.fit_transform(feature_ndarray[nan_mask].reshape(-1, 1)).reshape(
feature_ndarray[nan_mask].shape
)

raster_profile = ecoscope.io.raster.RasterProfile(
raster_profile = RasterProfile(
pixel_size=self.resolution,
crs=self.utm_crs,
nodata_value=np.nan,
band_count=1,
)
raster_profile.raster_extent = ecoscope.io.raster.RasterExtent(
x_min=self.xmin, x_max=self.xmax, y_min=self.ymin, y_max=self.ymax
)
ecoscope.io.raster.RasterPy.write(
raster_profile.raster_extent = RasterExtent(x_min=self.xmin, x_max=self.xmax, y_min=self.ymin, y_max=self.ymax)
RasterPy.write(
ndarray=feature_ndarray,
fp=output_path,
**raster_profile,
Expand Down
3 changes: 1 addition & 2 deletions ecoscope/analysis/seasons.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import shapely
from scipy.stats import norm
from sklearn.preprocessing import LabelEncoder
from sklearn.mixture import GaussianMixture

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -49,8 +50,6 @@ def std_ndvi_vals(aoi=None, img_coll=None, nir_band=None, red_band=None, img_sca


def val_cuts(vals, num_seasons=2):
from sklearn.mixture import GaussianMixture

distr = GaussianMixture(n_components=num_seasons, max_iter=500)
vals = vals["NDVI"].to_numpy().reshape(-1, 1)
distr.fit(vals)
Expand Down
19 changes: 10 additions & 9 deletions ecoscope/analysis/speed.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import shapely

import ecoscope.base
import lazy_loader as lazy

mapclassify = lazy.load("mapclassify")


class SpeedDataFrame(ecoscope.base.EcoDataFrame):
Expand Down Expand Up @@ -64,23 +67,21 @@ def apply_classification(x, k, cls_method="natural_breaks", multiples=[-2, -1, 1
The multiples of the standard deviation to add/subtract from the sample mean to define the bins. defaults=
"""

from mapclassify import classifiers

classification_methods = {
"equal_interval": classifiers.EqualInterval,
"natural_breaks": classifiers.NaturalBreaks,
"quantile": classifiers.Quantiles,
"std_mean": classifiers.StdMean,
"max_breaks": classifiers.MaximumBreaks,
"fisher_jenks": classifiers.FisherJenks,
"equal_interval": mapclassify.EqualInterval,
"natural_breaks": mapclassify.NaturalBreaks,
"quantile": mapclassify.Quantiles,
"std_mean": mapclassify.StdMean,
"max_breaks": mapclassify.MaximumBreaks,
"fisher_jenks": mapclassify.FisherJenks,
}

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, _, _ = classifiers._format_intervals(map_classifier, fmt="{:.2f}")
edges, _, _ = mapclassify.classifiers._format_intervals(map_classifier, fmt="{:.2f}")
return [float(i) for i in edges]


Expand Down
5 changes: 4 additions & 1 deletion ecoscope/base/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
)
from ecoscope.base.utils import cachedproperty

import lazy_loader as lazy

astroplan = lazy.load("astroplan")


class EcoDataFrame(gpd.GeoDataFrame):
"""
Expand Down Expand Up @@ -393,7 +397,6 @@ def get_daynight_ratio(self, n_grid_points=150) -> pd.Series:
pd.Series:
Daynight ratio for each unique individual subject in the grouby_col column.
"""
import astroplan

locations = to_EarthLocation(self.geometry.to_crs(crs=self.estimate_utm_crs()).centroid)

Expand Down
5 changes: 4 additions & 1 deletion ecoscope/mapping/map.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
import ecoscope
from ecoscope.contrib.foliumap import Map

import lazy_loader as lazy

ds = lazy.load("datashader")

warnings.filterwarnings("ignore", "GeoSeries.isna", UserWarning)


Expand Down Expand Up @@ -508,7 +512,6 @@ def add_datashader_gdf(
kwargs
Additional kwargs passed to datashader.transfer_functions.shade
"""
import datashader as ds

gdf = gdf.to_crs(epsg=4326)
bounds = gdf.geometry.total_bounds
Expand Down
3 changes: 1 addition & 2 deletions ecoscope/plotting/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import plotly.graph_objs as go
import shapely
from plotly.subplots import make_subplots
from sklearn.neighbors import KernelDensity


class EcoPlotData:
Expand Down Expand Up @@ -242,8 +243,6 @@ def speed(trajectory):


def plot_seasonal_dist(ndvi_vals, cuts, bandwidth=0.05, output_file=None):
from sklearn.neighbors import KernelDensity

x = ndvi_vals.sort_values().to_numpy().reshape(-1, 1)
kde = KernelDensity(kernel="gaussian", bandwidth=bandwidth).fit(x)
dens = np.exp(kde.score_samples(x))
Expand Down

0 comments on commit aabdce5

Please sign in to comment.