Вычисление среднего значения 2D-массива как функции расстояния от центра в Python - PullRequest
0 голосов
/ 05 июля 2018

Я пытаюсь вычислить среднее значение величины (в виде двумерного массива) как функцию ее расстояния от центра двумерной сетки. Я понимаю, что идея состоит в том, что я идентифицирую все элементы массива, которые находятся на расстоянии R от центра, а затем складываю их и делю на количество элементов. Тем не менее, у меня возникли проблемы с определением алгоритма, чтобы сделать это.

Я приложил рабочий пример кода для генерации 2d массива ниже. Код предназначен для расчета некоторых величин, которые являются результатом гравитационного линзирования, поэтому способ создания массива не имеет отношения к этой проблеме, но я прикрепил весь код, чтобы вы могли создать выходной массив для тестирования.

import numpy as np
import multiprocessing
import matplotlib.pyplot as plt
n = 100 # grid size

c = 3e8
G = 6.67e-11
M_sun = 1.989e30
pc = 3.086e16  # parsec
Dds = 625e6*pc          
Ds = 1726e6*pc #z=2
Dd = 1651e6*pc #z=1

FOV_arcsec = 0.0001
FOV_arcmin = FOV_arcsec/60.   


pix2rad = ((FOV_arcmin/60.)/float(n))*np.pi/180.
rad2pix = 1./pix2rad

Renorm = (4*G*M_sun/c**2)*(Dds/(Dd*Ds))
#stretch = [10, 2]




# To create a random distribution of points
def randdist(PDF, x, n):
    #Create a distribution following PDF(x). PDF and x
    #must be of the same length. n is the number of samples
    fp = np.random.rand(n,)
    CDF = np.cumsum(PDF)
    return np.interp(fp, CDF, x)


def get_alpha(args):    
    zeta_list_part, M_list_part, X, Y = args
    alpha_x = 0
    alpha_y = 0
    for key in range(len(M_list_part)):
        z_m_z_x = (X - zeta_list_part[key][0])*pix2rad
        z_m_z_y = (Y - zeta_list_part[key][1])*pix2rad
        alpha_x += M_list_part[key] * z_m_z_x / (z_m_z_x**2 + z_m_z_y**2)
        alpha_y += M_list_part[key] * z_m_z_y / (z_m_z_x**2 + z_m_z_y**2)
    return (alpha_x, alpha_y)

if __name__ == '__main__':
    # number of processes, scale accordingly
    num_processes = 1 # Number of CPUs to be used
    pool = multiprocessing.Pool(processes=num_processes)
    num = 100 # The number of points/microlenses
    r = np.linspace(-n, n, n)
    PDF = np.abs(1/r)
    PDF = PDF/np.sum(PDF)    # PDF should be normalized
    R = randdist(PDF, r, num)
    Theta = 2*np.pi*np.random.rand(num,)
    x1= [R[k]*np.cos(Theta[k])*1 for k in range(num)]
    y1 = [R[k]*np.sin(Theta[k])*1 for k in range(num)]
    # Uniform distribution
    #R = np.random.uniform(-n,n,num)
    #x1= np.random.uniform(-n,n,num)
    #y1 = np.random.uniform(-n,n,num)
    zeta_list = np.column_stack((np.array(x1), np.array(y1))) # List of coordinates for the microlenses 
    x = np.linspace(-n,n,n)
    y = np.linspace(-n,n,n)
    X, Y = np.meshgrid(x,y)
    M_list = np.array([0.1 for i in range(num)])
    # split zeta_list, M_list, X, and Y
    zeta_list_split = np.array_split(zeta_list, num_processes, axis=0)
    M_list_split = np.array_split(M_list, num_processes)
    X_list = [X for e in range(num_processes)]  
    Y_list = [Y for e in range(num_processes)]

    alpha_list = pool.map(
            get_alpha, zip(zeta_list_split, M_list_split, X_list, Y_list))
    alpha_x = 0
    alpha_y = 0
    for e in alpha_list:
        alpha_x += e[0] 
        alpha_y += e[1] 

alpha_x_y = 0
alpha_x_x = 0
alpha_y_y = 0
alpha_y_x = 0
alpha_x_y, alpha_x_x = np.gradient(alpha_x*rad2pix*Renorm,edge_order=2)
alpha_y_y, alpha_y_x = np.gradient(alpha_y*rad2pix*Renorm,edge_order=2) 
det_A = 1 - alpha_y_y - alpha_x_x + (alpha_x_x)*(alpha_y_y) - (alpha_x_y)*(alpha_y_x)
abs = np.absolute(det_A)
I = abs**(-1.)  
O = np.log10(I+1)
plt.contourf(X,Y,O,100)

Массив интереса - O, и я приложил график того, как он должен выглядеть. Он может отличаться в зависимости от случайного распределения точек. enter image description here

То, что я пытаюсь сделать, это построить средние значения O как функцию радиуса от центра сетки. В конце я хочу иметь возможность построить среднее значение O как функцию расстояния от центра на двухмерном линейном графике. Поэтому я полагаю, что первым шагом является определение окружностей радиуса R на основе X и Y.

def circle(x,y):
    r = np.sqrt(x**2 + y**2)
    return r 

Теперь мне просто нужно найти способ найти все значения O, которые имеют те же индексы, что и эквивалентные значения R. Kinda, смущенные в этой части, и были бы признательны за любую помощь.

1 Ответ

0 голосов
/ 05 июля 2018

Вы можете найти геометрические координаты круга с центром (0,0) и радиусом R следующим образом:

phi = np.linspace(0, 1, 50)
x = R*np.cos(2*np.pi*phi)
y = R*np.sin(2*np.pi*phi)

эти значения, однако, будут попадать не в обычную пиксельную сетку, а между ними.

Чтобы использовать их в качестве точек выборки, можно либо округлить значения и использовать их в качестве индексов, либо интерполировать значения из ближайших пикселей.

Внимание: Индексы пикселей и x, y не совпадают. В вашем примере (0,0) находится на картинке (50,50).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...