Skip to content

Commit

Permalink
Aug 10
Browse files Browse the repository at this point in the history
  • Loading branch information
chenyangkang committed Aug 10, 2023
1 parent 07b309d commit 6676a85
Show file tree
Hide file tree
Showing 9 changed files with 4,507 additions and 425 deletions.
202 changes: 146 additions & 56 deletions BirdSTEM/model/AdaSTEM.py

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions BirdSTEM/model/Hurdle.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import numpy as np
import warnings
from .dummy_model import dummy_model1
from sklearn.base import BaseEstimator



class Hurdle():
class Hurdle(BaseEstimator):
def __init__(self, classifier, regressor):
'''
The input classifier should have function:
Expand Down
3 changes: 2 additions & 1 deletion BirdSTEM/utils/plot_gif.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,13 @@ def animate(i, log_scale=log_scale, legend=False, return_plot_object=False):
ax.set_xlim(-180, 180)
ax.set_ylim(-90,90)
# ax.axis('off')
ax.set_title(f'DOY: {i+1}', fontsize=5)
ax.set_title(f'DOY: {i+1}', fontsize=20)

# tt = ax.axes
if return_plot_object == True:
return scat1,
else:
# ax.axis('off')
return ax.figure, #scat1.get_children() *scat1, #ax.figure,

### scale the color norm
Expand Down
73 changes: 40 additions & 33 deletions BirdSTEM/utils/quadtree.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,42 +47,42 @@ def get_points(self):
return self.points


def recursive_subdivide(node, grid_len_long_upper_threshold, grid_len_long_lower_threshold, \
def recursive_subdivide(node, grid_len_lon_upper_threshold, grid_len_lon_lower_threshold, \
grid_len_lat_upper_threshold, grid_len_lat_lower_threshold, \
points_lower_threshold):


if len(node.points)/2 <= points_lower_threshold:
if not ((node.width > grid_len_long_upper_threshold) or (node.height > grid_len_lat_upper_threshold)):
if not ((node.width > grid_len_lon_upper_threshold) or (node.height > grid_len_lat_upper_threshold)):
return

if (node.width/2 < grid_len_long_lower_threshold) or (node.height/2 < grid_len_lat_lower_threshold):
if (node.width/2 < grid_len_lon_lower_threshold) or (node.height/2 < grid_len_lat_lower_threshold):
return

w_ = float(node.width/2)
h_ = float(node.height/2)

p = contains(node.x0, node.y0, w_, h_, node.points)
x1 = Node(node.x0, node.y0, w_, h_, p)
recursive_subdivide(x1, grid_len_long_upper_threshold, grid_len_long_lower_threshold, \
recursive_subdivide(x1, grid_len_lon_upper_threshold, grid_len_lon_lower_threshold, \
grid_len_lat_upper_threshold, grid_len_lat_lower_threshold, \
points_lower_threshold)

p = contains(node.x0, node.y0+h_, w_, h_, node.points)
x2 = Node(node.x0, node.y0+h_, w_, h_, p)
recursive_subdivide(x2, grid_len_long_upper_threshold, grid_len_long_lower_threshold, \
recursive_subdivide(x2, grid_len_lon_upper_threshold, grid_len_lon_lower_threshold, \
grid_len_lat_upper_threshold, grid_len_lat_lower_threshold, \
points_lower_threshold)

p = contains(node.x0+w_, node.y0, w_, h_, node.points)
x3 = Node(node.x0 + w_, node.y0, w_, h_, p)
recursive_subdivide(x3, grid_len_long_upper_threshold, grid_len_long_lower_threshold, \
recursive_subdivide(x3, grid_len_lon_upper_threshold, grid_len_lon_lower_threshold, \
grid_len_lat_upper_threshold, grid_len_lat_lower_threshold, \
points_lower_threshold)

p = contains(node.x0+w_, node.y0+h_, w_, h_, node.points)
x4 = Node(node.x0+w_, node.y0+h_, w_, h_, p)
recursive_subdivide(x4, grid_len_long_upper_threshold, grid_len_long_lower_threshold, \
recursive_subdivide(x4, grid_len_lon_upper_threshold, grid_len_lon_lower_threshold, \
grid_len_lat_upper_threshold, grid_len_lat_lower_threshold, \
points_lower_threshold)

Expand Down Expand Up @@ -111,27 +111,27 @@ def find_children(node):
import matplotlib.patches as patches

class QTree():
def __init__(self, grid_len_long_upper_threshold, grid_len_long_lower_threshold, \
def __init__(self, grid_len_lon_upper_threshold, grid_len_lon_lower_threshold, \
grid_len_lat_upper_threshold, grid_len_lat_lower_threshold, \
points_lower_threshold, long_lat_equal_grid=True,\
points_lower_threshold, lon_lat_equal_grid=True,\
rotation_angle = 0, \
calibration_point_x_jitter = 0,\
calibration_point_y_jitter = 0):

self.points_lower_threshold = points_lower_threshold
self.grid_len_long_upper_threshold = grid_len_long_upper_threshold
self.grid_len_long_lower_threshold = grid_len_long_lower_threshold
self.grid_len_lon_upper_threshold = grid_len_lon_upper_threshold
self.grid_len_lon_lower_threshold = grid_len_lon_lower_threshold
self.grid_len_lat_upper_threshold = grid_len_lat_upper_threshold
self.grid_len_lat_lower_threshold = grid_len_lat_lower_threshold
self.long_lat_equal_grid = long_lat_equal_grid
self.lon_lat_equal_grid = lon_lat_equal_grid
# self.points = [Point(random.uniform(0, 10), random.uniform(0, 10)) for x in range(n)]
self.points = []
self.rotation_angle = rotation_angle
self.calibration_point_x_jitter = calibration_point_x_jitter
self.calibration_point_y_jitter = calibration_point_y_jitter


def add_long_lat_data(self, indexes, x_array, y_array):
def add_lon_lat_data(self, indexes, x_array, y_array):
if not len(x_array) == len(y_array) or not len(x_array) == len(indexes):
raise ValueError("input longitude and latitute and indexes not in same length!")

Expand All @@ -144,11 +144,11 @@ def add_long_lat_data(self, indexes, x_array, y_array):
[np.sin(theta), np.cos(theta)]
])
data = data @ rotation_matrix
long_new = (data[:,0] + self.calibration_point_x_jitter).tolist()
lon_new = (data[:,0] + self.calibration_point_x_jitter).tolist()
lat_new = (data[:,1] + self.calibration_point_y_jitter).tolist()

for index,long,lat in zip(indexes, long_new, lat_new):
self.points.append(Point(index, long, lat))
for index,lon,lat in zip(indexes, lon_new, lat_new):
self.points.append(Point(index, lon, lat))



Expand All @@ -162,23 +162,23 @@ def generate_griding_params(self):
left_bottom_point_y = np.min(y_list)

self.left_bottom_point = (left_bottom_point_x ,left_bottom_point_y)
if self.long_lat_equal_grid == True:
if self.lon_lat_equal_grid == True:
self.root = Node(left_bottom_point_x, left_bottom_point_y, \
max(self.grid_length_x, self.grid_length_y), \
max(self.grid_length_x, self.grid_length_y), self.points)
elif self.long_lat_equal_grid == False:
elif self.lon_lat_equal_grid == False:
self.root = Node(left_bottom_point_x, left_bottom_point_y, \
self.grid_length_x, \
self.grid_length_y, self.points)
else:
raise ValueError('The input long_lat_equal_grid not a boolean value!')
raise ValueError('The input lon_lat_equal_grid not a boolean value!')


def get_points(self):
return self.points

def subdivide(self):
recursive_subdivide(self.root, self.grid_len_long_upper_threshold, self.grid_len_long_lower_threshold, \
recursive_subdivide(self.root, self.grid_len_lon_upper_threshold, self.grid_len_lon_lower_threshold, \
self.grid_len_lat_upper_threshold, self.grid_len_lat_lower_threshold, \
self.points_lower_threshold)

Expand All @@ -199,8 +199,8 @@ def graph(self, scatter=True, show=True):
width_set.add(el.width)
height_set.add(el.height)

# print("Minimum segment area: %.3f units^2, min_long: %.3f units, min_lat: %.3f units" %(min(areas),min(width_set),min(height_set)))
# print("Maximum segment area: %.3f units^2, max_long: %.3f units, max_lat: %.3f units" %(max(areas),max(width_set),max(height_set)))
# print("Minimum segment area: %.3f units^2, min_lon: %.3f units, min_lat: %.3f units" %(min(areas),min(width_set),min(height_set)))
# print("Maximum segment area: %.3f units^2, max_lon: %.3f units, max_lat: %.3f units" %(max(areas),max(width_set),max(height_set)))

theta = -(self.rotation_angle/360) * np.pi * 2
rotation_matrix = np.array([
Expand Down Expand Up @@ -269,16 +269,19 @@ def get_final_result(self):
return result


def generate_temporal_bins(start, end, step, bin_interval):
def generate_temporal_bins(start, end, step, bin_interval, temporal_bin_start_jitter):
'''
start, end, step, bin_interval
'''
bin_interval = bin_interval #50
step = step #20
if not bin_interval - step > step:
raise AttributeError('Did not satisfy constrain: bin_interval - step > step')

start = start - np.random.uniform(low=0, high=bin_interval) ### ensure 20 DOY
if type(temporal_bin_start_jitter) == str and temporal_bin_start_jitter=='random':
jit = np.random.uniform(low=0, high=bin_interval)
elif type(temporal_bin_start_jitter) in [int, float]:
jit = temporal_bin_start_jitter

start = start - jit ### ensure 20 DOY
bin_list = []

i=0
Expand All @@ -294,10 +297,11 @@ def generate_temporal_bins(start, end, step, bin_interval):


def get_ensemble_quadtree(data,size=1,
grid_len_long_upper_threshold=25, grid_len_long_lower_threshold=5,
grid_len_lon_upper_threshold=25, grid_len_lon_lower_threshold=5,
grid_len_lat_upper_threshold=25, grid_len_lat_lower_threshold=5,
points_lower_threshold=50,
temporal_start = 1, temporal_end=366, temporal_step=20, temporal_bin_interval = 50,
temporal_bin_start_jitter = 'random',
save_gridding_plot=True,
save_path=''):
'''
Expand Down Expand Up @@ -326,28 +330,31 @@ def get_ensemble_quadtree(data,size=1,
temporal_bins = generate_temporal_bins(start = temporal_start,
end=temporal_end,
step=temporal_step,
bin_interval = temporal_bin_interval)

bin_interval = temporal_bin_interval,
temporal_bin_start_jitter = temporal_bin_start_jitter)

for time_block_index,bin_ in enumerate(temporal_bins):

time_start = bin_[0]
time_end = bin_[1]
sub_data=data[(data['DOY']>=time_start) & (data['DOY']<time_end)]


QT_obj = QTree(grid_len_long_upper_threshold=grid_len_long_upper_threshold, \
grid_len_long_lower_threshold=grid_len_long_lower_threshold, \
QT_obj = QTree(grid_len_lon_upper_threshold=grid_len_lon_upper_threshold, \
grid_len_lon_lower_threshold=grid_len_lon_lower_threshold, \
grid_len_lat_upper_threshold=grid_len_lat_upper_threshold, \
grid_len_lat_lower_threshold=grid_len_lat_lower_threshold, \
points_lower_threshold=points_lower_threshold, \

long_lat_equal_grid = True, rotation_angle = rotation_angle, \
lon_lat_equal_grid = True, rotation_angle = rotation_angle, \
calibration_point_x_jitter = calibration_point_x_jitter,\
calibration_point_y_jitter = calibration_point_y_jitter)

## Give the data and indexes. The indexes should be used to assign points data so that base model can run on those points,
## You need to generate the splitting parameters once giving the data. Like the calibration point and min,max.
QT_obj.add_long_lat_data(sub_data.index, sub_data['longitude'].values, sub_data['latitude'].values)

# print(sub_data.index, sub_data['longitude'].values, sub_data['latitude'].values)
QT_obj.add_lon_lat_data(sub_data.index, sub_data['longitude'].values, sub_data['latitude'].values)
QT_obj.generate_griding_params()

## Call subdivide to precess
Expand Down
Loading

0 comments on commit 6676a85

Please sign in to comment.