rdm
rdm

Reputation: 33

Radial color map on mesh plot

I'm trying to plot a mesh with a radial colormapping. That is, I want all the points in a constant radius to have the same color.

I tried this example but this allows me to modify the color on z-direction only, not the three coordinates.

Any help will be appreciated. Thanks.

edit

Here is the code. It calculates de array factor of an Antenna Array

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()

The plot_array_factor_3d() gives (x,y,z) given the spherical (r,theta,phi) (theta and phi are numpy.mgrid[] and r is array factor).

I want the radial colormap so it can represent the magnitude of the array factor.

This codes gives this output: array factor As you can see, those colors can't represent the magnitude of the magnetic field.

Thanks!

edit 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[]

Upvotes: 0

Views: 283

Answers (1)

rdm
rdm

Reputation: 33

I found a solution by replacing

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

with

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

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

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

this gives the radial color map

result

thanks!

edit 2

just need to add scalars on mlab.mesh(x,y,z,scalars=s)

Sorry and thanks.

Upvotes: 2

Related Questions