Home > Software engineering >  Seeking isolated indices using Python
Seeking isolated indices using Python

Time:04-05

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.

  • Related