numpy.arctan2(x1, x2, /, out=None, *, where=True, casting='same_kind', order='K', dtype=None, subok=True[, signature, extobj]) = ufunc 'arctan2'
ycoordinates.
xcoordinates.
If x1.shape != x2.shape
, they must be broadcastable to a common
shape (which becomes the shape of the output).
A location into which the result is stored. If provided, it must have a shape that the inputs broadcast to. If not provided or None, a freshlyallocated array is returned. A tuple (possible only as a keyword argument) must have length equal to the number of outputs.
This condition is broadcast over the input. At locations where the
condition is True, the out array will be set to the ufunc result.
Elsewhere, the out array will retain its original value.
Note that if an uninitialized out array is created via the default
out=None
, locations within it where the condition is False will
remain uninitialized.
For other keywordonly arguments, see the ufunc docs.
Array of angles in radians, in the range [pi, pi]
.
This is a scalar if both x1 and x2 are scalars.
NumPy arctan2
function helps us to calculate the arc tan value between X1 and X2 in radians. Here, X1 and 2 are parameters that we will discuss later. As we progress through this article, things will become clearer for you. Next, let's look at the syntax associated with it.
The method numpy.arctan2() calculates the elementwise arctangent ofArctan2 is a 4quadrant inverse function. Taking this into account, it gives a value between 0 and 2pi. The range of this function is 180 to 180 degrees. These are the 2 key points that distinguish Arctan2 from arctan features.arr1
/arr2
and selects the quadrant correctly. The quadrant is chosen so thatarctan2(x1, x2)
is the signed angle in radians between the ray ending at the origin and passing through point(1, 0)
and the ray ending at the origin and passing through point(x2, x1)
.
NumPy arctan  NumPy arctan2 
arctan is a 2 quadrant inverse function.  arctan2 is a 4 quadrant inverse function. 
The range of the arctan function is from 90 to 90 degree.  The range for arctan2 is 180 to 180 degree. 
This function accepts a single array.  This function as discussed take 2 input arrays. 
import numpy as ppool y=[1,1] x=[1,1.732] print(ppool.arctan2(y,x)) [0.78539816 0.52361148]Above we see a simple example of our arctan2 function. Now let's walk line by line and understand how we got the result. First, we imported the NumPy function. Then we defined our 2 sets of the array. By using the syntax of our function and the print statement, we get the result we want. Here both values are given in radians. Now if you want to check the result to some extent. To do this, we need to use this particular method:
Angle in degree = angle in radian * 180/pi
import numpy as ppool degree=0 y=[1,1.732] x=[2,1] b=ppool.arctan2(y,x) print(b) for vals in b: degree=vals*(180/3.14) print(degree)
[0.46364761 1.04718485] 26.578525356734104 60.02970472117416See how we get the values in radians and degrees. All steps are similar to the first example. The only difference we used a "for loop". If you want something simpler we can also use another method
import numpy as ppool y=[1,1.732] x=[2,1] b=ppool.arctan2(y,x)*(180/3.14) print(b)Here all you need to do is multiply the value (180 / 3.14) or (180 / ppool.pi) by the array. You can definitely use this method on the for loop method. But either way, you will get the desired output which is a degree value.
[26.57852536 60.02970472]
def doa(self, receiver, source): ''' Computes the direction of arrival wrt a source and receiver ''' s_ind = self.key2ind(source) r_ind = self.key2ind(receiver) # vector from receiver to source v = self.X[:,s_ind]  self.X[:,r_ind] azimuth =np.arctan2
(v[1], v[0]) elevation =np.arctan2
(v[2], la.norm(v[:2])) azimuth = azimuth + 2*np.pi if azimuth < 0. else azimuth elevation = elevation + 2*np.pi if elevation < 0. else elevation return np.array([azimuth, elevation])
def mtx_freq2visi(M, p_mic_x, p_mic_y):
"""
build the matrix that maps the Fourier series to the visibility
:param M: the Fourier series expansion is limited from M to M
:param p_mic_x: a vector that constains microphones x coordinates
:param p_mic_y: a vector that constains microphones y coordinates
:return:
"""
num_mic = p_mic_x.size
ms = np.reshape(np.arange(M, M + 1, step=1), (1, 1), order='F')
G = np.zeros((num_mic * (num_mic  1), 2 * M + 1), dtype=complex, order='C')
count_G = 0
for q in range(num_mic):
p_x_outer = p_mic_x[q]
p_y_outer = p_mic_y[q]
for qp in range(num_mic):
if not q == qp:
p_x_qqp = p_x_outer  p_mic_x[qp]
p_y_qqp = p_y_outer  p_mic_y[qp]
norm_p_qqp = np.sqrt(p_x_qqp ** 2 + p_y_qqp ** 2)
phi_qqp = np.arctan2
(p_y_qqp, p_x_qqp)
G[count_G, :] = (1j) ** ms * sp.special.jv(ms, norm_p_qqp) * \
np.exp(1j * ms * phi_qqp)
count_G += 1
return G
def vector_angle(u, v, direction=None): ''' vector_angle(u, v) yields the angle between the two vectors u and v. The optional argument direction is by default None, which specifies that the smallest possible angle between the vectors be reported; if the vectors u and v are 2D vectors and direction parameters True and False specify the clockwise or counterclockwise directions, respectively; if the vectors are 3D vectors, then direction may be a 3D point that is not in the plane containing u, v, and the origin, and it specifies around which direction (u x v or v x u) the the counterclockwise angle from u to v should be reported (the cross product vector that has a positive dot product with the direction argument is used as the rotation axis). ''' if direction is None: return np.arccos(vector_angle_cos(u, v)) elif direction is True: returnnp.arctan2
(v[1], v[0])  np.arctan2(u[1], u[0]) elif direction is False: returnnp.arctan2
(u[1], u[0])  np.arctan2(v[1], v[0]) else: axis1 = normalize(u) axis2 = normalize(np.cross(u, v)) if np.dot(axis2, direction) < 0: axis2 = axis2 returnnp.arctan2
(np.dot(axis2, v), np.dot(axis1, v))
def __init__(self, line):
data = line.split(' ')
data[1:] = [float(x) for x in data[1:]]
self.classname = data[0]
self.xmin = data[1]
self.ymin = data[2]
self.xmax = data[1]+data[3]
self.ymax = data[2]+data[4]
self.box2d = np.array([self.xmin,self.ymin,self.xmax,self.ymax])
self.centroid = np.array([data[5],data[6],data[7]])
self.unused_dimension = np.array([data[8],data[9],data[10]])
self.w = data[8]
self.l = data[9]
self.h = data[10]
self.orientation = np.zeros((3,))
self.orientation[0] = data[11]
self.orientation[1] = data[12]
self.heading_angle = 1 * np.arctan2
(self.orientation[1], self.orientation[0])
def stanleyControl(state, cx, cy, cyaw, last_target_idx):
"""
:param state: (State object)
:param cx: ([float])
:param cy: ([float])
:param cyaw: ([float])
:param last_target_idx: (int)
:return: (float, int, float)
"""
# Cross track error
current_target_idx, error_front_axle = calcTargetIndex(state, cx, cy)
if last_target_idx >= current_target_idx:
current_target_idx = last_target_idx
# theta_e corrects the heading error
theta_e = normalizeAngle(cyaw[current_target_idx]  state.yaw)
# theta_d corrects the cross track error
theta_d = np.arctan2
(K_STANLEY_CONTROL * error_front_axle, state.v)
# Steering control
delta = theta_e + theta_d
return delta, current_target_idx, error_front_axle
def calcTargetIndex(state, cx, cy):
"""
:param state: (State object)
:param cx: [float]
:param cy: [float]
:return: (int, float)
"""
# Calc front axle position
fx = state.x + CAR_LENGTH * np.cos(state.yaw)
fy = state.y + CAR_LENGTH * np.sin(state.yaw)
# Search nearest point index
dx = [fx  icx for icx in cx]
dy = [fy  icy for icy in cy]
d = [np.sqrt(idx ** 2 + idy ** 2) for (idx, idy) in zip(dx, dy)]
error_front_axle = min(d)
target_idx = d.index(error_front_axle)
target_yaw = normalizeAngle(np.arctan2
(fy  cy[target_idx], fx  cx[target_idx])  state.yaw)
if target_yaw > 0.0:
error_front_axle =  error_front_axle
return target_idx, error_front_axle
def vehicle_flat_reverse(zflag, params={}): # Get the parameter values b = params.get('wheelbase', 3.) # Create a vector to store the state and inputs x = np.zeros(3) u = np.zeros(2) # Given the flat variables, solve for the state x[0] = zflag[0][0] # x position x[1] = zflag[1][0] # y position x[2] =np.arctan2
(zflag[1][1], zflag[0][1]) # tan(theta) = ydot/xdot # And next solve for the inputs u[0] = zflag[0][1] * np.cos(x[2]) + zflag[1][1] * np.sin(x[2]) thdot_v = zflag[1][2] * np.cos(x[2])  zflag[0][2] * np.sin(x[2]) u[1] =np.arctan2
(thdot_v, u[0]**2 / b) return x, u # Function to compute the RHS of the system dynamics
def GetNeighborCells(self, p, nr, dp = None): ''' Returns all cells no more than a given distance in any direction from a specified cell p: The cell of which to get the neighbors nr: Neighbor radius dp: Direction preference ''' pi, pj, pk = p tqm = self.qm * self.qp nc = [(pi  i * tqm, pj  j * tqm, pk) for i in range(nr, nr + 1) for j in range(nr, nr + 1)] if dp is not None: #Sort points based on direction preference dpa =In this article, we cover NumPy's arctan2. In addition, we also saw its syntax and parameters. For better understanding, we saw some examples. In the end, we can conclude that NumPy arctan2 is a function that this function helps us to find the inverse tan value between 2 points. By default it returns the value in radians, but we can convert it to degrees using the methods discussed above. We hope this article has clarified all your doubts. But in case you have any unresolved questions, feel free to write them down in the comments section. Having read that, why not read about the following identity matrix.np.arctan2
(dp[1], dp[0]) #Get angle of direction prefered #Prefer directions in the direction of dp; sort based on magnitude of angle from last direction nc = sorted(nc, key = lambda t : np.abs(np.arctan2
(t[1], t[0])  dpa)) return nc #Gets the current 3d position of the player
My formula f=arctan(ImZ/ReZ)
There are two options:
Option 1 (atan):
ImZ=4.593172163003
ImR=4.297336384845
>>> z=y/x
>>> f1=math.atan(z)
>>> f1
0.8186613519278327
Option 2 (atan2)
>>> f=math.atan2(y,x)
>>> f
2.3229313016619604
Why are these two results different?
Atan takes single argument and Atan2 takes two arguments.The purpose of using two arguments instead of one is to gather information on the signs of the inputs in order to return the appropriate quadrant of the computed angle, which is not possible for the singleargument Atan
Atan2 result is always between pi and pi.
Reference: https://en.wikipedia.org/wiki/Atan2
numpy.arctan2 (arr1, arr2, casting = & # 39; same_kind & # 39 ;, order = & # 39; K & # 39 ;, dtype = None, ufunc & # 39; arctan & # 39;) :
Calculates the elementwise arctangent of arr1 / arr2 by choosing the correct quadrant. The quadrant is chosen so that arctan2 (x1, x2) is the angle sign in radians between a ray ending at the origin and passing through point (1, 0) and a ray ending at the origin and passing through through point (x2) x1).
Parameters:
arr1: [array_like] real valued; ycoordinates
arr2: [array_like] real valued; xcoordinates. It must match shape of ycordinates.
out: [ndarray, array_like [ OPTIONAL ]] array of same shape as x .
where: [array_like, optional] True value means to calculate the universal functions (ufunc) at that position, False value means to leave the value in the output alone.Note:
2pi Radians = 360 degrees
The convention is to return the angle z whose real part lies in [pi / 2 , pi / 2].Return: Elementwise arc tangent of arr1 / arr2. The values are in the closed interval [pi / 2, pi / 2].
Code # 1: Work

Output:
xcoordinates: [1, 1, 1, 1] ycoordinates: [1, 1, 1, 1] arctan2 values: [135. 45. 45. 135.]
Code # 2: Work

Output:
a: [0. 3.14159265 0.78539816] b: [1.57079633 1.57079633]
Links:
arctan2.html#numpy.arctan2>https://docs.scipy.org/doc/numpy1.13.0/reference/g enerated / numpy.arctan2.html # numpy.arctan2
,
Update: User cphyc has kindly created a Github repository for the code in this answer (see here), and bundled the code into a package which may be installed using pip install matplotliblabellines
.
Pretty Picture:
In matplotlib
it"s pretty easy to label contour plots (either automatically or by manually placing labels with mouse clicks). There does not (yet) appear to be any equivalent capability to label data series in this fashion! There may be some semantic reason for not including this feature which I am missing.
Regardless, I have written the following module which takes any allows for semiautomatic plot labelling. It requires only numpy
and a couple of functions from the standard math
library.
The default behaviour of the labelLines
function is to space the labels evenly along the x
axis (automatically placing at the correct y
value of course). If you want you can just pass an array of the x coordinates of each of the labels. You can even tweak the location of one label (as shown in the bottom right plot) and space the rest evenly if you like.
In addition, the label_lines
function does not account for the lines which have not had a label assigned in the plot
command (or more accurately if the label contains "_line"
).
Keyword arguments passed to labelLines
or labelLine
are passed on to the text
function call (some keyword arguments are set if the calling code chooses not to specify).
1
and 10
annotations in the top left plot. I"m not even sure this can be avoided.y
position instead sometimes.x
axis values are float
slabelLines
function assumes that all data series span the range specified by the axis limits. Take a look at the blue curve in the top left plot of the pretty picture. If there were only data available for the x
range 0.5
1
then then we couldn"t possibly place a label at the desired location (which is a little less than 0.2
). See this question for a particularly nasty example. Right now, the code does not intelligently identify this scenario and rearrange the labels, however there is a reasonable workaround. The labelLines function takes the xvals
argument; a list of x
values specified by the user instead of the default linear distribution across the width. So the user can decide which x
values to use for the label placement of each data series.Also, I believe this is the first answer to complete the bonus objective of aligning the labels with the curve they"re on. :)
label_lines.py:
from math import atan2,degrees
import numpy as np
#Label line with line2D label data
def labelLine(line,x,label=None,align=True,**kwargs):
ax = line.axes
xdata = line.get_xdata()
ydata = line.get_ydata()
if (x < xdata[0]) or (x > xdata[1]):
print("x label location is outside data range!")
return
#Find corresponding y coordinate and angle of the line
ip = 1
for i in range(len(xdata)):
if x < xdata[i]:
ip = i
break
y = ydata[ip1] + (ydata[ip]ydata[ip1])*(xxdata[ip1])/(xdata[ip]xdata[ip1])
if not label:
label = line.get_label()
if align:
#Compute the slope
dx = xdata[ip]  xdata[ip1]
dy = ydata[ip]  ydata[ip1]
ang = degrees(atan2(dy,dx))
#Transform to screen coordinates
pt = np.array([x,y]).reshape((1,2))
trans_angle = ax.transData.transform_angles(np.array((ang,)),pt)[0]
else:
trans_angle = 0
#Set a bunch of keyword arguments
if "color" not in kwargs:
kwargs["color"] = line.get_color()
if ("horizontalalignment" not in kwargs) and ("ha" not in kwargs):
kwargs["ha"] = "center"
if ("verticalalignment" not in kwargs) and ("va" not in kwargs):
kwargs["va"] = "center"
if "backgroundcolor" not in kwargs:
kwargs["backgroundcolor"] = ax.get_facecolor()
if "clip_on" not in kwargs:
kwargs["clip_on"] = True
if "zorder" not in kwargs:
kwargs["zorder"] = 2.5
ax.text(x,y,label,rotation=trans_angle,**kwargs)
def labelLines(lines,align=True,xvals=None,**kwargs):
ax = lines[0].axes
labLines = []
labels = []
#Take only the lines which have labels other than the default ones
for line in lines:
label = line.get_label()
if "_line" not in label:
labLines.append(line)
labels.append(label)
if xvals is None:
xmin,xmax = ax.get_xlim()
xvals = np.linspace(xmin,xmax,len(labLines)+2)[1:1]
for line,x,label in zip(labLines,xvals,labels):
labelLine(line,x,label,align,**kwargs)
Test code to generate the pretty picture above:
from matplotlib import pyplot as plt
from scipy.stats import loglaplace,chi2
from labellines import *
X = np.linspace(0,1,500)
A = [1,2,5,10,20]
funcs = [np.arctan,np.sin,loglaplace(4).pdf,chi2(5).pdf]
plt.subplot(221)
for a in A:
plt.plot(X,np.arctan(a*X),label=str(a))
labelLines(plt.gca().get_lines(),zorder=2.5)
plt.subplot(222)
for a in A:
plt.plot(X,np.sin(a*X),label=str(a))
labelLines(plt.gca().get_lines(),align=False,fontsize=14)
plt.subplot(223)
for a in A:
plt.plot(X,loglaplace(4).pdf(a*X),label=str(a))
xvals = [0.8,0.55,0.22,0.104,0.045]
labelLines(plt.gca().get_lines(),align=False,xvals=xvals,color="k")
plt.subplot(224)
for a in A:
plt.plot(X,chi2(5).pdf(a*X),label=str(a))
lines = plt.gca().get_lines()
l1=lines[1]
labelLine(l1,0.6,label=r"$Re=${}".format(l1.get_label()),ha="left",va="bottom",align = False)
labelLines(lines[:1],align=False)
plt.show()
First find the difference between the start point and the end point (here, this is more of a directed line segment, not a "line", since lines extend infinitely and don"t start at a particular point).
deltaY = P2_y  P1_y
deltaX = P2_x  P1_x
Then calculate the angle (which runs from the positive X axis at P1
to the positive Y axis at P1
).
angleInDegrees = arctan(deltaY / deltaX) * 180 / PI
But arctan
may not be ideal, because dividing the differences this way will erase the distinction needed to distinguish which quadrant the angle is in (see below). Use the following instead if your language includes an atan2
function:
angleInDegrees = atan2(deltaY, deltaX) * 180 / PI
EDIT (Feb. 22, 2017): In general, however, calling atan2(deltaY,deltaX)
just to get the proper angle for cos
and sin
may be inelegant. In those cases, you can often do the following instead:
(deltaX, deltaY)
as a vector.deltaX
and deltaY
by the vector"s length (sqrt(deltaX*deltaX+deltaY*deltaY)
), unless the length is 0.deltaX
will now be the cosine of the angle between the vector and the horizontal axis (in the direction from the positive X to the positive Y axis at P1
).deltaY
will now be the sine of that angle.EDIT (Feb. 28, 2017): Even without normalizing (deltaX, deltaY)
:
deltaX
will tell you whether the cosine described in step 3 is positive or negative.deltaY
will tell you whether the sine described in step 4 is positive or negative.deltaX
and deltaY
will tell you which quadrant the angle is in, in relation to the positive X axis at P1
:
+deltaX
, +deltaY
: 0 to 90 degrees.deltaX
, +deltaY
: 90 to 180 degrees.deltaX
, deltaY
: 180 to 270 degrees (180 to 90 degrees).+deltaX
, deltaY
: 270 to 360 degrees (90 to 0 degrees).An implementation in Python using radians (provided on July 19, 2015 by Eric Leschinski, who edited my answer):
from math import *
def angle_trunc(a):
while a < 0.0:
a += pi * 2
return a
def getAngleBetweenPoints(x_orig, y_orig, x_landmark, y_landmark):
deltaY = y_landmark  y_orig
deltaX = x_landmark  x_orig
return angle_trunc(atan2(deltaY, deltaX))
angle = getAngleBetweenPoints(5, 2, 1,4)
assert angle >= 0, "angle must be >= 0"
angle = getAngleBetweenPoints(1, 1, 2, 1)
assert angle == 0, "expecting angle to be 0"
angle = getAngleBetweenPoints(2, 1, 1, 1)
assert abs(pi  angle) <= 0.01, "expecting angle to be pi, it is: " + str(angle)
angle = getAngleBetweenPoints(2, 1, 2, 3)
assert abs(angle  pi/2) <= 0.01, "expecting angle to be pi/2, it is: " + str(angle)
angle = getAngleBetweenPoints(2, 1, 2, 0)
assert abs(angle  (pi+pi/2)) <= 0.01, "expecting angle to be pi+pi/2, it is: " + str(angle)
angle = getAngleBetweenPoints(1, 1, 2, 2)
assert abs(angle  (pi/4)) <= 0.01, "expecting angle to be pi/4, it is: " + str(angle)
angle = getAngleBetweenPoints(1, 1, 2, 2)
assert abs(angle  (pi+pi/4)) <= 0.01, "expecting angle to be pi+pi/4, it is: " + str(angle)
angle = getAngleBetweenPoints(1, 1, 1, 2)
assert abs(angle  (pi/2)) <= 0.01, "expecting angle to be pi/2, it is: " + str(angle)
All tests pass. See https://en.wikipedia.org/wiki/Unit_circle
Sorry EMS, but I actually just got another response from the matplotlib mailling list (Thanks goes out to Benjamin Root).
The code I am looking for is adjusting the savefig call to:
fig.savefig("samplefigure", bbox_extra_artists=(lgd,), bbox_inches="tight")
#Note that the bbox_extra_artists must be an iterable
This is apparently similar to calling tight_layout, but instead you allow savefig to consider extra artists in the calculation. This did in fact resize the figure box as desired.
import matplotlib.pyplot as plt
import numpy as np
plt.gcf().clear()
x = np.arange(2*np.pi, 2*np.pi, 0.1)
fig = plt.figure(1)
ax = fig.add_subplot(111)
ax.plot(x, np.sin(x), label="Sine")
ax.plot(x, np.cos(x), label="Cosine")
ax.plot(x, np.arctan(x), label="Inverse tan")
handles, labels = ax.get_legend_handles_labels()
lgd = ax.legend(handles, labels, loc="upper center", bbox_to_anchor=(0.5,0.1))
text = ax.text(0.2,1.05, "Aribitrary text", transform=ax.transAxes)
ax.set_title("Trigonometry")
ax.grid("on")
fig.savefig("samplefigure", bbox_extra_artists=(lgd,text), bbox_inches="tight")
This produces:
[edit] The intent of this question was to completely avoid the use of arbitrary coordinate placements of arbitrary text as was the traditional solution to these problems. Despite this, numerous edits recently have insisted on putting these in, often in ways that led to the code raising an error. I have now fixed the issues and tidied the arbitrary text to show how these are also considered within the bbox_extra_artists algorithm.
Last time I checked it, the scipy __init__
method executes a
from numpy import *
so that the whole numpy namespace is included into scipy when the scipy module is imported.
The log10
behavior you are describing is interesting, because both versions are coming from numpy. One is a ufunc
, the other is a numpy.lib
function. Why scipy is preferring the library function over the ufunc
, I don"t know off the top of my head.
EDIT: In fact, I can answer the log10
question. Looking in the scipy __init__
method I see this:
# Import numpy symbols to scipy name space
import numpy as _num
from numpy import oldnumeric
from numpy import *
from numpy.random import rand, randn
from numpy.fft import fft, ifft
from numpy.lib.scimath import *
The log10
function you get in scipy comes from numpy.lib.scimath
. Looking at that code, it says:
"""
Wrapper functions to more userfriendly calling of certain math functions
whose output datatype is different than the input datatype in certain
domains of the input.
For example, for functions like log() with branch cuts, the versions in this
module provide the mathematically valid answers in the complex plane:
>>> import math
>>> from numpy.lib import scimath
>>> scimath.log(math.exp(1)) == (1+1j*math.pi)
True
Similarly, sqrt(), other base logarithms, power() and trig functions are
correctly handled. See their respective docstrings for specific examples.
"""
It seems that module overlays the base numpy ufuncs for sqrt
, log
, log2
, logn
, log10
, power
, arccos
, arcsin
, and arctanh
. That explains the behavior you are seeing. The underlying design reason why it is done like that is probably buried in a mailing list post somewhere.
Python Workout isn’t designed to teach you Python, although I hope and expect that you’ll learn quite a bit along the way. It is meant to help you improve your understand ing of Python and how to...
23/09/2020
Taking into account the development of modern programming, especially the emerging programming languages that reflect modern practice, Numerical Programming: A Practical Guide for Scientists and...
08/08/2021
This book project was first presented to me during my first week in my current role of managing the data mining development at SAS. Writ ing a book has always been a bucket‐list item, and I was ver...
10/07/2020
I have developed this book to investigate Mesosbased cluster development and integration. I found that data center operating system (DCOS; and it’s commandline interface [CLI]) was a natural progr...
10/07/2020