Skip to content

Add tutorial #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
370 changes: 370 additions & 0 deletions FITS-tables.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,370 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Viewing and manipulating data from FITS tables\n",
"\n",
"## Authors\n",
"Lia Corrales, Kris Stern\n",
"\n",
"## Learning Goals\n",
"* Download a FITS table file from a URL \n",
"* Open a FITS table file and view table contents\n",
"* Make a 2D histogram with the table data\n",
"* Close the FITS file after use\n",
"\n",
"## Keywords\n",
"FITS, file input/output, table, numpy, matplotlib, histogram\n",
"\n",
"\n",
"## Summary\n",
"\n",
"This tutorial demonstrates the use of `astropy.utils.data` to download a data file, then uses `astropy.io.fits` and `astropy.table` to open the file. Lastly, `matplotlib` is used to visualize the data as a histogram."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"from astropy.io import fits\n",
"from astropy.table import Table\n",
"from matplotlib.colors import LogNorm\n",
"\n",
"# Set up matplotlib\n",
"import matplotlib.pyplot as plt\n",
"\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The following line is needed to download the example FITS files used in this tutorial."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from astropy.utils.data import download_file"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"FITS files often contain large amounts of multi-dimensional data and tables. \n",
"\n",
"In this particular example, we'll open a FITS file from a Chandra observation of the Galactic Center. The file contains a list of events with x and y coordinates, energy, and various other pieces of information."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"event_filename = download_file(\n",
" \"http://data.astropy.org/tutorials/FITS-tables/chandra_events.fits\", cache=True\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Opening the FITS file and viewing table contents"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Since the file is big, let's open it with `memmap=True` to prevent RAM storage issues."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"hdu_list = fits.open(event_filename, memmap=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"hdu_list.info()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this case, we're interested in reading EVENTS, which contains information about each X-ray photon that hit the detector."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To find out what information the table contains, let's print the column names."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(hdu_list[1].columns)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we'll take this data and convert it into an [astropy table](http://docs.astropy.org/en/stable/table/). While it's possible to access FITS tables directly from the ``.data`` attribute, using [Table](http://docs.astropy.org/en/stable/api/astropy.table.Table.html#astropy.table.Table) tends to make a variety of common tasks more convenient."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"evt_data = Table(hdu_list[1].data)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For example, a preview of the table is easily viewed by simply running a cell with the table as the last line:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"evt_data"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can extract data from the table by referencing the column name. Let's try making a histogram for the energy of each photon, which will give us a sense for the spectrum (folded with the detector's efficiency)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"energy_hist = plt.hist(evt_data[\"energy\"], bins=\"auto\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Making a 2D histogram with some table data"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We'll make an image by binning the x and y coordinates of the events into a 2D histogram."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This particular observation spans five CCD chips. First, we determine the events that only fell on the main (ACIS-I) chips, which have number ids 0, 1, 2, and 3."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ii = np.in1d(evt_data[\"ccd_id\"], [0, 1, 2, 3])\n",
"np.sum(ii)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Method 1: Use numpy to make a 2D histogram and imshow to display it"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This method allows us to create an image without stretching:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"NBINS = (100, 100)\n",
"\n",
"img_zero, yedges, xedges = np.histogram2d(evt_data[\"x\"][ii], evt_data[\"y\"][ii], NBINS)\n",
"\n",
"extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]\n",
"\n",
"plt.imshow(\n",
" img_zero, extent=extent, interpolation=\"nearest\", cmap=\"gist_yarg\", origin=\"lower\"\n",
")\n",
"\n",
"plt.xlabel(\"x\")\n",
"plt.ylabel(\"y\")\n",
"\n",
"# To see more color maps\n",
"# http://wiki.scipy.org/Cookbook/Matplotlib/Show_colormaps"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Method 2: Use hist2d with a log-normal color scheme"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"NBINS = (100, 100)\n",
"img_zero_mpl = plt.hist2d(\n",
" evt_data[\"x\"][ii], evt_data[\"y\"][ii], NBINS, cmap=\"viridis\", norm=LogNorm()\n",
")\n",
"\n",
"cbar = plt.colorbar(ticks=[1.0, 3.0, 6.0])\n",
"cbar.ax.set_yticklabels([\"1\", \"3\", \"6\"])\n",
"\n",
"plt.xlabel(\"x\")\n",
"plt.ylabel(\"y\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Close the FITS file"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When you're done using a FITS file, it's often a good idea to close it. That way you can be sure it won't continue using up excess memory or file handles on your computer. (This happens automatically when you close Python, but you never know how long that might be...)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"hdu_list.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exercises"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Make a scatter plot of the same data you histogrammed above. The [plt.scatter](http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.scatter) function is your friend for this. What are the pros and cons of doing it this way?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Try the same with the [plt.hexbin](http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.hexbin) plotting function. Which do you think looks better for this kind of data?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Choose an energy range to make a slice of the FITS table, then plot it. How does the image change with different energy ranges?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"astropy-tutorials": {
"author": "Lia R. Corrales <lia@astro.columbia.edu>",
"date": "January 2014",
"description": "astropy.utils.data to download the file, astropy.io.fits to open and view the file, matplotlib for making both 1D and 2D histograms of the data.",
"link_name": "Viewing and manipulating data from FITS tables",
"name": "",
"published": true
},
"language_info": {
"codemirror_mode": {
"name": "ipython"
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
6 changes: 3 additions & 3 deletions metadata.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
title: "Example Title"
slug: "Example-Title"
source: "tutorial--example-title"
title: "FITS Tables"
slug: "FITS-tables"
source: "tutorial--FITS-tables"
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
astropy
matplotlib
numpy