Spectral Access#

This notebook is one of a set produced by NAVO to demonstrate data access with python tools.

In this notebook, we show how to search for and retrieve spectra from VO services using the Registry and the Simple Spectral Access (SSA) protocol.

import numpy as np

import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline

import requests, io

from astropy.table import Table
import astropy.io.fits as fits
from astropy.coordinates import SkyCoord
# For downloading files
from astropy.utils.data import download_file

import pyvo as vo

# There are a number of relatively unimportant warnings that show up, so for now, suppress them:
import warnings
warnings.filterwarnings("ignore", module="astropy.io.votable.*")
warnings.filterwarnings("ignore", module="pyvo.utils.xml.*")

Finding available Spectral Access Services#

First, we find out what spectral access services (‘ssa’) are available in the Registry offering x-ray data.

services = vo.regsearch(servicetype='ssa',waveband='x-ray')
services.to_table()['ivoid','short_name']
Table length=7
ivoidshort_name
objectobject
ivo://nasa.heasarc/chanmasterChandra
ivo://nasa.heasarc/hitomasterHITOMASTER
ivo://nasa.heasarc/intbscINTEGRAL/BSC
ivo://nasa.heasarc/xrismmastrXRISMMASTR
ivo://nasa.heasarc/xtemasterRXTE
ivo://ned.ipac/sed_data_near_positionNED_SED
ivo://wfau.roe.ac.uk/heavens_at_isdc/light-curvesHEAVENS @ ISDC

We can look at only the Chandra entry:

chandra_service = [s for s in services if 'Chandra' in s.short_name][0]
chandra_service.access_url
'https://heasarc.gsfc.nasa.gov/xamin/vo/ssa?table=chanmaster&'

Chandra Spectrum of Delta Ori#

Getting the list of spectra.

delori = SkyCoord.from_name("Delta Ori")

spec_tables = chandra_service.search(pos=delori,diameter=0.1)
spec_tables.to_table().show_in_notebook()
WARNING: AstropyDeprecationWarning: show_in_notebook() is deprecated as of 6.1 and to create
         interactive tables it is recommended to use dedicated tools like:
         - https://github.com/bloomberg/ipydatagrid
         - https://docs.bokeh.org/en/latest/docs/user_guide/interaction/widgets.html#datatable
         - https://dash.plotly.com/datatable [warnings]
Table length=6
idxobsidstatusnameradectimedetectorgratingexposuretypepipublic_datedatalinkSSA_start_timeSSA_tmidSSA_stop_timeSSA_durationSSA_coord_obsSSA_raSSA_decSSA_fovSSA_titleSSA_referenceSSA_datalengthSSA_datamodelSSA_instrumentSSA_publisherSSA_formatSSA_wavelength_minSSA_wavelength_maxSSA_bandwidthSSA_bandpasscloud_access
degdegdsddddsdegdegdegdegmmmm
0639archivedDELTA ORI83.00125-0.2991751556.1364ACIS-SHETG49680GOCassinelli5203711724:chandra.obs.misc51556.136400463----49680.0--83.00125-0.299170.81acisf00639N005_pha2.fitshttps://heasarc.gsfc.nasa.gov/FTP/chandra/data/byobsid/9/639/primary/acisf00639N005_pha2.fits.gz12Spectrum-1.0ACIS-SHEASARCapplication/fits1.2398e-106.1992e-096.07522e-093.16159e-09{"aws":{"bucket_name":"nasa-heasarc","region":"us-east-1","policy":"open","key":"chandra/data/byobsid/9/639/primary/acisf00639N005_pha2.fits.gz"}}
17416archiveddelta Ori (HD 36486)83.00167-0.2990854413.427HRC-SLETG97080GORaassen5478311725:chandra.obs.misc54413.4270486111----97080.0--83.00167-0.299080.81hrcf07416N004_pha2.fitshttps://heasarc.gsfc.nasa.gov/FTP/chandra/data/byobsid/6/7416/primary/hrcf07416N004_pha2.fits.gz2Spectrum-1.0HRC-SHEASARCapplication/fits1.2398e-106.1992e-096.07522e-093.16159e-09{"aws":{"bucket_name":"nasa-heasarc","region":"us-east-1","policy":"open","key":"chandra/data/byobsid/6/7416/primary/hrcf07416N004_pha2.fits.gz"}}
214567archivedDelta Ori83.00167-0.2990856280.7037ACIS-SHETG116500GOCorcoran5664711726:chandra.obs.misc56280.7036921296----116500.0--83.00167-0.299080.81acisf14567N003_pha2.fitshttps://heasarc.gsfc.nasa.gov/FTP/chandra/data/byobsid/7/14567/primary/acisf14567N003_pha2.fits.gz12Spectrum-1.0ACIS-SHEASARCapplication/fits1.2398e-106.1992e-096.07522e-093.16159e-09{"aws":{"bucket_name":"nasa-heasarc","region":"us-east-1","policy":"open","key":"chandra/data/byobsid/7/14567/primary/acisf14567N003_pha2.fits.gz"}}
314568archivedDelta Ori83.00167-0.2990856288.1612ACIS-SHETG123600GOCorcoran5665511727:chandra.obs.misc56288.1612268519----123600.0--83.00167-0.299080.81acisf14568N003_pha2.fitshttps://heasarc.gsfc.nasa.gov/FTP/chandra/data/byobsid/8/14568/primary/acisf14568N003_pha2.fits.gz12Spectrum-1.0ACIS-SHEASARCapplication/fits1.2398e-106.1992e-096.07522e-093.16159e-09{"aws":{"bucket_name":"nasa-heasarc","region":"us-east-1","policy":"open","key":"chandra/data/byobsid/8/14568/primary/acisf14568N003_pha2.fits.gz"}}
414569archivedDelta Ori83.00167-0.2990856283.254ACIS-SHETG120850GOCorcoran5665011728:chandra.obs.misc56283.2539814815----120850.0--83.00167-0.299080.81acisf14569N003_pha2.fitshttps://heasarc.gsfc.nasa.gov/FTP/chandra/data/byobsid/9/14569/primary/acisf14569N003_pha2.fits.gz12Spectrum-1.0ACIS-SHEASARCapplication/fits1.2398e-106.1992e-096.07522e-093.16159e-09{"aws":{"bucket_name":"nasa-heasarc","region":"us-east-1","policy":"open","key":"chandra/data/byobsid/9/14569/primary/acisf14569N003_pha2.fits.gz"}}
514570archivedDelta Ori83.00167-0.2990856285.5508ACIS-SHETG124100GOCorcoran5665211729:chandra.obs.misc56285.5507986111----124100.0--83.00167-0.299080.81acisf14570N003_pha2.fitshttps://heasarc.gsfc.nasa.gov/FTP/chandra/data/byobsid/0/14570/primary/acisf14570N003_pha2.fits.gz12Spectrum-1.0ACIS-SHEASARCapplication/fits1.2398e-106.1992e-096.07522e-093.16159e-09{"aws":{"bucket_name":"nasa-heasarc","region":"us-east-1","policy":"open","key":"chandra/data/byobsid/0/14570/primary/acisf14570N003_pha2.fits.gz"}}

Accessing one of the spectra.

## If you only run this once, you can do it in memory in one line:
##  This fetches the FITS as an astropy.io.fits object in memory
# hdu_list = spec_tables[0].getdataobj()
## But if you might run this notebook repeatedly with limited bandwidth,
##  download it once and cache it.
file_name = download_file(spec_tables[0].getdataurl(),cache=True)
hdu_list = fits.open(file_name)

Simple example of plotting a spectrum#

spec_table = Table(hdu_list[1].data)
spec_table
Table length=12
SPEC_NUMTG_MTG_PARTTG_SRCIDXYCHANNELCOUNTSSTAT_ERRBACKGROUND_UPBACKGROUND_DOWNBIN_LOBIN_HI
int16int16int16int16float32float32int16[8192]int16[8192]float32[8192]int16[8192]int16[8192]float64[8192]float64[8192]
1-3114094.91384132.0761 .. 81920 .. 01.8660254 .. 1.86602540 .. 00 .. 07.159166666667378 .. 0.33333333333333337.160000000000712 .. 0.33416666666666667
2-2114094.91384132.0761 .. 81920 .. 01.8660254 .. 1.86602540 .. 00 .. 010.738750000000886 .. 0.510.740000000000887 .. 0.50125
3-1114094.91384132.0761 .. 81920 .. 01.8660254 .. 1.86602540 .. 00 .. 021.477500000001772 .. 1.021.480000000001773 .. 1.0025
41114094.91384132.0761 .. 81920 .. 01.8660254 .. 1.86602540 .. 00 .. 021.477500000001772 .. 1.021.480000000001773 .. 1.0025
52114094.91384132.0761 .. 81920 .. 01.8660254 .. 1.86602540 .. 00 .. 010.738750000000886 .. 0.510.740000000000887 .. 0.50125
63114094.91384132.0761 .. 81920 .. 01.8660254 .. 1.86602540 .. 00 .. 07.159166666667378 .. 0.33333333333333337.160000000000712 .. 0.33416666666666667
7-3214094.91384132.0761 .. 81920 .. 01.8660254 .. 1.86602540 .. 00 .. 013.985000000001373 .. 0.333333333333333313.98666666666804 .. 0.33499999999999996
8-2214094.91384132.0761 .. 81920 .. 01.8660254 .. 1.86602540 .. 00 .. 020.977500000001505 .. 0.520.980000000001507 .. 0.5025
9-1214094.91384132.0761 .. 81920 .. 01.8660254 .. 1.86602540 .. 00 .. 041.95500000000301 .. 1.041.960000000003014 .. 1.005
101214094.91384132.0761 .. 81920 .. 01.8660254 .. 1.86602540 .. 00 .. 041.95500000000301 .. 1.041.960000000003014 .. 1.005
112214094.91384132.0761 .. 81920 .. 01.8660254 .. 1.86602540 .. 00 .. 020.977500000001505 .. 0.520.980000000001507 .. 0.5025
123214094.91384132.0761 .. 81920 .. 01.8660254 .. 1.86602540 .. 00 .. 013.985000000001373 .. 0.333333333333333313.98666666666804 .. 0.33499999999999996
matplotlib.rcParams['figure.figsize'] = (12, 10)

for i in range(len(spec_table)):

    ax = plt.subplot(6,2,i+1)
    pha = plt.plot( spec_table['CHANNEL'][i],spec_table['COUNTS'][i])
    ax.set_yscale('log')

    if spec_table['TG_PART'][i] == 1:
        instr='HEG'
    if spec_table['TG_PART'][i] == 2:
        instr='MEG'
    if spec_table['TG_PART'][i] == 3:
        instr='LEG'

    ax.set_title("{grating}{order:+d}".format(grating=instr, order=spec_table['TG_M'][i]))

    plt.tight_layout()
../../_images/30257b95e25f26fd51bc900a1b1267a46c0c5e5f7382083c2daffec6fe02ba33.png

This can then be analyzed in your favorite spectral analysis tool, e.g., pyXspec. (For the winter 2018 AAS workshop, we demonstrated this in a notebook that you can consult for how to use pyXspec, but the pyXspec documentation will have more information.)