{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Observing Run Preparation Module\n", "\n", "**Lecturer:** Robert Quimby
\n", "**Live Session:** Robert Quimby, Varun Bhalerao
\n", "**Jupyter Notebook Author:** Shubham Srivastav, Cameron Hummels & Robert Quimby\n", "\n", "This is a Jupyter notebook lesson taken from the GROWTH Summer School 2020. For other lessons and their accompanying lectures, please see: http://growth.caltech.edu/growth-astro-school-2020-resources.html\n", "\n", "## Objective\n", "Demonstrate how to plan observations prior to an observing run.\n", "\n", "## Key steps\n", "- Select targets\n", "- Get visibility and airmass plots\n", "- Get moon separation angles\n", "- Calculate exposure times for targets\n", "\n", "## Required dependencies\n", "\n", "See GROWTH school webpage for detailed instructions on how to install these modules and packages. Nominally, you should be able to install the python modules with `pip install `. The external astromatic packages are easiest installed using package managers (e.g., `rpm`, `apt-get`).\n", "\n", "### Python modules\n", "* python 3\n", "* astropy\n", "* numpy\n", "* matplotlib\n", "* astroplan\n", "* pytz\n", "\n", "### External packages\n", "None" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from astropy import units as u\n", "from astropy.time import Time\n", "from astropy.coordinates import SkyCoord\n", "from astropy.coordinates import EarthLocation\n", "import pytz\n", "%matplotlib inline\n", "from astroplan import Observer, FixedTarget\n", "from astropy.utils.iers import conf\n", "conf.auto_max_age = None\n", "from astroplan import download_IERS_A \n", "from astropy.coordinates import get_sun, get_moon, get_body\n", "from astroplan import moon_illumination" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Date and Time\n", "- Dates and times are in UTC\n", "- Default time is 00:00:00 UTC (verify this)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "date = Time(\"2018-12-03\", format='iso')\n", "print(date)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### What is the current UTC?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "now = Time.now()\n", "print(now)\n", "print(now.jd)\n", "print(now.mjd)\n", "print(now.decimalyear)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise\n", "What time will it be (in UTC) after 1 hour 45 minutes from `now`? Complete the line below to print it out." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Using UT1\n", "- To keep accurate time, the changes in earth's rotation period have to be taken into account.\n", "- AstroPy does this using a convention called UT1, that is tied to the rotation of earth with respect to the position of distant quasars. IERS - International Earth Rotation and Reference Systems Service keeps continuous tabs on the orientation of the earth and updates the data in the IERS bulletin.\n", "Update the bulletin:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "download_IERS_A()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Check to see what observatories are available in the database." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"Available observatories: \\n{0}\"\n", " .format(', '.join(EarthLocation.get_site_names())))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Setting up observatory location" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Let us manually add the location for the Liverpool Telescope\n", "latitude = 28.76234 * u.deg\n", "longitude = -17.87925 * u.deg\n", "elevation = 2363 * u.m\n", "location = EarthLocation.from_geodetic(longitude, latitude, elevation)\n", "\n", "# You can optionally specify a time zone as well. \n", "# A list of timezones can be found at https://stackoverflow.com/questions/13866926/is-there-a-list-of-pytz-timezones\n", "liverpool = Observer(location = location, timezone = 'Europe/Madrid',\n", " name = \"LT\", description = \"Liverpool Telescope\")\n", "liverpool" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# If you know the name, you can set a location accordingly\n", "location = EarthLocation.of_site(\"Roque de los Muchachos\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### Sunset, Sunrise, Midnight" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Calculating the sunset, midnight and sunrise times for our observatory \n", "# What is astronomical twilight?\n", "sunset_liverpool = liverpool.sun_set_time(now, which='nearest')\n", "eve_twil_liverpool = liverpool.twilight_evening_astronomical(now, which='nearest')\n", "midnight_liverpool = liverpool.midnight(now, which='next')\n", "morn_twil_liverpool = liverpool.twilight_morning_astronomical(now, which='next')\n", "sunrise_liverpool = liverpool.sun_rise_time(now, which='next')\n", "\n", "print(\"Sunset at Liverpool will be at {0.iso} UTC\".format(sunset_liverpool))\n", "print(\"Astronomical evening twilight at Liverpool will be at {0.iso} UTC\".format(eve_twil_liverpool))\n", "print(\"Midnight at Liverpool will be at {0.iso} UTC\".format(midnight_liverpool))\n", "print(\"Astronomical morning twilight at Liverpool will be at {0.iso} UTC\".format(morn_twil_liverpool))\n", "print(\"Sunrise at Liverpool will be at {0.iso} UTC\".format(sunrise_liverpool))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise \n", "Find the effective length of time (in hours) available for optical astronomical observations at Liverpool Telescope tonight" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Local Sidereal Time (LST)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#What is the LST now at Liverpool Telescope?\n", "#What would the LST be at Liverpool Telescope at local midnight?\n", "lst_now = liverpool.local_sidereal_time(now)\n", "lst_mid = liverpool.local_sidereal_time(midnight_liverpool)\n", "print(\"LST at Liverpool Telescope now is {0:.2f}\".format(lst_now))\n", "print(\"LST at Liverpool Telescope at local midnight will be {0:.2f}\".format(lst_mid))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Choosing targets for observations\n", "Targets can be defined by name or coordinates.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# using coordinates\n", "coords = SkyCoord('18h53m35.097s +33d01m44.8831s', frame='icrs') # coordinates of the Ring Nebula (M57) \n", "m57 = FixedTarget(name = 'M57', coord=coords)\n", "m57.ra.hms" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# by name\n", "target = FixedTarget.from_name('m57') # Messier 57\n", "target.coord" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Check to see if target is \"up\" at evening twilight (assume \"up\" means more than 30 degrees above the horizon). Also check if target is available at midnight and morning twilight." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# check if the target is up\n", "print(liverpool.target_is_up(eve_twil_liverpool, m57, horizon=30*u.deg))\n", "print(liverpool.target_is_up(midnight_liverpool, m57, horizon=30*u.deg))\n", "print(liverpool.target_is_up(morn_twil_liverpool, m57, horizon=30*u.deg))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Altitude and Azimuth of target at evening twilight\n", "aa = liverpool.altaz(eve_twil_liverpool, m57)\n", "aa.alt.degree, aa.az.degree" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Determine the time at which the target rises" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "m57rise = liverpool.target_rise_time(now, m57, which = 'next', horizon=0*u.deg)\n", "print(m57rise.iso) #default format is JD" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Dealing with moving targets" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "get_body('jupiter', now)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# get moon position at midnight \n", "get_moon(midnight_liverpool)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# How bright is the moon at midnight?\n", "moon_illumination(midnight_liverpool)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# We can turn solar system objects into 'pseudo-fixed' targets to plan observations\n", "saturn_midnight = FixedTarget(name = 'Saturn', coord = get_body('saturn', midnight_liverpool))\n", "saturn_midnight.coord" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Airmass\n", "- Ideally, targets should be observed when they have the least airmass. Airmass ranges from 1 (zenith) to ~38 at the horizon.\n", "- Airmass is 2.0 at alt=30, 2.9 at alt=20 and 3.9 at alt=15 degrees\n", "- As a general rule of thumb, try observing targets when airmass < 2\n", "- Let us find the airmass of M57 at midnight at Liverpool Telescope" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#Is the target up at Liverpool Telescope at midnight?\n", "liverpool.target_is_up(midnight_liverpool, target)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#lets check the alt and az of the target at midnight\n", "target_altaz = liverpool.altaz(midnight_liverpool, target)\n", "target_altaz.altaz" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That is about midway up from the horizon, not too bad." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#Find the airmass\n", "target_altaz.secz" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Plots to help planning" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can visualize what we have done so far using some plots" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "from astroplan.plots import plot_sky, plot_airmass" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#position of target at midnight\n", "plot_sky(target, liverpool, midnight_liverpool);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let us see how the target moves over the course of the night" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "t_start = eve_twil_liverpool\n", "t_end = morn_twil_liverpool\n", "t_observe = t_start + (t_end - t_start) * np.linspace(0.0, 1.0, 20)\n", "plot_sky(target, liverpool, t_observe);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's plot the airmass as a function of time" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plot_airmass(target, liverpool, t_observe)\n", "plt.grid();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The airmass is above 2 for the better part of the night, making M57 a reasonable summer target from Liverpool Observatory.\n", "Note that the default airmass limit is 3 in astroplan, corresponding to ~19 degrees elevation." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Finder Charts" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from astroplan.plots import plot_finder_image\n", "from astroquery.skyview import SkyView" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Load an image of the field in which the target lies." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# field of view corresponding to the IO:O instrument on the Liverpool Telescope\n", "fov = 10*u.arcmin\n", "\n", "# plot the image\n", "plot_finder_image(target, fov_radius=fov); " ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "Now let's define an array of targets to work with" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "target_names = ['vega', 'polaris', 'm1', 'm42', 'm55']\n", "targets = [FixedTarget.from_name(target) for target in target_names]\n", "targets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Which of these targets are up now?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "liverpool.target_is_up(now, targets)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Which of these targets are up at local midnight?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "liverpool.target_is_up(midnight_liverpool, targets)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise\n", "Find out the times at which the targets rise to an elevation of 10 degrees. Use target_rise_time. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How high is Vega above the horizion now?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "liverpool.altaz(now, targets[0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's plot the elevation of Vega to see how it varies over the night" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "times = (t_start - 0.5 * u.h) + (t_end - t_start + 1 * u.h) * np.linspace(0.0, 1.0, 40)\n", "elevations = liverpool.altaz(times, targets[0]).alt\n", "ax = plt.gca()\n", "ax.plot_date(times.plot_date, elevations.deg)\n", "ax.set(xlabel = 'Time UTC [MM-DD HH]', ylabel = 'Altitude [deg]')\n", "plt.setp(ax.get_xticklabels(), rotation=45, ha='right')\n", "plt.grid()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise\n", "Plot the altitude as a function of time for tonight for each of the targets in a single plot" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise\n", "Plot sky positions for each target using plot_sky for tonight at Liverpool Telescope in a single plot." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise\n", "Plot airmass vs time for each target in targets for tonight at Liverpool Telescope." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "### Observational Constraints\n", "You can set specific constraints that define when a target is \"observable\"\n", "- twilight level (e.g., \"Civil\")\n", "- airmass\n", "- altitude limits" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from astroplan import (AltitudeConstraint, AirmassConstraint,\n", " AtNightConstraint, MoonSeparationConstraint)\n", "constraints = [AltitudeConstraint(15*u.deg, 84*u.deg),\n", " AirmassConstraint(3), AtNightConstraint.twilight_civil(), MoonSeparationConstraint(min = 10 * u.deg)]\n", "t_range = Time([t_start - 0.5 * u.hour, t_end + 0.5 * u.hour])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from astroplan import is_observable, is_always_observable, months_observable\n", "\n", "# Are targets ever observable in the time range?\n", "ever_observable = is_observable(constraints, liverpool, targets, time_range=t_range)\n", "print(ever_observable)\n", "\n", "# Are targets always observable in the time range?\n", "always_observable = is_always_observable(constraints, liverpool, targets, time_range=t_range)\n", "print(always_observable)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The functions is_observable and ever_observable return boolean arrays. Let's print their output in tabular form." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from astropy.table import Table\n", "observability_table = Table()\n", "observability_table['targets'] = [target.name for target in targets]\n", "observability_table['ever_observable'] = ever_observable\n", "observability_table['always_observable'] = always_observable\n", "print(observability_table)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or we could do this directly using the observability_table function " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from astroplan import observability_table\n", "table = observability_table(constraints, liverpool, targets, time_range = t_range)\n", "print(table)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "# During what months are the targets ever observable?\n", "months_observable(constraints, liverpool, targets)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Exercise\n", "- Create a list of your favourite targets and store it in a text file with 3 columns - name, RA and Dec. Or you could use 'targetlists.txt' which already contains a list of targets. \n", "- Read the text file, and store the targets as FixedTarget objects.\n", "- Get observability tables for all the targets for different moon separation angles (10, 20, 30... degrees)\n", "- Plot airmass and sky position as a function of time for tonight for all your targets." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.7" } }, "nbformat": 4, "nbformat_minor": 2 }