Select indices in an array along an angle

Viewed 119

I have an array of data, say a 10 x 10 array as shown below

A=array([[ 50, 385,  67, 445, 336, 305,  48, 419, 106,  39],
       [217, 188, 139,  64, 258, 340, 188,  18,  58, 278],
       [201,  43, 457, 196, 149, 289, 350,  86, 495, 448],
       [379, 376, 217, 124, 264,  69, 378, 296, 200, 416],
       [234,  65, 420,  44, 489, 451,  46, 216, 136,  97],
       [470, 162, 183, 480, 149, 482, 456, 294,  89, 337],
       [164, 335, 443, 305,  30, 381, 341, 331, 149, 261],
       [389, 160, 448, 304,  30, 280, 333, 360, 166, 300],
       [ 63, 346, 321, 229, 432, 129, 100, 217,  83, 196],
       [218,  33, 430, 237, 225, 391, 393, 344, 457,  82]])

If I randomly select the index of data point 149, and an angle of 45 degree for example and I want 5 data points, I want it to return the indexes of the 5 data points along that 45 degree line. As shown here. My angles are in ranges of 45 degrees, i.e -45, -90, ..., 180. So I can have data around the selected index like this

In the case of the example above, it should return the indexes of data points

[149, 451, 378, 86, 58]
1 Answers

This code works: (use python 3.8 or newer):

A=list([[ 50, 385,  67, 445, 336, 305,  48, 419, 106,  39],
       [217, 188, 139,  64, 258, 340, 188,  18,  58, 278],
       [201,  43, 457, 196, 149, 289, 350,  86, 495, 448],
       [379, 376, 217, 124, 264,  69, 378, 296, 200, 416],
       [234,  65, 420,  44, 489, 451,  46, 216, 136,  97],
       [470, 162, 183, 480, 149, 482, 456, 294,  89, 337],
       [164, 335, 443, 305,  30, 381, 341, 331, 149, 261],
       [389, 160, 448, 304,  30, 280, 333, 360, 166, 300],
       [ 63, 346, 321, 229, 432, 129, 100, 217,  83, 196],
       [218,  33, 430, 237, 225, 391, 393, 344, 457,  82]])
    
def where_is_each_datapoint(A):
    places = dict()
    for r_i , row in enumerate(A):
        for c_i , col in enumerate(row):
            if col in places.keys():
                places[col].append((r_i,c_i))
            else:
                places[col] = [(r_i,c_i)]
    return places

places = where_is_each_datapoint(A)

point = 149
angle = 45
number_of_datapoints = 5

def get_row_col_steps(angle):
    if angle in [360, -360]:
        return (0,1)
    elif angle in [315, -45]:
        return (1,1)
    elif angle in [270, -90]:
        return (1,0)
    elif angle in [225, -135]:
        return (1,-1)
    elif angle in [180, -180]:
        return (0,-1)
    elif angle in [135, -225]:
        return (-1,-1)
    elif angle in [90, -270]:
        return (-1,0)
    elif angle in [45, -315]:
        return (-1,1)
    return (0,0)

def find_datapoints(all_datapoints,point,angle,places,number_of_datapoints):
    result_datapoints = []
    place_of_point = places[point]
    row_step, col_step = get_row_col_steps(angle)
    for place in place_of_point:
        possible_result = []
        place_row = place[0]
        place_col = place[1]
        for i in range(number_of_datapoints):
            try:
                if (next_place_row := place_row + row_step*i) > 0 and (next_place_col := place_col + col_step*i) > 0:  # <--- This part should change for python versions lower than 3.8
                    possible_result.append(all_datapoints[next_place_row][next_place_col])
            except:
                break
        if len(possible_result) == number_of_datapoints:
            result_datapoints.append(possible_result)
    return result_datapoints

print(find_datapoints(A,point,angle,places,number_of_datapoints))

For python versions lower than 3.8:

[...]
if place_row + row_step*i > 0 and place_col + col_step*i > 0:
    possible_result.append(all_datapoints[place_row + row_step*i][place_col + col_step*i])
[...]

Ouput:

[[149, 451, 378, 86, 58]]

Explantion:

  1. where_is_each_datapoint(): This function gets a list like similar to yours, and make a dictionary which it's keys are the data points and the values are the coordinates. There may be several data points with same value, for example in this list, there are three 149s.
  2. get_row_col_steps(): This function gets an angle and gives a pair of (row_step, col_step), for example if it get 45 it will return (-1,1).
  3. find_datapoints(): This function returns all data points. Because it can be several data points with same value, so it can be several solutions for this, and it may be several set of data points for a specific point , angle ,and number_of_datapoints. for example if point = 149 , angle = 45 ,but number_of_datapoints = 2; there are 3 solutions: [149, 340], [149, 451], and [149, 337].
Related