这是我在这里的第一个问题,所以请指出我做错了什么。
我正在实现方程式,以计算球角(https://en.wikipedia.org/wiki/Solution_of_triangles#Solving_spherical_triangles)。由于math.acos和np.arccos仅针对[-1,1]定义,因此我要编写try / except语句。在math.acos上效果很好,但我一直在获得
RuntimeWarning:在arccos中遇到无效值
当我使用np.arccos时。因为我想计算一个非常长的文件的球面角,所以我需要np.arccos以便可以得到vectorizarion的好处。关于发生这种情况或如何改进代码的任何想法?
这是我的尝试:
import numpy as np
import math
def spherical_to_cartesian(latr, lonr):
"""Convert a point given latitude and longitude in radians to
3D cartesian coordinates, assuming a sphere radius of one."""
return np.array((
np.cos(latr) * np.cos(lonr),
np.cos(latr) * np.sin(lonr),
np.sin(latr)
))
def angle_between_vectors(u, v):
'Return the angle between two vectors in any dimension space in radians'
return np.arccos(np.dot(u, v) / (np.linalg.norm(u) * np.linalg.norm(v)))
def angle_3pts(p1, p2, p3):
'Convert the points to numpy latitude/longitude radians space'
p1_rad = np.radians(np.array(p1))
p2_rad = np.radians(np.array(p2))
p3_rad = np.radians(np.array(p3))
'The points in 3D cartesian coordinates'
p1_cartesian = spherical_to_cartesian(*p1_rad)
p2_cartesian = spherical_to_cartesian(*p2_rad)
p3_cartesian = spherical_to_cartesian(*p3_rad)
'The angle between vectors'
ang_12 = angle_between_vectors(p1_cartesian, p2_cartesian)
ang_23 = angle_between_vectors(p2_cartesian, p3_cartesian)
ang_31 = angle_between_vectors(p3_cartesian, p1_cartesian)
print(ang_12, ang_23, ang_31)
'''Calculate spherical angle:
https://en.wikipedia.org/wiki/Solution_of_triangles#Solving_spherical_triangles'''
print((np.cos(ang_31) - np.cos(ang_12)*np.cos(ang_23))/(np.sin(ang_12)*np.sin(ang_23)))
try:
angle_3d = np.degrees(np.arccos((np.cos(ang_31) - np.cos(ang_12)*np.cos(ang_23))/(np.sin(ang_12)*np.sin(ang_23))))
except:
angle_3d = 180.
return angle_3d
point1 = (0, 0)
point2 = (0, 10)
point3 = (0, 20)
ang = angle_3pts(point1, point2, point3)
当我在try公式中使用math.acos时,效果很好,但是np.arccos会产生错误
答案 0 :(得分:0)
arccos
是ufunc
,并带有where
和out
参数:
In [226]: x = np.linspace(-2,2,20)
In [227]: np.arccos(x, where=(abs(x)<1), out=np.full_like(x,np.pi))
Out[227]:
array([3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265,
2.8157097 , 2.39918372, 2.12505816, 1.89208492, 1.67625485,
1.4653378 , 1.24950774, 1.01653449, 0.74240893, 0.32588296,
3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265])
这可以指定应跳过哪些输入值,以及使用什么输入值。
与试用版math
相比:
def foo(x):
try:
return math.acos(x)
except ValueError:
return math.pi
In [239]: np.array([foo(i) for i in x])
Out[239]:
array([3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265,
2.8157097 , 2.39918372, 2.12505816, 1.89208492, 1.67625485,
1.4653378 , 1.24950774, 1.01653449, 0.74240893, 0.32588296,
3.14159265, 3.14159265, 3.14159265, 3.14159265, 3.14159265])