Skip to article frontmatterSkip to article content

Functions (and HII regions in M33)

In this week’s lab, we’ll see how to construct and use Python functions in practice, using a narrowband image of the galaxy M33 as our dataset.

Our ultimate goal will be to nicely plot and crop our image to make scientific measurements of the physical size of certain features in the galaxy.

We’ll also see at the end why writing functions was a useful way to organize and carry out this analysis. We’ll start focusing just on the image. In Part II, there is a scientific overview regarding HII regions and why we are interested in them.

# Some libraries we'll need throughout
from astropy.io import fits 
from astropy.wcs import WCS 
import numpy as np 
import matplotlib.pyplot as plt

Part 0: Warm up

Before we dive into new things, let’s re-familiarize ourselves with how to write some simple functions.

Part 1: Loading and viewing astronomical images

Astronomical images (those taken at a telescope like Keck Observatory, or in space, like HST or JWST) are, at their core, a 2D array of values. In general, we take images in one band (color) at a time, and if we want color images like those you can take with a camera, we have to later combine those images.

The vast majority of astronomical images that have been, and continue to be, taken are stored in a special file format called FITS. Fits stands for Flexible Image Transport System. It’s a binary format which requires specialized programs to open. One is SAOImage DS9, a GUI based tool I recommend having if you will be working with astronomical images.

In Python, we can use the astropy.io.fits module to load the header (a dictionary of information about the file) and data (images) from a FITS file.

Within a FITS file, information is stored in what are called extensions. These are like separate buckets/folders, and thus allow one to store multiple images, or an image + table, or multiple tables, within 1 file. But usually, we have a simple file with 1 image in the 0th extension, and its header.

When we load a FITS file, we usually also want to know something about the coordinates (on the sky, so RA and DEC) of the things in our image. To do this, we need to know the WCS (world coordinate system) coordinates of the image. The information needed to make one of these is in the image header, and there is an astropy function to convert a header to a wcs object.

The code below will load the M33 image we’ve provided into Python, setting the 2D array im as the image, and the wcs object via the astropy routine.

from astropy.io import fits 
from astropy.wcs import WCS 

with fits.open('./M33_halpha.fits') as hdu:
    im = hdu[0].data 
    wcs = WCS(hdu[0].header)

We can, if we wish, encapsulate this operation into a function. It’s short enough that it’s not overly onerous to write out each time. But we can make these three lines into one, which might make our code easier to read when loading many different fits files throughout a script.

There are now 13 lines of logic in our function, and hopefully it is becoming clear why making such a function is so useful --- we can now very quickly and easily load and plot any fits file, or any array we have on hand, with wcs on or off, with limits setting, all in one line.

Part II: The Size of HII Regions

The Science

For the rest of the assignment, we will be investigating the physical size of HII regions in nearby galaxy M33. Not sure what that means? Here’s a quick primer.

Stars form of many different masses (from much smaller than the sun to much larger), with many more low mass stars forming than massive stars^*. While very few high mass (e.g., 3-10+ MM_{\odot}) stars form at a time in a galaxy, they have an outsized effect, dominating the light of the low mass stars (though they live much shorter lives). They are also the only stars (dubbed O-type) who put out significant light in the ultraviolet part of the spectrum. We know that our own sun does emit some light in the UV (that’s the more high energy, dangerous light that can give us cancer, hence sunscreen), but these stars pump out most of their light in the UV.

UV light has enough energy to ionize the atoms in gas (especially hydrogen gas), which means to knock the bound electron out of the atom and leave behind a proton and an electron. In some equilibrium, these electrons recombine with protons, and the electrons cascade through several energy levels as they fall toward the ground (most bound) state. For each gap they drop, the atom emits a photon with an equivalent energy to the difference between the levels traversed.

This process of recombination produces light at specific wavelengths, so when you look at planetary nebulae, star forming regions, or supernova remnanta (see below), the colors are representitive of the different elements and energy levels being traversed.

eagle nebula The Eagle Nebule, where we can see the hollow region being blown out by young stars (with the famous pillars of creation remaining, soon to be whittled down. Credit: ESO

Bright, young stars actually put out enough radiation to “blow out” and push on the gas remaining from the clouds from which they formed. This carves our roughly spherical regions known as Strömgen spheres, the inner boundary of which is usually lit up in this ionized emission. The size of the sphere blown out depends on the total amount of flux coming from the bright stars, which in turn depends on how many of them there are.

In our image of M33, we can see lots of these roughly spherical regions being highlighted by the narrow, Hα filter being used to observe the galaxy. By measuring their size in pixels and using our knowledge of the distance to M33, we can perform some simple trigonometry to determine their actual physical sizes. As a bonus, we can then roughly estimate the number of O-type stars responsible for the visible HII region. (note that Starforming region and HII region are roughly synonymous; HII is the chemical name for ionized hydrogen).

*

Stars that form together out of one more massive cloud have masses drawn from what is called an initial mass function, or IMF, which is roughly exponential.

# Here is an an example of ~what you should be seeing
(<Figure size 700x700 with 1 Axes>, <Axes: >)
<Figure size 700x700 with 1 Axes>