Un poco de trasfondo: quiero calcular el factor de matriz de una matriz de antenas MxN, que viene dado por la siguiente ecuación:

eq1 Donde w_i son el peso complejo del i-ésimo elemento, (x_i, y_i, z_i) es la posición del i-ésimo elemento, k es el número de onda, theta y phi son la elevación y el azimut respectivamente, e i varía de 0 a MxN-1.

En el código tengo:

-theta y phi son np.mgrid con forma (200,200) cada uno,

-w_i, y (x, y, z) _i son np.array con forma (NxM,) cada uno

Entonces AF es una matriz np. con forma (200,200) (suma sobre i). No hay ningún problema hasta ahora, y puedo hacer que AF haga fácilmente:

af = zeros([theta.shape[0],phi.shape[0]])
for i in range(self.size[0]*self.size[1]):
            af = af + ( w[i]*e**(-1j*(k * x_pos[i]*sin(theta)*cos(phi) + k * y_pos[i]* sin(theta)*sin(phi)+ k * z_pos[i] * cos(theta))) )

Ahora, cada w_i depende de la frecuencia, entonces AF también, y ahora tengo w_i con forma (NxM, 1000) (tengo 1000 muestras de cada w_i en frecuencia). Traté de usar el cambio de código anterior

af = zeros([1000,theta.shape[0],phi.shape[0]])

Pero obtengo 'los operandos no se pueden transmitir juntos'. Puedo resolver esto usando un bucle for a través de los valores 1000, pero es lento y es un poco feo. Entonces, ¿cuál es la forma correcta de hacer la suma o la forma correcta de definir correctamente w_i y AF?

Cualquier ayuda sería apreciada. Gracias.

editar El código con la nueva dimensión que intento agregar es el siguiente:

from numpy import *

class AntennaArray:
    def __init__(self,f,asize=None,tipo=None,dx=None,dy=None):
        self.Lambda = 299792458 / f
        self.k = 2*pi/self.Lambda
        self.size = asize
        self.type = tipo
        self._AF_DATA_SIZE = 200
        self.theta,self.phi =  mgrid[0 : pi : self._AF_DATA_SIZE*1j,0 : 2*pi : self._AF_DATA_SIZE*1j]

        self.element_pos = None
        self.element_amp = None
        self.element_pha = None

        if dx == None:
            self.dx = self.Lambda/2
        else:
            self.dx = dx

        if dy == None:
            self.dy = self.Lambda/2
        else:
            self.dy = dy


        self.generate_array()


    def generate_array(self):


        M = self.size[0]
        N = self.size[1]
        dx = self.dx
        dy = self.dy

        x_pos = arange(0,dx*N,dx)
        y_pos = arange(0,dy*M,dy)
        z_pos = 0

        ele = zeros([N*M,3])

        for i in range(M):
            ele[i*N:(i+1)*N,0] = x_pos[:]


        for i in range(M):
            ele[i*N:(i+1)*N,1] = y_pos[i]


        self.element_pos = ele


        #self.array_factor = self.calculate_array_factor()

    def calculate_array_factor(self):

        theta,phi = self.theta,self.phi

        k = self.k

        x_pos = self.element_pos[:,0]
        y_pos = self.element_pos[:,1]
        z_pos = self.element_pos[:,2]

        w = self.element_amp*exp(1j*self.element_pha)



        if len(self.element_pha.shape) > 1:
            #I have f_size samples of w_i(f)
            f_size = self.element_pha.shape[1]
            af = zeros([f_size,theta.shape[0],phi.shape[0]])
        else:
            #I only have w_i
            af = zeros([theta.shape[0],phi.shape[0]])


        for i in range(self.size[0]*self.size[1]):
        **strong text**#This for loop does the summation over i
            af = af + ( w[i]*e**(-1j*(k * x_pos[i]*sin(theta)*cos(phi) + k * y_pos[i]* sin(theta)*sin(phi)+ k * z_pos[i] * cos(theta))) )
        return af

Traté de probarlo con el siguiente main

from numpy import *
f_points = 10

M = 2
N = 2

a = AntennaArray(5.8e9,[M,N])

a.element_amp = ones([M*N,f_points])
a.element_pha = zeros([M*N,f_points])

af = a.calculate_array_factor()

Pero me

ValueError: 'los operandos no se pudieron transmitir junto con las formas (10,) (200,200)'

Tenga en cuenta que si configuro

a.element_amp = ones([M*N])
a.element_pha = zeros([M*N])

Esto funciona bien

Gracias.

1
rdm 30 oct. 2019 a las 01:25

1 respuesta

La mejor respuesta

Eché un vistazo al código y creo que este bucle for:

af = zeros([theta.shape[0],phi.shape[0]])
for i in range(self.size[0]*self.size[1]):
            af = af + ( w[i]*e**(-1j*(k * x_pos[i]*sin(theta)*cos(phi) + k * y_pos[i]* sin(theta)*sin(phi)+ k * z_pos[i] * cos(theta))) )

Está mal en muchos sentidos. Estás mezclando dimensiones, no puedes hacer un bucle de esa manera.
Y, por cierto, para aprovechar al máximo la eficiencia de numpy, nunca recorra las matrices. Ralentiza significativamente la ejecución.

Traté de reelaborar esa parte.

Primero, le aconsejo que no use from numpy import *, es una mala práctica (consulte aquí ). Utilice import numpy as np. Volví a introducir la abreviatura np, para que puedas entender qué proviene de numpy.

Caso independiente de frecuencia

Este primer fragmento asume que w es una matriz 1D de longitud 4: estoy descuidando la dependencia de frecuencia de w, para mostrarle cómo puede obtener lo que ya obtuvo sin el bucle for y usando en su lugar el poder de numpy.

af_points = w[:,np.newaxis,np.newaxis]*np.e**(-1j*
           (k * x_pos[:,np.newaxis,np.newaxis]*np.sin(theta)*np.cos(phi) + 
            k * y_pos[:,np.newaxis,np.newaxis]*np.sin(theta)*np.sin(phi) + 
            k * z_pos[:,np.newaxis,np.newaxis]*np.cos(theta)
           ))
af = np.sum(af_points, axis=0)

Estoy usando transmisión numpy para obtener una matriz 3D llamada { {X0}}, cuya forma es (4, 200, 200). Para hacerlo, utilizo np.newaxis para extender el número de ejes de una matriz con el fin de usar la transmisión correctamente. Más aquí en np.newaxis .
Entonces, w[:,np.newaxis,np.newaxis] es una matriz de forma (4, 1, 1). De manera similar para x_pos[:,np.newaxis,np.newaxis], y_pos[:,np.newaxis,np.newaxis] y z_pos[:,np.newaxis,np.newaxis]. Dado que los ángulos tienen forma (200, 200), se puede transmitir y af_points tiene forma (4, 200, 200). Finalmente, la suma se realiza mediante np.sum, sumando sobre el primer eje para obtener una matriz (200, 200).

Caso dependiente de la frecuencia

Ahora w tiene forma (4, 10), donde 10 son los puntos de frecuencia. La idea es la misma, solo considere que la frecuencia es una dimensión adicional en sus matrices numpy: ahora af_points será una matriz de forma (4, 10, 200, 200) donde 10 son las f_points has definido.

Para que sea comprensible, he dividido el cálculo:

#exp_point is only the exponent, frequency independent. Will be a (4, 200, 200) array.
exp_points = np.e**(-1j*
            (k * x_pos[:,np.newaxis,np.newaxis]*np.sin(theta)*np.cos(phi) + 
             k * y_pos[:,np.newaxis,np.newaxis]*np.sin(theta)*np.sin(phi) +
             k * z_pos[:,np.newaxis,np.newaxis]*np.cos(theta)
            ))
af_points = w[:,:,np.newaxis,np.newaxis] * exp_points[:,np.newaxis,:,:]
af = np.sum(af_points, axis=0)

Y ahora af tiene forma (10, 200, 200).

1
Community 20 jun. 2020 a las 09:12