<p>It's generally best to use Astropy's <a href="https://docs.astropy.org/en/stable/table/index.html" rel="nofollow noreferrer"><code>Table/QTable</code></a> 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 <code>BinTableHDU</code> section in element #1 of the <code>HDUList</code> into a Table:</p>
<pre><code>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=&quot;blue&quot;, alpha=0.5)
plt.gca().invert_yaxis()
plt.minorticks_on()
plt.xlabel(r&quot;<span class="math-container">$T_{eff}$</span>&quot;)
plt.ylabel(r&quot;<span class="math-container">$\log g$</span>&quot;)
</code></pre>
<p>(It <em>appears</em> that the data is from <a href="https://arxiv.org/pdf/2310.07764.pdf" rel="nofollow noreferrer">Schiavon et al. 2015</a> 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 <em>think</em> it's <a href="https://www.sdss4.org/dr17/data_access/value-added-catalogs/?vac_id=apogee-globular-cluster-members-catalog" rel="nofollow noreferrer">this</a> 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 <code>Documents/</code> folder of the user's home directory - should work on Windows, Linux and Mac.).</p>
<p>This code produces the following plot:
<a href="https://i.sstatic.net/aLyir.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/aLyir.png" alt="Example plot " /></a></p>
<p>You can actually get the table in a single line by using the <code>Table.read()</code> method directly:</p>
<pre><code>table = QTable.read(Path.home().joinpath('Documents', 'GC_members_VAC-v1_1.fits'))
</code></pre>

CC BY-SA 4.0
2023-11-21T12:34:52.100Z
+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()`](https://docs.python.org/3/library/pathlib.html?highlight=pathlib#pathlib.Path.home)`/ "Documents" / "GC_members_VAC-v1_1.fits"))`)
Aaron F
CC BY-SA 4.0
2023-11-21T17:12:34.643Z
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?
astrosnapper
CC BY-SA 4.0
2023-11-21T18:53:03.737Z
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.
Rob1
CC BY-SA 4.0
2023-11-21T19:43:33.373Z
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
astrosnapper
CC BY-SA 4.0
2023-11-21T22:54:30.517Z
yes it is, i get `WindowsPath('C:/Users/Aaron')` or `PosixPath('/home/aaron')` depending where i run it
Aaron F
CC BY-SA 4.0
2023-11-22T00:23:58.657Z
Modified, happy now... ? ;-)
astrosnapper
CC BY-SA 4.0
2023-11-22T00:25:33.440Z
ahh, 'tis a thing of beauty!
Aaron F
CC BY-SA 4.0
2023-11-21T01:14:34.573Z
2023-11-22T00:22:26.797Z
2023-11-22T00:22:26.797Z
astrosnapper
<p>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?</p>
<pre><code>from astropy.io import fits

import matplotlib.pyplot as plt

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

teff=b[1].data[&quot;TEFF&quot;]

logg=b[1].data[&quot;LOGG&quot;]

plt.scatter(teff,logg,s=1000,color=&quot;blue&quot;,alpha=0.5)

plt.xlabel(&quot;TEFF&quot;)

plt.ylabel(&quot;LOGG&quot;)

plt.title(&quot;Scatter plot of astrophysical data&quot;)

plt.show()
</code></pre>
<p>This yields</p>
<p><code>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') ----&gt; 5 teff=b[1].data['TEFF'] 6 logg=b[1].data['LOGG'] 8 plt.scatter(teff,logg,s=1000,color=&quot;blue&quot;,alpha=0.5) AttributeError: 'str' object has no attribute 'data'</code></p>

CC BY-SA 4.0
2023-11-19T18:22:55.397Z
What errors?  Are the errors specific to the `fits` package?
James K
CC BY-SA 4.0
2023-11-20T05:55:17.997Z
As @JamesK says, we will need to see the actual errors or provide a link to the input FITS table before we can help
astrosnapper
CC BY-SA 4.0
2023-11-20T18:41:32.310Z
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'
Rob1
CC BY-SA 4.0
2023-11-20T18:43:05.230Z
Attribute error. That's the error message I get. It seems to have a problem with the fifth line for some reason.
Rob1
CC BY-SA 4.0
2023-11-20T19:12:53.463Z
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`](https://docs.astropy.org/en/stable/io/fits/api/hdulists.html#astropy.io.fits.HDUList), apparently: https://docs.astropy.org/en/stable/io/fits/api/files.html#open ) and adjust your code accordingly
Aaron F
<python><fits>
Plotting scatter graphs with fits binary file?
Rob1
# Plotting scatter graphs with fits binary file?

(Asked by: username_0 on 2023-11-19)

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'

**Tags:** python, fits

> **Comments:**
> **username_1**: What errors?  Are the errors specific to the `fits` package?  
> **username_2**: As @JamesK says, we will need to see the actual errors or provide a link to the input FITS table before we can help  
> **username_0**: 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'  
> **username_0**: Attribute error. That's the error message I get. It seems to have a problem with the fifth line for some reason.  
> **username_3**: 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`](https://docs.astropy.org/en/stable/io/fits/api/hdulists.html#astropy.io.fits.HDUList), apparently: https://docs.astropy.org/en/stable/io/fits/api/files.html#open ) and adjust your code accordingly  

---

## 1 answers

### Answer by username_2 on 2023-11-21. Score: 5

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:

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

> **Comments:**
> **username_3**: +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()`](https://docs.python.org/3/library/pathlib.html?highlight=pathlib#pathlib.Path.home)`/ "Documents" / "GC_members_VAC-v1_1.fits"))`)  
> **username_2**: 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?  
> **username_0**: 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.  
> **username_2**: 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  
> **username_3**: yes it is, i get `WindowsPath('C:/Users/Aaron')` or `PosixPath('/home/aaron')` depending where i run it  
> **username_2**: Modified, happy now... ? ;-)  
> **username_3**: ahh, 'tis a thing of beauty!  

---

