How to change the subplot width/height ratio using matplotlib.pyplot? - python

If the following code is run
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
a=[[1,2,3],[4,4,4]]
gridspec.GridSpec(2,1)
plt.subplot2grid((2,1), (0,0), colspan=2, rowspan=1)
plt.figure(figsize=(10, 5))
plt.imshow(a)
plt.savefig('fig.png',bbox_inches='tight')
I got the picture below. How to set the width/height ratio of subplot as 1:2, so it can be longer?
Basically, how to do this:

By default matplotlib shows images with a 1:1 aspect ratio, i.e. each pixel is as wide as it is high. Aspect is defined as height/width. You can set aspect=2 to get an image with pixels twice as heigh as wide.
plt.imshow(a, aspect=2)

Related

plot over an image Python

I am trying to plot a scatter graphic over an image. The problem is that the image is in logarithmic scale, so I need to change the scale of the scatter to a determined one. But when I do that, the image changes aswell, when I don't want it to change.
Code:
import pandas as pd
import matplotlib.pyplot as plt
import math
table = pd.read_csv('Coef_Data.csv', sep = ',', header = 0)
img = plt.imread("img.png")
plt.figure(1)
plt.scatter(table['Fcoef'], table['Vcoef'], zorder=1)
plt.imshow(img,zorder=0)
plt.imshow(img, extent=[0, 1e6, 0, 1e6])
plt.ylabel('Vcoef')
plt.xlabel('Fcoef')
Plot with the image over the graphic with the scale in a wrong way
The real scale is logarithmic (from 10^0 to 10^6)
when I try this, the image turns into a scribble:
plt.yscale('log')
plt.xscale('log')
Just trying to change the scale of the plot without changing the image.
Thanks

Insert a matplotlib text on an existing image and preserve dpi

I would like to use matplotlib flexible text abilities on an existing image in PNG format with 300 dpi resolution.
I must preserve size and resolution.
what I tried :
from pylab import *
background = imread('Invitation.png')
imshow(background)
text(500,100, "n° 00001", size=20, rotation=30,
ha="right", va="top",
bbox=dict(boxstyle="round",
ec=(1., 0.5, 0.5),
fc=(1., 0.8, 0.8),
))
axis(off)
savefig('Invitation00001.png',dpi=300)
close()
But I encounter bounding box problems and dpi loss (left is before, right is after):
What is the good way to keep the original image features in the result?
Is there an alternative (at image level ?) for slanted text box ?
Thanks for any advice.
Generate a figure with correct size and axes that occupy the whole figure:
import matplotlib.pyplot as plt
im = plt.imread('Invitation.png')
f = plt.figure(figsize = (im.shape[1]/300, im.shape[0]/300) #figure with correct aspect ratio
ax = plt.axes((0,0,1,1)) #axes over whole figure
ax.imshow(im)
ax.text(...) #whatever text arguments
ax.axis('off')
f.savefig('Invitation00001.png',dpi=300)

Scale legend matplotlib [duplicate]

Any ideas on how can I insert a scale bar in a map in matplotlib that shows the length scale? something like the one I have attached.
Or maybe any ideas on measuring and showing distances automatically (not drawing an arrow and writing the distance manually!)?
Thanks :)
There is a an already existing class for scalebars in matplotlib called AnchoredSizeBar. In the below example AnchoredSizeBar is used to add a scalebar to an image (or map over a 100x100 meter area of randomness).
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.anchored_artists import AnchoredSizeBar
import matplotlib.font_manager as fm
fontprops = fm.FontProperties(size=18)
fig, ax = plt.subplots()
ax.imshow(np.random.random((10,10)),extent=[0,100,0,100])
Extent defines the images max and min of the horizontal and vertical values.
scalebar = AnchoredSizeBar(ax.transData,
20, '20 m', 'lower center',
pad=0.1,
color='white',
frameon=False,
size_vertical=1,
fontproperties=fontprops)
ax.add_artist(scalebar)
The four first arguments to AnchoredSizeBar are the transformation object of the coordinate system, scalebar length, label and location. Further optional arguments change the layout. These are explained in the documentation.
ax.set_yticks([])
ax.set_xticks([])
This gives
I would try the matplotlib-scalebar package. (For something like your example c.)
Assuming you are plotting a map image with imshow or similar, and you know the pixel width/cell-size (the real-world equivalent size of one pixel on the map image), you can automatically create the scale bar:
This example is straight off the PyPi matplotlib-scalebar package page but here it is for completeness:
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
from matplotlib_scalebar.scalebar import ScaleBar
plt.figure()
image = plt.imread(cbook.get_sample_data('grace_hopper.png'))
plt.imshow(image)
scalebar = ScaleBar(0.2) # 1 pixel = 0.2 meter
plt.gca().add_artist(scalebar)
plt.show()

Python wordcloud without any whitespaces around the plot

I am working with wordcloud module in python3 and trying to save a figure that should only give me the image of the wordcloud without any whitespaces around the cloud. I tried many ticks mentioned here in stackexchange but they didn't work. Below is my default code, which can get rid of the whitespace on the left and right but not on the top and bottom. If I make the other two values in ax = plt.axes([0,0,1,1]) to 0 as well then I get an empty image.
wordcloud = WordCloud(font_path=None, width = 1500, height=500,
max_words=200, stopwords=None, background_color='whitesmoke', max_font_size=None, font_step=1, mode='RGB',
collocations=True, colormap=None, normalize_plurals=True).generate(filteredText)
import matplotlib.pyplot as plt
fig = plt.figure()
ax = plt.axes([0,0,1,1])
plt.imshow(wordcloud, interpolation="nearest")
plt.axis('off')
plt.savefig('fig.png', figsize = (1500,500), dpi=300)
Could someone please help me out with this?
The wordcloud is an image, i.e. an array of pixels. plt.imshow makes pixels square by default. This means that unless the image has the same aspect ratio than the figure, there will be white space either the top and bottom, or the left and right side.
You can free the fixed aspect ratio setting aspect="auto",
plt.imshow(wc, interpolation="nearest", aspect="auto")
the result of which is probably undesired.
So what you would really want is to adapt the figure size to the image size.
Since the image is 1500 x 500 pixels, you may choose a dpi of 100 and a figure size of 15 x 5 inch.
wc = wordcloud.WordCloud(font_path=None, width = 1500, height=500,
max_words=200, stopwords=None, background_color='whitesmoke', max_font_size=None, font_step=1, mode='RGB',
collocations=True, colormap=None, normalize_plurals=True).generate(text)
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(15,5), dpi=100)
ax = plt.axes([0,0,1,1])
plt.imshow(wc, interpolation="nearest", aspect="equal")
plt.axis('off')
plt.savefig(__file__+'.png', figsize=(15,5), dpi=100)
plt.show()
At the end using matplotlib may not be the best choice anyways. Since you only want to save the image, you could just use
from scipy.misc import imsave
imsave(__file__+'.png', wc)

Matplotlib imshow() stretch to "fit width"

I've got an image, and a measure associated with each column of its pixels. I'm using pyplot to create a figure with the image on top, and a plot of the column measurements below. I'm using something like this:
import numpy as np
import matplotlib.pyplot as plt
A = np.random.rand(34*52).reshape(34,52)
means = np.average(A,axis=0)
plt.figure()
plt.subplot(2,1,1)
plt.imshow(A, interpolation='nearest' )
plt.subplot(2,1,2)
plt.plot(means)
plt.show()
How can I stretch the image's width to the match that of the plots. That way, when looking at the measurements in the plot, the souce pixels will be in a column directly above it.
Turns out that it's as simple as giving aspect='auto' to the imshow call.
plt.imshow(A, interpolation='nearest', aspect='auto')

Categories

Resources