'Plotting all of a trigonometric function (x^2 + y^2 == 1) with matplotlib and python

As an exercise in learning Matplotlib and improving my math/coding I decided to try and plot a trigonometric function (x squared plus y squared equals one).

Trigonometric functions are also called "circular" functions but I am only producing half the circle.

#Attempt to plot equation x^2 + y^2 == 1

import numpy as np
import matplotlib.pyplot as plt
import math

x = np.linspace(-1, 1, 21)  #generate np.array of X values -1 to 1 in 0.1 increments
x_sq = [i**2 for i in x]

y = [math.sqrt(1-(math.pow(i, 2))) for i in x]   #calculate y for each value in x
y_sq = [i**2 for i in y]

#Print for debugging / sanity check
for i,j in zip(x_sq, y_sq):
    print('x: {:1.4f}    y: {:1.4f}         x^2: {:1.4f}    y^2: {:1.4f}         x^2 + Y^2 = {:1.4f}'.format(math.sqrt(i), math.sqrt(j), i, j, i+j))

#Format how the chart displays
plt.figure(figsize=(6, 4))
plt.axhline(y=0, color='y')
plt.axvline(x=0, color='y')
plt.grid()

plt.plot(x, y, 'rx')

plt.show()

My plot. It has not negative Y values

I want to plot the full circle. My code only produces the positive y values and I want to plot the full circle.

Here is how the full plot should look. I used Wolfram Alpha to generate it.

The correct implicit contour plot from Wolfram Alpha

Ideally I don't want solutions where the lifting is done for me such as using matplotlib.pyplot.contour. As a learning exercise, I want to "see the working" so to speak. Namely I ideally want to generate all the values and plot them "manually".

The only method I can think of is to re-arrange the equation and generate a set of negative y values with calculated x values then plot them separately. I am sure there is a better way to achieve the outcome and I am sure one of the gurus on Stack Overflow will know what those options are.

Any help will be gratefully received. :-)



Solution 1:[1]

The equation x**2 + y**2 = 1 describes a circle with radius 1 around the origin. But suppose you wouldn't know this already, you can still try to write this equation in polar coordinates,

x = r*cos(phi)
y = r*sin(phi)
(r*cos(phi))**2 + (r*sin(phi))**2 == 1
r**2*(cos(phi)**2 + sin(phi)**2) == 1

Due to the trigonometric identity cos(phi)**2 + sin(phi)**2 == 1 this reduces to

r**2 == 1

and since r should be real,

r == 1

(for any phi).

Plugging this into python:

import numpy as np
import matplotlib.pyplot as plt

phi = np.linspace(0, 2*np.pi, 200)
r = 1
x = r*np.cos(phi)
y = r*np.sin(phi)
plt.plot(x,y)
plt.axis("equal")
plt.show()

enter image description here

Solution 2:[2]

This happens because the square root returns only the positive value, so you need to take those values and turn them into negative values.

You can do something like this:

import numpy as np
import matplotlib.pyplot as plt

r = 1 # radius 
x = np.linspace(-r, r, 1000)
y = np.sqrt(r-x**2)

plt.figure(figsize=(5,5), dpi=100) # figsize=(n,n), n needs to be equal so the image doesn't flatten out
plt.grid(linestyle='-', linewidth=2)
plt.plot(x, y, color='g')
plt.plot(x, -y, color='r')
plt.legend(['Positive y', 'Negative y'], loc='lower right')
plt.axhline(y=0, color='b')
plt.axvline(x=0, color='b')
plt.show()

And that should return this: PLOT

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ImportanceOfBeingErnest
Solution 2 Shiruzui