Skip to content

Commit

Permalink
small fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
patel-zeel committed Jul 22, 2021
1 parent b7f914e commit 0c0c3a0
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 89 deletions.
1 change: 0 additions & 1 deletion polire/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@
from .kriging.kriging import Kriging
from .gp.gp import GP
from .custom.custom import CustomInterpolator
from .rfsi.rfsi import RFSI
2 changes: 1 addition & 1 deletion polire/base/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def predict(self, X, **kwargs):
"""

assert len(X.shape) == 2, "X must be a 2D array got shape = "+str(X.shape)
assert X.shape[1] == 2, "X can not have more than 2 dimensions"
# assert X.shape[1] == 2, "X can not have more than 2 dimensions"

# checking if model is fitted or not
assert self._fit_called, "First call fit method to fit the model"
Expand Down
2 changes: 1 addition & 1 deletion polire/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
med_res = 100
high_res = 1000

RESOLUTION = {"low": 10, "standard": 100, "high": 1000}
RESOLUTION = {"low": low_res, "standard": med_res, "high": high_res}
115 changes: 115 additions & 0 deletions polire/preprocessing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import numpy as np
from .idw.idw import IDW
from .utils.distance import haversine, euclidean


class SpatialFeatures:
"""Generate spatial features from N-closest locations
Args:
n_closest : 'N' closest locations
idw : To use idw output as one of the feature
idw_exponent : Exponent to be used in idw (if idw is False, ignore)
coordinate_type : 'Eucleadian' or 'Geographic' (if idw is False, ignore)
resolution : 'low', 'standard' or 'high' (if idw is False, ignore)
"""

def __init__(self, n_closest: int = 5, idw: bool = True, idw_exponent: float = 2,
coordinate_type: str = 'Euclidean', resolution: str = 'standard') -> None:

self.n_closest = n_closest
self.idw = idw
self.idw_exponent = idw_exponent
self.coordinate_type = coordinate_type
self.resolution = resolution
if self.coordinate_type == 'Eucledian':
self.distance = euclidean
elif self.coordinate_type == 'Geographic':
self.distance = haversine
else:
raise NotImplementedError(
'"'+self.coordinate_type+'" is not implemented yet or invalid')

def fit(self, X: np.ndarray, y: np.ndarray) -> object:
"""[summary]
Args:
X : Reference X data (longitude, latitude, time, ...)
y : Reference y data
Returns:
self
"""
self.X = X
self.y = y

def transform(self, X: np.ndarray) -> np.ndarray:
"""Transform features
Args:
X (np.ndarray): (longitude, latitude, time, ...)
Raises:
Exception: If not already fitted
Returns:
np.ndarray: Transformed features
"""
try:
self.X
except AttributeError:
raise Exception("Not fitted yet. first call the 'fit' method")

Xflag = False
if np.all(X == self.X):
Xflag = True

F = np.empty((X.shape[0], (X.shape[1] - 3) +
self.n_closest*2 + self.idw)) * np.nan
for t in np.unique(X[:, 2]): # Iterating over time
mask = X[:, 2] == t # rows with time t
trn_mask = self.X[:, 2] == t
X_local = X[mask]
self_X_local = self.X[trn_mask]

lonlat = X_local[:, :2] # locs
self_lonlat = self_X_local[:, :2] # Reference locs
dst = self.distance(lonlat, self_lonlat)
if Xflag:
idx = dst.argsort()[:, 1:self.n_closest+1]
else:
idx = dst.argsort()[:, :self.n_closest]

# Feature set 1: closest distances
f1 = dst[np.arange(lonlat.shape[0])[:, None], idx]

self_y_local = self.y[trn_mask] # Train obs
ymat = self_y_local[:, None].repeat(lonlat.shape[0], 1).T
# Feature set 2: closest observations
f2 = ymat[np.arange(lonlat.shape[0])[:, None], idx]

if self.idw:
def for_each_row(i):
i = i[0]
model = IDW(exponent=self.idw_exponent)
model.resolution = self.resolution
model.coordinate_type = self.coordinate_type
model.fit(self_lonlat[idx[i]], self_y_local[idx[i]])
return model.predict(lonlat[i][None, :])

# Feature set 3: IDW observation
f3 = np.apply_along_axis(
for_each_row, axis=1, arr=np.arange(lonlat.shape[0]).reshape(-1, 1))
F[mask] = np.concatenate([X_local[:, 3:], f1, f2, f3], axis=1)
else:
F[mask] = np.concatenate([X_local[:, 3:], f1, f2], axis=1)

return F

def fit_transform(self, X: np.ndarray, y: np.ndarray):
self.fit(X, y)
return self.transform(X)
Empty file removed polire/rfsi/__init__.py
Empty file.
72 changes: 0 additions & 72 deletions polire/rfsi/rfsi.py

This file was deleted.

9 changes: 0 additions & 9 deletions polire/rfsi/test.py

This file was deleted.

21 changes: 20 additions & 1 deletion polire/utils/distance.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,27 @@

def haversine(X1, X2):
"""
Inspired from https://stackoverflow.com/a/29546836/13330701
Arguments
---------
One test point
Multiple Train Points
Long Lat Order
"""

# Non-vectorized version
# X1 = X1.reshape(1, 2)
# difference = (X1 - X2) * np.pi / 180
# test_point_lat = X1[:, 1] * np.pi / 180
# training_locations_lat = X2[:, 1] * np.pi / 180

# a = np.sin(difference[:, 0] / 2)**2 * np.cos(test_point_lat) * np.cos(training_locations_lat) +\
# np.sin(difference[:, 1] / 2)**2
# radius = 6371
# c = 2 * np.arcsin(np.sqrt(a))
# return radius * c

# Vectorized code
lon1, lat1, lon2, lat2 = map(
np.radians, [X1[:, 0, None], X1[:, 1, None], X2[:, 0, None], X2[:, 1, None]])

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
URL = 'https://sustainability-lab.github.io/polire'
LICENSE = 'new BSD'
DOWNLOAD_URL = 'https://sustainability-lab.github.io/polire'
VERSION = "0.1.1"
VERSION = "0.1.2"
INSTALL_REQUIRES = REQ
CLASSIFIERS = ['Intended Audience :: Science/Research',
'Intended Audience :: Developers',
Expand Down
6 changes: 3 additions & 3 deletions tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,19 @@


def common(model):
print(repr(model), end=' ')
init = time()
model.fit(X, y)
y_new = model.predict(X_new)

assert y_new.shape == (40, )
print(repr(model), 'Passed', 'Time:', np.round(time()-init, 3), 'seconds')
print('Passed', 'Time:', np.round(time()-init, 3), 'seconds')


def test_basic():
from polire import (IDW, Spline, Trend, GP, Kriging,
NaturalNeighbor, SpatialAverage,
CustomInterpolator, RFSI)
CustomInterpolator)
from sklearn.linear_model import LinearRegression

common(IDW())
Expand All @@ -31,7 +32,6 @@ def test_basic():
common(NaturalNeighbor())
common(SpatialAverage())
common(CustomInterpolator(LinearRegression(normalize=True)))
common(RFSI())


if __name__ == '__main__':
Expand Down

0 comments on commit 0c0c3a0

Please sign in to comment.