Как отобразить 2D-таблицу поиска в массив (python)? - PullRequest
2 голосов
/ 19 февраля 2020

У меня есть три 2D-массива одинаковой формы, назовем их тэта, фи и А. Пусть тэта и фи будут углами к вектору нормали, видимому с разных расстояний на поверхности:

size = 100 # this value is fixed
x = np.arange(-size, size)
y = np.arange(-size, size)
xx, yy = np.meshgrid(xx, yy)
theta = np.arctan((xx**2+yy**2)**0.5 / 100) # angle from distance 100
phi = np.arctan((xx**2+yy**2)**0.5 / 1000) # angle from distance 1000

И пусть A будет двухмерной картой измеренных значений, где ось x является тэтой, а ось y - фи с известными и линейными шагами (которая на самом деле не совпадает с формой тета и фи). Что мне нужно, так это значения A (тета, фи), выраженные как A (x, y). Кажется, я не могу понять, как преобразовать A (тэта, фи) в A (x, y), хотя я знаю и тэта (x, y) и фи (x, y).

Что я пробовал: С помощью scipy.interpolate.interp2d я могу сопоставить А с тем же количеством строк и столбцов, что и тета и фи. Теперь я могу перебирать индексы и угадывать / округлять лучшие совпадающие индексы в моем массиве

B = np.zeros(A.shape)
for i in range(0,A.shape[0]):
  for j in range(0,A.shape[1]):
    B[i,j] = A[int(f_theta*theta[i,j]),int(f_phi*phi[i,j])]

, где f_theta и f_phi - это факторы, определяемые по измеренной длине шага индекса. Это выглядит как очень плохое и неэффективное кодирование для меня, и как грубое приближение того, что я на самом деле хочу сделать (что такое обратное интерполяционное отображение?). Это напоминает мне таблицы поиска, преобразования координат и интерполяции, но ни с одним из этих ключевых слов я не нашел что-то подходящее для решения проблемы. Мой python опыт выкрикивает, что для этого будет модуль / функция, которую я не знаю.

Правка об ограничениях: диапазон оси в А (тета, фи) больше, чем диапазон тета (х, у) и фи (х, у), так что сопоставленное значение всегда существует. Мне не нужно отображать B обратно в A, поэтому нет проблем с отсутствующими значениями. Многие значения на карте A (тэта, фи) никогда не будут использоваться.

Правка для ясности: я приведу пример с небольшими матрицами в надежде прояснить ситуацию:

# phi given in degrees
phi = np.array([
    [2,1,2],
    [1,0,1],
    [2,1,2],
])
# theta given in degrees
theta = np.array([
    [6,4,6],
    [4,0,5],
    [6,5,6],
])
# A[0,0] is the value at phi=0deg, theta=0deg
# A[0,1] is the value at phi=1deg, theta=0deg
# A[1,1] is the value at phi=1deg, theta=1deg etc
# this is a toy example, the actual A cannot be constructed by a simple rule
A = np.array([
    [0.0,0.1,0.2],
    [1.0,1.1,1.2],
    [2.0,2.1,2.2],
    [3.0,3.1,3.2],
    [4.0,4.1,4.2],
    [5.0,5.1,5.2],
    [6.0,6.1,6.2],
])
# what I want to reach:
B = [[6.2,4.1,6.2],
     [4.1,0.0,5.1],
     [6.2,5.1,6.2]]

I Нужно уточнить, что я сделал здесь несколько упрощений:

1) Для данной тэты я могу проверить соответствующую фи, посмотрев в таблицу: тета [i, j] соответствует фи [i, j]. Но конструкция примера слишком упрощена, например, они не имеют одинакового происхождения, это зашумленные данные, и поэтому я не могу дать аналитическое выражение theta (phi) или phi (theta)

2) Значения в моей фактической тэте и фи - это числа с плавающей точкой, и моя фактическая величина А также измеряется нецелыми шагами (например, 0,45 градуса на шаг в направлении тета, 0,2 градуса на шаг в направлении фи)

3) в принципе, как Существует строгая связь между тэтой и фи, мне нужен только определенный c 1D "след" значений A, чтобы найти B, но я не понимаю, как найти эту трассу, или как создать B из трассы. Эта трассировка в примере будет [A [0,0], A [4,1], A [5,1], A [6,2]] = [0.0,4.1,5.1,6.2]

1 Ответ

1 голос
/ 20 февраля 2020

Вы можете сделать, например, билинейную интерполяцию:

from scipy.interpolate import interpn

delta = [1.0, 1.0] # theta, phi
points = [np.arange(s)*d for s, d in zip(A.shape, delta)]
xi = np.stack((theta, phi), axis = -1)
B = interpn(points, A, xi)

Это дает:

print(B)
[[6.2 4.1 6.2]
 [4.1 0.  5.1]
 [6.2 5.1 6.2]]
...