Plotting a png as background on a Log scale Plot - matplotlib

I have created an X/Y plot with data ranging for x=0.1 to 10 and Y=1.0 to 1000. Both scales are log10.
I would like to underlay an image that is also scaled to the same log values.
When I plot the png file under the scatter, it scales the png according to the log scale, and distorts the image. How do it stop it doing that?
This is what I get This is what the background should look like
sbt=plt.imread('/Users/????????/Desktop/SBT2.png')
fig, axs=plt.subplots()
axs.plot(df['Rf'],df['qc/pa'],'bo', linewidth=0.2)
axs.set_yscale('log')
axs.set_xscale('log')
axs.set_xlim(0.1,10)
axs.set_ylim(1.0,1000)
axs.set_xlabel('Friction Ratio, Rf %')
axs.set_ylabel('Cone Resistance, (qc/pa)')
axs.imshow(sbt,aspect='auto',extent=(0.1,10,1,1000))

Related

Does changing the y-axis and x-axis label changes anything in the image using imshow?

I want to show values as pixels. But my x-axis and y-axis show different range.I don't know what these values are telling us. But I read somewhere that we have to read the values as intensity values. They will not be visualized on the axis. Then what these axis are telling us? Secondly if I use xticks and yticks to label x and y axis does it has any effect on the image? Does it flip anything in the image?
`# a is an array of shape(500,2)
plt.xticks(np.arange(0,2))
plt.yticks(np.arange(0,500))
plt.imshow(a,aspect='auto',cmap=plt.cm.gray)`

Matplotlib multiple scatter subplots - reduce svg file size

I generated a plot in Matplotlib which consists of 50 subplots. In each of these subplots I have a scatterplot with about 3000 datapoints. I'm doing this, because I just want to have an overview of the different scatter plots in a document I'm working on.
This also works so far and looks nice, but the problem is obviously that the SVG file that I'm getting is really big (about 15 MB). And Word just can't handle such a big SVG file.
So my question: is there a way to optimize this SVG file? A lot of my datapoints in the scatter plots are overlapping each other, so I guess it should be possible remove many "invisible" ones of them without changing the visible output. (so something like this in illustrator seems to be what I want to do: Link) Is it also possible to do something like this in Inkscape? Or even directly in Matplotlib?
I know that I can just produce a PNG file, but I would prefer to have the plot as a vector graphic in my document.
If you want to keep all the data points as vector graphics, its unlikely you'll be able to reduce the file size.
While not ideal, one potential option is to rasterize only the data points created by ax.scatter, and leave the axes, labels, titles, etc. all as vector elements on your figure. This can dramatically reduce the file size, and if you set the dpi high enough, you probably won't lose any useful information from the plot.
You can do this by setting rasterized=True when calling ax.scatter.
You can then control the dpi of the rasterized elements using dpi=300 (or whatever dpi you want) when you fig.savefig.
Consider the following:
import matplotlib.pyplot as plt
figV, axesV = plt.subplots(nrows=10, ncols=5)
figR, axesR = plt.subplots(nrows=10, ncols=5)
for ax in figV.axes:
ax.scatter(range(3000), range(3000))
for ax in figR.axes:
ax.scatter(range(3000), range(3000), rasterized=True)
figV.savefig('bigscatterV.svg')
figR.savefig('bigscatterR.svg', dpi=300)
bigscatterV.svg has a file size of 16MB, while bigscatterR.svg has a file size of only 250KB.

Relationship between dpi and figure size

I have created a figure using matplotlib but I have realized the plot axis and the drawn line gets zoomed out.
Reading this earlier discussion thread, it explains how to set the figure size.
fig, ax = plt.subplots()
fig.set_size_inches(3, 1.5)
plt.savefig(file.jpeg, edgecolor='black', dpi=400, facecolor='black', transparent=True)
With the above code (other configurations removed for brevity), I do get a resulting image file with 1200 X 600 desired dimensions(should we say resolution too?) and desired file size.
The projected image is scaled out in an unusual way, annotations for example are enlarged. While I can set the size of the labels on the axis, the figure doesn't look proportional with respect to the scale since the bottom and right spines are large and so are the plotted lines.
The question, therefore, is, what configurations are going wrong?
Figure size (figsize) determines the size of the figure in inches. This gives the amount of space the axes (and other elements) have inside the figure. The default figure size is (6.4, 4.8) inches in matplotlib 2. A larger figure size will allow for longer texts, more axes or more ticklabels to be shown.
Dots per inches (dpi) determines how many pixels the figure comprises. The default dpi in matplotlib is 100. A figure of figsize=(w,h) will have
px, py = w*dpi, h*dpi # pixels
# e.g.
# 6.4 inches * 100 dpi = 640 pixels
So in order to obtain a figure with a pixel size of e.g. (1200,600) you may chose several combinations of figure size and dpi, e.g.
figsize=(15,7.5), dpi= 80
figsize=(12,6) , dpi=100
figsize=( 8,4) , dpi=150
figsize=( 6,3) , dpi=200
etc.
Now, what is the difference? This is determined by the size of the elements inside the figure. Most elements like lines, markers, texts have a size given in points.
Matplotlib figures use Points per inch (ppi) of 72. A line with thickness 1 point will be 1./72. inch wide. A text with fontsize 12 points will be 12./72. inch heigh.
Of course if you change the figure size in inches, points will not change, so a larger figure in inches still has the same size of the elements. Changing the figure size is thus like taking a piece of paper of a different size. Doing so, would of course not change the width of the line drawn with the same pen.
On the other hand, changing the dpi scales those elements. At 72 dpi, a line of 1 point size is one pixel strong. At 144 dpi, this line is 2 pixels strong. A larger dpi will therefore act like a magnifying glass. All elements are scaled by the magnifying power of the lens.
A comparisson for constant figure size and varying dpi is shown in the image below on the left. On the right you see a constant dpi and varying figure size. Figures in each row have the same pixel size.
Code to reproduce:
import matplotlib.pyplot as plt
%matplotlib inline
def plot(fs,dpi):
fig, ax=plt.subplots(figsize=fs, dpi=dpi)
ax.set_title("Figsize: {}, dpi: {}".format(fs,dpi))
ax.plot([2,4,1,5], label="Label")
ax.legend()
figsize=(2,2)
for i in range(1,4):
plot(figsize, i*72)
dpi=72
for i in [2,4,6]:
plot((i,i), dpi)

How to plot images of different size at the same resolution?

A collection of images are plotted as follow:
figure(num=None, figsize=(16, 14), dpi=300)
k=1
for i in range(1,10):
for j in range(1,6):
subplot(9,5,k,xticks=[],yticks=[])
imshow(rgb_chromosomes[k-1],interpolation='nearest')
k=k+1
It is visible that from a image to an other, pixels are not the same size.
How to fix that issue?
Use interpolation= 'bilinear' and subsample the result with regular spacing (say take every other four pixel, this depends on the final pixel size you want) and form a tiny image. Then magnify this tiny image with 'nearest' interpolation.
You can also keep the 'nearest' setting for the first interpolation, but the result will look ugly.
so, from image to image are the pixels different sizes? From context, I am guessing that these are all snippets from the same image/imaging conditions and you want the scale to be the same in all of them.
Something like:
fig, ax_lst = plt.subplots(9, 6) # better way to set up your axes
for k, ax in enumerate(ax_lst.ravel()):
ax.imshow(rgb_chromosomes[k], interpolation='none')
ax.set_xlim([0, max_image_width])
ax.set_ylim([0, max_image_height])
ax.set_frame_on(False)

How to get Gnuplot not to crop scientific notation

I'm using gnuplot to generate the following surface plot.
The important part of the command file I'm using is:
set terminal pdfcairo size 3,3;
In particular the size 3,3 resizes the plot to the way I want but crops out part of the z-axis label in the process. If I use a wider size like size 4,3 or don't use the size option at all then the z-axis labels fit as follows:
It seems that gnuplot doesn't take the width of the label into consideration when resizing the plot.
Is there a way to maybe move the plot to the right before resizing to 3,3 so that there's room to scientific notation?
You can set the lmargin option:
set lmargin 10
(or whatever size doesn't crop the label).