I have a list of indices which are the output based on a certain criterion: (0,0),(0,1),(0,2),(1,0),(1,1),(2,1),(2,2)
. I am trying to write a code which would tell me isolated indices (having only 1 neighbor) assuming the possible locations: [(i 1,j), (i-1,j), (i,j 1), (i,j-1)]
. Clearly, in this list, (0,2) and (2,2)
are isolated.
import numpy as np
import time
import csv
def get_neighbor_indices(position, dimensions):
'''
dimensions is a shape of np.array
'''
i, j = position
indices = [(i 1,j), (i-1,j), (i,j 1), (i,j-1)]
return [
(i,j) for i,j in indices
if i>=0 and i<dimensions[0]
and j>=0 and j<dimensions[1]
]
def iterate_array(init_i, init_j, arr, condition_func):
'''
arr is an instance of np.array
condition_func is a function (value) => boolean
'''
indices_to_check = [(init_i,init_j)]
checked_indices = set()
result = []
t0 = None
t1 = None
timestamps = []
while indices_to_check:
pos = indices_to_check.pop()
if pos in checked_indices:
continue
item = arr[pos]
checked_indices.add(pos)
if condition_func(item):
result.append(item)
t1=time.time()
if(t0==None):
t0=t1
timestamps.append(t1-t0)
indices_to_check.extend(
get_neighbor_indices(pos, arr.shape)
)
return result,timestamps
P1=np.array([[0.7184708 , 0.83700632, 0.92137644],
[0.69481528, 0.74513563, 1.10474071],
[4.63803705, 0.91581599, 0.98006721]])
T,timestamps=iterate_array(0,0, P1, lambda x : x < 1.0)
out = list(zip(*np.where(np.isin(P1, T))))
print([out])
# print(timestamps)
header1 = ['T','Timestamps']
header2 = ['T','Indices']
data = [T,timestamps]
with open('Data_0.007.csv', 'w') as f:
writer = csv.writer(f)
# write the header
writer.writerow(header1)
# write the data
writer.writerows(zip(T,timestamps))
with open('Indices_0.007.csv', 'w') as f:
writer = csv.writer(f)
# write the header
writer.writerow(header2)
# write the data
writer.writerows(zip(T,out))
CodePudding user response:
Here's a somewhat roundabout way of doing things. There's probably a better way, but this is the best I've got:
indices = [(0,0),(0,1),(0,2),(1,0),(1,1),(2,1),(2,2)]
def get_isolated_indices(indices):
indices = np.array(indices)
indices = indices[np.argsort(indices[:, 0])]
# I'm calling the 1st number in each pair the row number
# and the 2nd number in each pair the column number.
# max_row_num = max_vals[0]
# max_col_num = max_vals[1]
max_vals = np.max(indices, axis=0)
# For easier indexing
rows = indices[:, 0]
cols = indices[:, 1]
isolated = []
for i in range(len(indices)):
this_row = indices[i, 0]
this_col = indices[i, 1]
# If this_row = 0 or this_row = max_row_val (in this case, 2), nearby rows are not allowed to have values -1 or 3.
nearby_row_vals = list(range(max(0, this_row - 1), min(this_row 1, max_vals[0]) 1))
nearby_col_vals = list(range(max(0, this_col - 1), min(this_col 1, max_vals[1]) 1))
# These masks get the index pairs with the same row number or same column number.
same_row_mask = rows == this_row
same_col_mask = cols == this_col
# These masks get the index pairs who have an allows row or column number
# that is different from the current index pair's row/column number.
diff_rows_mask = (rows >= np.min(nearby_row_vals)) & (rows <= np.max(nearby_row_vals)) & (rows != this_row)
diff_cols_mask = (cols >= np.min(nearby_col_vals)) & (cols <= np.max(nearby_col_vals)) & (cols != this_col)
# Need to make sure we avoid including neighbors that are different in both row and column number.
# E.g. we don't want to count (1,1) as a neighbor of (0,0)
intersection1 = np.logical_and(same_row_mask, same_col_mask)
intersection2 = np.logical_and(same_row_mask, diff_cols_mask)
intersection3 = np.logical_and(diff_rows_mask, same_col_mask)
# final_intersection is a 1D array with length = len(indices)/
# final_intersection is True if the index pair is a neighbor (or is the index pair itself)
final_intersection = np.logical_or(np.logical_or(intersection1, intersection2), intersection3)
# Need to subtract by 1 because the index pair is initially counted as its own neighbor.
num_neighbors = np.sum(final_intersection) - 1
if num_neighbors <= 1:
isolated.append((this_row, this_col))
return isolated
isolated_pairs = get_isolated_indices(indices)
Let me know if you have any questions.