Skip to content

Commit

Permalink
Seasonal and value index creation methods added
Browse files Browse the repository at this point in the history
  • Loading branch information
insaite committed Oct 19, 2023
1 parent 2a4d30d commit f64880b
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 4 deletions.
39 changes: 35 additions & 4 deletions ecoscope/analysis/seasons.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import ee
import numpy as np
import pandas
import pandas as pd
import shapely
import sklearn.mixture
from scipy.stats import norm
Expand Down Expand Up @@ -36,9 +35,9 @@ def std_ndvi_vals(aoi=None, img_coll=None, band=None, img_scale=1, start=None, e

ndvi_vals = coll.toBands().reduceRegion("mean", geo, bestEffort=True).values().getInfo()

df = pd.DataFrame(
df = pandas.DataFrame(
{
"img_date": pd.to_datetime(coll.aggregate_array("system:time_start").getInfo(), unit="ms", utc=True),
"img_date": pandas.to_datetime(coll.aggregate_array("system:time_start").getInfo(), unit="ms", utc=True),
"NDVI": ndvi_vals,
}
).dropna(axis=0)
Expand Down Expand Up @@ -102,9 +101,41 @@ def seasonal_windows(ndvi_vals, cuts, season_labels):
{
"start": pandas.Series([grp["img_date"].iloc[0] for _, grp in grpd]),
"end": pandas.Series([grp["img_date"].iloc[-1] for _, grp in grpd]).apply(
lambda x: x + pd.Timedelta(days=1)
lambda x: x + pandas.Timedelta(days=1)
),
"season": pandas.Series(grp["season"].iloc[0] for name, grp in grpd),
"unique_season": pandas.Series([name for name, _ in grpd]),
}
).set_index("unique_season")


def add_seasonal_index(df, index_name, start_date, end_date, aoi_geom_filter=None, seasons=2, season_labels=["dry", "wet"]):

aoi_ = None
try:
aoi_ = aoi_geom_filter.dissolve().iloc[0]['geometry']
except:
aoi_ = aoi_geom_filter

if len(season_labels) != seasons:
raise Exception(f"Parameter value 'seasons' ({seasons}) must match the number of 'season_labels' elements ({season_labels})")
# extract the standardized NDVI ndvi_vals within the AOI
ndvi_vals = std_ndvi_vals(
aoi_,
start=since_filter.isoformat(),
end=until_filter.isoformat()
)

# calculate the seasonal transition point
cuts = val_cuts(ndvi_vals, seasons)

# determine the seasonal time windows
windows = seasonal_windows(ndvi_vals, cuts, season_labels)

# Categorize the fixtime values according to the season
bins = pandas.IntervalIndex(data=windows.apply(lambda x: pandas.Interval(x["start"], x["end"]), axis=1))
labels = windows.season
df[index_name] = pandas.cut(df[time_col], bins=bins).map(dict(zip(bins,labels)))

# set the index
return df.set_index(index_name, append=True)
49 changes: 49 additions & 0 deletions ecoscope/base/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,52 @@ def create_modis_interval_index(start, intervals, overlap=pd.Timedelta(0), close
left = pd.DatetimeIndex(left)

return pd.IntervalIndex.from_arrays(left=left, right=left + pd.Timedelta(days=16), closed=closed)


def add_val_index(df, index_name, val):
"""
Parameters
----------
df : pd.DataFrame
Dataframe to create index on
index_name : str
Name of index
val : str
Current column to rename and set as index
Returns
-------
pd.DataFrame
"""
if val in df.columns:
return df.rename(columns={val: index_name}).set_index(index_name, append=True)
else:
df[index_name] = val
df = df.set_index(index_name, append=True)
return df


def add_temporal_index(df, index_name, time_col, directive):
"""
Parameters
----------
df : pd.DataFrame
Dataframe to create index on
index_name : str
Name of temporal index
time_col : str
Name of the time column
directive : str
Time format string
Returns
-------
pd.DataFrame
"""
if directive and time_col:
df[index_name] = df[time_col].dt.strftime(directive)
return df.set_index(index_name, append=True)
else:
return df

0 comments on commit f64880b

Please sign in to comment.