Cosine distance including radius - python specific - python

In R we have a function, distCosine, within a package Geosphere, here
I am current;y looking to find a similar function in Python, but all I can find is SciPy's implementation here. This does not include the radius.
Is there a Python based working of this R function? Else I have found some to work write out one myself

You can see the source code for the R distCosine function... just write one in python:
from math import acos, sin, cos, pi
def distCosine(p1, p2, r=6378137):
p1 = [p * pi / 180 for p in p1]
p2 = [p * pi / 180 for p in p2]
out = acos(sin(p1[1]) * sin(p2[1]) +\
cos(p1[1]) * cos(p2[1]) *\
cos(p1[0] - p2[0])) * r
return out
distCosine([0, 0], [90, 90])
# 10018754.171394622
You might want to add some error checking of sorts, but this works on the example provided by the R package...

Related

How to solve (x+1)e^x=c(constant) in Python?

I would like to solve the (x+1)e^x=c equation in Python.
The equation has been successfully solved by hand using lambert w functions as depicted in the figure below:
Using same steps, I would like to solve (x+1)e^x programmatically. I have coded it using the module SymPy as per the step shown in the figure above , but without success.
Is there any to solve these kinds of equations in Python?
import numpy as np
from sympy import *
n = symbols('n')
sigmao=0.06866
sigmas=0.142038295
theta=38.9
rad=(np.pi/180)*38.9076
cos=np.cos(rad)
sec=1/np.cos(rad)
out = (0.06*0.7781598455*n*(1-exp(-2*0.42*sec*n))+exp(-2*0.42*n*sec)*sigmas)/sigmao
#Apply diff for the above expression.
fin=diff(out, n)
print(solve(fin,n))
from scipy.optimize import fsolve
import numpy as np
const = 20
def func(x):
return [(x[0]+1) * np.exp(x[0]) - const]
result = fsolve(func, [1])[0]
print('constant: ', const, ', solution: ', result)
#check
print('check: ', (result+1) * np.exp(result))
#Output[]:
constant: 20.0 , solution: 1.9230907433218063
check: 20.0
Preview : https://onlinegdb.com/By8Z2Jwgw
Your expression is very numeric. As sympy's solve tries to find a perfect symbolic solution, sympy gets into troubles.
To find numeric solutions, sympy has nsolve (which allows sympy's expressions but behind the scenes calls mpmath's numeric solver). Unlike solve, here an initial guess is needed:
from sympy import symbols, exp, diff, nsolve, pi, cos
n = symbols('n')
sigmao = 0.06866
sigmas = 0.142038295
theta = 38.9076
rad = (pi / 180) * theta
sec = 1 / cos(rad)
out = (0.06 * 0.7781598455 * n * (1 - exp(-2 * 0.42 * sec * n)) + exp(-2 * 0.42 * n * sec) * sigmas) / sigmao
# Apply diff for the above expression.
fin = diff(out, n)
result = nsolve(fin, n, 1)
print(result, fin.subs(n, result).evalf())
Result: 1.05992379637846 -7.28565300819065e-17
Note that when working with numeric values, you should be very careful to use as many digits as possible to avoid accumulation of errors. Whenever you have an exact expression, it is recommended to leave that expression into the code, instead of replacing it with digits. (Usually, 64 bits or about 16 digits are used in calculations, but for intermediate calculations 80 bits can be taken into account).
To solve the original question with sympy:
from sympy import symbols, Eq, exp, solve
x = symbols('x')
solutions = solve(Eq((x + 1) * exp(x), 20))
for s in solutions:
print(s.evalf())
Result: 1.92309074332181

How to simplify sympy vectors?

I am doing some symbolic vector calculations using sympy, but I can't simplify the arguments of the vector class in a proper way. Consider this code:
from sympy.physics.mechanics import ReferenceFrame, dot, cross
from sympy import symbols, sin, cos, simplify
alpha, theta, l = symbols('alpha theta l')
def Rodrigues(v, k, angle):
return cos(angle) * v + cross(k, v) * sin(angle) + k * dot(k, v) * (1- cos(angle))
N = ReferenceFrame('N')
P0 = -l * N.y
P2 = Rodrigues(
Rodrigues(P0, -N.z, alpha),
Rodrigues(N.x, -N.z, alpha),
theta)
which returns:
trying the simplify(P2) I get the error:
AttributeError: 'function' object has no attribute 'x'
which I think is because the simplify requires a sympy expression object. trying the dir(P2) there is a simplify method which returns:
<bound method Vector.simplify of - l*sin(alpha)*cos(theta)*N.x - l*cos(alpha)*cos(theta)*N.y + (-l*sin(alpha)**2 - l*cos(alpha)**2)*sin(theta)*N.z>
which I have no idea what it is! trying the P2.args I get:
[(Matrix([
[ -l*sin(alpha)*cos(theta)],
[ -l*cos(alpha)*cos(theta)],
[(-l*sin(alpha)**2 - l*cos(alpha)**2)*sin(theta)]]), N)]
which is a 1D List of a 2D tuple with a nested 3x1 sympy Matrix! I don't know whos choice was to make the vector class so obscure, but now I can simplify the last element with simplify(P2.args[0][0][2]) and change the function to:
def Rodrigues(v, k, angle):
tmpVec = cos(angle) * v + cross(k, v) * sin(angle) + k * dot(k, v) * (1- cos(angle))
tmpFrame = tmpVec.args[0][1]
return simplify(tmpVec.args[0][0][0]) * tmpFrame.x + simplify(tmpVec.args[0][0][1]) * tmpFrame.y + simplify(tmpVec.args[0][0][2]) * tmpFrame.z
which to me seems like a very bad solution.
I was wondering if you could help me know if there is a more Pythonic way to do this. For example, force sympy to simplify all expressions by default. Or maybe I'm using the vector.simplify method in a wrong way? Thanks for your support in advance.
P.S. Rodrigues rotation formula
Instead of print(P2.simplify) you need to call this method like print(P2.simplify()). After that you will get - l*sin(alpha)*cos(theta)*N.x - l*cos(alpha)*cos(theta)*N.y - l*sin(theta)*N.z as output which is the same to last version of your def Rodrigues.
An alternative solution is to force sympy to simplify all vectors by default:
from sympy.physics.vector import Vector
Vector.simp = True
more info here

How can I calculate tangent with degrees instead of radians?

I am trying to make a basic tool to make my everyday easier, solving some assignments for me. Unfortunately, I can't figure out how to make it calculate in degrees when tangent is being used.
My code:
import math
class Astro():
def start(self):
velocity = input("What is the galaxy's velocity? (m/s) \n")
peculiar = (float(velocity) - 938600) ** 2
mass = (3 * float(peculiar) * (10 ** 11) * 50 * (10 ** 6) * (8 * (180 / math.pi))
* 9.46 * (10 ** 15)) / (2 * 6.67 * (10 ** -11))
print("The galaxy's mass is " + str(mass) + " kg. \n")
if __name__ == '__main__':
sup = Astro()
sup.start()
EDIT: Sorry for the lack of context; this is about calculating the masses of galaxies using 2 functions, the first one, line 7 to get the peculiar velocity, and the second one in lines 8-9 to get the actual mass of the considered galaxy.
SOLVED: math.tan(8 * pi / 180)
Thank you for all your help!
Computers work in radians. Try
answer = tan(angle * pi / 180)
to use your angle in degrees into a trig function. Or try
answer = atan(number) * 180 / pi
to get answer in degrees.
The math package has the functions radians and degrees but under the hood these are just:
def radians(deg):
return deg * pi / 180
def degrees(rad):
return rad * 180 / pi
Here is a wrapper you can use to make degree-using trig functions (just had it lying around somewhere, although I use numpy instead of math)
import math
import itertools
import functools
def _use_deg(f, arc = False):
if not arc:
def df(*args):
args = list(args)
for index, value in enumerate(args):
try:
args[index] = math.radians(value)
except TypeError:
pass
return f(*args)
else:
def df(*args):
return math.degrees(f(*args))
return functools.wraps(f)(df)
sind = _use_deg(math.sin)
cosd = _use_deg(math.cos)
tand = _use_deg(math.tan)
arcsind = _use_deg(math.asin, True)
arccosd = _use_deg(math.acos, True)
arctand = _use_deg(math.atan, True)
arctan2d = _use_deg(math.atan2, True)
You don't want to get in a fight with the math library. Let the math library give you an answer in radians, then multiply it's answer by 180/math.pi to get degrees.

Nonlinear root finding in numpy from two complex equations

Why it does not calculate properly?
Correct solution is c=25.672 and b2=10.24.
Here solver returns the input values.
Thanks for help!
from numpy import *
from scipy.optimize import *
#UNITS:
psi = 6895.
ft=0.3048
inch=0.0254
psisqin=psi*sqrt(inch)
#DATA:
K_Ict=1500.*psisqin
K_Icb=1700.*psisqin
sigma_2=6700.*psi
sigma_1=6000.*psi
sigma_3=7200.*psi
hp=105.*ft
P = 6500*psi
def f(p):
b2,c= p
F1 = sqrt(pi*c)*(K_Icb-K_Ict)/2 - ( (sigma_2-sigma_1)*sqrt(c**2-b2**2) - (sigma_3-sigma_1)*sqrt(c**2-(hp-b2)**2) )
F2 = sqrt(pi)*(K_Icb+K_Ict)/(2*sqrt(c)) - ( (sigma_2-sigma_1)*arcsin(b2/c) + (sigma_3-sigma_1)*arcsin((hp-b2)/c) - (sigma_2+sigma_3-2*P)*pi/2 )
return (F1,F2)
b2, c = fsolve(f,(16.002,30))
print b2, c
Not entirely sure why but I think it's because you are leaving one of the roots out of the range, so it just returns the boundaries you gave. The true reason depends on whatever method is using to find the roots. The documentation states:
fsolve is a wrapper around MINPACK’s hybrd and hybrj algorithms.
These algorithms are a bit beyond my expertise but you'll find documentation about them easily. This link is one example.
In any case if you change the boundaries to contain both your roots you should obtain the correct results (within a tolerance):
from numpy import *
from scipy.optimize import *
#UNITS:
psi = 6895.
ft=0.3048
inch=0.0254
psisqin=psi*sqrt(inch)
#DATA:
K_Ict=1500*psisqin
K_Icb=1700*psisqin
sigma_2=6700*psi
sigma_1=6000*psi
sigma_3=7200*psi
hp=105.*ft
P = 6500*psi
def f(p):
b2,c= p
F1 = sqrt(pi*c)*(K_Icb-K_Ict)/2
F1 = sqrt(pi*c)*(K_Icb-K_Ict)/2 - ( (sigma_2-sigma_1)*sqrt(c**2-b2**2) - (sigma_3-sigma_1)*sqrt(c**2-(hp-b2)**2) )
F2 = sqrt(pi)*(K_Icb+K_Ict)/(2*sqrt(c)) - ( (sigma_2-sigma_1)*arcsin(b2/c) + (sigma_3-sigma_1)*arcsin((hp-b2)/c) - (sigma_2+sigma_3-2*P)*pi/2 )
return (F1,F2)
b2, c = fsolve(f,(9.002,30))
print(b2, c)
This results in:
10.2613616029 25.63857432

Python - Vincenty's inverse formula not converging (Finding distance between points on Earth)

I'm attempting to implement Vincenty's inverse problem as described on wiki HERE
The problem is that lambda is simply not converging. The value stays the same if I try to iterate over the sequence of formulas, and I'm really not sure why. Perhaps I've just stared myself blind on an obvious problem.
It should be noted that I'm new to Python and still learning the language, so I'm not sure if it's misuse of the language that might cause the problem, or if I do have some mistakes in some of the calculations that I perform. I just can't seem to find any mistakes in the formulas.
Basically, I've written in the code in as close of a format as I could to the wiki article, and the result is this:
import math
# Length of radius at equator of the ellipsoid
a = 6378137.0
# Flattening of the ellipsoid
f = 1/298.257223563
# Length of radius at the poles of the ellipsoid
b = (1 - f) * a
# Latitude points
la1, la2 = 10, 60
# Longitude points
lo1, lo2 = 5, 150
# For the inverse problem, we calculate U1, U2 and L.
# We set the initial value of lamb = L
u1 = math.atan( (1 - f) * math.tan(la1) )
u2 = math.atan( (1 - f) * math.tan(la2) )
L = (lo2 - lo1) * 0.0174532925
lamb = L
while True:
sinArc = math.sqrt( math.pow(math.cos(u2) * math.sin(lamb),2) + math.pow(math.cos(u1) * math.sin(u2) - math.sin(u1) * math.cos(u2) * math.cos(lamb),2) )
cosArc = math.sin(u1) * math.sin(u2) + math.cos(u1) * math.cos(u2) * math.cos(lamb)
arc = math.atan2(sinArc, cosArc)
sinAzimuth = ( math.cos(u1) * math.cos(u2) * math.sin(lamb) ) // ( sinArc )
cosAzimuthSqr = 1 - math.pow(sinAzimuth, 2)
cosProduct = cosArc - ((2 * math.sin(u1) * math.sin(u2) ) // (cosAzimuthSqr))
C = (f//16) * cosAzimuthSqr * (4 + f * (4 - 3 * cosAzimuthSqr))
lamb = L + (1 - C) * f * sinAzimuth * ( arc + C * sinArc * ( cosProduct + C * cosArc * (-1 + 2 * math.pow(cosProduct, 2))))
print(lamb)
As mentioned the problem is that the value "lamb" (lambda) will not become smaller. I've even tried to compare my code to other implementations, but they looked just about the same.
What am I doing wrong here? :-)
Thank you all!
First, you should convert you latitudes in radians too (you already do this for your longitudes):
u1 = math.atan( (1 - f) * math.tan(math.radians(la1)) )
u2 = math.atan( (1 - f) * math.tan(math.radians(la2)) )
L = math.radians((lo2 - lo1)) # better than * 0.0174532925
Once you do this and get rid of // (int divisions) and replace them by / (float divisions), lambda stops repeating the same value through your iterations and starts following this path (based on your example coordinates):
2.5325205864224847
2.5325167509030906
2.532516759118641
2.532516759101044
2.5325167591010813
2.5325167591010813
2.5325167591010813
As you seem to expect a convergence precision of 10^(−12), it seems to make the point.
You can now exit the loop (lambda having converged) and keep going until you compute the desired geodesic distance s.
Note: you can test your final value s here.
Even if it is correctly implemented, Vincenty's algorithm will fail to
converge for some points. (This problem was noted by Vincenty.)
I give an algorithm which is guaranteed to
converge in Algorithms for geodesics; there's a python
implementation available here. Finally, you can find more
information on the problem at the Wikipedia page,
Geodesics on an ellipsoid. (The talk page has examples
of pairs of points for which Vincenty, as implemented by the NGS,
fails to converge.)

Categories

Resources