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
Related
I wanted to plot this image in fits format.
But I get this instead
I've tried to change the axes with imshow but it doesn't do anything better. This is the code that i'm using.
import matplotlib.pyplot as plt
from astropy.visualization import astropy_mpl_style
plt.style.use(astropy_mpl_style)
from astropy.utils.data import get_pkg_data_filename
from astropy.io import fits
image_file = get_pkg_data_filename('Or.fits')
fits.info(image_file)
image_data = fits.getdata(image_file, ext=0)
print(image_data.shape)
plt.figure()
plt.imshow(image_data, cmap='gray')
plt.colorbar()
From the second image that you posted in your question, it seems that image_data has super large values with most the data points being very small. Try mapping data points logarithmically to hopefully solve the problem.
Add the below to the beginning of your code:
from matplotlib.colors import LogNorm
And change your plotting line to the following so that matplotlib uses the logarithm of those values when plotting your image.
plt.imshow(image_data, cmap='gray', norm=LogNorm())
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()
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()
This question lend code from Joe Kington(how to insert a small image on the corner of a plot with matplotlib?):
import matplotlib.pyplot as plt
import Image
import numpy as np
im = Image.open('/home/jofer/logo.png')
height = im.size[1]
# We need a float array between 0-1, rather than
# a uint8 array between 0-255
im = np.array(im).astype(np.float) / 255
fig = plt.figure()
plt.plot(np.arange(10), 4 * np.arange(10))
# With newer (1.0) versions of matplotlib, you can
# use the "zorder" kwarg to make the image overlay
# the plot, rather than hide behind it... (e.g. zorder=10)
fig.figimage(im, 0, fig.bbox.ymax - height)
# (Saving with the same dpi as the screen default to
# avoid displacing the logo image)
fig.savefig('/home/jofer/temp.png', dpi=80)
plt.show()
I tried the following:
import matplotlib.pyplot as plt
import Image
import numpy as np
im = Image.open('/home/po/pic.jpg')
height = im.size[1]
im = np.array(im).astype(np.float) / 255
fig = plt.figure()
fig.subplots_adjust(top=0.80)
fig.patch.set_facecolor('black')
ax1 = fig.add_subplot(1, 1, 1, axisbg='white')
fig.figimage(im, 0, fig.bbox.ymax - height)
But my image is at the center rather than at the middle, is there a way to shift it up, i have tried read up on http://effbot.org/imagingbook/image.htm but to no avail
Thanks in advance:)
I don't see the need for an extra module import when matplotlib has the capabilities to do the same.
If you want to make an inset, simply add (and position) an extra axes object to the figure window. It has some advantages over the figimage method here, because figimage
Adds a non-resampled image to the figure
(matplotlib docs).
Here's an example:
from scipy import misc
face = misc.face()
import matplotlib.pyplot as plt
plt.plot(range(10), range(10))
ax = plt.axes([0.5,0.8, 0.1, 0.1], frameon=True) # Change the numbers in this array to position your image [left, bottom, width, height])
ax.imshow(face)
ax.axis('off') # get rid of the ticks and ticklabels
plt.show()
I used face as an image, to make sure anyone can run the code, but you can have matplotlib load your image by typing:
image = plt.imread('/home/po/pic.jpg')
This replaces your call to the Image module, making it obsolete. The variable image serves the same purpose as the variable face in the small script above.
Depending on your use-case, it may be far faster and cleaner to just resize the image in your photo editor and then use two lines of code:
img = image.imread("my_image.png")
plt.figimage(img, 100, 200, zorder=1, alpha=0.3)
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')