Arnold Schwarzenegger
Arnold Schwarzenegger

Reputation: 99

Python type error: 'numpy.ndarray' object is not callable

I'm defining a set of functions to convert from an Earth-centered reference frame to classical orbital elements. Here are my codes:

import numpy as np
import matplotlib.pyplot as plt

#converting r,v to orbital elements
u = 3.986*10e14 #gravitational parameter for Earth
list_r = [-2413.9, 6083.8, -1136.0]
r = np.array(list_r)
list_v= [-6.5461, -3.1365, -3.6385] 
v = np.array(list_v)

def h(r,v):
    return np.cross(r,v)


list_k = [0,0,1]
k = np.array(list)

def n(k,h):
    return np.cross(k,h)
def e_vec(v,r):
    vector = 1/u * (np.dot((np.linalg.norm(v))**2-u/np.linalg.norm(r),r)-np.dot(np.dot(r,v),v))
    return vector

def p(h,u):
    return (np.linalg.norm(h))**2/u
        

def a(p,e):
    return p/(1-np.linalg.norm(e_vec)**2)



def i(h):
    
    return np.arccos(np.dot(k,h(r,v))/np.linalg.norm(h(r,v)))
   

list_I = [1,0,0]
I = np.array(list_I)

def ohm(I,n):

    nI = np.dot(n(h),I)
    ohm = np.acos(nI/n)
    return ohm
    
def w(n,e):
    w = np.arccos(np.dot(n,e)/(np.linalg.norm(n)*np.linalg.norm(e)))
    return w

def f(e,r):
    f = np.arccos(np.dot(e_vec(v,r),r)/(np.linalg.norm(e_vec(v,r))*np.linalg.norm(r)))
    return f
print(h(r,v))
print(e_vec(v,r))
print(p(h(r,v),u))
print(i(h(r,v)))
print(ohm(I,n))
print(w)
print(f)

I'm getting this error : TypeError: 'numpy.ndarray' object is not callable, for the function i(h). I don't know how I should fix this.

Upvotes: 1

Views: 9186

Answers (3)

hpaulj
hpaulj

Reputation: 231315

While local variables can be short, single names, functions should be more informative. In particular you have defined a function h, but you also use h as a local variable. That confuses you (and us).

In several of the functions h is a local variable, and an array (at least that's that np.cross expects):

def n(k,h):
    return np.cross(k,h)

Similarly for

def p(h,u):
    return (np.linalg.norm(h))**2/u

But i breaks that pattern:

def i(h):
    return np.arccos(np.dot(k,h(r,v))/np.linalg.norm(h(r,v)))

Here h only works if it is a function. But you haven't passed in r, v or k.

def i(k,h):
    return np.arccos(np.dot(k,h)/np.linalg.norm(h)

is more consistent with your other functions. It is also more consistent with

print(i(h(r,v)))

Upvotes: 1

Daniel F
Daniel F

Reputation: 14399

Your problem is you're getting confused by scoping.

h(r, v) is the result of a function, and thus a numpy array - while h is the function itself. You're passing h(r, v) to i as h, but still expecting h in scope i to be a function.

Also k isn't in scope for i, so that will also cause an error. you should probabaly define

def i(k, r, v): 
    return np.arccos(np.dot(k, h(r, v)) / np.linalg.norm(h(r, v)))

and pass i(k, r, v), or define:

def i(k, h): 
    return np.arccos(np.dot(k, h) / np.linalg.norm(h))

and pass i(k, h(r, v))

An even better method would be to wrap it all in a class and keep all your variables in a self scope so that it's easier to keep track, but the frontend work of object-oriented programming may be a step beyond what you want.

Upvotes: 0

Jasper
Jasper

Reputation: 434

You have a function named def h(r,v) and you also name the argument as h. This is a conflict. In the function i's scope, name h refers to the argument, that is, an numpy.ndarray, not the function. You should avoid using the same name.

Upvotes: 1

Related Questions