从另一个函数调用python中的函数(为函数的变量创建一个数组)

时间:2017-01-04 13:32:21

标签: python

我有这个代码有三个函数叫做(Bx,Bhalo,Bdisk)这三个函数只接受数组(例如shape(1000)):

import numpy as np
import logging
import warnings
import gmf
signum = lambda x: (x < 0.) * -1. + (x >= 0) * 1.
pi = np.pi
#Class with analytical functions that describe the GMF according to the model of JF12  
class GMF(object):     
    def __init__(self): # self:is automatically set to reference the newly created object that needs to be initialized      
    self.Rsun   = -8.5          # position of the sun along the x axis  in kpc  
############################################################################
    # Disk Parameters
############################################################################
    self.bring, self.bring_unc  = 0.1,0.1   # floats, field strength in ring at 3 kpc < r < 5 kpc
    self.hdisk, self.hdisk_unc  = 0.4, 0.03 # float, disk/halo transition height 
    self.wdisk, self.wdisk_unc  = 0.27,0.08 #  floats, transition width
    self.b      = np.array([0.1,3.,-0.9,-0.8,-2.0,-4.2,0.,2.7]) # (8,1)-dim np.arrays, field strength of spiral arms at 5 kpc
    self.b_unc  = np.array([1.8,0.6,0.8,0.3,0.1,0.5,1.8,1.8]) # uncertainty 
    self.rx     = np.array([5.1,6.3,7.1,8.3,9.8,11.4,12.7,15.5])#  (8,1)-dim np.array,dividing lines of spiral lines coordinates of neg. x-axes that intersect with arm
    self.idisk  = 11.5 * pi/180.  #  float, spiral arms pitch angle
#############################################################################
    # Halo Parameters
#############################################################################
    self.Bn, self.Bn_unc    = 1.4,0.1   #  floats, field strength northern halo
    self.Bs, self.Bs_unc    = -1.1,0.1  #  floats, field strength southern halo
    self.rn, self.rn_unc    = 9.22,0.08 # floats, transition radius south, lower limit 
    self.rs, self.rs_unc    = 16.7,0.   # transition radius south, lower limit
    self.whalo, self.whalo_unc  = 0.2,0.12  # floats, transition width
    self.z0, self.z0_unc        = 5.3, 1.6  # floats, vertical scale height
##############################################################################
    # Out of plaxe or "X" component Parameters
##############################################################################
    self.BX0, self.BX_unc   = 4.6,0.3   # floats,  field strength at origin
    self.ThetaX0, self.ThetaX0_unc  = 49. * pi/180., pi/180. # elev. angle at z = 0, r > rXc
    self.rXc, self.rXc_unc  = 4.8, 0.2  # floats, radius where thetaX = thetaX0
    self.rX, self.rX_unc    = 2.9, 0.1  # floats, exponential scale length
    # striated field
    self.gamma, self.gamma_unc  = 2.92,0.14 # striation and/or rel. elec. number dens. rescaling
    return  
##################################################################################
##################################################################################
    # Transition function given by logistic function eq.5
##################################################################################
    def L(self,z,h,w): 

    if np.isscalar(z):
        z = np.array([z]) # scalar or numpy array with positions (height above disk, z; distance from center, r)
    ones = np.ones(z.shape[0])
    return 1./(ones + np.exp(-2. *(np.abs(z)- h)/w))    
####################################################################################
    # return distance from center for angle phi of logarithmic spiral
    # r(phi) = rx * exp(b * phi) as np.array
####################################################################################
    def r_log_spiral(self,phi):

    if np.isscalar(phi): #Returns True if the type of num is a scalar type.
        phi = np.array([phi])
    ones = np.ones(phi.shape[0])
    # self.rx.shape = 8
    # phi.shape = p
    # then result is given as (8,p)-dim array, each row stands for one rx
    # vstack : Take a sequence of arrays and stack them vertically to make a single array
    # tensordot(a, b, axes=2):Compute tensor dot product along specified axes for arrays >=1D.
    result = np.tensordot(self.rx , np.exp((phi - 3.*pi*ones) / np.tan(pi/2. - self.idisk)),axes = 0)
    result = np.vstack((result, np.tensordot(self.rx , np.exp((phi - pi*ones) / np.tan(pi/2. - self.idisk)),axes = 0) ))
    result = np.vstack((result, np.tensordot(self.rx , np.exp((phi + pi*ones) / np.tan(pi/2. - self.idisk)),axes = 0) ))
    return np.vstack((result, np.tensordot(self.rx , np.exp((phi + 3.*pi*ones) / np.tan(pi/2. - self.idisk)),axes = 0) ))    
#############################################################################################
    # Disk component in galactocentric cylindrical coordinates (r,phi,z)
#############################################################################################
    def Bdisk(self,r,phi,z):
    # Bdisk is purely azimuthal (toroidal) with the field strength b_ring
    """ 
    r:  N-dim np.array, distance from origin in GC cylindrical coordinates, is in kpc
    z:  N-dim np.array, height in kpc in GC cylindrical coordinates
    phi:N-dim np.array, polar angle in GC cylindircal coordinates, in radian    
    Bdisk:  (3,N)-dim np.array with (r,phi,z) components of disk field for each coordinate tuple
    Bdisk|: N-dim np.array, absolute value of Bdisk for each coordinate tuple
    """
    if (not r.shape[0] == phi.shape[0]) and (not z.shape[0] == phi.shape[0]):
        warnings.warn("List do not have equal shape! returning -1", RuntimeWarning)
        return -1
    # Return a new array of given shape and type, filled with zeros.
    Bdisk = np.zeros((3,r.shape[0]))    # Bdisk vector in r, phi, z   
    ones        = np.ones(r.shape[0])
    r_center    = (r >= 3.) & (r < 5.1)
    r_disk      = (r >= 5.1) & (r <= 20.)
    Bdisk[1,r_center] = self.bring

    # Determine in which arm we are
    # this is done for each coordinate individually
    if np.sum(r_disk):
        rls = self.r_log_spiral(phi[r_disk])

        rls = np.abs(rls - r[r_disk])
        arms = np.argmin(rls, axis = 0) % 8
        # The magnetic spiral defined at r=5 kpc and fulls off as 1/r ,the field direction is given by:
        Bdisk[0,r_disk] = np.sin(self.idisk)* self.b[arms] * (5. / r[r_disk]) 
        Bdisk[1,r_disk] = np.cos(self.idisk)* self.b[arms] * (5. / r[r_disk])

    Bdisk  *= (ones - self.L(z,self.hdisk,self.wdisk)) # multiplied by (1-L) 
    return Bdisk, np.sqrt(np.sum(Bdisk**2.,axis = 0)) # the Bdisk, the normalization 
    # axis=0 : sum over index 0(row)
    # axis=1 : sum over index 1(columns)    
##############################################################################################
    # Halo component 
###############################################################################################
    def Bhalo(self,r,z):    
    # Bhalo is purely azimuthal (toroidal), i.e. has only a phi component
    if (not r.shape[0] == z.shape[0]):
        warnings.warn("List do not have equal shape! returning -1", RuntimeWarning)
        return -1

    Bhalo = np.zeros((3,r.shape[0]))    # Bhalo vector in r, phi, z  rows: r, phi and z component
    ones  = np.ones(r.shape[0])
    m = ( z != 0. )
    # SEE equation 6.
    Bhalo[1,m] = np.exp(-np.abs(z[m])/self.z0) * self.L(z[m], self.hdisk, self.wdisk) * \
            ( self.Bn * (ones[m] - self.L(r[m], self.rn, self.whalo)) * (z[m] > 0.) \
            + self.Bs * (ones[m] - self.L(r[m], self.rs, self.whalo)) * (z[m] < 0.) )
    return Bhalo , np.sqrt(np.sum(Bhalo**2.,axis = 0))    
##############################################################################################
    # BX component (OUT OF THE PLANE) 
###############################################################################################
    def BX(self,r,z):   
    #BX is purely  ASS  and poloidal, i.e. phi component = 0    
    if (not r.shape[0] == z.shape[0]):
        warnings.warn("List do not have equal shape! returning -1", RuntimeWarning)
        return -1

    BX= np.zeros((3,r.shape[0]))    # BX vector in r, phi, z  rows: r, phi and z component
    m = np.sqrt(r**2. + z**2.) >= 1.

    bx = lambda r_p: self.BX0 * np.exp(-r_p / self.rX) # eq.7
    thetaX = lambda r,z,r_p: np.arctan(np.abs(z)/(r - r_p)) # eq.10

    r_p = r[m] *self.rXc/(self.rXc + np.abs(z[m] ) / np.tan(self.ThetaX0)) # eq. 9

    m_r_b = r_p > self.rXc  # region with constant elevation angle
    m_r_l = r_p <= self.rXc # region with varying elevation angle

    theta = np.zeros(z[m].shape[0])
    b     = np.zeros(z[m].shape[0])

    r_p0 = (r[m])[m_r_b]  - np.abs( (z[m])[m_r_b] ) / np.tan(self.ThetaX0) # eq.8
    b[m_r_b] = bx(r_p0) * r_p0/ (r[m])[m_r_b] # the field strength in the constant elevation angle (b_x(r_p)r_p/r)
    theta[m_r_b] = self.ThetaX0 * np.ones(theta.shape[0])[m_r_b]

    b[m_r_l] = bx(r_p[m_r_l]) * (r_p[m_r_l]/(r[m])[m_r_l] )**2. # the field strength with varying elevation angle (b_x(r_p)(r_p/r)**2)
    theta[m_r_l] = thetaX((r[m])[m_r_l] ,(z[m])[m_r_l] ,r_p[m_r_l])

    mz = (z[m] == 0.)
    theta[mz]   = np.pi/2.

    BX[0,m] = b * (np.cos(theta) * (z[m] >= 0) + np.cos(pi*np.ones(theta.shape[0]) - theta) * (z[m] < 0))
    BX[2,m] = b * (np.sin(theta) * (z[m] >= 0) + np.sin(pi*np.ones(theta.shape[0]) - theta) * (z[m] < 0))
    return BX, np.sqrt(np.sum(BX**2.,axis=0))   

现在我想把这三个功能加在一起; Btotal = Bx + Bhalo + Bdisk,这些函数是圆柱坐标(r,theta,z)中的矢量场,我从圆柱转换为笛卡尔(x,y,z),我定义了一个名为矢量的函数来计算新的两个矢量,称为n1 ,n2(得到两个垂直向量到Btotal)。使用随机微分方程对下面的代码中的许多粒子(~10000)计算粒子的扩散,我试图通过定义的r调用三个函数(形式上面的代码) ,theta,z使用它的扩散方程并绘制结果  即:
在for循环中我必须获得一个形状(3,1)[我将(0,1)]中的范围放入(r,theta,z)然后将值转换为笛卡儿(x,y,z)用它来分别找到n1,n2,d eltaX,deltaY,deltaZ! :

import scipy as sp
import numpy as np
import numpy.random as npr
from numpy.lib.scimath import logn # to logartnim scale
import math as math
from random import seed,random, choice
from pylab import *
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import gmf 
###########################################################
gmfm = gmf.GMF()
#############################################################
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_xlabel(r'$\ X$',size=16)
ax.set_ylabel(r'$\ Y$',size=16)
ax.set_zlabel(r'$\ Z$',size=16)
ax.set_title(' Diffusion Particles in GMF in 3D ')
#############################################################
def vectors(b): 
    b = b/np.sqrt(np.sum(b**2.,axis=0))
    b = b/np.linalg.norm(b)     
    z = np.array([0.,0.,1.])
    n1 = np.cross(z,b,axis=0)
    n1 = n1/np.linalg.norm(n1) 
    n2 = np.cross(b,n1,axis=0)
    n2 = n2/np.linalg.norm(n2) 
    return n1,n2
#############################################################
def CylindricalToCartesian(r,theta,z):
    x= r*np.cos(theta)
    y= r*np.sin(theta)
    z= z
    return np.array([x, y, z])  

############################################################
T=1 # 100 
N=10000
dt=float(T)/N 
D= 1 # 2
DII=10
n= 1000
seed(3)
finalpositions=[]
###############################################################
for number in range(0,1):

  finalpositions.append([])  
  r=[]
  theta=[]
  z=[]
  r.append(0)
  theta.append(0)
  z.append(0)

  x=[]
  y=[]

  x.append(8.5)
  y.append(0)


  for i in range(n): 

    Bdisk, Babs_d = gmfm.Bdisk(r,theta,z)
    Bhalo, Babs_h = gmfm.Bhalo(r,z)
    BX, Babs_x = gmfm.BX(r,z)
    Btotal = Bdisk + Bhalo + BX 


    FieldInXYZ = CylindricalToCartesian(r[-1],theta[-1],z[-1])

    FieldInXYZ =Btotal(x[-1],y[-1],z[-1])
    localB = Btotal(x[-1],y[-1],z[-1])
    print 'FieldInXYZ:', FieldInXYZ       
    #print 'localB:',localB

    n1, n2 = vectors(localB)        
    s = np.random.normal(0, 1, 3)


  finalpositions[-1].append(x)
  finalpositions[-1].append(y)
  finalpositions[-1].append(z)


allxes = [] 
allyes = []
allzes = []


for p in finalpositions:
  allxes.append(p[0][-1])
  allyes.append(p[1][-1]) 
  allzes.append(p[1][-1])

plt.plot(allxes, allyes,allzes, 'o') 
plt.show()

但是我收到了一个错误:

AttributeError                            Traceback (most recent call last)
/usr/lib/python2.7/dist-packages/IPython/utils/py3compat.pyc in execfile(fname, *where)
    202             else:
    203                 filename = fname
--> 204             __builtin__.execfile(filename, *where)

/home/January.py in <module>()
     71   for i in range(n):
     72
---> 73     Bdisk, Babs_d = gmfm.Bdisk(r,theta,z)
     74     Bhalo, Babs_h = gmfm.Bhalo(r,z)
     75     BX, Babs_x = gmfm.BX(r,z)

/home/gmf.py in Bdisk(self, r, phi, z)
     80         Bdisk|: N-dim np.array, absolute value of Bdisk for each coordinate tuple
     81         """
---> 82         if (not r.shape[0] == phi.shape[0]) and (not z.shape[0] == phi.shape[0]):
     83             warnings.warn("List do not have equal shape! returning -1", RuntimeWarning)
     84             return -1

AttributeError: 'list' object has no attribute 'shape'

我不知道我做错了什么?!任何帮助将不胜感激

1 个答案:

答案 0 :(得分:1)

回溯会告诉您问题的确切位置:您使用r.shape type(r)list,而numpy.ndarray则为r = []。追溯问题会显示您声明r,然后将gmfm.Bdisk传递给Bdisk, Babs_d = gmfm.Bdisk(numpy.ndarray(r),theta,z)

相反,你可以这样做:

list

(第73行); (如果您有其他numpy.ndarray被视为{{1}} s,那么您当然需要相应地转换它们。)