I am trying to evaluate an expression for 4 different values for on of my variables. I am trying do create a for loop using np.arange as my variable is a float.
import numpy as np
for Mf in np.arange(0.8,0.01,1.5):
Vinf=Mf*(gamma*R*tatm)**0.5
print(Mf)
I want to evaluate the above expression for Mf = 0.8, 0.9, 1.2 and 1.5. I simply don't know how to do this or using a for loop is even appropriate. Finally, I want to save the output Vinf in an array. How could I achieve all of this?
Edit:
Ok I got the above code working thanks to user gmds. I am trying to use the list created for Mf_values to be used in the expression for P0 in my code. I have tried it in the following way:
Mf_values=[0.8, 0.9, 1.2, 1.5]
Vinf_values=[Mf_value*(gamma*R*tatm)**0.5 for Mf_value in Mf_values]
print(Vinf_values)
P0=[(1+((gamma-1)/2)*(Mf_values**2)**(gamma/(gamma-1))]
print(P0)
T0=(1+((gamma-1)/2)*(Mf_values**2))*tatm
I want to use the 4 different Mf_values for solving the expression for P0 and T0 and save the results in a list in a similar fashion to Vinf_values. However, python gives me the following error:
P0=[(1+((gamma-1)/2)*(Mf_values**2)**(gamma/(gamma-1))]
^
SyntaxError: invalid syntax
How do I solve this issue?
You can use a list comprehension:
Mf_values = [0.8, 0.9, 1.2, 1.5]
Vinf_values = [Mf_value * (gamma * R * tatm) ** 0.5 for Mf_value in Mf_values]
For this tiny example you don't need any numpy, You can do it in pure python like this:
Vinfs = []
for Mf in [0.8, 0.9, 1.2, 1.5]:
Vinf=Mf*(gamma*R*tatm)**0.5
Vinfs.append(Vinf)
Vinfs = np.array(Vinfs) # If you want to have `ndarray` as your output
Related
I'm trying to implement a fast entropy calculation for a float list of probabilities.
Instead of looping through a list, checking if not zero each time, I'm attempting to mask zeros using numpy's built in masking functionality. It works absolutely fine, unless I try to put it into a function, at which point it breaks. Any suggestions?
# Works fine!!
distribution = np.array([0.20, 0.3, 0.25, 0.25, 0])
log_dist = np.log2(distribution, out=np.zeros_like(distribution), where=(distribution!=0))
entropy = -np.sum(distribution * log_dist)
print(entropy)
# Breaks!
def calculate_entropy(distribution):
log_dist = np.log2(distribution, out=np.zeros_like(distribution), where=(distribution!=0))
entropy = -np.sum(distribution * log_dist)
return entropy
calculate_entropy([0.20, 0.3, 0.25, 0.25, 0])
output:
nan
Error message:
/var/folders/bt/vk3t9rnn2jz5d1wgj2rc3v200000gn/T/ipykernel_61321/2272953976.py:3: RuntimeWarning: divide by zero encountered in log2
log_dist = np.log2(distribution, out=np.zeros_like(distribution), where=(distribution!=0))
/var/folders/bt/vk3t9rnn2jz5d1wgj2rc3v200000gn/T/ipykernel_61321/2272953976.py:4: RuntimeWarning: invalid value encountered in multiply
entropy = -np.sum(distribution * log_dist)
I was expecting the function to work exactly the same, what am I missing?
Ugh, I'm an idiot. I forgot to convert the list into a numpy array. fix:
def calculate_entropy(distribution):
distribution = np.array(distribution)
log_dist = np.log2(distribution, out=np.zeros_like(distribution), where=(distribution!=0))
entropy = -np.sum(distribution * log_dist)
return entropy
calculate_entropy([0.20, 0.3, 0.25, 0.25, 0])
How do you use the new Polynomials sub-package in numpy to give it new x values and get an output of y values?
https://numpy.org/doc/stable/reference/routines.polynomials.package.html
In prior versions of numpy it went something like this:
poly = np.poly1d(np.polyfit(x, y, 3)
new_x = np.linspace(0, 100)
new_y = poly(new_x)
The new version I am struggling to give it x values that give me the y values of each?
from numpy.polynomial import Polynomial
poly = Polynomial(Polynomial.fit(x, y, 3))
When I give it an array of x it just returns the coefficients.
You can directly call the resulting series to evaluate it:
from numpy.polynomial import Polynomial
poly = Polynomial.fit(x, y, 3)
new_y = poly(new_x)
Check this page of the documentation it has several examples.
Unfortunately, the answer by #Joan Charmant and the supportive comment #rh109019 do not work.
The intuitive way suggested by #Joan Charmant is, basically, what the question's about: it doesn't work.
Evidently, there is a new method introduced in numpy.polynomial.polynomial devoted specifically to evaluating polynomials. See here.
Here's my code where I'm comparing the two approaches.
import numpy as np
Pgauge = np.asarray([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0])
NIST = np.asarray([1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 8.1])
calibrationCurve = np.polynomial.polynomial.Polynomial.fit(Pgauge,
NIST,
deg=1
)
print("The polynomial: {}".format(calibrationCurve))
x = np.asarray([0, 1]) # values of x to evaluate the polynomial at
c = calibrationCurve.coef # coefficients of the polynomial
print("The intuitive (wrong) way: {}".format(calibrationCurve(x)))
print("The correct way: {}".format(np.polynomial.polynomial.polyval(x, c)))
The first print command prints out the polynomial:4.6+3.5x.
If we want to evaluate it at the points 0 and 1 (x = np.asarray([0, 1])), we expect to get 4.6 and 8.1 respectively.
The second print command (that reads "The intuitive (wrong) way"), uses the method suggested by #Joan Charmant. It gives [0.1, 1.1] as the result. Which is wrong. Though seemingly, it looks ok: it gives two numbers as expected. But the numbers themselves are wrong. I don't know how these numbers were calculated. But if I had a bigger series of data, I wouldn't go with a calculator through it and assume I've got a correct result.
The last print command makes use of the polyval method suggested in the user manual that I cited above. And it works perfectly well. It gives [4.6, 8.1] as the result.
It so happens that my answer is wrong as well (see all the comments below by #user2357112 supports Monica).
But still, I'll leave it here for the folks who, like me, fell the victim of the confusing new numpy.polynomial library.
FIRST: why my code is wrong?
Everything's ok with it. But the line print("The polynomial: {}".format(calibrationCurve)) doesn't give me what, I think, it must give me. It takes the correct polynomial, changes its coefficients somehow and prints out a new polynomial with the changed coefficients. Still, it does store the correct polynomial in its memory and when you do the thing suggested by #Joan Charmant it may give you the correct answer if you ask it properly.
SECOND: how to use the new numpy.polynomial library in order to get a correct result?
Due to that peculiarity, you have to introduce a new line of code. Namely, do the Polynomial.fit() and immediately afterwards use the .convert() method. Then work with the converted polynomial only.
Here's my code that works correctly now.
import numpy as np
Pgauge = np.asarray([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0])
NIST = np.asarray([1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 8.1])
calibrationCurveMessedUp = np.polynomial.polynomial.Polynomial.fit(Pgauge,
NIST,
deg=1
)
calibrationCurve = calibrationCurveMessedUp.convert()
print("The polynomial: {}".format(calibrationCurve))
print("The rounded polynomial coefficients: {}".format(calibrationCurve.coef))
x = np.asarray([0, 1]) # values of x to evaluate the polynomial at
print(calibrationCurve(x))
THIRD: a little note.
Apparently, there is a possibility to get the correct polynomial without the additional line of code. Probably, you have to give the correct window and domain parameters to the Polynomial.fit() function. Or may be there is another way.
If anybody knows such a way, you're welcome to edit my current answer and add your code.
I am trying to use scipy.optimize.fsolve() to solve for x that makes the function equal to zero, but keep getting the error above. My code is:
import scipy.optimize as optimize
from scipy.stats import genextreme as gev
gevcombined = [(-0.139, 3.035, 0.871),(-0.0863, 3.103, 0.818),(-0.198, 3.13, 0.982)]
ratio = [0.225, 0.139, 0.294]
P = [0.5,0.8,0.9,0.96,0.98,0.99]
def mixedpop(x):
for j in range(len(ratio)):
F = (ratio[j]*gev.cdf(x,gevcombined[j][0],gevcombined[j][1],gevcombined[j][2]))+((1-ratio[j]*gev.cdf(x,gevcombined[j][0],gevcombined[j][1],gevcombined[j][2]))-P
return F
initial = 10
Rm = optimize.fsolve(mixedpop,initial)
I keep getting the error:
ValueError:the array returned by a function changed size between calls
What does this error mean? The expected output would be a value for each value of P. So the values of x from Rm would equal something like [3.5, 4, 5.4, 6.3, 7.2, 8.1] for each ratio
Okay I figured out how to get fsolve to work for an array of solutions.
It works if I write the whole thing like this:
Rm = []
initial = [10,10,10,10,10,10]
for j in range(len(ratio)):
f = lambda x : (ratio[j]*gev.cdf(x,gevcombined[j][0],gevcombined[j][1],gevcombined[j][2]))+((1-ratio[j]*gev.cdf(x,gevcombined[j][0],gevcombined[j][1],gevcombined[j][2]))-P
Rm.append(list(optimize.fsolve(f,initial)))
And my output is:
[[3.37, 4.37, 5.13, 6.43, 7.91, 9.88],[3.41, 4.42, 5.09, 6.13, 7.07, 8.18],[3.49, 4.87, 5.95, 7.51, 8.80, 10.19]]
the error occures because the shape of initial does not match your variables.
initial = np.ones(len(x))
However I cannot make my head around what your function is doing. it does the trick for me.
I'm working on a project where I want to use madgwick's AHRS filter. I'm trying to use the translated Python code (Jonas Boër, 2015) but I can't get it to work properly. The script can be found here https://github.com/morgil/madgwick_py
I'm having trouble understanding the use of classes. Below is a script were I first import the class which is stated in madgwickahrs.py. Second I define 1 frame of random data for the gyroscope, accelerometer and magnetometer.
After this I initialize the class and call the different functions inside the class. (note: with the normal array of data I should put this in a loop to calculate the new list of quaternions for each frame)
import numpy as np
from madgwickahrs import MadgwickAHRS
gyr = np.array( [1.6, 0.6, 1.5])
acc = np.array( [1.2, 1.9, 1.3])
mag = np.array( [2.1, 1.3, 2.1])
gyr_rad = gyr * (np.pi/180)
new_data = MadgwickAHRS()
# No parameters filled in means it will use the parameters stated
in the script (sampleperiod = 1/256, quaternion = [1 0 0 0], beta = 1)
new_data.update(gyr_rad,acc,mag)
new_data.update_imu(gyr_rad,acc)
The problem is that I don't know how to retrieve the calculated new quaternions and preferably asign it to a new variable so I can use it for the rest of the script.
Hope I made my self clear and someone can help me!
Thanks!
For me the following method worked:
heading = MadgwickAHRS()
while True:
ninedofxyz = self._ninedof.read()
heading.update(ninedofxyz[0], ninedofxyz[2], ninedofxyz[1])
ahrs = heading.quaternion.to_euler_angles()
roll = ahrs[0]
pitch = ahrs[1]
yaw = ahrs[2]
More info is given here: https://github.com/morgil/madgwick_py/issues/2
The MadgwickAHRS also has the Quaternion class implementation which contains the get_q() for retrieving the new quaternion values.
new_data.quaternion.get_q()
Hi I have two numpy arrays (in this case representing depth and percentage depth dose data) as follows:
depth = np.array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ,
1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2. , 2.2,
2.4, 2.6, 2.8, 3. , 3.5, 4. , 4.5, 5. , 5.5])
pdd = np.array([ 80.40649399, 80.35692155, 81.94323956, 83.78981286,
85.58681373, 87.47056637, 89.39149833, 91.33721651,
93.35729334, 95.25343909, 97.06283306, 98.53761309,
99.56624117, 100. , 99.62820672, 98.47564754,
96.33163961, 93.12182427, 89.0940637 , 83.82699219,
77.75436857, 63.15528566, 46.62287768, 29.9665386 ,
16.11104226, 6.92774817, 0.69401413, 0.58247614,
0.55768992, 0.53290371, 0.5205106 ])
which when plotted give the following curve:
I need to find the depth at which the pdd falls to a given value (initially 50%). I have tried slicing the arrays at the point where the pdd reaches 100% as I'm only interested in the points after this.
Unfortunately np.interp only appears to work where both x and y values are incresing.
Could anyone suggest where I should go next?
If I understand you correctly, you want to interpolate the function depth = f(pdd) at pdd = 50.0. For the purposes of the interpolation, it might help for you to think of pdd as corresponding to your "x" values, and depth as corresponding to your "y" values.
You can use np.argsort to sort your "x" and "y" by ascending order of "x" (i.e. ascending pdd), then use np.interp as usual:
# `idx` is an an array of integer indices that sorts `pdd` in ascending order
idx = np.argsort(pdd)
depth_itp = np.interp([50.0], pdd[idx], depth[idx])
plt.plot(depth, pdd)
plt.plot(depth_itp, 50, 'xr', ms=20, mew=2)
This isn't really a programming solution, but it's how you can find the depth. I'm taking the liberty of renaming your variables, so x(i) = depth(i) and y(i) = pdd(i).
In a given interval [x(i),x(i+1)], your linear interpolant is
p_1(X) = y(i) + (X - x(i))*(y(i+1) - y(i))/(x(i+1) - x(i))
You want to find X such that p_1(X) = 50. First find i such that x(i)>50 and x(i+1), then the above equation can be rearranged to give
X = x(i) + (50 - y(i))*((x(i+1) - x(i))/(y(i+1) - y(i)))
For your data (with MATLAB; sorry, no python code) I make it approximately 2.359. This can then be verified with np.interp(X, depth, pdd)
There are several methods to carry out interpolation. For your case, you are basically looking for the depth at 50% which is not available in your data. The simplest interpolation is the linear case. I'm using numerical recipes library in C++ for acquiring the interpolated value via several techniques, therefore,
Linear Interpolation: see page 117
interpolated value depth(50%): 2.35915
Polynomial Interpolation: see page 117
interpolated value depth(50%): 2.36017
Cubic Spline Interpolation: see page 120
interpolated value depth(50%): 2.19401
Rational Function Interpolation: see page 124
interpolated value depth(50%): 2.35986