In sympy.physics.units identical units automatically simplify when they are used in equations. However, when units are different scales of the same dimension, they are not automatically simplified. For example:
from sympy.physics.units import *
(5000 * gram) / (2 * gram)
# 2500
(5 * kilogram) / (2 * gram)
# (5 * kilogram) / (2 * gram)
5 * gram + 1 * kilogram
# 5*gram + kilogram
5 * gram + 1000 * gram
# 1005*gram
1000*liter/(5000*liter)
# 1/5
1000*liter/(5*meter**3)
# 200*liter/meter**3
Is there an easy way to force unit simplification, at least in cases where the units are different scales of the same dimension?
I am looking for the same effect as using .subs() on all the units, just automated to use the information already contained in the expression, equivalent to
((5 * kilogram) / (2 * gram)).subs({gram: gram, kilogram: 1000 * gram, ...})
The issue of scale can be solved by print_unit_base method of the unit system. For example,
from sympy.physics.units.systems import MKS
expr = (5 * kilogram) / (2 * gram)
new_expr = expr.xreplace({q: MKS.print_unit_base(q) for q in expr.atoms(Quantity)})
Now new_expr is 2500.
A simpler function to use is convert_to(expr, kilogram) (which also returns 2500) but this depends on knowing that units of mass are an issue. print_unit_base uniformizes all units of the given unit system.
With liter, since it's not really a prefixed-meter-cubed, we need convert_to:
expr2 = 1000*liter/(5*meter**3)
convert_to(expr2, meter) # 1/5
Related
I try to write code for that calculation angles from lengths of triangle. formula is
cos(a)=b^2+c^2-a^2/2bc. (Triangle is here)
angle1 = acosf((powf(length2,2) + powf(length3,2) - powf(length1,2)) / 2 * length2 * length3)* 180 / 3.14153;
angle2 = acosf((powf(length1,2) + powf(length3,2) - powf(length2,2)) / 2 * length1 * length3)* 180 / 3.14153;
angle3 = 180 - (angle2 + angle1);
Everything is float. When entered 5-4-3 inputs outcome this.
angle one is 90.0018
angle two is nan
angle three is nan
changing order doesn't matter, only gives output for 5.
You are doing:
angle1 = acosf((powf(length2,2) + powf(length3,2) - powf(length1,2)) / 2 * length2 * length3)* 180 / 3.14153;
You should be doing:
angle1 = acosf((powf(length2,2) + powf(length3,2) - powf(length1,2)) / (2 * length2 * length3))* 180 / 3.14153;
Explanation: The problem is caused by the following formula, which is in fact badly written:
cos(a)=b^2+c^2-a^2/2bc
// This, obviously, is wrong because
// you need to group the firt three terms together.
// Next to that, everybody understands that the last "b" and "c" are divisors,
// yet it would be better to write it as:
cos(a)=(b^2+c^2-a^2)/(2bc)
The brackets, I added in the code, are similar to the replacement of /2bc by /(2bc).
I am using SAS for research. My question is how to find the nearest match in the same column. Please see the following for a quick illustration. I am new to SAS programming, and only have a preliminary guess that proc sql might do the work. What I am doing now is manually adjusting - it is painful and especially so for over 3,000 observations.
I want to find the nearest "Value" match that could add up to zero. For example, for firm AA in 1st quarter 2000, I want to match the nearest two numbers that could add up to 100. I don't want the 50 for firm AA in 2002Q2 nor firm BB 2000Q4. In addition, I also struggle with the case for firm BB, and have no idea how to perform the matching: the two negative numbers add up to -200, the two positive numbers add up to +200, and they maybe in same or different years. To help you understand better, please find the following table for what I have in mind at the end of the day:
For the BB case, it can be 2001Q3 "-100" matched to "50" in 2000Q4, it is also fine if it matches to "100" in 2001Q1 - the order doesn't matter. Thanks in advance! Any help is really appreciated!
Regards,
Michael
At +/- 2 quarters, each row has at most 5 items that need to be to checked in combination.
There are 15 combinations that include the current row (0 column) and at least one other row.
combo -2 -1 0 1 2
1 * * *
2 * *
3 * *
4 * * * *
5 * * *
6 * * *
7 * *
8 * * * * *
9 * * * *
10 * * * *
11 * * *
12 * * * *
13 * * *
14 * * *
15 * *
You could check all these combinations for each row to find your cases 'of sums to zero' in the context of combinations with replacement.
I'm trying to play a stereo signal using these two phase shifted tones and I can't make it
import numpy as np
import sounddevice as sd
fs = 44100
duration = 1
frequency = 440
phase = 90 * 2 * np.pi / 360
sine_A = (np.sin(2 * np.pi * np.arange(fs * duration) * frequency / fs + phase)).astype(
np.float32)
sine_B = (np.sin(2 * np.pi * np.arange(fs * duration) * frequency / fs)).astype(np.float32)
sumSine= np.array([sine_A, sine_B])
sd.play(sumSine)
And it returns me the following error:
sounddevice.PortAudioError: Error opening OutputStream: Invalid number of channels
I can't track which is the problem
As you've found out, you were not concatenating sine_A and sine_B correctly. The way you did it, an array with two rows and many columns was created. Since sd.play() expects the columns to be channels, you obviously gave it too many, that's why it complained.
You should concatenate the two array in a way that they form the two columns of a new array. I think the easiest way to do this is:
np.column_stack((sine_A, sine_B))
It will still not work, though.
When you call sd.play(), it starts playing in the background and then immediately returns. Since you are exiting your script right after that, you won't really hear anything of your nice sine tone.
To wait for the playback to be finished, you could e.g. use sd.wait().
In the end, your script might look something like this:
import numpy as np
import sounddevice as sd
fs = 44100
duration = 1
frequency = 440
phase = np.pi / 2
t = np.arange(int(fs * duration)) / fs
sine_A = np.sin(2 * np.pi * frequency * t + phase)
sine_B = np.sin(2 * np.pi * frequency * t)
stereo_sine = np.column_stack((sine_A, sine_B))
sd.play(stereo_sine, fs)
sd.wait()
BTW, you can also have a look at my little tutorial, which shows similar things.
The problem was in the way I did the numpy array.
It must be like
stereoSignal = numpy.array([[a,b], [c,d],...])
The correct aproximation is below.
fs = 44100
duration = 1
frequency = 440
phase = 90 * 2 * np.pi / 360
sine_A = (np.sin(2 * np.pi * np.arange(fs * duration) * frequency / fs + phase)).astype(
np.float32)
sine_B = (np.sin(2 * np.pi * np.arange(fs * duration) * frequency / fs)).astype(np.float32)
sumSine = np.array([list(i) for i in zip(sine_A, sine_B)])
sd.play(sumSine, mapping=[1, 2])
I attach the complete code in this link:
https://github.com/abonellitoro/not-in-phase-stereo-tone-generator
I am running an MCMC sampler which requires the calculation of the hypergeometric function at each step using scipy.special.hyp2f1().
At certain points on my grid (which I do not care about) the solutions to the hypergeometric function are quite unstable and SciPy prints the warning:
Warning! You should check the accuracy
This is rather annoying, and over 1000s of samples may well slow down my routine.
I have tried using special.errprint(0) with no luck, as well as disabling all warnings in Python using both the warnings module and the -W ignore flag.
The offending function (called from another file) is below
from numpy import pi, hypot, real, imag
import scipy.special as special
def deflection_angle(p, (x1, x2)):
# Find the normalisation constant
norm = (p.f * p.m * (p.r0 ** (t - 2.0)) / pi) ** (1.0 / t)
# Define the complex plane
z = x1 + 1j * x2
# Define the radial coordinates
r = hypot(x1, x2)
# Truncate the radial coordinates
r_ = r * (r < p.r0).astype('float') + p.r0 * (r >= p.r0).astype('float')
# Calculate the radial part
radial = (norm ** 2 / (p.f * z)) * ((norm / r_) ** (t - 2))
# Calculate the angular part
h1, h2, h3 = 0.5, 1.0 - t / 2.0, 2.0 - t / 2.0
h4 = ((1 - p.f ** 2) / p.f ** 2) * (r_ / z) ** 2
special.errprint(0)
angular = special.hyp2f1(h1, h2, h3, h4)
# Assemble the deflection angle
alpha = (- radial * angular).conjugate()
# Separate real and imaginary parts
return real(alpha), imag(alpha)`
Unfortunately, hyp2f1 is notoriously hard to compute over some non-trivial areas of the parameter space. Many implementations would dilently produce inaccurate or wildly wrong results. Scipy.special tries hard to at least monitor convergence. An alternative could be to usr arbitrary precision implementations, e.g. mpmath. But these would certainly be quite a bit slower, so MCMC users beware.
EDIT: Ok, this seems to be scipy version dependent. I tried #wrwrwr's example on scipy 0.13.3, and it reproduces what you see: "Warning! You should check the accuracy" is printed regardless of the errprint status. However, doing the same with the dev version, I get
In [12]: errprint(True)
Out[12]: 0
In [13]: hyp2f1(0.5, 2/3., 1.5, 0.09j+0.75j)
/home/br/virtualenvs/scipy_py27/bin/ipython:1: SpecialFunctionWarning: scipy.special/chyp2f1: loss of precision
#!/home/br/virtualenvs/scipy_py27/bin/python
Out[13]: (0.93934867949609357+0.15593972567482395j)
In [14]: errprint(False)
Out[14]: 1
In [15]: hyp2f1(0.5, 2/3., 1.5, 0.09j+0.75j)
Out[15]: (0.93934867949609357+0.15593972567482395j)
So, apparently it got fixed at some point between 2013 and now. You might want to upgrade your scipy version.
I have a value in temperature and I want to get a resistance value from this temperature.
I use Steinhart-Hart method but this equation always returns 7,39 regardless of temperatures and coefficients.
My second implementation based on steinhart method (see below) doesn't work with negative coefficients.
Do you know what's the problem with my code ?
double WSensor::temperatureToResistance(double _temp)
{
double Temp = _temp + 273.15;
double X = ((this->therm->getA() - (1 / Temp)) / this->therm->getC());
double Y = this->therm->getB() / this->therm->getC();
double argExpo = pow(-(X / 2) + pow((X*X) / 4 + (Y*Y*Y) / 27, 1.0 / 2.), 1.0 / 3.0) - pow((-(X / 2) - pow((X*X) / 4 + (Y*Y*Y) / 27, 1.0 / 2.0)) * (-1), 1.0 / 3.0);
return exp(argExpo);
}
After 3 days of work, I know why this equation does not work on arduino : overflowing.
Some parts of the equation create float too large for this board model (Arduino Uno).
One of the solutions is to rephrase the equation to prevent bigger results. But this solution takes too much time and need good mathematical skills, that's why I decided to move the equation in an external API.