Fill area between two curves in python - python

I am trying to shade the area between two curves that I have plotted.
This is what I plotted.
Using the following code.
plt.scatter(z1,y1, s = 0.5, color = 'blue')
plt.scatter(z2,y2, s = 0.5, color = 'orange')
I tried using plt.fill_between() but for this to work I need to have the same data on the x_axis (would need to do something like plt.fill_between(x,y1,y2)).
Is there any other function that might help with this or am I just using fill_between wrong.

You can try with:
plt.fill(np.append(z1, z2[::-1]), np.append(y1, y2[::-1]), 'lightgrey')
For example:
import numpy as np
import matplotlib.pyplot as plt
x1 = np.array([1,2,3])
y1 = np.array([2,3,4])
x2 = np.array([2,3,4,5,6])
y2 = np.array([1,2,3,4,5])
# plt.plot(x1, y1, 'o')
# plt.plot(x2, y2, 'x')
plt.scatter(x1, y1, s = 0.5, color = 'blue')
plt.scatter(x2, y2, s = 0.5, color = 'orange')
plt.fill(np.append(x1, x2[::-1]), np.append(y1, y2[::-1]), 'lightgrey')
plt.show()

Try this code:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0.0, 2, 0.01)
y1 = np.sin(2 * np.pi * x)
y2 = 1.2 * np.sin(4 * np.pi * x)
fig, (ax1) = plt.subplots(1, sharex=True)
ax1.fill_between(x, 0, y1)
ax1.set_ylabel('between y1 and 0')

Related

Plot minimum of two arrays

I have two arrays for x-values and two corresponding arrays for y-values which I wish to plot.
import numpy as np
import matplotlib.pyplot as plt
x1 = np.linspace(-2,2,100)
x2 = np.linspace(0,4,100)
y1 = x1**2+1
y2 = (x2-1.5)**2
plt.plot(x1,y1)
plt.plot(x2,y2)
plt.show()
This produces the following plot.
But instead of this, I want to plot only the minima of these two curves, i.e. only the region of y1 where y1<y2 and only the region of y2 where y2<y1. Something like this.
Since x1 and x2 are different, I can't use np.minimum(). Is there an efficient way to do this with numpy and/or matplotlib?
I would like to have a general approach that also works when y1 and y2 are not determined from some function I know, but are taken from e.g. a dataset.
You could interpolate both functions onto a common x, and then take their minimum.
import numpy as np
import matplotlib.pyplot as plt
x1 = np.linspace(-2, 2, 100)
x2 = np.linspace(0, 4, 100)
y1 = x1 ** 2 + 1
y2 = (x2 - 1.5) ** 2
plt.plot(x1, y1, ls=':')
plt.plot(x2, y2, ls=':')
xc = np.sort(np.concatenate([x1, x2]))
y1c = np.interp(xc, x1, y1, left=y2.max(), right=y2.max())
y2c = np.interp(xc, x2, y2, left=y1.max(), right=y1.max())
plt.plot(xc, np.minimum(y1c, y2c), lw=10, alpha=0.4)
plt.show()
One solution is to cross compute the functions with the other xs and mask:
import numpy as np
import matplotlib.pyplot as plt
x1 = np.linspace(-2,2,100)
x2 = np.linspace(0,4,100)
y1 = x1**2+1
y1b = x2**2+1
y2 = (x2-1.5)**2
y2b = (x1-1.5)**2
plt.plot(x1, np.where(y1<y2b, y1, np.nan))
plt.plot(x2, np.where(y2<y1b, y2, np.nan))
plt.show()
output:

Finding intersection of two graphs with different numpy sizes

I would like to find the intersection of two graphs. It took me 674 points to plot the first graph and only 14 points to plot the second graph.
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
df = pd.read_csv("test1.csv",,skiprows=range(9),names=['A', 'B', 'C','D'])
df2 = pd.read_csv("test2.csv",skiprows=range(1),names=['X','Y'])
x1 = df['A'].tolist()
x1 = np.array(x1)
y1 = df['D'].tolist()
y1 = np.array(y1)
x2 = df2['X'].tolist()
x2 = np.array(x2)
y2 = df2['Y'].tolist()
y2 = np.array(y2)
idx = np.argwhere(np.diff(np.sign(y1 - y2))).flatten()
fig, ax = plt.subplots()
ax.plot(x1, y1, 'blue')
ax.plot(x2, y2, 'red')
plt.show()
However, I am getting this error from the code above due to the different sizes of numpy. Any ways I can solve this?
operands could not be broadcast together with shapes (674,) (14,)
You should compute interpolations of both curves with scipy.interpolate.interp1d, then you can calculate indeces of intersection points with the method you used.
I assume you have two curves with x1, x2, y1 and y2 coordinates, with different lengths and x axis limits:
x1 = np.linspace(-2, 12, 674)
x2 = np.linspace(0, 8, 14)
y1 = np.sin(x1)
y2 = np.cos(x2) + 1
So, you have to compute interpolation functions:
f1 = interp1d(x1, y1, kind = 'linear')
f2 = interp1d(x2, y2, kind = 'linear')
Then, you need to evaluate new curves on a common x axis, so new curves will have the same length:
xx = np.linspace(max(x1[0], x2[0]), min(x1[-1], x2[-1]), 1000)
y1_interp = f1(xx)
y2_interp = f2(xx)
Finally, you can compute indices of interpolation points as you already did:
idx = np.argwhere(np.diff(np.sign(y1_interp - y2_interp))).flatten()
Complete Code
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
x1 = np.linspace(-2, 12, 674)
x2 = np.linspace(0, 8, 14)
y1 = np.sin(x1)
y2 = np.cos(x2) + 1
f1 = interp1d(x1, y1, kind = 'linear')
f2 = interp1d(x2, y2, kind = 'linear')
xx = np.linspace(max(x1[0], x2[0]), min(x1[-1], x2[-1]), 1000)
y1_interp = f1(xx)
y2_interp = f2(xx)
idx = np.argwhere(np.diff(np.sign(y1_interp - y2_interp))).flatten()
fig, ax = plt.subplots()
ax.plot(x1, y1, 'blue', label = 'y1')
ax.plot(x2, y2, 'red', label = 'y2')
for index in idx:
ax.plot(xx[index], y1_interp[index], marker = 'o', markerfacecolor = 'black', markeredgecolor = 'black')
plt.show()
Plot

Clip a contourf() plot in 3D plot

I'm making multiple density plots in 3D with a circle shape, using contourf.
What I want to do is similar to a clip_path for a pcolormesh plot.
How can I clip the plot in 3D in particular for a contourf plot?
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches
fig = plt.figure()
ax = fig.gca(projection='3d')
x = np.linspace(0, 1, 100)
X, Y = np.meshgrid(x, x)
levels = np.linspace(-0.1, 0.4, 100) #(z_min,z_max,number of contour),
a=0
b=1
c=2
Z1 = a+.1*np.sin(2*X)*np.sin(4*Y)
Z2 = b+.1*np.sin(3*X)*np.sin(4*Y)
Z3 = c+.1*np.sin(4*X)*np.sin(5*Y)
plt.contourf(X, Y,Z1, levels=a+levels,cmap=plt.get_cmap('rainbow'))
plt.contourf(X, Y,Z2, levels=b+levels,cmap=plt.get_cmap('rainbow'))
plt.contourf(X, Y,Z3, levels=c+levels,cmap=plt.get_cmap('rainbow'))
ax.set_xlim3d(0, 1)
ax.set_ylim3d(0, 1)
ax.set_zlim3d(0, 2)
plt.show()
Are you sure your code generated that output image with the given parameters? I only got some blue squares. Tweaking a bit, it starts looking like yours.
To clip the contours, consider masking the Z arrays. As in:
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
import numpy.ma as ma
fig = plt.figure()
ax = fig.gca(projection='3d')
x = np.linspace(0, 1, 100)
X, Y = np.meshgrid(x, x)
levels = np.linspace(-0.1, 0.4, 100) #(z_min,z_max,number of contour),
a = 0
b = 1
c = 2
Z1 = a + .3 * np.sin(2 * X) * np.sin(4 * Y)
Z2 = b + .3 * np.sin(3 * X) * np.sin(4 * Y)
Z3 = c + .3 * np.sin(4 * X) * np.sin(5 * Y)
mask_cond = (X - .5) ** 2 + (Y - .5) ** 2 > .25
Z1 = ma.masked_where(mask_cond, Z1)
Z2 = ma.masked_where(mask_cond, Z2)
Z3 = ma.masked_where(mask_cond, Z3)
plt.contourf(X, Y, Z1, levels=a + levels, cmap='rainbow')
plt.contourf(X, Y, Z2, levels=b + levels, cmap='rainbow')
plt.contourf(X, Y, Z3, levels=c + levels, cmap='rainbow')
ax.set_xlim3d(0, 1)
ax.set_ylim3d(0, 1)
ax.set_zlim3d(0, 3)
plt.show()

How to fill area between two sets of data connected by line?

I have two sets of data that are shown like lines in graph. How to fill with color area between them?
import matplotlib.pyplot as plt
curve1, = plt.plot(xdata, ydata)
curve2, = plt.plot(xdata, ydata)
I tried:
x = np.arange(0,12,0.01)
plt.fill_between(x, curve1, curve2, color='yellow')
Thank you
You have to use the ydata as arguments for your fill_between, not the curves.
Either use ydata directly, or get them from your curve1/2 objects like ydata=curve1.get_ydata().
Here is an example adapted from the docs:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(-5, 5, 0.01)
y1 = -5*x*x + x + 10
y2 = 5*x*x + x
c1, = plt.plot(x, y1, color='black')
c2, = plt.plot(x, y2, color='black')
# If you want/have to get the data form the plots
# x = c1.get_xdata()
# y1 = c1.get_ydata()
# y2 = c2.get_ydata()
plt.fill_between(x, y1, y2, where=y2 >y1, facecolor='yellow', alpha=0.5)
plt.fill_between(x, y1, y2, where=y2 <=y1, facecolor='red', alpha=0.5)
plt.title('Fill Between')
plt.show()
In the end you get:

Bloch Sphere appears for some reasons

I'm trying to draw something called the bloch sphere, but I got its image even when it's not supposed to happen. I wrote the following codes.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from itertools import product, combinations
class quantum_gates:
def __init__(self,x2,y2,z2):
x2 = input("x:")
y2 = input("y:")
z2 = input("z:")
x2 = float(x2)
y2 = float(y2)
z2 = float(z2)
self.x2 = x2
self.y2 = y2
self.z2 = z2
if self.x2**2 + self.y2**2 + self.z2**2 != 1:
print("Wrong input(x^2+y^2+z^2 has to be 1)")
else:
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect("equal")
u, v = np.mgrid[0:2*np.pi:20j, 0:np.pi:10j]
x = np.cos(u)*np.sin(v)
y = np.sin(u)*np.sin(v)
z = np.cos(v)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
ax.plot_wireframe(x, y, z, color="black")
ax.quiver(0,0,0,x2,y2,z2,color="red")
For example, when I put quantum_gates(2,3,1),which is self.x2^2 + self.y2^2 + self.z2^2 != 1, I get the image of the sphere and a red arrow.
What am I supposed to do to get them only when self.x2^2+self^y2+self.z2^2 = 1?

Categories

Resources