Reputation:
I am trying to open a full-color image from a '.fits'
file. But, when comparing it to the corresponding '.gif'
image, there appears to be an error regarding its color and size.
How can I view the real-color image in its proper dimensions?
As an example, one can select the '.fits'
file and corresponding '.gif'
file located at the top of this webpage. My example code, which uses the APLPY module, is below.
def from_fits_to_image(color_scheme, rloc, rname='synop_Ml_0.2104', rext='.fits', cmap=None):
"""
color_scheme : 'rgb', 'grayscale', or 'false color'; color scheme of image to be shown
rloc : type <str>; location of file to be read
rname : type <str>; name of file to be read
rext : type <str>; extension of file to be read
cmap : None or type <str>; colormap
"""
rpath = rloc + rname + rext
if color_scheme == 'rgb':
pic = aplpy.FITSFigure(rpath)
# pic.show_rgb(alt_filename) # what filename is supposed to go here?
else:
pic = aplpy.FITSFigure(rpath)
if color_scheme == 'grayscale':
pic.show_grayscale()
elif color_scheme == 'false color':
if cmap is None:
pic.show_colorscale()
else:
pic.show_colorscale(cmap=cmap)
# plt.savefig(...)
plt.show()
So long as one provides the proper rloc
(the location of the downloaded '.fits'
file) and color_scheme
, the above code will run.
Calling the function below will show an empty plot of the proper dimensions. To make it non-empty, I must supply another existing filename, though I am unclear on what exactly that should be.
from_fits_to_image(color_scheme='rgb', rloc=rloc)
Each of the function calls below reveal a plot that has been resized to small. While color_scheme='grayscale'
seems to colorize the plot properly, the other methods do not properly colorize the image.
from_fits_to_image('grayscale', rloc=rloc)
from_fits_to_image('false color', rloc=rloc)
from_fits_to_image('false color', rloc=rloc, cmap='plasma')
For comparison, the '.gif'
image is below. Ideally, the output will look exactly like the image below.
EDIT:
I have tried using astropy
, PIL
, and pyfits
unsuccessfully. Any help would be appreciated.
EDIT 2:
Below is the result using fits
from astropy.io
.
from astropy.io import fits
def reada(rloc, rname='synop_Ml_0.1998', rext='.fits'):
""" """
rpath = rloc + rname + rext
# hdu_list = fits.open(rpath)
# hdu_list.info()
pic = fits.getdata(rpath)
plt.imshow(pic)
plt.show()
reada(rloc=rloc)
I've played with the vmin
and vmax
kwargs, but to no success. Also, using pyfits
to open the file results in the following error, even when using pyfits.open(rpath, uint=True, do_not_scale_image_data=True)
:
TypeError: Image data can not convert to float
Upvotes: 1
Views: 712
Reputation: 3893
Judging from the gif, it seems that the image is a false-color one, and it's a matter of choosing a right color map. I can't say if there's an equivalent color map in python to the one you've linked to, but we can find something that is pretty close, recreating all the features in the image:
fig = aplpy.FITSFigure('synop_Ml_0.2104.fits')
fig.show_colorscale(vmin=-60, vmax=60, cmap='hot')
which shows the following (note that aplpy
does not understand this coordinate system so it plots the figure in pixel coordinates):
The second part of the question is more tricky, and I can't fully answer it. Firstly, you need to convert the Carrington time into longitude, and sine latitude into degrees, and then plot the new values for the axis labels either instead of the old ones or as a parasite axes alongside the old ones (you can refer to an parasite axes example here).
Now it looks like the Carrington time is just degrees rotated since November 9, 1853, and the x-axis spans exactly 360, so I assume the conversion is simply an offset by 757079.95, the the x-axis value at the left edge. We can double-check it on the world coordinates, by looking at how the pixel span of the map corresponds to the coordinate span:
In [88]: fig._wcs.wcs_pix2world(fig._ax1.get_xlim(), fig._ax1.get_ylim(), origin=1)
Out[88]: [array([757439.95, 757079.95]), array([-1., 1.])]
and the difference in values for the xaxis edges, 757079.95 and 757439.95, is exactly 360 degrees.
So then we can use some matplotlib
tricks to manually offset the coordinate values to force them to go from zero to 360 and get the xaxis to match your gif image:
# using hidden attributes is non-pythonic but aplpy does not leave us other options
ax = fig._ax1
x_range = ax.get_xlim()
new_ticklabels = np.arange(60, 361, 60)
new_tick_positions = new_ticklabels / 360. * x_range[1] + x_range[0]
ax.set_xticks(new_tick_positions)
ax.set_xticklabels(new_ticklabels)
fig.axis_labels.set_xtext('Carrington Longitude')
Keep in mind that aplpy
is a library designed for plotting celestial, not solar, coordinates, so getting the axes transform to work properly could be a rather painful process. An alternative way, and perhaps a better one, would be to plot the fits file with sunpy
, a python library for solar physics. However, I have never used it, and it seems to throw an error for this particular fits file. Looks like you need to modify the header of the fits file to get the coordinates properly read. Perhaps you can get in touch with sunpy
community if you want to use the library?
Upvotes: 2