{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "# Get Images from the PS1 Image Server\n", "\n", "The PanStarrs survey has imaged the entire night sky north of -30$^{\\circ}$. Although this makes makes it useful for many kinds of work, you may want to focus on one particular target or region. You might do this using the [PS1 image cutout web interface](http://ps1images.stsci.edu/cgi-bin/ps1cutouts). If you have many targets, a programmatic query would be better for this.\n", "\n", "This tutorial will demonstrate a way you can interface with the image server programmatically. To accomplish this, we'll follow this step-by-step workflow:\n", "\n", "* [Request a list of Available Images at Our Target Coordinates](#imlist)\n", "* [Generate the Image URL from the Filename](#imurl)\n", "* [Download the Images](#download)\n", " * [JPEG Images: Monochrome and Color](#jpeg)\n", " * [FITS Images](#fits)\n", "\n", "For more details on the services being used, see the PS1 Image Cutout Service documentation.\n", "\n", "### Imports\n", "We'll need to import a few packages to run our code.\n", "* `requests`, `io`, and `PIL` to request and read JPG images from the image server\n", "* `astropy` to read and visualize FITS files" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2024-10-21T18:54:36.726133Z", "iopub.status.busy": "2024-10-21T18:54:36.725936Z", "iopub.status.idle": "2024-10-21T18:54:37.766500Z", "shell.execute_reply": "2024-10-21T18:54:37.765857Z" } }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import numpy\n", "import requests\n", "import warnings\n", "\n", "from astropy.io import fits\n", "from astropy.visualization import PercentileInterval, AsinhStretch\n", "from astropy.table import Table\n", "from io import BytesIO\n", "from PIL import Image" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "## Getting a List of Images\n", "Before we download any images, we should query for a list of observations that include our target. In this case, we're looking for the Crab Nebula, so we'll need to input the corresponding coordinates.\n", "\n", "To make this task a little easier, we'll create a helper function called `get_image_table()` that takes in our coordinates and returns a table of results. To do this, we are essentially generating a URL with our query embedded, then reading the resulting webpage." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2024-10-21T18:54:37.768516Z", "iopub.status.busy": "2024-10-21T18:54:37.768333Z", "iopub.status.idle": "2024-10-21T18:54:37.771843Z", "shell.execute_reply": "2024-10-21T18:54:37.771287Z" } }, "outputs": [], "source": [ "def get_image_table(ra,dec,filters=\"grizy\"):\n", " \"\"\"\n", " Query ps1filenames.py service to get a list of images\n", " \n", " ra, dec = position in degrees\n", " filters = string with filters to include. includes all by default\n", " Returns a table with the results\n", " \"\"\"\n", " service = \"https://ps1images.stsci.edu/cgi-bin/ps1filenames.py\"\n", " # The final URL appends our query to the PS1 image service\n", " url = f\"{service}?ra={ra}&dec={dec}&filters={filters}\"\n", " # Read the ASCII table returned by the url\n", " table = Table.read(url, format='ascii')\n", " return table" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With the helper function defined, it's now straightforward to execute our query." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2024-10-21T18:54:37.773803Z", "iopub.status.busy": "2024-10-21T18:54:37.773498Z", "iopub.status.idle": "2024-10-21T18:54:38.501751Z", "shell.execute_reply": "2024-10-21T18:54:38.501154Z" } }, "outputs": [ { "data": { "text/html": [ "
projcell | subcell | ra | dec | filter | mjd | type | filename | shortname | badflag |
---|---|---|---|---|---|---|---|---|---|
int64 | int64 | float64 | float64 | str1 | float64 | str5 | str70 | str43 | int64 |
1784 | 59 | 83.63321 | 22.01446 | g | 0.0 | stack | /rings.v3.skycell/1784/059/rings.v3.skycell.1784.059.stk.g.unconv.fits | rings.v3.skycell.1784.059.stk.g.unconv.fits | 0 |
1784 | 59 | 83.63321 | 22.01446 | i | 0.0 | stack | /rings.v3.skycell/1784/059/rings.v3.skycell.1784.059.stk.i.unconv.fits | rings.v3.skycell.1784.059.stk.i.unconv.fits | 0 |
1784 | 59 | 83.63321 | 22.01446 | r | 0.0 | stack | /rings.v3.skycell/1784/059/rings.v3.skycell.1784.059.stk.r.unconv.fits | rings.v3.skycell.1784.059.stk.r.unconv.fits | 0 |
1784 | 59 | 83.63321 | 22.01446 | y | 0.0 | stack | /rings.v3.skycell/1784/059/rings.v3.skycell.1784.059.stk.y.unconv.fits | rings.v3.skycell.1784.059.stk.y.unconv.fits | 0 |
1784 | 59 | 83.63321 | 22.01446 | z | 0.0 | stack | /rings.v3.skycell/1784/059/rings.v3.skycell.1784.059.stk.z.unconv.fits | rings.v3.skycell.1784.059.stk.z.unconv.fits | 0 |