Edited at

# geometry > calculate polar and azimuth angles from (x,y,z) vector > Equations and Numpy Implementation > polarAzimuthCalc_171209.py > v0.1..v0.3

More than 1 year has passed since last update.

Environment

GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 16.04 LTS desktop amd64
TensorFlow v1.2.1
cuDNN v5.1 for Linux
CUDA v8.0
Python 3.5.2
IPython 6.0.0 -- An enhanced Interactive Python.
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
scipy v0.19.1
geopandas v0.3.0
MATLAB R2017b (Home Edition)


The equation of gamma is modified to use arctan2().

In addition, the code is modified (refactored) a little.

We introduce the calculation of the zenith and azimuth angles from a (x,y,z) vector.

The zenith angle is in [0, pi) and the azimuth is in [0, 2pi), where [ and ( denote open and closed, respectively.

## Equations

### Definition of the zenith and azimuth angles

We define the zenith and azimuth angles as $\beta$ and $\gamma$.

The (x,y,z) and the ($\beta$ and $\gamma$) is related as follows:

x = cos\gamma sin\beta ... (1) \\
y = sin\gamma sin\beta ... (2) \\
z = cos\beta ...(3)


### Definition of the directions

We define $\beta$ and $\gamma$ as follows in terms of the directions.

• for $\beta$ = 0

• x = 0, y = 0, z = 1

• > corresponds to z axis

• for $\gamma$ = 0

• x = $sin\beta$

• y = 0

• (z = $cos\beta$)

• > corresponds to x axis in (x,y) plane

### Equation of beta

From Eq.(3)

\beta = arccos(z) ... (4)


By using numpy.arccos(), the range of beta is [0, pi).

### Equation of gamma

From Eq.(2) divided by Eq.(1)

\frac{y}{x} = \frac{\sin\gamma}{\cos\gamma} = tan\gamma ... (5.1)


\gamma = arctan(\frac{y}{x}) ... (5.2)


numpy.arctan2() returns values in [-pi, pi).

The value is converted to [0, 2pi) for the convenience of the later data processing.

## Numpy Implemantation v0.1..v0.3

polarAzimuthCalc_171209.py

import numpy as np
import sys

'''
v0.3 Dec. 17, 2017
- refactor > add function comment
v0.2 Dec. 10, 2017
- fix bug: calc_gamma_rad() was too complicated
_+ use arctan2()
v0.1 Dec. 09, 2017
'''

'''
polar angle [0, pi]
'''
return np.arccos(pvec[2])  # arccos:[0, pi]

'''
azimuth angle [0, 2pi]
'''
gamma = np.arctan2(pvec[1], pvec[0])
if gamma < 0.0:
gamma += 2 * np.pi
return gamma

def Test_group_run_axes():
pvecs = [
[0, 0, 1],  # z direction
[0, 0, -1],  # z direction
[0, 1, 0],  # y direction
[0, -1, 0],  # y direction
[1, 0, 0],  # x direction
[-1, 0, 0],  # x direction
]
for elem in pvecs:

fmt = "{0} \tbeta:{1:.5f} gamma:{2:.5f}"
print(msg)

return resx, resy, resz

def Test_group_run_random():
bt_stp = np.pi / 4.0  # beta step
gm_stp = np.pi / 4.0  # gamma step
for bt_in in np.arange(0.0, np.pi, bt_stp):
for gm_in in np.arange(0.0, 2 * np.pi, gm_stp):
# print(bt_in, gm_in)
wrk = Test_calc_xyz(bt_in, gm_in)
if abs(gm_in - gm_out) > sys.float_info.epsilon:
print("%+.5e" % (gm_in - gm_out), end=' ')
print("NG:", end=" ")
else:
continue
msg = ','.join("%+.5f" % elem for elem in wrk)
print(msg, end=' -- ')
fmt = "b{0:.5f} b{1:.5f} g{2:.5f} g{3:.5f}"
msg = fmt.format(bt_in, bt_out, gm_in, gm_out)
print(msg)

if __name__ == '__main__':
Test_group_run_random()
#Test_group_run_axes()



### Run example

The above code executes the Test_group_run_random().

In the Test_group_run_random(), $\beta$ and $\gamma$ are taken evenly in the each dimension.

\$ python3 polarAzimuthCalc_171209.py
+7.85398e-01 NG: +0.00000,+0.00000,+1.00000 -- b0.00000 b0.00000 g0.78540 g0.00000
+1.57080e+00 NG: +0.00000,+0.00000,+1.00000 -- b0.00000 b0.00000 g1.57080 g0.00000
-7.85398e-01 NG: -0.00000,+0.00000,+1.00000 -- b0.00000 b0.00000 g2.35619 g3.14159
+7.85398e-01 NG: -0.00000,-0.00000,+1.00000 -- b0.00000 b0.00000 g3.92699 g3.14159
+1.57080e+00 NG: -0.00000,-0.00000,+1.00000 -- b0.00000 b0.00000 g4.71239 g3.14159
+5.49779e+00 NG: +0.00000,-0.00000,+1.00000 -- b0.00000 b0.00000 g5.49779 g-0.00000
+4.44089e-16 NG: -0.50000,-0.50000,+0.70711 -- b0.78540 b0.78540 g3.92699 g3.92699
+4.44089e-16 NG: -0.70711,-0.70711,+0.00000 -- b1.57080 b1.57080 g3.92699 g3.92699


There are several errors.

• (0, 0, 1) returns gamma errors

• Since the value of gamma is degenerated

• error of 4.4e-16 in the last two lines

• sys.float_info_epsilon is 2.220e-16

• the errors (4.4e-16) is twice of the sys.float_info_epsilon

https://stackoverflow.com/questions/9528421/value-for-epsilon-in-python

answered Mar 2 '12 at 5:51

Ergwun

But don't forget the pitfalls of using it as an absolute error margin for floating point comparisons. E.g. for large numbers, rounding error could exceed epsilon.

Maybe, pitfalls...