Placing a title on quiverplot (vector field plot) in python - python

So I found many questions on plotting vector fields.
Some great sources on making these plots would be:
Chapter 4 Graphics with Matplotlib
matplotlib.axes.Axes.quiverkey
Visualizing a vector field with matplotlib
Vector Fields
I found many questions on creating these plots on stack exchange. The difference is my question is particularly with regards to adding a title to these plots. The old plt.title() did not work to do this. The best solution I had so far was creating a legend with the desired title then forcing it up using the coordinates. My solution however looks horrible. My question is how does one add a title to a quiver plot/vector plot.
My code so far was
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
x,y = np.meshgrid(np.linspace(-20,20,15),np.linspace(-20,20,15))
xdot = x
ydot = x+y
# Plot
fig, ax = plt.subplots(figsize=(8,6))
Q = ax.quiver(x, y, xdot, ydot, scale=500, angles='xy') # Quiver key
ax.quiverkey(Q,-10,22,30,"5.1.7",coordinates='data',color='k')
xl = plt.xlabel("x")
yl = plt.ylabel("y")
plt.show()
Summary
So to summarize my question. How does one add a title to the quiver plot above. Could you please provide a solution with the plot.
Sorry if this is a trivial question I am relatively new to both Python and plotting quiver plots. I am using google colab rather than jupyter if that could influence anything.

plt.title() should work but the trick is the position that you add it. A good rule of thumb is to add it last just before plt.show() always.

Related

How do I set the aspect ratio for a plot in Python with Spyder?

I'm brand new to Python, I just switched from Matlab. The distro is Anaconda 2.1.0 and I'm using the Spyder IDE that came with it.
I'm trying to make a scatter plot with equal ratios on the x and y axes, so that this code prints a square figure with the vertices of a regular hexagon plotted inside.
import numpy
import cmath
import matplotlib
coeff = [1,0,0,0,0,0,-1]
x = numpy.roots(coeff)
zeroplot = plot(real(x),imag(x), 'ro')
plt.gca(aspect='equal')
plt.show()
But plt.gca(aspect='equal') returns a blank figure with axes [0,1,0,1], and plt.show() returns nothing.
I think the main problem is that plt.gca(aspect='equal') doesn't just grab the current axis and set its aspect ratio. From the documentation, (help(plt.gca)) it appears to create a new axis if the current one doesn't have the correct aspect ratio, so the immediate fix for this should be to replace plt.gca(aspect='equal') with:
ax = plt.gca()
ax.set_aspect('equal')
I should also mention that I had a little bit of trouble getting your code running because you're using pylab to automatically load numpy and matplotlib functions: I had to change my version to:
import numpy
import cmath
from matplotlib import pyplot as plt
coeff = [1,0,0,0,0,0,-1]
x = numpy.roots(coeff)
zeroplot = plt.plot(numpy.real(x), numpy.imag(x), 'ro')
ax = plt.gca()
ax.set_aspect('equal')
plt.show()
People who are already comfortable with Python don't generally use Pylab, from my experience. In future you might find it hard to get help on things if people don't realise that you're using Pylab or aren't familiar with how it works. I'd recommend disabling it and trying to get used to accessing the functions you need through their respective modules (e.g. using numpy.real instead of just real)

How to separate one graph from the set of multiple graphs on figure

I will not be able to put the code here because it is my assignment.
My program is printing multiple graphs on one plot. Please look at the example figure on the following link: Python: Plot multiple graphs on the same figure
The link above is just an example. That is not my code nor do I have the same program. My topic is completely different. That figure is just for reference.
The line of code I am using to achieve this is: plot(a,b, label=str(meters))
What I want to do is get any one of those graph from those three curves and also plot it separately as if it is the main graph. I am doing all this inside a function, and I have created an array of numbers to loop through these different values to get three different graphs.
Do you mean something like this?
import numpy as np
import matplotlib.pyplot as plt
plt.ion()
a = np.arange(5)
line1, = plt.plot(a, a**2) # a new figure instance is opened automatically
line2, = plt.plot(a, a**3-a)
line3, = plt.plot(a, 4*a-a**2/2.)
fig_handle = plt.figure() # Force a new figure instance to open
plt.plot(a, a**2) # This will replot 'line1', but in this new figure instance.
If not, please update your question, perhaps showing the code you already have.
Note that this is information you could find on the matplotlib pyplot tutorial.

Combining mayavi and matplotlib in the same figure

I will be making animations. In each frame I want to contain both a mayavi plot obtained with
mlab.pipeline.iso_surface(source, some other superfluous args)
and a matplotlib plot obtained using simply
pylab.plot(args)
I have scripts to do both separately, but have no idea how to go about combining them into one figure. I want the end product to be one script which contains the code from both the scripts that I currently have.
AFAIK, there is no direct way because the backends used are so different. It does not seem possible to add matplotlib axes to mayavi.figure or vice versa.
However, there is a "kind of a way" by using the the mlab.screenshot.
import mayavi.mlab as mlab
import matplotlib.pyplot as plt
# create and capture a mlab object
mlab.test_plot3d()
img = mlab.screenshot()
mlab.close()
# create a pyplot
fig = plt.figure()
ax1 = fig.add_subplot(121)
ax1.plot([0,1], [1,0], 'r')
# add the screen capture
ax2 = fig.add_subplot(122)
ax2.imshow(img)
ax2.set_axis_off()
This is not necessarily the nicest possible way of doing things, and you may bump into resolution problems, as well (check the size of the mayavi window). However, it gets the job done in most cases.
Adding to the answer by DrV which helped me a great deal, you can work with the mlab figure to set resolution before screenshot such as with batch plotting:
mfig = mlab.figure(size=(1024, 1024))
src = mlab.pipeline.scalar_field(field_3d_numpy_array)
mlab.pipeline.iso_surface(src)
iso_surface_plot = mlab.screenshot(figure=mfig, mode='rgba', antialiased=True)
mlab.clf(mfig)
mlab.close()
# Then later in a matplotlib fig:
plt.imshow(iso_surface_plot)

Second y-axis label getting cut off

I'm trying to plot two sets of data in a bar graph with matplotlib, so I'm using two axes with the twinx() method. However, the second y-axis label gets cut off. I've tried a few different methods with no success (tight_layout(), setting the major_pads in rcParams, etc...). I feel like the solution is simple, but I haven't come across it yet.
Here's a MWE:
#!/usr/bin/env python
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
matplotlib.rcParams.update({'font.size': 21})
ax = plt.gca()
plt.ylabel('Data1') #Left side
ax2 = ax.twinx()
for i in range(10):
if(i%2==0):
ax.bar(i,np.random.randint(10))
else:
ax2.bar(i,np.random.randint(1000),color='k')
plt.ylabel('Data2') #Right
side
plt.savefig("test.png")
I just figured it out: the trick is to use bbox_inches='tight' in savefig.
E.G. plt.savefig("test.png",bbox_inches='tight')
I encountered the same issue which plt.tight_layout() did not automatically solve.
Instead, I used the labelpad argument in ylabel/set_ylabel as such:
ax.set_ylabel('label here', rotation=270, color='k', labelpad=15)
I guess this was not implemented when you asked this question, but as it's the top result on google, hopefully it can help users of the current matplotlib version.

Matplotlib autoscale

I need to get a plot that fits the data automatically using matplotlib. This is the code I was given:
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
....
lines = LineCollection(mpl.line_holder, colors=mpl.colorholder , linestyle='solid')
plt.axes().add_collection(lines)
plt.axes().set_aspect('equal', 'datalim')
plt.draw()
plt.show()
This creates a plot, however the window is always the same (0-~.8) no matter what the data is, even if all of the data is outside that window. The resulting window has no ability to zoom out, only in, so this is a major problem. I can't find anywhere where any kind of sizing is set, nor can II find details on what defaults are. I need the window to automatically fit the data, but I can't find any function that does it (for some reason, autoscale_on(True) doesn't do it). The data is highly variable, so setting hard limits is not an option. How can i get this to display properly?
Not sure if this what you wanted, but I can change it if this was not what you were looking for.
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
import pylab as p
fig = plt.figure()
pts1 = []
pts2 = []
for i in range(100):
pts1.append([i,i])
pts2.append([-i-3,-i])
lines = LineCollection([pts1,pts2], linestyles='solid')
subplt = fig.add_subplot(111,aspect='equal')
subplt.add_collection(lines)
subplt.autoscale_view(True,True,True)
p.show()
Hope that helps.
Have a look at Eli Bendersky's Website, specifically this post. The example at the bottom of the post can be downloaded. It allows you to set whether the x axis will follow the plot or will remain static while the y axis changes with the data.

Categories

Resources