I am still a newbie in python and I need to use PyAstronomy module for writing a code. I want to call this function as an Input for another code:
def phaseAngle(pos, los='-z'):
"""
Calculate the phase angle.
Parameters
----------
pos : array
Either a one-dimensional array with xyz coordinate or a
[3,N] array containing N xyz positions.
los : LineOfSight object
A `LineOfSight` object from the pyasl giving the line of
sight.
Returns
-------
Phase angle : The phase angle in degrees. Depending on the input,
it returns a single value or an array.
"""
from PyAstronomy.pyasl import LineOfSight
l = LineOfSight(los)
if pos.shape == (3,):
# It is a single value
return numpy.arccos(numpy.sum(-pos * (-l.los)) /
numpy.sqrt(numpy.sum(pos**2))) / numpy.pi * 180.
else:
# It is an array of positions
N = len(pos[::, 0])
result = numpy.zeros(N)
for i in smo.range(N):
print(i, numpy.sum((-pos[i, ::]) * (-l.los)), pos[i, ::])
result[i] = numpy.arccos(numpy.sum((-pos[i, ::]) * (-l.los)) /
numpy.sqrt(numpy.sum(pos[i, ::]**2)))
return result / numpy.pi * 180.
In the main code the inputs are entered this way by calling KeplerEllipse from pyasl:
...
from PyAstronomy import pyasl
...
ke = pyasl.KeplerEllipse(1.3, 2., e=0.5, Omega=70., i=10.0, w=110.0)
that works very well and gives the positions and velocities as the outputs. But I need to use this phase angle as another input. But, I don't know how to inverse the output and input of def phaseAngle(pos, los='-z') so that I use the phase angle as an input and add it to
ke = pyasl.KeplerEllipse(1.3, 2., e=0.5, Omega=70., i=10.0, w=110.0, ??? )
If the missing argument you are looking for is the phase angle then invoke the PhaseAngle function. As Sven says in the comments, in Python you can inline and nest pretty much at will. So:
ke = pyasl.KeplerEllipse(1.3, 2., e=0.5, Omega=70., i=10.0, w=110.0, phaseAngle(?, ?) )
You have to supply phase angle with pos argument, and los if you don't want the default. It'll spit out the phaseAngle, which will be inserted where you need the argument.
For debugging you can also pre-compute like so:
phase_angle = phaseAngle(?, ?) # Put in the pos and los arguments here
ke = pyasl.KeplerEllipse(1.3, 2., e=0.5, Omega=70., i=10.0, w=110.0, phase_angle)
I think this answers your questions? There is no inversion involved though. This is forward-direction function evaluation.
If you have created:
def func():
pass
Then you will call it:
func()
Related
I have a matlab code that is going to use a PSO algorithm that is constructed in python, that as several parameters, knowing that one of those parameters is a 10x5 matrix, and is always giving me an error when i try to run the matlab code, so i put the code and the error that occurs next:
PS: I already tested the pso algorithm in python with same matrix, but when i use it in matlab, it doesn't work.
MATLAB code:
s = size(CurrentPop, 1);
velocity_matrix = [];
NewPop = [];
for gen = 1:gen_max
NewPop, velocity_matrix = py.pso_algorithm.pso(n_chr, n_par, CurrentPop, velocity_matrix, gen);
CurrentPop = EvaluateFirestation(NewPop, n_par, fuelmodels);
The error that appears that always occurs in the following line of the python function particles = particles_array[:, :n_par]:
Error using pso_algorithm>pso (line 46)
Python Error: TypeError: slice indices must be integers or None or have an index method
Python function 'pso' might not be able to accept at least one input argument at position 3. The function may require a specific data type that you can construct from the MATLAB array. For more information, see the documentation for Python function 'pso' and working with Python arrays.
Python function:
def pso(population, n_par, current_pop, velocity_matrix, generation):
# Initialization
# Population
particles_array = np.array(current_pop)
particles = particles_array[:, :n_par]
# Particle's best position
pbest_position = particles
# Fitness
# ULTIMA COLUNA DE CURRENT_POP
pbest_fitness = particles_array[:, n_par]
# Index of the best particle
gbest_index = np.argmin(pbest_fitness) # VAI BUSCAR O INDICE DO MENOR VALOR EM PBEST_FITNESS
# Global best particle position
gbest_position = pbest_position[gbest_index]
# Velocity (starting from 0 speed)
if generation == 1:
velocity = [[0.0 for j in range(n_par)] for i in range(population)]
else:
velocity = velocity_matrix
for n in range(population):
# Update the velocity of each particle
velocity[n] = update_velocity(particles[n], velocity[n], pbest_position[n], gbest_position, n_par)
# Move the particles to new position
particles[n] = update_position(particles[n], velocity[n])
particles = np.insert(particles, n_par, pbest_fitness, axis=1)
velocity = np.array(velocity)
# print(particles)
# print(velocity)
return particles, velocity
I have a code in which I need the solar radiance. To calculate it I use the Planck function, which I have defined as:
def planck_W(self, x, t):
return (2*self.h*self.c**2/x**5) / (np.exp(self.h*self.c / (self.k*x*t)) -1)
Where x is the wavelength and t is the temperature, and the output is the radiance value.
However I want to be able to use also values coming from a CSV with different solar spectra, which already provides radiance values for different wavelengths. The sturcture of the CSV is Name of the spectrum used, _xx (wavelength), _yy (radiance)
self.spectra_list= pd.read_csv('solar.csv',converters={'_xx': literal_eval, '_yy':literal_eval)
def planck_W(self):
self.spectra_list= pd.read_csv('solar.csv',converters={'_xx':literal_eval, '_yy':literal_eval)
return interp1d( np.array(self._xx)*1e-9,
np.array(self._yy),
kind='linear')
Later I need to use this curve for a calculation at a wavelength range given by another variable, it starts with:
n0 = simpson((planck_W(s.wavelength)...
and I get the error:
planck_W() takes 1 positional argument but 2 were given
I'm kinda new to programming and don't have much idea what I'm doing, how do I manage to make it take the CSV values?
def planck_W(self):
This is the function signature which expects only self. But, while calling the function s.wavelength is supplied.
This causes the the error takes 1 positional argument but 2 were given.
self is not an argument in your case. Since you not pasted whole code I'm just guessing that planck_W() function is a part of a bigger picture which need to a class indeed.
If this is the case your function call should look like this:
n0 = simpson(planck_W())
wavelength value you put in your call is not used anywhere.
Otherwise, if you need that value, you have to add wavelength parameter like this:
def planck_W(self, wavelength):
and then use it inside the function
I hope this explains the situation
You should understand the difference between a function and a method.
Function
A function is a piece of code that may or may not take arguments/keywords and perform some actions.
The main reason for a function to be a thing might be to prevent repeating same code.
Example:
Calculate the sin of a given angle (In radians) See: https://en.wikipedia.org/wiki/Sine#Series_definition
angle = 3.1416
factorial3 = 1
for i in range(1, 4):
factorial3 *= i
factorial5 = 1
for i in range(1, 6):
factorial5 *= i
factorial7 = 1
for i in range(1, 8):
factorial7 *= i
sine = angle - ((angle * angle * angle) / factorial3) + ((angle * angle * angle * angle * angle) / factorial5) - \
((angle * angle * angle * angle * angle * angle * angle) / factorial7)
We can see the repeating pattern here.
The factorial and power are used multiple times. Those can be functions:
def factorial(n):
result = 1
for i in range(1, n+1):
result *= i
return result
def power(base, pow):
result = 1
for _ in range(pow):
result *= base
return result
sine2 = angle - (power(angle, 3) / factorial(3)) + (power(angle, 5) / factorial(5)) - (power(angle, 7) / factorial(7))
Method
A method is a function of a class.
We can create an object from a class and ask questions to the object (using method and attributes) and get results.
When you are calling a method of a class you use name spacing as such:
object_from_class = TheClass()
object_from_class.the_method(*possible_args)
Now you refereeing to the_method of the object_from_class.
The question is what if you want to refer to a method of the object inside the object.
Let's say we have a class which does trigonometric operations. We can have a sin, cos, tan etc.
You see here when we trying to calculate tan we do not need a whole new method. We can use sin/cos. Now I need to refer to the methods inside the object.
class Trigonometry:
def sin(self, angle):
return some_thing
def cos(self, angle):
return some_thing_else
def tan(self, angle):
return self.sin(angle) / self.cos(angle)
self.sin is equivalent of object_from_class.the_method when you are inside the object.
Note: Some languages, such as javascript, usesthis instead of self
Now, in your case, you are calling a method of an object def planck_W(self): which takes no arguments (technically it takes 1 argument but you should provide none) and passing some. That's why python is complaining about what number of arguments.
My question is if there's a way to take some values in a function that are not
integrated in odeint.
Exemple: if I have a derivative dy(x)/dt = A*x+ln(x) and before to get this equation I computed A throught of a intermediate equation like A = B*D . I would like to take the A's value during the process.
More detailed (only exemple):
def func(y,t)
K = y[0]
B = 3
A = cos(t**2) + B
dy/dt = A*t+ln(t)
return [dy/dt]
Can I take A's values of function?
The answer for Josh Karpel
The code is like that:
def Reaction(state,t):
# Integrate Results
p = state[0]
T = state[1]
# function determine enthalpy of system
f1(T,p) = enthalpy
# function determine specific volume of system
f2(T,p) = specific volume
# function determine heat release by reactions
f3(T,p,t) = heat release by reactions
# Derivatives
dp/dt = f(T,p,enthalpy,specific volume,heat release by reactions)
dT/dt = f(T,p,enthalpy,specific volume,heat release by reactions)
The real code is bigger than that. But, I would like to know if there is a way to store the values of f1 (enthalpy), f2 (specific volume), f3 (heat release) as a vector or tuple during the process of solution of odeint with the same size of p and T.
It's not entirely clear what you want, but it sounds like you need to pass another value to the function you're integrating over. There are two options I can think of:
scipy.integrate.odeint takes an args argument which contains extra arguments to be passed to the integrand function, which could then have signature y(t, A).
You could use functools.partial to construct a new function which has the argument A for the integrand function y(t, A) already set.
I have a function that produces an array within it, and I want to do work on the generated array outside of the function, in python. How can I make the function save the array such that this can be done?
Thanks!
My function is here:
def lane_emden(n, delxi=0.00001, xilim=25):
theta = 1
dtdx = 0
xi = 0.01
#Starting values
dtdx_values = [dtdx]
theta_values = [theta]
xi_values = [xi]
#Initial values for the lists
while theta>=0 and xi<=xilim :
dtdx_new = dtdx - ((2*(2/xi*dtdx)) + theta**n)*delxi
theta_new = theta + delxi*dtdx_new
xi_new = xi + delxi
#Equations to create new values for iterative diff eq solving
dtdx = dtdx_new
theta = theta_new
xi = xi_new
#Replace the old values with the new ones
dtdx_values.append(dtdx)
theta_values.append(theta)
xi_values.append(xi)
#Store these new values in previously defined lists
results = np.array((theta_values, xi_values))
#create an array of the results (probably done incorrectly)
return results
#This is how I tried to get the array saved outside the function
I'm very new to Python, any help would be greatly appreciated!
[Edit] Function call as requested.
Input
lane_emden(5)
Output
array([[ 1.00000000e+00, 1.00000000e+00, 1.00000000e+00, ...,
2.10576105e-01, 2.10576063e-01, 2.10576022e-01],
[ 1.00000000e-02, 1.00100000e-02, 1.00200000e-02, ...,
2.49999900e+01, 2.50000000e+01, 2.50000100e+01]])
You already return your array, so now you just need to use it. array = lane_emden(3) for example.
Looks like you are using numpy: results = np.array((theta_values, xi_values)). The documentation for numpy.array() states the first argument must be an array-like object:
An array, any object exposing the array interface, an object whose array method returns an array, or any (nested) sequence.
I think you want numpy.asarray() instead: results = np.asarray((theta_values, xi_values)).
I want to use the newton function loaded as
from scipy.optimize import newton
in order to find the zeros of a function enetered by the user. I write a script that first ask to the user to specify a function together with its first derivative, and also the starting point of the algorithm. First of all typing help(newton) I saw which parameters takes the function and the relative explanation:
newton(func, x0, fprime=None, args=(), tol=1.48e-08, maxiter=50)
func : function
The function whose zero is wanted. It must be a function of a
single variable of the form f(x,a,b,c...), where a,b,c... are extra
arguments that can be passed in the `args` parameter.
In which way I have to pass my function? If I use for func e.g. x**3 (and its first derivative) the response is NameError: name 'x' is not defined. On the internet I find that first I have to define my function and its first derivative and pass the names as parameters. So I made the following
fie = raw_input('Enter function in terms of x (e.g. x**2 - 2*x). F= ')
dfie = raw_input('Enter first derivative of function above DF = ')
x0 = input('Enter starting point x0 = ')
def F(x,fie):
y = eval(fie)
return y
def DF(x, dfie):
dy = eval(dfie)
return dy
print newton(F,x0,DF)
But I get the output
102 for iter in range(maxiter):
103 myargs = (p0,) + args
--> 104 fder = fprime(*myargs)
105 if fder == 0:
106 msg = "derivative was zero."
TypeError: DF() takes exactly 2 arguments (1 given)
and the same issue for F if I omit DF. Looking at the code in /usr/local/share/src/scipy/scipy/optimize/zeros.py I see that it evaluates the first derivative with fder=fprime(*myargs) so maybe I have to put in args something that make it working. I was thinking about it but no solution comes to me.
First, be aware that using eval makes your program vulnerable to malicious users. If that concern does not apply, you can create F and DF like this:
F = eval('lambda x :'+fie)
DF = eval('lambda x :'+dfie)
Then both functions expect only a single argument, and you can leave the args argument empty.
EDIT. If you really want to stick to your code as closely as possible, this should also work, but it does not look very nice to me. newton will send the same args to both functions.
def F(x,fie,dfie):
y = eval(fie)
return y
def DF(x,fie,dfie):
dy = eval(dfie)
return dy
print newton(F,x0,DF,(fie,dfie))