Skip to content

Commit 3818534

Browse files
authored
Add files via upload
1 parent 4230462 commit 3818534

File tree

2 files changed

+235
-0
lines changed

2 files changed

+235
-0
lines changed

Toolbox.py

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import numpy as np
2+
import pandas as pd
3+
import os
4+
from scipy.stats import pearsonr
5+
from sklearn.manifold import MDS
6+
7+
def two_d_norm(xy):
8+
# xy is N x 2 xy cordinates, returns normed-xy on [0,1]
9+
norm_xy = (xy - xy.min(axis = 0)) / (xy - xy.min(axis = 0)).max(axis = 0)
10+
return norm_xy
11+
12+
def two_d_eq(xy,Nn):
13+
# xy is N x 2 xy cordinates, returns eq-xy on [0,1]
14+
xx_rank = np.argsort(xy[:,0])
15+
yy_rank = np.argsort(xy[:,1])
16+
eq_xy = np.full(xy.shape,np.nan)
17+
for ii in range(xy.shape[0]):
18+
xx_idx = xx_rank[ii]
19+
yy_idx = yy_rank[ii]
20+
eq_xy[xx_idx,0] = ii * 1/Nn
21+
eq_xy[yy_idx,1] = ii * 1/Nn
22+
return eq_xy
23+
24+
#embedding = MDS(n_components=2)
25+
#mds_xy = embedding.fit_transform(transposed_input)
26+
# to pixels
27+
def Assign_features_to_pixels(xy,nn,verbose = False):
28+
# For each unassigned feature, find its nearest pixel, repeat until every ft is assigned
29+
# xy is the 2-d coordinates (normalized to [0,1]); nn is the image width. Img size = n x n
30+
# generate the result summary table, xy pixels; 3rd is nan for filling the idx
31+
Nn = xy.shape[0]
32+
33+
from itertools import product
34+
pixel_iter = product([x for x in range(nn)],repeat = 2)
35+
result_table = np.full((nn*nn,3),np.nan)
36+
ii = 0
37+
for each_pixel in pixel_iter:
38+
result_table[ii,:2] = np.array(each_pixel)
39+
ii+=1
40+
# Use numpy array for speed
41+
42+
from sklearn.metrics import pairwise_distances
43+
44+
# xy = eq_xy
45+
centroids = result_table[:,:2] / nn + 0.5/nn
46+
pixel_avail = np.ones(nn*nn).astype(bool)
47+
feature_assigned = np.zeros(Nn).astype(bool)
48+
49+
dist_xy_centroids = pairwise_distances(centroids,xy,metric='euclidean')
50+
51+
while feature_assigned.sum()<Nn:
52+
# Init the pick-relationship table
53+
pick_xy_centroids = np.zeros(dist_xy_centroids.shape).astype(bool)
54+
55+
for each_feature in range(Nn):
56+
# for each feature, find the nearest available pixel
57+
if feature_assigned[each_feature] == True:
58+
# if this feature is already assigned, skip to the next ft
59+
continue
60+
else:
61+
# if not assigned:
62+
for ii in range(nn*nn):
63+
# find the nearest avail pixel
64+
nearest_pixel_idx = np.argsort(dist_xy_centroids[:,each_feature])[ii]
65+
if pixel_avail[nearest_pixel_idx] == True:
66+
break
67+
else:
68+
continue
69+
pick_xy_centroids[nearest_pixel_idx,each_feature] = True
70+
71+
for each_pixel in range(nn*nn):
72+
# Assign the feature No to pixels
73+
if pixel_avail[each_pixel] == False:
74+
continue
75+
else:
76+
# find all the "True" features. np.where returns a tuple size 1
77+
related_features = np.where(pick_xy_centroids[each_pixel,:] == 1)[0]
78+
if len(related_features) == 1:
79+
# Assign it
80+
result_table[each_pixel,2] = related_features[0]
81+
pixel_avail[each_pixel] = False
82+
feature_assigned[related_features[0]] = True
83+
elif len(related_features) > 1:
84+
related_dists = dist_xy_centroids[each_pixel,related_features]
85+
best_feature = related_features[np.argsort(related_dists)[0]] # Sort, and pick the nearest one among them
86+
result_table[each_pixel,2] = best_feature
87+
pixel_avail[each_pixel] = False
88+
feature_assigned[best_feature] = True
89+
if verbose:
90+
print(">> Assign features to pixels:", feature_assigned.sum(),"/",Nn)
91+
result_table = result_table.astype(int)
92+
93+
img = np.full((nn,nn),'NaN').astype(object)
94+
for each_pixel in range(nn*nn):
95+
xx = result_table[each_pixel,0]
96+
yy = result_table[each_pixel,1]
97+
ft = 'F' + str(result_table[each_pixel,2])
98+
img[xx,yy] = ft
99+
return img.astype(object)
100+
print(">>>> MDS")
101+
#eq_xy = two_d_eq(mds_xy)
102+
#Img = Assign_features_to_pixels(eq_xy,nn,verbose=1)
103+
#Init_Corr_MDS = InitCorr(dist_mat,Img,nn)

paraHill.py

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Created on Mon Aug 12 14:30:06 2019
4+
5+
@author: Ruibzhan & Omid Bazgir
6+
"""
7+
8+
from scipy.stats import pearsonr
9+
import numpy as np
10+
import random
11+
from scipy.spatial import distance
12+
import pickle
13+
import pandas as pd
14+
import time
15+
from itertools import product
16+
17+
#%%
18+
def universial_corr(dist_matr, mapping_in_int):
19+
# dist_matr is a sqr matr
20+
Nn = dist_matr.shape[0]
21+
# find what is the int coordinates for each feature, get an array
22+
# Because np.where returns a tuple (x_position array, y_position array), a generation is used
23+
coord = np.array([[item[0] for item in np.where(mapping_in_int == ii)] for ii in range(Nn)])
24+
# get a 1-d form distance the euclidean dist between pixles positions
25+
pixel_dist = distance.pdist(coord)
26+
pixel_dist = pixel_dist.reshape(len(pixel_dist),1)
27+
# convert the 2-d distance to 1d distance
28+
feature_dist = distance.squareform(dist_matr)
29+
feature_dist = feature_dist.reshape(len(feature_dist),1)
30+
## pearsonr returns a tuple
31+
#corrs = pearsonr(feature_dist,pixel_dist)[0]
32+
L2_Norm = np.sqrt(sum((pixel_dist - feature_dist)**2)/sum(feature_dist**2))
33+
return L2_Norm
34+
#%%
35+
def evaluate_swap(coord1,coord2,dist_matr,mapping_in_int,original_corr = -2):
36+
# Coord are in list[]
37+
# Avoid messing up with the origianl map
38+
# The correlation before swap can be passed to save some calculation
39+
the_map = mapping_in_int.copy()
40+
# If out of bound, return NaN.
41+
if coord1[0]<0 or coord1[1]<0 or coord2[0]<0 or coord2[1]<0:
42+
return np.nan
43+
if coord1[0]>=the_map.shape[0] or coord1[1]>=the_map.shape[0] or coord2[0]>=the_map.shape[0] or coord2[1]>=the_map.shape[0]:
44+
return np.nan
45+
# If not given, recompute.
46+
if original_corr<-1 or original_corr>1:
47+
original_corr = universial_corr(dist_matr,the_map)
48+
# Swap
49+
try:
50+
temp = the_map[coord1[0],coord1[1]]
51+
the_map[coord1[0],coord1[1]] = the_map[coord2[0],coord2[1]]
52+
the_map[coord2[0],coord2[1]] = temp
53+
changed_corr = universial_corr(dist_matr,the_map)
54+
return(changed_corr - original_corr)
55+
except IndexError:
56+
raise Warning ("Swap index:", coord1,coord2,"Index error. Check the coordnation.")
57+
return np.nan
58+
59+
def evaluate_centroid(centroid,dist_matr,mapping_in_int):
60+
original_corr = universial_corr(dist_matr,mapping_in_int)
61+
results = [100000] # just to skip the 0 position
62+
for each_direc in product([-1,0,1],repeat = 2):
63+
#print(each_direc)
64+
# directions are returned as tuple (-1,1), (-1,0), (-1,1), (0,0), ....
65+
swap_coord = [centroid[0]+each_direc[0],centroid[1]+each_direc[1]]
66+
evaluation = evaluate_swap(centroid,swap_coord,dist_matr,mapping_in_int,original_corr)
67+
results.append(evaluation)
68+
results_array = np.array(results)
69+
#best_swap_direc = np.where(results_array == np.nanmax(results_array))[0][0]
70+
best_swap_direc = np.where(results_array == np.nanmin(results_array))[0][0]
71+
# Give the best direction as a int
72+
return best_swap_direc
73+
74+
def evaluate_centroids_in_list(centroids_list,dist_matr,mapping_in_int):
75+
# and returns a dict
76+
results = dict()
77+
for each_centr in centroids_list:
78+
each_centr = tuple(each_centr)
79+
evaluation = evaluate_centroid(each_centr,dist_matr,mapping_in_int)
80+
results.update({each_centr:evaluation})
81+
return results
82+
83+
#%%
84+
def execute_coordination_swap(coord1,coord2,mapping_in_int):
85+
# try passing the ref. directly
86+
the_map = mapping_in_int#.copy()
87+
# If out of bound, return NaN.
88+
if coord1[0]<0 or coord1[1]<0 or coord2[0]<0 or coord2[1]<0:
89+
raise Warning("Swapping failed:",coord1,coord2,"-- Negative coordnation.")
90+
return the_map
91+
if coord1[0]>the_map.shape[0] or coord1[1]>the_map.shape[0] or coord2[0]>the_map.shape[0] or coord2[1]>the_map.shape[0]:
92+
raise Warning("Swapping failed:",coord1,coord2,"-- Coordnation out of bound.")
93+
return the_map
94+
95+
temp = the_map[coord1[0],coord1[1]]
96+
the_map[coord1[0],coord1[1]] = the_map[coord2[0],coord2[1]]
97+
the_map[coord2[0],coord2[1]] = temp
98+
99+
return(the_map)
100+
101+
# Initial centriod id & Swapping direction:
102+
# 1 2 3
103+
# 4 5 6
104+
# 7 8 9
105+
# 0 in swapping is preserved for the header.
106+
107+
def execute_direction_swap(centroid,mapping_in_int,direction = 5):
108+
# Need to notice that [0] is the vertival coord, [1] is the horiz coord. similar to the matlab images.
109+
coord1 = list(centroid)
110+
coord2 = list(centroid)
111+
if direction not in range(1,10):
112+
raise ValueError("Invalid swapping direction.")
113+
if direction == 5:
114+
return mapping_in_int
115+
116+
if direction in [1,4,7]:
117+
coord2[1] -=1
118+
elif direction in [3,6,9]:
119+
coord2[1] +=1
120+
121+
if direction in [1,2,3]:
122+
coord2[0] -=1
123+
elif direction in [7,8,9]:
124+
coord2[0] +=1
125+
126+
the_map = execute_coordination_swap(coord1,coord2,mapping_in_int)
127+
return the_map
128+
129+
def execute_dict_swap(swapping_dict, mapping_in_int):
130+
for each_key in swapping_dict:
131+
execute_direction_swap(each_key,mapping_in_int,direction = swapping_dict[each_key])
132+
return mapping_in_int

0 commit comments

Comments
 (0)