1
$\begingroup$

Basically I'm trying to create code in python which will allow me to open a Fit's binary file, read it and create a scatter diagram with it. Hopefully plotting LogG vs Teff. But it seems like whichever way I do it,I just get one error or another. This is my code any ideas on how to fix it?

from astropy.io import fits

import matplotlib.pyplot as plt

b=fits.open("C:\\Users\\Robsh\\Documents\\VAC_GC_DR17_synspec_rev1-v1_1.fits")

teff=b[1].data["TEFF"]

logg=b[1].data["LOGG"]

plt.scatter(teff,logg,s=1000,color="blue",alpha=0.5)

plt.xlabel("TEFF")

plt.ylabel("LOGG")

plt.title("Scatter plot of astrophysical data")

plt.show()

This yields

AttributeError Traceback (most recent call last) Cell In[6], line 5 2 import matplotlib.pyplot as plt 4 fits.open=('VAC_GC_DR17_synspec_rev1-v1_1.fits') ----> 5 teff=b[1].data['TEFF'] 6 logg=b[1].data['LOGG'] 8 plt.scatter(teff,logg,s=1000,color="blue",alpha=0.5) AttributeError: 'str' object has no attribute 'data'

$\endgroup$
5
  • 2
    $\begingroup$ What errors? Are the errors specific to the fits package? $\endgroup$
    – James K
    Nov 19, 2023 at 18:22
  • 1
    $\begingroup$ As @JamesK says, we will need to see the actual errors or provide a link to the input FITS table before we can help $\endgroup$ Nov 20, 2023 at 5:55
  • 1
    $\begingroup$ AttributeError Traceback (most recent call last) Cell In[6], line 5 2 import matplotlib.pyplot as plt 4 fits.open=('VAC_GC_DR17_synspec_rev1-v1_1.fits') ----> 5 teff=b[1].data['TEFF'] 6 logg=b[1].data['LOGG'] 8 plt.scatter(teff,logg,s=1000,color="blue",alpha=0.5) AttributeError: 'str' object has no attribute 'data' $\endgroup$
    – Rob1
    Nov 20, 2023 at 18:41
  • 1
    $\begingroup$ Attribute error. That's the error message I get. It seems to have a problem with the fifth line for some reason. $\endgroup$
    – Rob1
    Nov 20, 2023 at 18:43
  • 1
    $\begingroup$ that error is telling you that b[1] is a string, and doesn't have a property called "data". you should inspect the contents of b and see what it contains (an HDUList, apparently: docs.astropy.org/en/stable/io/fits/api/files.html#open ) and adjust your code accordingly $\endgroup$
    – Aaron F
    Nov 20, 2023 at 19:12

1 Answer 1

5
$\begingroup$

It's generally best to use Astropy's Table/QTable functionality to manipulate the table data, rather than dealing with the FITS binary table directly. Building on what you have already, this involves turning the BinTableHDU section in element #1 of the HDUList into a Table:

from pathlib import Path
from astropy.io import fits
from astropy.table import QTable
import matplotlib.pyplot as plt

# Can also do `fits_table = Path.home() / 'Documents' / 'GC_members_VAC-v1_1.fits'` instead of below line
fits_table = Path.home().joinpath('Documents', 'GC_members_VAC-v1_1.fits')
hdulist = fits.open(fits_table)
print(hdulist.info)
Filename: C:\Users\foobar\Documents\GC_members_VAC-v1_1.fits
No.    Name      Ver    Type      Cards   Dimensions   Format
  0  PRIMARY       1 PrimaryHDU      16   (15172,)   uint8
  1  Joined        1 BinTableHDU    499   7737R x 242C   ['30A', '18A', 'D', 'D', 'D', 'D', 'D', 'D', 'I', '64A', '58A', '71A', '77A', '6A', 'J', '20A', '30A', 'D', 'D', 'D', 'D', 'E', 'E', 'E', 'E', 'E', 'E', '16A', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'J', 'J', 'E', 'E', '16A', 'E', '32A', 'E', 'E', 'J', 'J', 'J', 'J', 'J', 'J', '132A', '32A', '32A', 'J', 'E', 'E', 'K', '132A', 'K', '132A', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'J', 'J', 'E', 'E', 'E', 'E', 'E', 'E', 'K', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', '8A', '189E', '21E', '9E', '81E', 'E', '9E', '81E', '9K', 'K', '256A', 'E', 'E', 'E', '27E', '27D', '27E', '27E', '27E', '27E', '27E', '27E', '27K', 'J', 'K', '10A', '27E', '27E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', 'E', 'E', 'E', 'J', '100J']
# Turn into QTable
table = QTable(hdulist[1].data)

# Basic plot
plt.scatter(table['TEFF'], table['LOGG'], color="blue", alpha=0.5)
plt.gca().invert_yaxis()
plt.minorticks_on()
plt.xlabel(r"$T_{eff}$")
plt.ylabel(r"$\log g$")

(It appears that the data is from Schiavon et al. 2015 whose paper references the filename you have in your question but the link in their paper doesn't obviously lead to the same file. I think it's this Value Added Catalog, but that has a different filename but does have the two columns you mention with the same names so is probably the same dataset, just renamed... I've also used the user and platform-independent Python way of giving the path to the file in Documents/ folder of the user's home directory - should work on Windows, Linux and Mac.).

This code produces the following plot: Example plot

You can actually get the table in a single line by using the Table.read() method directly:

table = QTable.read(Path.home().joinpath('Documents', 'GC_members_VAC-v1_1.fits'))
$\endgroup$
7
  • $\begingroup$ +1, but the code is missing a from astropy.table import QTable. (also pathlib is preferred these days: table = QTable.read(str(pathlib.Path.home()/ "Documents" / "GC_members_VAC-v1_1.fits"))) $\endgroup$
    – Aaron F
    Nov 21, 2023 at 12:34
  • 1
    $\begingroup$ Fixed the missing import, thanks for the catch. Porting brain to Pathlib is on the to-do list for my Copious Free Time; I know it allows use of a single path separator on all platforms, is the .home() similarly functional on all platforms? $\endgroup$ Nov 21, 2023 at 17:12
  • $\begingroup$ Yeah,Ricardo is currently my supervisor for msc.He set me the task of reproducing some graphs but I have been having some trouble with the coding.We were actually discussing it last night and he said that he usually does it the way I tried and couldn't figure out what was wrong with it.He said he'd get back to me.I'll try it your way though and see what answer I get.Thanks. $\endgroup$
    – Rob1
    Nov 21, 2023 at 18:53
  • $\begingroup$ I don't see anything obviously wrong with your code unless fits.open() is returning something strange unexpectedly. However the use of QTable has a couple of advantages anyway: 1) automatic handling of units and conversion to Quantity objects if the right things are present in the FITS table, 2) easier support for sorting, subsetting, masking and the other benefits of the Astropy Table/QTable 3) easier export of the table in a variety of other formats $\endgroup$ Nov 21, 2023 at 19:43
  • $\begingroup$ yes it is, i get WindowsPath('C:/Users/Aaron') or PosixPath('/home/aaron') depending where i run it $\endgroup$
    – Aaron F
    Nov 21, 2023 at 22:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .