Как рассчитать расстояния в 3D-координатах в массиве - PullRequest
2 голосов
/ 20 июня 2019

Я пытаюсь рассчитать начальные и последующие расстояния между точками. Данные, которые мне дали, представляют собой CSV, где каждые три столбца соответствуют светодиодному маркеру. т.е. столбец 1 - это координата x для маркера 1, столбец 2 - координата y для маркера 1, столбец 3 - координата z для маркера 1 ets. каждая строка соответствует времени, когда место было записано. Мне трудно найти лучший способ упорядочить данные, чтобы я мог их использовать. Мне нужно а) найти начальные местоположения и начальные расстояния между маркерами в момент времени 0 и б) найти любое изменение расстояния между маркерами в разное время.

Первоначально я поместил все x-координаты в массив, все y-координаты в массив и все z-координаты в массив, но понял, что не могу (не знал как?) Перебирать массивы так, Я мог найти разницу между соседними точками. то есть. расстояние между маркером 1 и маркером 2 равно sqrt ((x2-x1) ** 2+ (y2-y1) ** 2+ (z2-z1) ** 2), но поскольку x2 и x1 находятся в одном массиве, они не могут t (не знал как?), чтобы повторить разницу между всеми xs (и ys и zs, соответственно). В приведенном ниже коде я переставил массивы, чтобы можно было перебирать строки (не столбцы)

for i in range(m): #where m is the number of markers
    x_diff= x_array[i+1]-x_array[i]
    y_diff=y_array[i+1]-y_array[i]
    z_diff=z_array[i+1]-z_array[i]
    dist=np.sqrt(x_diff**2+y_diff**2+z_diff**2)

Я бы хотел массив, в котором каждый столбец - это евклидово расстояние между соседними маркерами, а строки соответствуют расстоянию в каждый момент времени.

Ответы [ 3 ]

1 голос
/ 20 июня 2019

Вы можете использовать функцию SciPy pdist для парных расстояний. Например,

>>> X
array([[1, 2, 3],
       [1, 2, 3],
       [4, 0, 0]])
>>> from scipy.spatial.distance import pdist
>>> pdist(X)
array([0.        , 4.69041576, 4.69041576])

Расстояния выводятся в виде пар (0,1), (0,2), (1,2).

0 голосов
/ 20 июня 2019

Вам нужно превратить этот двумерный массив в трехмерный.

rows, cols = csv.shape
csv_3d = csv.reshape(rows, -1, 3)

Затем np.diff вдоль второй оси (между точками)

del_csv_3d = np.diff(csv_3d, axis = 1)

Затем взять норму попоследняя ось

out = np.linalg.norm(del_csv_3d , axis = -1)

Это должны быть данные, которые вам нужны.

0 голосов
/ 20 июня 2019

Вот пошаговая инструкция, начиная с массива, который выложен как ваш оригинальный csv:

# 2 time points, 4 markers, values between 0 and 8
csv = np.random.randint(0,9,(2,12))
csv
# array([[8, 5, 3, 2, 3, 2, 2, 5, 6, 8, 2, 4],
#        [8, 2, 7, 4, 7, 7, 8, 0, 3, 0, 2, 4]])

# reshape to get x,y,z aligned
m,n = csv.shape
xyz = csv.reshape(m,-1,3)
xyz
# array([[[8, 5, 3],
#         [2, 3, 2],
#         [2, 5, 6],
#         [8, 2, 4]],
#
#        [[8, 2, 7],
#         [4, 7, 7],
#         [8, 0, 3],
#         [0, 2, 4]]])

# get coordinate-wise differences between adjacent markers
dist_1d = np.diff(xyz,axis=1)
dist_1d
# array([[[-6, -2, -1],
#         [ 0,  2,  4],
#         [ 6, -3, -2]],
#
#        [[-4,  5,  0],
#         [ 4, -7, -4],
#         [-8,  2,  1]]])

# compute squared Euclidean distance
# (you could take the square root of that but if you are
# only interested in changes it doesn't seem necessary)
eucl2 = (dist_1d*dist_1d).sum(axis=2)
eucl2
# array([[41, 20, 49],
#        [41, 81, 69]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...