I've been working on temperature maps and have been trying to save images using the matplotlib colourmap viridis. Originally, I was using the following code to create images and then save them:
# define normalisation and colourmap
norm = Normalize(vmin=2, vmax=42)
cmap = plt.get_cmap('viridis').copy()
cmap.set_bad('white', 1.)
# apply colourmap to normalised data
map = cmap(norm(map))
# create and save figure
plt.imshow(map, cmap=cmap)
plt.axis('off')
plt.savefig(imgpath, bbox_inches='tight', pad_inches=0)
plt.cla()
This method was giving me the following image:
result using plt.imshow() and plt.savefig()
I quickly noticed that plt.savefig() does not save the image with the original pixel resolution, but does so based on my screen resolution. So instead, I used plt.imsave, which preserves the original size of the array. Because plt.imsave doesn't have a flag for cmap, I applied it directly as follows:
plt.imsave(imgpath, arr=cmap(norm(map)), format='png')
However, using plt.imsave gave me a different map: result using plt.imsave(). The same thing happens when cmap is applied directly when using plt.imshow()
I can't figure out what I'm doing wrong, I've tried with different maps from different areas, I'm sure that I've been using exactly the same instance of the colourmap and normalisation on both methods.
Can anyone tell me what the difference between the two methods is?
Related
I've been stuck for a few days trying to plot a TIF file over a basemap (Google Maps or Mapbox) using Python. I don't know if this is actually possible because I didn't find examples and nothing very clear about it, the most I found is how to plot vector files (shp) on top of basemaps, but nothing about raster.
I have a raster (rainfall_clipped.tif) that is in EPSG:4326 and I'm trying to plot it on top of a MapBox map using the Contextily package. At first I suspected that it could be a projection problem, but even doing the conversions to EPSG:3857, it didn't work. In the documentation Contextily says that it accepts both projections.
Contextily seems to understand the projections, even because it generates the map with the correct axes, the big problem is that it doesn't plot the TIF file on the map. And it's also reading the raster because it loaded the colorbar with the correct values. I don't know if the layer order is wrong or what else it could be.
Below is the code I am using and then the image that is being generated:
data = rasterio.open("rainfall_clipped.tif")
# Read the bounds
left, bottom, right, top = data.bounds
# Create a figure and axes
fig, ax = plt.subplots(figsize=(10, 10))
# Add the raster data to the plot using imshow
im = ax.imshow(data.read(1), extent=[left, right, bottom, top], cmap="Blues")
# Add a colorbar
fig.colorbar(im, ax=ax)
# Add a basemap using contextily
ctx.add_basemap(ax, crs=data.crs, source=ctx.providers.MapBox(accessToken="my_key", id="mapbox/satellite-v9"))
# Show the plot
plt.show()
This code is generating this image:
Output image
What I'm trying to do is something like below:
Expected image
Any suggestions what I can do?
i'm generating a dataset from 1D signals with a 2D transformation that generates 2D pictures. I'm using matplotlib to save the output with the following line:
plt.savefig(name_s , dpi = 'figure' , bbox_inches='tight', pad_inches=0.0 , format='png')
I'm having some trouble unerstanding if an high numerical dpi value is needed or if it is just a rescale, in particular when with the dpi = 'figure' parameter the function outputs a lower resolution image.
Moreover, if there is a specific format i can use to generate or save better images or any advice in general is gladly accepted.
I'm trying to create a pdf using Python's reportlab module.
I generated a png with matplotlib and saved it in the pdf file using report labs canvas.drawImage method.
My problem is that the generated png file is very fuzzy. I specified the size in inches with plt.figure(figsize=(20,10)) and saved the picture with the plt.savefig method.
This works out perfectly (except the fuzzy quality of the picture).
But when I increase the dpi within the savefig method the size of the picture increases.
Is there any way to improve the dpi without changing the picture size.
Or is there a way to resize it to the predefined values?
Thanks!
f = df.plot()
fig = f.get_figure()
fig.set_size_inches((2,2))
fig.savefig('C:/temp/foo.png', bbox_inches='tight', dpi=1500)
I went through the documentation of both but the documentation does not specify for a specific use case for both. I have also found that sometimes the imshow() property on its own displays the figures but sometimes the show() property needs to be used to display the figure. In the documentation , the imshow() property mentions about displaying the image on the axes but the word "axes" is missing from the show() property. What does the word axes more specifically refer to?
imshow() documentation
show() documentation
Except for both, imshow and show having the word "show" in them, they have nothing in common.
imshow is a plotting command. It is hence on the same level as other plotting commands like plot, scatter, pcolor, contour etc. Those plotting command will produce some graphical data representation inside an axes. An axes is essentially the rectangle you see around your plot.
plt.show() is the command you need to give at the end to produce the graphical output. It is the function which makes the figure which has previously been produced by one or more plotting commands to actually show up on screen - hence the name "show".
So you usually have
import matplotlib.pyplot as plt
<plotting command>
plt.show()
E.g.
plt.scatter(...)
plt.show()
or
plt.imshow(...)
plt.show()
Now in some cases, depending on the environment where you run your code, the use of plt.show() is not needed. This is because the environment is aware of there being a matplotlib plot being generated and it will therefore generate its output automatically for you without the need to call plt.show(). This would be mainly inside of IPython sessions or Jupyter notebooks.
In summary: In order to produce a plot with an image, you call plt.imshow(..). Whether or not you then need to call plt.show() to invoke the representation on screen depends on the environment. In case you do not want to show the image on screen, but e.g. save it to a file instead, you would omit plt.show() and call
plt.imshow(...)
plt.savefig(...)
instead.
well as you can see in the doc, imshow displays an image while show displays a figure.
Imshow's arguments are array_type objects, such as a jpeg picture (which can be of shape n x m x 3 for coloured, or n x m for black and white.
When you run a script that calls methods as .plot(), or hist(), you need to call .show() to display them.
To display your image, you call imshow().
Hope it helps.
I was trying to run the following code at the moment:
imgplot = plt.imshow(dose_data, extent = [0,4,0,6], aspect = 'auto')
On the console, I typed the following input:
In[38]:imgplot
Out[38]: <matplotlib.image.AxesImage at 0x123ebd198>
And the output made me wonder what the object is. After consulting the documentation, it seems like an AxesImage object (AxesImage Documentation). However I was wondering how to use the object stored in imgplot. At the moment I can neither see what it is, nor save it to an image.
P.S. I know how to show an image and how to save an image. I was just wondering how this object could be useful and what it actually is (like, is it an image object? an array? or some other weird type of object?)
As you have already found out, the return type of plt.imshow() is a matplotlib.image.AxesImage. The object img you get when calling img = plt.imshow() is an instance of that class.
In general, you do not have to care about this object, since it's bound to an axes and most of what you want to do, like showing a figure or saving it, does not require any control over that AxesImage itself.
Like with any other object, it may be useful for getting access to some of its properties for later use. e.g. img.cmap returns the colormap of the imgage, img.get_extent() provides you with the image extent.
There are two applications coming to my mind, where the AxesImage is frequently used:
Updating the image data: If you want to change the image data without producing a new plot, you may use
img.set_data(data)
This may be useful when working with user interactions or with animations.
Creating a colorbar: When creating a colorbar in a plot with several images, it may not be obvious for which image this colorbar should be created, thus
plt.colorbar(img, cax=cax) sets the colorbar of the image img to the axes cax.
For further details, you would probably need to refine your question, asking more specifically about some property, application, potential use etc.
If you wish to use the object nature of plot objects, proceed by first initiating a figure and axes object.
figure, axes = plt.subplots()
# or:
figure = plt.figure()
axes = figure.add_subplot(111)
Then you can plot using the axes object. The axes object lets you manipulate most things you can see in the plot.
axes.imshow(...)
Or save figures
figure.savefig('file.png')