<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 @username_1 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`](https://docs.astropy.org/en/stable/table/index.html) 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](https://arxiv.org/pdf/2310.07764.pdf) 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](https://www.sdss4.org/dr17/data_access/value-added-catalogs/?vac_id=apogee-globular-cluster-members-catalog) 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 ](https://i.sstatic.net/aLyir.png)](https://i.sstatic.net/aLyir.png)

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/username_3')` or `PosixPath('/home/username_3')` depending where i run it  
> **username_2**: Modified, happy now... ? ;-)  
> **username_3**: ahh, 'tis a thing of beauty!  

---

