I have a plotting routine and I show the result with
plt.show()
as this is the easiest way for me to see my data. Once I have found and area which I want to look at i want to plot the exact same area again for a different set of data which has the same xy dimensions. The easies way for me would be to see the coordinates of the corners after the zoom or the origin of the zoom and the size in xy direction.
I found this solution . If I understand it correctly I have to manually change the plotting script with the new x y limits for each subsequent plot I want to make.
Is there a possibility to show the limit of the manual zoom in the panel itself and have the possibility to perform and actual input in dedicated fields such that I can recreate this zoom?
Do you mean something like this?
This "Figure options" dialog is present in the Qt backend. To use it,
import matplotlib
matplotlib.use("Qt4Agg") # or "Qt5Agg" depending on the version
Related
I'm not sure whether this is a Cartopy or Matplotlib question, so I apologize if this would have been better suited for Matplotlib.
I am transitioning from NCL (NCAR Command Language https://www.ncl.ucar.edu/) to Python. Previously, I was using NCL to contour with a method of "CellFill" (https://www.ncl.ucar.edu/Document/Graphics/Resources/cn.shtml#cnFillMode). In Python, I am using pcolormesh to render a gridded dataset with a horizontal grid spacing of 3-km. In NCL, regardless of whether I am plotting the full domain or an area zoom, the resolution of the resulting image appears to be consistent using a PNG output. In Python however, if I use pcolormesh with an area zoom it looks identical to my NCL plot but if I try and plot the full domain, it looks different.
I've traced this down to the figure resolution. At the full domain view in Python, however I have my figure settings configured causes the 3-km cells in certain areas to become "blurred together" making it appear as if the entire region is a certain contour value when in actuality there are areas with no values in between.
Here is a CONUS example of pcolormesh:
And here is a full CONUS version from NCL:
There are several areas of note, but one obvious area is the NM/AZ region. If I zoom in very closely in both Python and NCL in this region, the resulting images look identical. But at the CONUS view it looks like there's much more shading in this area than there actually should be in the Python version.
crs = ccrs.PlateCarree() # Lat/Lon
fig = plt.figure(1, figsize=(15, 15))
ax.add_feature(cfeature.COASTLINE.with_scale('50m'), linewidth=BORDERWIDTH,edgecolor=BORDERCOLOR)
ax.add_feature(cfeature.STATES, linewidth=BORDERWIDTH,edgecolor=BORDERCOLOR)
ax.add_feature(cfeature.BORDERS, linewidth=BORDERWIDTH,edgecolor=BORDERCOLOR)
ax1 = plt.subplot(111,projection=crs)
norm = BoundaryNorm(LEVELS,ncolors=plt.get_cmap('plasma').N,clip=False)
cf1 = ax1.pcolormesh(diffsum.lon0,diffsum.lat0,diffsum,cmap='plasma',transform=ccrs.PlateCarree(),norm=norm)
plt.savefig('testing%s.png' % (DSTRING))
Note that if I manually increase the DPI used in the resulting image to something rediculous like 1000, or increase the figure size to 100x100 inches, it also looks OK but the resulting image is so gigantic it makes it cumbersome to view on the screen.
Is there something I am missing about pcolormesh that I should be doing to help better adapt the resolution of the cells being shaded with respect to the resolution of the actual figure itself?
I have drawn a trajectory plot in python using matplotlib of a boat like so:
Now I want to add some arrows, like wind direction, true heading etc. However I want the arrows to have the same size no matter which zoom-level the plot is at. I tried matplotlib.pyplot.arrow, however there I have to define the length of the arrows. I could make matplotlib.pyplot.arrow work, but then I'd have to get the height and width of the plot, and scale my arrows accordingly, so I wondered if there was a better way to obtain scale-independent arrows for these points?
You want to use matplotlib.axes.Axes.annotate instead. See the docs for more info!
Basically, set the xycoords parameter to "axes fraction" to instruct it to plot using relative fraction of the axes itself rather than data coordinates.
I would like to blit a 2d image (like a png) to a location in 3-space on a 3D matplotlib figure. Essentially, I want the image to always be facing the user regardless of how the plot is rotated. It would be best if the blitted image did not scale as the user zoomed in and out as well.
One would think that this would be easy to do by accessing the low level rastering functions in matplotlib, but I can't find any documentation that describes what I would like to do.
If you put in an image as an annotation, zooming in on the axes will not scale the image. For example, see this demo. (To run the demo script, replace grace_hopper.png with lena.png.)
For example, just for an easy reference on zooming I've added a line of blue squares to the plot. The top image below show the unzoomed, and I've zoomed in in the lower one.
How can I save Python plots at very high quality?
That is, when I keep zooming in on the object saved in a PDF file, why isn't there any blurring?
Also, what would be the best mode to save it in?
png, eps? Or some other? I can't do pdf, because there is a hidden number that happens that mess with Latexmk compilation.
If you are using Matplotlib and are trying to get good figures in a LaTeX document, save as an EPS. Specifically, try something like this after running the commands to plot the image:
plt.savefig('destination_path.eps', format='eps')
I have found that EPS files work best and the dpi parameter is what really makes them look good in a document.
To specify the orientation of the figure before saving, simply call the following before the plt.savefig call, but after creating the plot (assuming you have plotted using an axes with the name ax):
ax.view_init(elev=elevation_angle, azim=azimuthal_angle)
Where elevation_angle is a number (in degrees) specifying the polar angle (down from vertical z axis) and the azimuthal_angle specifies the azimuthal angle (around the z axis).
I find that it is easiest to determine these values by first plotting the image and then rotating it and watching the current values of the angles appear towards the bottom of the window just below the actual plot. Keep in mind that the x, y, z, positions appear by default, but they are replaced with the two angles when you start to click+drag+rotate the image.
Just to add my results, also using Matplotlib.
.eps made all my text bold and removed transparency. .svg gave me high-resolution pictures that actually looked like my graph.
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
# Do the plot code
fig.savefig('myimage.svg', format='svg', dpi=1200)
I used 1200 dpi because a lot of scientific journals require images in 1200 / 600 / 300 dpi, depending on what the image is of. Convert to desired dpi and format in GIMP or Inkscape.
Obviously the dpi doesn't matter since .svg are vector graphics and have "infinite resolution".
You can save to a figure that is 1920x1080 (or 1080p) using:
fig = plt.figure(figsize=(19.20,10.80))
You can also go much higher or lower. The above solutions work well for printing, but these days you want the created image to go into a PNG/JPG or appear in a wide screen format.
Okay, I found spencerlyon2's answer working. However, in case anybody would find himself/herself not knowing what to do with that one line, I had to do it this way:
beingsaved = plt.figure()
# Some scatter plots
plt.scatter(X_1_x, X_1_y)
plt.scatter(X_2_x, X_2_y)
beingsaved.savefig('destination_path.eps', format='eps', dpi=1000)
In case you are working with seaborn plots, instead of Matplotlib, you can save a .png image like this:
Let's suppose you have a matrix object (either Pandas or NumPy), and you want to take a heatmap:
import seaborn as sb
image = sb.heatmap(matrix) # This gets you the heatmap
image.figure.savefig("C:/Your/Path/ ... /your_image.png") # This saves it
This code is compatible with the latest version of Seaborn. Other code around Stack Overflow worked only for previous versions.
Another way I like is this. I set the size of the next image as follows:
plt.subplots(figsize=(15,15))
And then later I plot the output in the console, from which I can copy-paste it where I want. (Since Seaborn is built on top of Matplotlib, there will not be any problem.)
I have some data made of coordinates and the count of each coordinate which I plot in a heatmap like this:
pyplot.subplot(211)
pyplot.scatter(longitudes, latitudes, c=counts)
pyplot.colorbar()
which is inspired by this great answer here in SO.
If you look closely you can see, that the dots shape the worldmap somehow. To underline this effect I'd like to put the real country boarders (simply drawn would be enough) as background to my plot. Is this possible with matplotlib? Maybe there is some (hidden) builtin in matplotlib?
You can likely achieve this if you have some image of the world map that you want as a background. You can read this into a numpy array and plot the image. Then you should be able to add your scatter plot overtop of the image. This matplotlib cookbook example shows how to insert images and such. There is also the matplotlib image tutorial that may be of use.
I've not used it, but you may also be interested in the basemap toolkit for matplotlib. In particular, the section on drawing a map background mentions specifically a drawcountries() method.