Subplotting an enlarged section of a fits image? - python

I'm attempting to open up an astronomical image and plot it as a figure, which is done by my code, however, I am trying to enlarge a section of the fits file as a subplot on the same figure.
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('814wmos.fits')
image_data = fits.getdata('814wmos.fits', ext=0)
plt.figure()
plt.imshow(image_data, cmap='gray')
This gives me my fits file, and plots it, which without 'zooming' in on the coordinates[350:450,500:600] shows/ tells me very little. How can I plot this area as a subplot next to original image, of the same size (zoomed in for same axes)?

Related

Plot a FITS image with changed axes

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())

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

How to show multiple images in one figure?

I use Python lib matplotlib to plot functions, and I know how to plot several functions in different subplots in one figure, like this one,
And when handling images, I use imshow() to plot images, but how to plot multiple images together in different subplots with one figure?
The documentation provides an example (about three quarters of the way down the page):
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
fig = plt.figure()
a=fig.add_subplot(1,2,1)
img = mpimg.imread('../_static/stinkbug.png')
lum_img = img[:,:,0]
imgplot = plt.imshow(lum_img)
a.set_title('Before')
plt.colorbar(ticks=[0.1,0.3,0.5,0.7], orientation ='horizontal')
a=fig.add_subplot(1,2,2)
imgplot = plt.imshow(lum_img)
imgplot.set_clim(0.0,0.7)
a.set_title('After')
plt.colorbar(ticks=[0.1,0.3,0.5,0.7], orientation='horizontal')
# ---------------------------------------
# if needed inside the application logic, uncomment to show the images
# plt.show()
Basically, it's the same as you do normally with creating axes with fig.add_subplot...
Simple python code to plot subplots in a figure;
rows=2
cols=3
fig, axes = plt.subplots(rows,cols,figsize=(30,10))
plt.subplots_adjust(wspace=0.1,hspace=0.2)
features=['INDUS','RM', 'AGE', 'DIS','PTRATIO','MEDV']
plotnum=1
for idx in features:
plt.subplot(rows,cols,plotnum)
sns.distplot(data[idx])
plotnum=plotnum+1
plt.savefig('subplots.png')
go through below link for more detail
https://exploredatalab.com/how-to-plot-multiple-subplots-in-python-with-matplotlib/

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')

How to insert a small image on the corner of a plot with matplotlib?

What I want is really simple: I have a small image file called "logo.png" that I want to display on the upper left corner of my plots. But you can't find any example of that in the matplotlib examples gallery.
I'm using django, and my code is something like this:
def get_bars(request)
...
fig = Figure(facecolor='#F0F0F0',figsize=(4.6,4))
...
ax1 = fig.add_subplot(111,ylabel="Valeur",xlabel="Code",autoscale_on=True)
ax1.bar(ind,values,width=width, color='#FFCC00',edgecolor='#B33600',linewidth=1)
...
canvas = FigureCanvas(fig)
response = HttpResponse(content_type='image/png')
canvas.print_png(response)
return response
If you want the image at the corner of your actual figure (rather than the corner of your axis), look into figimage.
Perhaps something like this? (using PIL to read the image):
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()
Another option, if you'd like to have the image be a fixed fraction of the figure's width/height is to create a "dummy" axes and place the image in it with imshow. This way the image's size and position is independent of DPI and the figure's absolute size:
import matplotlib.pyplot as plt
from matplotlib.cbook import get_sample_data
im = plt.imread(get_sample_data('grace_hopper.jpg'))
fig, ax = plt.subplots()
ax.plot(range(10))
# Place the image in the upper-right corner of the figure
#--------------------------------------------------------
# We're specifying the position and size in _figure_ coordinates, so the image
# will shrink/grow as the figure is resized. Remove "zorder=-1" to place the
# image in front of the axes.
newax = fig.add_axes([0.8, 0.8, 0.2, 0.2], anchor='NE', zorder=-1)
newax.imshow(im)
newax.axis('off')
plt.show()
There is now a much easier way, using the new inset_axes command (matplotlib >3.0 required).
This command allows one to define a new set of axes as a child of an existing axes object. The advantage of this is that you can define your inset axes in whatever units you please, like axes fraction or data coordinates, using the appropriate transform expression.
So here's a code example:
# Imports
import matplotlib.pyplot as plt
import matplotlib as mpl
# read image file
with mpl.cbook.get_sample_data(r"C:\path\to\file\image.png") as file:
arr_image = plt.imread(file, format='png')
# Draw image
axin = ax.inset_axes([105,-145,40,40],transform=ax.transData) # create new inset axes in data coordinates
axin.imshow(arr_image)
axin.axis('off')
The advantage of this method is that your image will scale automatically as your axes get rescaled!

Categories

Resources