I have a list of values in Python, which I'm plotting with matplotlib. I'm then trying to use ginput in matplotlib to click two points on the graph, from which the X coordinates will be taken, between which to slice my original list. However, I can't seem to find a way to do this.
I already have a list of numbers called MIList, and the following code isn't working for me:
startinput = plt.ginput(2)
print("clicked", startinput)
startinputxvalues = [x[0] for x in startinput]
print(startinputxvalues)
x1 = startinputxvalues[0]
print(x1)
x2 = startinputxvalues[1]
print(x2)
slicedMIList = [MIList[int(x1):int(x2)]]
plt.plot(slicedMIList)
This gives me an array, but it doesn't plot these values on my graph - does anyone have any input as to what I'm doing wrong?
Thanks
The main point is that you need to redraw the canvas, once changes have been made to it. So in order for the new plot to become visible you can call
plt.gcf().canvas.draw()
Here is a complete working code:
import matplotlib.pyplot as plt
import numpy as np
X = np.arange(10)
Y = np.sin(X)
plt.plot(X, Y)
startinput = plt.ginput(2)
x, y = zip(*startinput)
Ysliced = Y[int(x[0]):int(x[1])+1]
Xsliced = X[int(x[0]):int(x[1])+1]
plt.plot(Xsliced, Ysliced, color="C3", linewidth=3)
#draw the canvas, such that the new plot becomes visible
plt.gcf().canvas.draw()
plt.show()
Related
Hello fellow developers,
I am working on a project where I have to plot real time data coming from the sensors. I have created a naive generator that gives data points to plot. I was referencing the code from the documentation but it doesn't draw anything, even though the program is reading all the data points from the file. I have include screenshots of the outputs.
The first value in the tuple is the x value and the second value is the list of y value. I am plotting only the 1 value from the y value's list.
The graph opens but the plot is not drawn.
What could be the possible issue with the code?
from getData import GetData
import numpy as np
import matplotlib
# matplotlib.use('MacOSX')
from matplotlib import pyplot as plt
def getNextPoint(getDataObj):
dataPoint = getDataObj.__next__()
if dataPoint != None:
x,y = dataPoint
print(x,y)
return x,y
else:
return getNextPoint(getDataObj)
def run(niter=1000):
fig, ax = plt.subplots()
getDataObj = GetData()
x, y = getNextPoint(getDataObj)
points = ax.plot(x, y[0], animated=True)[0]
plt.show(block=False)
plt.pause(0.1)
background = fig.canvas.copy_from_bbox(fig.bbox)
ax.draw_artist(points)
fig.canvas.blit(fig.bbox)
for ii in range(niter):
# restore background
fig.canvas.restore_region(background)
# update the xy data
x, y = getNextPoint(getDataObj)
points.set_data(x, y[0])
# redraw just the points
ax.draw_artist(points)
# fill in the axes rectangle
fig.canvas.blit(fig.bbox)
fig.canvas.flush_events()
ax.autoscale()
# plt.show()
if __name__ == '__main__':
run()
I am able to get a Surface Plot using matplotlib with this code:
ax = figure.gca(projection = "3d")
ax.plot_surface(meshed_slopes, meshed_intercepts, errors.reshape(1, meshed_slopes.shape[0]), cmap = cm.autumn_r)
But when I try to do the same using Plotly I get a blank graph.
This is the code am using to plot the surface plot-
import plotly.graph_objects as go
import numpy as np
meshed_slopes, meshed_intercepts = np.meshgrid(slopes, intercepts)
fig = go.Figure(go.Surface(
x = meshed_slopes,
y = meshed_intercepts,
z = errors.reshape(1, meshed_slopes.shape[0])
))
fig.show()
How can I fix this?
Thanks in advance!!!
Since you haven't provided the data so we can take a look I'm going to explain what plotly needs to make the plot work :
x and y needs to be both (n,) shape and same shape
z should be a matrix or a table with (n,n) size
I would suggest a dataframe as it might be easier for you to create everything
(Since I have low rep, I can't write comments so I'm posting this as an answear)
Make sure that x, y, z are 2D arrays.
import plotly.graph_objects as go
import numpy as np
x, y = np.mgrid[-2:2:50j, -2:2:50j]
z = np.cos(x**2 + y**2)
fig = go.Figure([
go.Surface(x=x, y=y, z=z)
])
fig
An equation which is represent as below
sin(x)*sin(y)*sin(z)+cos(x)*sin(y)*cos(z)=0
I know the code to plot function for z=f(x,y) using matplotlib but to plot above function I don’t know the code, but I tried MATLAB MuPad code which is as follows
Plot(sin(x)*sin(y)*sin(z)+cos(x)*sin(y)*cos(z),#3d)
This will be much easier if you can isolate z. Your equation is the same as sin(z)/cos(z) = -cos(x)*sin(y)/(sin(x)*sin(y)) so z = atan(-cos(x)*sin(y)/(sin(x)*sin(y))).
Please don't mistake me, but I think your given equation to plot can be reduced to a simple 2D plot.
sin(x)*sin(y)*sin(z)+cos(x)*sin(y)*cos(z) = 0
sin(y)[sin(x)*sin(z)+cos(x)*cos(z)] = 0
sin(y)*cos(x-z) = 0
Hence sin(y) = 0 or cos(x-z)=0
Hence y = n*pi (1) or x-z=(2*n + 1)pi/2
Implies, x = z + (2*n + 1)pi/2 (2)
For (1), it will be a straight line (the plot of y vs n) and in second case, you will get parallel lines which cuts x-axis at (2*n + 1)pi/2 and distance between two parallel lines would be pi. (Assuming you keep n constant).
Assuming, your y can't be zero, you could simplify the plot to a 2D plot with just x and z.
And answering your original question, you need to use mplot3d to plot 3D plots. But as with any graphing tool, you need values or points of x, y, z. (You can compute the possible points by programming). Then you feed those points to the plot, like below.
from mpl_toolkits import mplot3d
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax = plt.axes(projection="3d")
xs = [] # X values
ys = [] # Y values
zs = [] # Z values
ax.plot3D(xs, ys, zs)
plt.show()
How to draw something like this?
There's kind of like a horizontal line until next data point show up, then a vertical line to adjust the location y. The usual plot function in matplotlib just plot a straight line between two data point, which doesn't satisfy what I need.
You may use one of the drawstyles "steps-pre", "steps-mid", "steps-post" to get a a step-like appearance of your curve.
plt.plot(x,y, drawstyle="steps-pre")
Full example:
import matplotlib.pyplot as plt
import numpy as np; np.random.seed()
x = np.arange(12)
y = np.random.rand(12)
styles = ["default","steps-pre","steps-mid", "steps-post"]
fig, axes = plt.subplots(nrows=len(styles), figsize=(4,7))
for ax, style in zip(axes, styles):
ax.plot(x,y, drawstyle=style)
ax.set_title("drawstyle={}".format(style))
fig.tight_layout()
plt.show()
Just as #cricket_007 said in the comments -- make each y value repeat at the next x value. Below a way how to achieve this with numpy.
EDIT:
Thanks to the comment by #ImportanceOfBeingErnest I replaced the original code that extended the data with a much simpler solution.
from matplotlib import pyplot as plt
import numpy as np
#producing some sample data
x = np.linspace(0,1,20)
y = np.random.rand(x.shape[0])
#extending data to repeat each y value at the next x value
##x1 = np.zeros(2*x.shape[0]-1)
##x1[::2] = x
##x1[1::2] = x[1:]
x1 = np.repeat(x,2)[1:]
##y1 = np.zeros(2*y.shape[0]-1)
##y1[::2] = y
##y1[1::2] = y[:-1]
y1 = np.repeat(y,2)[:-1]
plt.plot(x1, y1)
plt.show()
The result looks like this:
I have two arrays x,y obtained from a machine learning calculations and I wish to make a scatter plot with the reference data x on the diagonal in a way to visualize better the predicted values y against the true ones x. Please can you suggest me how to do it in python or gnuplot?
import numpy as np
import matplotlib.pyplot as plt
N = 50
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
plt.scatter(x, y, c=colors)
plt.plot( [0,1],[0,1] )
plt.savefig('a.png')
This will produce:
Check this page for more information.
a simple example:
import matplotlib.pyplot as plt
import numpy as np
x=np.linspace(0,100,101)
y=np.random.normal(x) # add some noise
plt.plot(x,y,'r.') # x vs y
plt.plot(x,x,'k-') # identity line
plt.xlim(0,100)
plt.ylim(0,100)
plt.show()
In matplotlib, you can also draw an "infinite" line in order to avoid having to define the exact coordinates. For example, if you have an axes ax, you can do:
pt = (0, 0)
ax.axline(pt, slope=1, color='black')
where pt is an intersection point. Note if pt isn't included in the limits of the plot, the limits will be modified to include it.