Matplotlib of plotting implicit function (Max{abs(x1),abs(x2)} <= 1) [duplicate] - python

This question already has answers here:
Is it possible to plot implicit equations using Matplotlib?
(6 answers)
Closed 3 days ago.
How can I use matplotlib to plot the function max{abs(x1),abs(x2)} <= 1 ?
The graph should be like this
enter image description here
I have really no idea.

A standard way to plot an implicit function uses:
a fine grid of x and y positions in some range; this grid can be created by np.meshgrid
a function z of x and y, e.g. z = x**2 + y**2
plt.contourf() between two levels, e.g. between minus infinity and 1, to show the area
plt.contour() with one level to draw one or more curves to indicate that level
import matplotlib.pyplot as plt
import numpy as np
x, y = np.meshgrid(np.linspace(-2, 2, 100), np.linspace(-2, 2, 100))
z = np.maximum(np.abs(x), np.abs(y))
plt.contourf(x, y, z, levels=[-np.inf, 1], colors=['skyblue'], alpha=0.3)
plt.contour(x, y, z, levels=[1], colors=['skyblue'])
plt.axis('equal') # show squares undeformed
plt.tight_layout()
plt.show()

If you just want a square from -1 to 1 in both axes, then you can do:
import matplotlib.pyplot as plt
x = [-1, -1, 1, 1, -1]
y = [-1, 1, 1, -1, -1]
plt.plot(x, y)

Related

Is there any way to express changing color from Matplotlib, Python?

Before you reading, I apologize about broken English.
I have a data array of moving mass, and want to show them by time area.
Like:
import matplotlib.pyplot as plt
import numpy as np
x = np.array([0, 1, 2, 3])
y = np.array([3, 4, 5, 6])
plt.plot(x,y)
In this code, I just want to see them with different color each rows.
For example,
point (0,3) is white dot,
point (3,5) is black dot,
and (1,4) , (2,5) are gray dot but different brightness.
I just started python, so I searched pyplot lib but didn't find examples.
I tried with Seaborn library, and Pyplot 3d examples. But didn't find solution to express what want to do.
If your aim is to identify the order of your points, you can use a colormap, specifying that the vector that determines the coloring is simply the sequence of the indices of the points.
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(20201222)
x = np.random.randint(5, 20, 20)
y = np.random.randint(5, 20, 20)
r = range(len(x))
plt.scatter(x, y, s=80, c=r, cmap='plasma')
plt.grid()
cb = plt.colorbar()
cb.set_ticks(r)
cb.set_ticklabels(("%d"%(order+1) for order in r))
and eventually the very awaited overworked implementation
import numpy as np
import matplotlib.pyplot as plt
from scipy import interpolate
np.random.seed(20201222)
x = np.random.rand(20)*5+np.arange(20)/3
y = np.random.rand(20)*5+np.arange(20)/3
tck, u = interpolate.splprep([x,y] ,s=0.05)
x1, y1 = interpolate.splev(np.linspace(0, 1, 3333), tck)
r = range(len(x))
plt.plot(x1, y1, color='k', lw=0.4, alpha=0.4)
plt.scatter(x, y, s=60, c=r, cmap='Greys', ec='grey', zorder=4)
plt.xlim((0,12)), plt.ylim((0,12))
plt.grid(1)
plt.gca().set_aspect(1)
cb = plt.colorbar()
cb.set_ticks((0, len(x)-1))
cb.set_ticklabels(('First', 'Last'))
Pass a color argument into a scatter function that displays given points and any defined features.
#array declaration
#...
for x1, y1 in zip(x, y):
if x1 == 0:
color = "white"
elif x1 == 1 or x1 == 2:
color = "gray"
elif x1 == 3:
color = "black"
plt.scatter(x1, y1, c=color)
# plot linear line from arrays
We use the zip class to iterate through both arrays at once, allowing us to plot each point from the given arrays. We use the x-coordinates from the x array to determine what color to label the dot. The scatter function puts this point on the graph, giving us options to change features of the given dot(s).
--
The final code would look something like this:
import matplotlib.pyplot as plt
import numpy as np
x = np.array([0, 1, 2, 3])
y = np.array([3, 4, 5, 6])
for x1, y1 in zip(x, y):
if x1 == 0:
color = "white"
elif x1 == 1 or x1 == 2:
color = "gray"
elif x1 == 3:
color = "black"
plt.scatter(x1, y1, c=color)
plt.plot(x, y)
plt.show()
Documentation on matplotlib's scatter function can be found here
poiboi was on the right track. Here's an example which automatically sets a linear gradient for the colours of the dots.
import matplotlib.pyplot as plt
import numpy as np
x = [0, 1, 2, 3]
y = [3, 4, 5, 6]
plt.scatter(x, y, c=x[:: -1], cmap='gray', vmin=min(x), vmax=max(x))
plt.show()
The c keyword argument tells Matplotlib which colour to use for which point using a grey colourmap. By default, said colourmap goes from black to white, so we pass x reversed. vmin and vmax are the least and greatest values to be assigned colours. Note that the first point is white (hence invisible).

How to plot this 2D sinusoidal parametric function

I have a 2D sinusoidal function and I want to plot its boundary threshold of t=0. Could someone give me a hint on how to do it?
f (x, y) = sin(10x) + cos(4y) − cos(3xy)
x ∈ [0, 1], y ∈ [0, 2], with a boundary threshold of t = 0
The expected plot should look like this: Plot A dashed lines
Actually the function I am referring to is a toy one from paper "Active Learning For Identifying Function Threshold Boundaries"(https://papers.nips.cc/paper/2005/file/8e930496927757aac0dbd2438cb3f4f6-Paper.pdf)
Page 4 of that paper
Update: I tried the following code but apparently it does not give what I want. The top view is a straight line from (0,0) to (1,2), instead of some curves...
ax = plt.axes(projection='3d')
# Data for a three-dimensional line
xline = np.linspace(0, 1, 1000)
yline = np.linspace(0, 2, 1000)
zline = np.sin(10*xline)+np.cos(4*yline)-np.cos(3*xline*yline)
ax.plot3D(xline, yline, zline, 'gray')
Welcome to stackoverflow. Your math is wrong. Your function f is a function of two variables, f(x, y). Hence you need to evaluate it on a grid (all combinations of valid x and y values), if you want to find the solutions for f = 0 computationally. Your code is currently evaluating f only on the y = 2x axis (hence the "straight line from (0,0) to (1, 2) in top-down view").
import numpy as np
import matplotlib.pyplot as plt
def f(x, y):
return np.sin(10*x)+np.cos(4*y)-np.cos(3*x*y)
x = np.arange(0, 1, 1e-3)
y = np.arange(0, 2, 1e-3)
XX, YY = np.meshgrid(x, y)
ZZ = f(XX, YY)
plt.contour(XX, YY, ZZ, levels=[0.])
plt.show()

Matplotlob: Plot open interval, connect line to empty circle [duplicate]

This question already has an answer here:
How to plot the lines first and points last in matplotlib
(1 answer)
Closed 3 years ago.
I would like to plot a line that ends in an empty circle. Essentially a visualization of the open interval [0, 1) My attempt is:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 1, 20)
y = 1 + x*2
l, = plt.plot(x[:-1], y[:-1])
plt.scatter(x[-1], y[-1], marker='o', facecolor='none', edgecolor=l.get_color())
Unfortunately, the line does not connect to the circle. Alternatively, I can plot all of plt.plot(x, y), but then the line is inside the circle. What is a nice way of plotting it such that the line touches exactly the circle and does not go further?
I'm looking for an approach that allows me to reproduce this for other lines and does not require a lot of fine-tuning for each use case.
A trick here is that plotting with a white background and raising the z order will plot the circle above the line:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 1, 20)
y = 1 + x*2
l, = plt.plot(x, y) # Change: plot whole series
plt.scatter(
x[-1], y[-1], marker='o',
facecolor='white', # Change: to opaque color
edgecolor=l.get_color(),
linewidth=l.get_linewidth(), # Change: match line width
zorder=10 # Change: raise to higher level.
)
Another solution is to use the newer markevery options to specify where markers go as a list. This way we can use a single plot call:
plt.plot(x, y, 'o',
linestyle='-',
markevery=[-1],
markerfacecolor='white',
markeredgewidth=1.5)
Result:
As an alternative solution you may just increase the number of samples. That also works.
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 1, 100)
y = 1 + x*2
l, = plt.plot(x[:-1], y[:-1])
plt.scatter(x[-1], y[-1], marker='o', facecolor='none', edgecolor=l.get_color())

Add color to line plot in matplotlib depending on given values [duplicate]

This question already has answers here:
How to plot a gradient color line in matplotlib?
(7 answers)
Closed 3 years ago.
So I have a normal scatter plot:
import numpy as np
import matplotlib.pyplot as plt
import random
x = np.random.random_sample((100,))
x = np.sort(x)
y = x + np.sin(np.pi * x)
z = 5 * x
fig = plt.figure()
plot = plt.scatter(x, y, s= 10, c = z, cmap='coolwarm')
fig.colorbar(plot)
plt.grid(True, 'both')
plt.show()
that produces a plot something like this
However, I would really like to add a line to scatter and connect these points. It may sound ridiculous since it is easy to follow the points in given case, but imagine if the data would be more scattered and possibly multiple datasets ...
So my goal is to add a line to the scatter above, but the color of the line should change according to value of 'z', the same way scatter plot does. Is that even possible?
EDIT:
The x, y, z provided above is just random data to explain the problem. In reality, you can imagine the points (x, y) coordinates are given from an experiment meaning in general there is no relation between x, y, z or even if it is, it is NOT known upfront.
You can add another scatterplot using np.linspace() function:
import numpy as np
import matplotlib.pyplot as plt
import random
x = np.random.random_sample((100,))
x = np.sort(x)
y = x + np.sin(np.pi * x)
z = 5 * x
fig = plt.figure()
plot = plt.scatter(x, y, s= 10, c = z, cmap='coolwarm')
fig.colorbar(plot)
plt.grid(True, 'both')
# add another scatterplot
x_line = np.linspace(np.min(x), np.max(x), num=1000)
y_line = x_line + np.sin(np.pi * x_line)
z_line = 5 * x_line
plt.scatter(x_line, y_line, c=z_line, s=0.1, cmap='coolwarm')
plt.show()

How to change the axis dimension from pixel to length in matplotlib? is there any code in general?

Since the complete simulation is to big to post it right here only the code to plot the spectrum is given (I think this is enough)
d = i.sum(axis=2)
pylab.figure(figsize=(15,15))
pylab = imshow(d)
plt.axis('tight')
pylab.show()
This spectrum is given in pixel. But I would like to have this in the units of length. I will hope you may give me some advices.
Do you mean that you want axis ticks to show your custom dimensions instead of the number of pixels in d? If yes, use the extent keyword of imshow:
import numpy
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
d = numpy.random.normal(size=(20, 40))
fig = plt.figure()
s = fig.add_subplot(1, 1, 1)
s.imshow(d, extent=(0, 1, 0, 0.5), interpolation='none')
fig.tight_layout()
fig.savefig('tt.png')
I'm guess a bit at what your problem is, so let's start by stating my interpretation/ You have some 2D data d that you plot using imshow and the units on the x and y axes are in the number of pixels. For example in the following we see the x axis labelled from 0 -> 10 for the number of data points:
import numpy as np
import matplotlib.pyplot as plt
# Generate a fake d
x = np.linspace(-1, 1, 10)
y = np.linspace(-1, 1, 10)
X, Y = np.meshgrid(x, y)
d = np.sin(X**2 + Y**2)
plt.imshow(d)
If this correctly describes your issue, then the solution is to avoid using imshow, which is designed to plot images. Firstly this will help as imshow attemps to interpolate to give a smoother image (which may hide features in the spectrum) and second because it is an image, there is no meaningful x and y data so it doesn't plot it.
The best alternative would be to use plt.pcolormesh which generate a psuedocolor plot of a 2D array and takes as arguments X and Y, which are both 2D arrays of points to which the values of d correspond.
For example:
# Generate a fake d
x = np.linspace(-1, 1, 10)
y = np.linspace(-1, 1, 10)
X, Y = np.meshgrid(x, y)
d = np.sin(X**2 + Y**2)
plt.pcolormesh(X, Y, d)
Now the x and y values correspond to the values of X and Y.

Categories