Measuring the Milky Way with Stars

What is this all about?

For this lab, students will investigate Python and Jupyter Notebook to analyze real astronomical images in order to calculate the interstellar distance to a star cluster across the Milky Way from our solar system. They will learn how to write Python code that runs in a Jupyter Notebook such that the brightness of stars in an astronomical image can be determined. Next, students will complete the functions in the project to determine how far away a single star in the cluster is from Earth. This is a chance to try hands-on astronomical research techniques in the field of aperture photometry. The real astronomical image data will be directly manipulated and analyzed by code the students create. Groups can compare their final images and results to answer questions about the astronomy of stars and stellar distances within the Milky Way. Students can experience their discoveries the same way Harlow Shapley first learned the true size and shape of the Milky Way.

Summer 2020 Update: Check out my iPoster about this project presented at The 236th Meeting of the American Astronomical Society!

Just so we’re clear…

  • This page is meant as a primer for other educators on how to use this lab with their classes. The text is both meant for “teacher talk” and as instructions for the instructor. The linked Jupyter Notebook​1​ below is what students are meant to use for the the activity. If you want to just download the notebooks:

Background before we dive in…

Did you know the first person to figure out the size and shape of the Milky Way galaxy, Harlow Shapley, had nothing more than some pictures of stars in far-off star clusters? All we need is light from a star to figure out a lot about the star, including how far it is from us. How can we measure astronomical distances? (listen for student responses) One technique is to use “standard candles,” which are astronomical objects that have well-known brightnesses. What are some other standard candles we have discussed in astronomy so far? (listen for student responses) By measuring how bright an object appears to us and knowing the actual brightness from some analysis, we can work out how far the object is from us. This is where the inverse square law comes in.

Remember that the inverse square law is one of the most useful tools in astronomy. It says that light spreads out as it rushes away from a star such that the brightness of the light decreases by a factor of 1 divided the change in distance squared. How is the inverse square law related to the relation for finding the surface area of a sphere? (allow the students time to recall the formula)

Harlow Shapley used a handy tool for a standard candle called RR Lyrae variable stars. We will do the same thing here. A variable star literally swells up and gets brighter and redder and then after a time shrinks again and gets dimmer and bluer. Imagine if the sun became 50% bigger than normal in the morning but by the evening shrink to 50% smaller than normal. It would make Earth a hard place to live. But luckily for us, for a star that takes a day to dim and then brighten and dim again, like the RR Lyrae type of variable, we know exactly how bright that star really is. What is the astronomical term we use for the intrinsic brightness of a star? (again, wait for responses) All we need  to do is use some clever math and the inverse square law and we can measure distances in the Milky Way once we find one of these variable stars.

We are in luck! We have 5 images of a globular cluster full of these RR Lyrae stars. Each image was taken in the same night. If we look at the images as an animation, the RR Lyrae stars are the ones that appear to blink brighter and dimmer. We will choose one and measure its light using some Python code.

Scientists often have to work on software engineering projects like this. We will write only some code, but we will take existing code, and make it do something new! We will engineer a solution to the given problem using the software tools and techniques available to us.

This is an interactive programming project called a Jupyter Notebook. There is background information, examples, and live code to run, test, and complete. All of this happens directly in your web browser rather than using a separate development application.

Need more info before starting?

Let’s get started!

The best way to start is to dive in! The supplied Jupyter Notebook has some background information, sample code, and the start code for you to complete. Start by loading the Jupyter Notebook on your computer. That might be by uploading the notebook to the Azure Notebook server or by starting Jupyter Notebook on your own computer and opening the starter notebook. We are using the Jupyter Notebook software (either local or online) to edit and write Python code. Python coding is becoming a big part of modern astronomical research. You’re using the same tools as professional astronomers in this activity.

The challenge here is to complete the code left blank by reading through the example code and working with other students to make your code work as expected. There are questions scattered throughout for you to answer in addition to the code to be completed.

Read through the background info until you get to the “Coding and Questions” section. Each cell in the Jupyter Notebook will have questions for you to answer as you interact with completed code or code to complete on your own and sometimes both. Don’t forget to test your solutions using the examples provided before moving on to the next cell. You’ll need all the parts to work individually before putting them together as a whole.

Many of the code cells are meant to be read and then run, but not altered, since they run correctly to start with. Below is a list of the functions to complete and descriptions of the incomplete cells for students to finish. Any code that has an ellipsis (…) needs to be completed.

Functions to complete:

  • distance_modulus – Function to find the distance of an astronomical object in parsecs if given the apparent, m, and absolute, M, magnitudes of the object. Use some algebra and rearrange the distance modulus equation to return the distance in parsecs of the object. Don’t forget how exponents work: x^2 (x squared) would be written as x**2.
    Distance modulus formula:    
  • process_image
    • This function consumes:
      • a filename which can be local or a URL for a FITS file,
      • the starting and ending points marking the bounding box for the image,
      • and whether or not the image needs to be flipped (both vertical and horizontal)
    • This function returns:
      • the apparent magnitude of the target star
    • The process image function is where we bring the steps together. Here is where the engineering process is needed.
      • Get the image data using the filename and mirror flag.
      • Get the subtracted data and background using the data from step 1
      • Extract a list of sources using the subtracted data, the background, and the given x and y pairs (2 x values and 2 y values).
      • Set the target as the center of the image.
      • Get the flux for our target star.
      • Get the flux for our calibration star.
      • Determine the apparent magnitude of the calibration star.
      • Calibrate the apparent magnitude of the target star.
      • Print and return our target star magnitude.

The 5 cells that call the “process_image” function will produce a number and also an image. This is image number 5 with the targets selected.

Note that the calibration star magnitude should be around 14.81 for each of the 5 processed images. The magnitude of the target star should vary between about 14.2 at the brightest and 15.5 at the dimmest.

The distance in the teacher notebook to cluster NGC 3201 yields a distance of 4.87 kpc or 15884 light years. For comparison, the Milky Way is about 100,000 light years across, and the sun is about 25,000 light years from the edge of the Milky Way galaxy.

Description of cells for students to complete using Jupyter Notebook:

# Process image 1
    Run process_image using the following parameters:

# Process image 2
    Run process_image using the following parameters:

# Process image 3
    Run process_image using the following parameters:

# Process image 4
    Run process_image using the following parameters:

# Process image 5
""" NOTE: This image was taken by a different telescope in the network 
and subsequently was slightly different than the other 4 images.
Be sure to set mirror to True for this star.
    Run process_image using the following parameters:
# Print out list of determined magnitudes for target star from the 5 images.
# Note the more negative a magnitude is, the brighter.
# Did the star vary in over the 5 images as expect for an RR Lyrae?
# Do the magnitudes make sense? Are any brighter or dimmer than the others?

# Select the brightest magnitude to use in the distance modulus calculation
# The command np.min(list) will return the smallest value in list.
# Why the smallest magnitude if we want the brightest one from the list?
brightest = np.min(target_mags)
brightest = ...

# Subtract off the reddening factor from our brightest value: 0.25
# The 0.25 is to correct for dust scattering some of the light.
# This is known as stellar reddening. The value was taken from literature.
m_target = ...

# Print our new apparent magnitude for our target star.

# Finally we find the distance to the globular cluster based on our analysis.
# Convert the given distance from pc to kpc.
distance = ...

# Print the distance in kpc .
print('Distance to NGC 3201: '+str(...)+' kpc')

Wrap thing up!

How far away is NGC 3201? According to other researchers, the distance to NGC 3201 is 16 kly or 4.9 kpc. How does your analysis compare?

Students should share their code and their results with one another. Consider a gallery walk or take volunteers to project the final result from various groups for the class to see. Discuss where difficulties arose and tackle questions about how students’ algorithms compared with one another.

What would have to change if we selected a new target star? How could we apply what we have done here for a different star cluster?


  • You probably want students to turn on the line numbering in Jupyter Notebook.
    • Have students go to View->Toggle Line Numbers in the menu bar.
  • Software engineering is meant to be a collaborative process. It’s best to treat this activity as a group activity and have groups share ideas and solutions to problems between themselves.


This project was developed through a combination of two NSF grant-funded programs: Teacher research internship at McDonald Observatory under the direction of University of Texas at Austin Department of Astronomy (NSF Grant No. AST-1616040 principal investigators Dr. C. Sneden & Dr. K. Finkelstein) and Expeditions in Computing Research Experience for Teachers under the direction of the Department of Electrical and Computer Engineering and the Office of STEM Engagement at Rice University (NSF Grant No. IIS-1730574 principal investigators Dr. A. Sabharwal & Dr. C. Nichol). Thanks also to Christina Crawford and Allen Antoine from the Rice Office of STEM Engagement. And thanks to Asa Stahl from Rice astrophysics and my colleague Justin Hickey from Episcopal High School in Bellaire, Texas, for inspiring me to create a Python astronomy lesson and helping with feedback. The project extensively depends on the SEP​3​ and Source Extractor​4​ libraries. The code uses standard implementations of the Numpy​2​ and AstroPy​5,6​ libraries. All images were taken using the Skynet Robotic Telescope Network​7​.


Measure the Milky Way with Stars Maker Challenge by Jimmy Newland is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.


Maker Challenge Testing Info

A similar activity was field-tested during the Research Experience for Teachers at Rice University in the summer of 2019 in conjunction with the Landes Research Group coding day. Most of the teachers and all of the students had never done any programming. There were 6 teachers and 6 students from public high schools in the area. The students were juniors and seniors. As an engineering activity, the students were asked to combine existing code with code they tested an wrote to complete a task.

  1. 1.
    KLUYVER T, RAGAN-KELLEY B, PÉREZ F, GRANGER B. Jupyter Notebooks—a publishing format for reproducible computational workflows. Positioning and Power in Academic Publishing: Players, Agents and Agendas. Published online 2016:87-90. doi:10.3233/978-1-61499-649-1-87
  2. 2.
    van der Walt S, Colbert SC, Varoquaux G. The NumPy Array: A Structure for Efficient Numerical Computation. Comput Sci Eng. Published online March 2011:22-30. doi:10.1109/mcse.2011.37
  3. 3.
    Barbary K. SEP: Source Extractor as a library. JOSS. Published online October 5, 2016:58. doi:10.21105/joss.00058
  4. 4.
    Bertin E, Arnouts S. SExtractor: Software for source extraction. Astron Astrophys Suppl Ser. Published online June 1996:393-404. doi:10.1051/aas:1996164
  5. 5.
    Robitaille TP, Tollerud EJ, et al. Astropy: A community Python package for astronomy. A&A. Published online September 30, 2013:A33. doi:10.1051/0004-6361/201322068
  6. 6.
    Price-Whelan AM, Sipőcz BM, et al. The Astropy Project: Building an Open-science Project and Status of the v2.0 Core Package. AJ. Published online August 23, 2018:123. doi:10.3847/1538-3881/aabc4f
  7. 7.
    Smith AB, Caton DB, Hawkins RL. Implementation and Operation of a Robotic Telescope on Skynet. PASP. Published online March 30, 2016:055002. doi:10.1088/1538-3873/128/963/055002

Leave a Reply