Радиальная карта цветов на сетке - PullRequest
0 голосов
/ 19 июня 2019

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

Я пробовал в этом примере , но это позволяет мне изменять цвет только по оси z, а не по трём координатам.

Любая помощь будет оценена. Спасибо.

1010 * редактировать *

Вот код. Он рассчитывает коэффициент массива антенной решетки

from AntennaArray2 import *
from mayavi import mlab

a = AntennaArray(5.8e9,[1,4],'uniform') #creates an array of antennas object

op = 1  #opacity of the plot

a.move_array([-a.dx*1.5,0,0])   #moves the elements of the array, centering them in (0,0,0)

fig = mlab.figure(bgcolor=(1,1,1))

phases1 = array([109.77, 9.639, -85.92, -174.355])      #phases of the array elements
phases2 = array([-167.8, 149.42, 115.28, 102.74])
phases1*= pi/180
phases2*= pi/180

a.set_element_phase(phases1)    #steers the array for the given elements phases

x,y,z = a.plot_array_factor_3d()    #calculates the array factor of the array. 


mesh = mlab.mesh(x,y,z,opacity=op)

mlab.show()

plot_array_factor_3d() дает (x,y,z) с учетом сферического (r, theta, phi) (theta и phi - numpy.mgrid [], а r - коэффициент массива).

Мне нужна радиальная карта цветов, чтобы она могла представлять величину фактора массива.

Этот код дает такой вывод: array factor Как вы можете видеть, эти цвета не могут представлять величину магнитного поля.

Спасибо!

редактировать 2

from numpy import *
import warnings
class AntennaArray:
    def __init__(self,f,size=None,tipo=None,dx=None,dy=None):
        self.Lambda = 299792458 / f
        self.k = 2*pi/self.Lambda
        self.size = size
        self.type = tipo
        self._AF_DATA_SIZE = 200
        self.theta,self.phi =  mgrid[0 : 2*pi : self._AF_DATA_SIZE*1j,0 : pi : self._AF_DATA_SIZE*1j]
        self.antenna_array = 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

        if tipo is not None:
            self.generate_array(tipo,size[0],size[1],self.dx,self.dy)

        if self.antenna_array is not None:
            self.array_factor = self.calculate_array_factor()

        self.antennaField = 1

    def generate_array(self,tipo,*args):
        """generate_array
        Genera una matriz que contiene la informacion del array.
        Columna 1: posiciones x de los elementos
        Columna 2: posiciones y de los elementos
        Columna 3: posiciones z de los elementos
        Columna 4: amplitudes de los elementos
        Columna 5: fase relativa de cada elemento.


        Ejemplo: array uniforme de 4x1 (4 elementos sobre el eje x)
        [[0, 0, 0,  1,  0],        z
         [1, 0, 0,  1,  0],        |
         [2, 0, 0,  1,  0],        |      <dx>
         [3, 0, 0,  1,  0]]        |O____O____O____O______
                                    0    1    2    3       x

        @ Argumentos
        Tipo: 
        + uniform: genera array uniforme de MxN (todos los pesos 1, las fases 0)
        args = (M,N,dx,dy)

        + difference: genera un array de MxN, todos los pesos -1 hasta la mitad de los elementos y luego +1.
        todas las fases son 0.
        args = (M,N,dx,dy)

        + matrix: recibe como argumento una matriz (numpy.array()) de MxN. En donde hay un numero en la matriz distinto de 0
        coloca un elemento ahi, cuya amplitud y fase es el valor en la poscion de la matriz.
        El segundo argumento son las distancias dx y dy.
        args = (ARRAY,dx,dy)

        @ Return
        antenna_array: numpy.array() (MxN x 5) que contiene la informacion del arreglo.
        """
        if tipo == 'uniform':

            M = args[0]
            N = args[1]
            dx = args[2]
            dy = args[3]

            self.size = [M,N]
            x_pos = arange(0,dx*N,dx)
            y_pos = arange(0,dy*M,dy)
            z_pos = 0

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

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


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

            ele[:,3]=1

            self.antenna_array = ele

        if tipo == 'difference':

            M = args[0]
            N = args[1]
            dx = args[2]
            dy = args[3]

            self.size = [M,N]
            x_pos = arange(0,dx*N,dx)
            y_pos = arange(0,dy*M,dy)
            z_pos = 0

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

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


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

            ele[:,3]=1

            self.antenna_array = ele

        if tipo == 'matrix':
            x = args[0]

            if (size(x.shape) > 1):
                if (x.shape[1] > 1) :  
                    dy = args[2]

            if (x.shape[0] is not None) or (x.shape[1] > 1):   
                dx = args[1]

            M = x.shape[0]
            if size(x.shape) > 1:
                N = x.shape[1]
            else:
                N = 1

            self.size = [M,N]
            ele = zeros([M*N,5])

            ele[:,0] = where(x!=0)[0]*self.dx
            if (size(x.shape) > 1):
                ele[:,1] = where(x!=0)[1]*self.dy
            else:
                ele[:,1] = 0
            ele[:,2] = 0
            ele[:,3] = x[where(x!=0)]  
            ele[:,4] = 0

            self.antenna_array = ele

            self.array_factor = self.calculate_array_factor()

    def calculate_array_factor(self):
        '''No llamar esta funcion
        ''' 

        theta,phi = self.theta,self.phi

        k = self.k

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

        w = self.antenna_array[:,3]*exp(1j*self.antenna_array[:,4])

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

        for i in range(self.antenna_array.shape[0]):
            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

    def set_antenna_field(self,antennaFarfield):
        '''Asigna el patron de la antena de cada elemento del array.
        Cuando esta funcion es llamada, recalcula el patron de antena.
        Si el tamanio de antennaFarfield es distinto del tamanio de array_factor, entonces
        re-calcula el factor de arreglo de manera que tengan el mismo tamanio

        @ Argumentos
            antennaFarfield: numpy.array que contiene los valores del campo de la antena
            en coordenadas esfericas.
        '''

        self.antennaField = antennaFarfield
        if antennaFarfield.shape[0] != self.array_factor.shape[0]:
            self._AF_DATA_SIZE = antennaFarfield.shape[0]
            self.array_factor,_,__ = self.calculate_array_factor()
        self.antennaFactor = self.array_factor * self.antennaField

    def set_element_phase(self,phase):
        warnings.warn('La fase va por filas. Cuidado con los arrays planares.')
        M,N = self.size[0],self.size[1]
        for i in range(M*N):
            self.antenna_array[i,4] = phase[i]

        self.array_factor = self.calculate_array_factor()
        return

    def plot_array_factor_3d(self):
        '''Devuelve el factor de array en x,y,z.
        Para plotear, utilizar la funcion mlab.mesh(x,y,z) de 
        mayavi. La cantidad de puntos (tamanio de x y z) depende de 
        DATA_SIZE de la funcion Antennaantenna_array().
        '''
        af = self.array_factor
        theta,phi = self.theta,self.phi
        r = abs(af)
        x = r * sin(theta) * cos(phi)
        y = r * sin(theta) * sin(phi)
        z = r * cos(theta)
        return x,y,z

    def plot_antenna_field_3d(self):
        '''Devuelve el campo de antena en x,y,z.
        Para plotear, utilizar la funcion mlab.mesh(x,y,z) de 
        mayavi. La cantidad de puntos (tamanio de x y z) depende de 
        DATA_SIZE de la funcion Antennaantenna_array().
        '''
        af= self.antennaField
        theta,phi = self.theta,self.phi
        r = abs(af)
        x = r * sin(theta) * cos(phi)
        y = r * sin(theta) * sin(phi)
        z = r * cos(theta)
        return x,y,z

    def plot_antenna_factor_3d(self):
        '''Devuelve el factor de antena  en x,y,z.
        Para plotear, utilizar la funcion mlab.mesh(x,y,z) de 
        mayavi. La cantidad de puntos (tamanio de x y z) depende de 
        DATA_SIZE de la funcion Antennaantenna_array().
        Nota: FactorAntenna = Factorantenna_array x CampoAntenna
        '''
        af= self.antennaFactor
        theta,phi = self.theta,self.phi
        r = abs(af)
        x = r * sin(theta) * cos(phi)
        y = r * sin(theta) * sin(phi)
        z = r * cos(theta)
        return x,y,z

    def move_array(self,pos):
        """Mueve el arreglo de antenas y actualiza el antenna_array factor.

        @ Argumentos:
            pos: tuple, list o numpy.array(). Contiene la posicion en X, en Y y en Z.
        """
        pos_x = pos[0]
        pos_y = pos[1]
        pos_z = pos[2]
        self.antenna_array[:,0] += pos_x
        self.antenna_array[:,1] += pos_y
        self.antenna_array[:,2] += pos_z
        self.array_factor = self.calculate_array_factor()

    def steer_array(self,theta_s,phi_s):
        '''Desfasa cada elemento del arreglo para hacer que este apunte en la direccion
        de theta_s y phi_s (azimuth y angulo de elevacion).

        @ Argumentos:
            theta_s,phi_s: angulo de elevacion y de azimuth respectivamente en radianes.
        '''

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

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

        for i in range(M*N):
            self.antenna_array[i,4]= self.k*(x_pos[i]*sin(theta_s)*cos(phi_s)+y_pos[i]*sin(theta_s)*sin(phi_s)+z_pos[i]*cos(theta_s))
        self.array_factor = self.calculate_array_factor()

    def plot_array(self):
        '''
        Muestra como estan distribuidos los elementos del array en el espacio.
        @ Return:
            x,y: puntos donde estan los elementos del array.
        ''' 
        x = zeros(self.antenna_array.shape[0])
        y = zeros(self.antenna_array.shape[0])
        for i in range(self.antenna_array.shape[0]):
            x[i] = self.antenna_array[i,0]/self.Lambda
            y[i] = self.antenna_array[i,1]/self.Lambda
        return x,y

    def plot_array_factor_2d(self,theta_p = None, phi_p = None):
        '''Devuelve AF(theta,phi=phi_p) o AF(theta=theta_p,phi)
        segun corresponda. Si theta_p es no None, phi_p debe ser
        None, sino se retorna error.

        @ Argumentos:
            theta_p: angulo theta que se quiere observar.
            phi_p:   angulo phi que se quiere observar.

        @ Return
            x,y:  datos para plotear el grafico en 2D. devuelve 0,0 si
            theta_p y phi_p son distintos de None.

        '''
#         af = self.array_factor
#         theta,phi = self.theta,self.phi
#         r = abs(af)
#         x = r * sin(theta) * cos(phi)
#         y = r * sin(theta) * sin(phi)
#         z = r * cos(theta)

#         rot_azimuth = array([
#             [cos(phi_p),-sin(phi_p),0],
#             [sin(phi_p), cos(phi_p),0],
#             [0         , 0         ,1]
#         ])


#         rot_zenith = array([
#             [1           ,0        ,0],
#             [0,cos(phi_p),-sin(phi_p)],
#             [0,sin(phi_p), cos(phi_p)]
#         ])




#         if theta_p is None:
#             af2d = self.array_factor[]

1 Ответ

2 голосов
/ 19 июня 2019

Я нашел решение, заменив

mesh = mlab.mesh(x,y,z,opacity=op)

с

x = x.flatten()
y = y.flatten()
z = z.flatten()

s = sqrt( x**2 + y**2 + z**2)

mlab.points3d(x,y,z,s)

это дает радиальную карту цветов

результат

спасибо!

редактировать 2

просто нужно добавить скаляры на mlab.mesh(x,y,z,scalars=s)

Извините и спасибо.

...