{ "cells": [ { "cell_type": "markdown", "metadata": { "id": "bYYGJvqP-Csl" }, "source": [ "# Identifying transiting exoplanet signals in a light curve" ] }, { "cell_type": "markdown", "metadata": { "id": "gOFEJAKe-vjA" }, "source": [ "## Learning Goals\n", "\n", "By the end of this tutorial, you will:\n", "\n", " - Understand the \"Box Least Squares\" (BLS) method for identifying transit signals.\n", " - Know how to use the Lightkurve [BoxLeastSquaresPeriodogram](https://docs.lightkurve.org/reference/api/lightkurve.periodogram.BoxLeastSquaresPeriodogram.from_lightcurve.html?highlight=boxleastsquaresperiodogram) to identify a transiting planet.\n", " - Be able to estimate the period, epoch, and duration of the transit.\n", " - Be able to plot the phase-folded transit light curve.\n", " - Be familiar with the interactive Box Least Squares periodogram in Lightkurve." ] }, { "cell_type": "markdown", "metadata": { "id": "7NGNkiQB-sKQ" }, "source": [ "## Introduction\n", "\n", "The *Kepler* and *TESS* missions are optimized for finding new transiting exoplanets. [Lightkurve](http://docs.lightkurve.org/) provides a suite of tools that help make the process of identifying and characterizing planets convenient and accessible.\n", "\n", "In this tutorial, we will show you how to conduct your own search for transiting exoplanets in *Kepler* and *TESS* light curves. [Lightkurve](http://docs.lightkurve.org/) uses the [Astropy](https://www.astropy.org/) implementation of the Box Least Squares (BLS) method to identify transit signals. This tutorial demonstrates the basics of how to optimally use Lightkurve's BLS tools." ] }, { "cell_type": "markdown", "metadata": { "id": "EAzRgQPpAcBR" }, "source": [ "## Imports\n", "This tutorial requires the [**Lightkurve**](http://docs.lightkurve.org/) package, which uses [**Matplotlib**](https://matplotlib.org/) for plotting." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "azlcSd2lAjhy" }, "outputs": [], "source": [ "import lightkurve as lk\n", "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": { "id": "IChTo8Ir3-Ju" }, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": { "id": "r6p8DOLURorT" }, "source": [ "## 1. Downloading a Light Curve and Removing Long-Term Trends" ] }, { "cell_type": "markdown", "metadata": { "id": "QQLSlKKPOxEW" }, "source": [ "As an example, we will download all available [*Kepler*](https://archive.stsci.edu/kepler) observations for a known multi-planet system, [Kepler-69](https://iopscience.iop.org/article/10.1088/0004-637X/768/2/101)." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 387 }, "executionInfo": { "elapsed": 72588, "status": "ok", "timestamp": 1601412555227, "user": { "displayName": "Susan Mullally", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GhoAkTlu5JCXqC32438ISJU86DPSZdvoBOLwtOQMfU=s64", "userId": "01921813910966567332" }, "user_tz": 240 }, "id": "6mO0bXd6Rw5X", "outputId": "0bbf9a53-3897-483a-d2a0-7737981a6494" }, "outputs": [], "source": [ "# Search for Kepler observations of Kepler-69\n", "search_result = lk.search_lightcurve('Kepler-69', author='Kepler', cadence='long')\n", "# Download all available Kepler light curves\n", "lc_collection = search_result.download_all()\n", "lc_collection.plot();" ] }, { "cell_type": "markdown", "metadata": { "id": "v3CQzkKfPO8e" }, "source": [ "Each observation has a different offset, so in order to successfully search this light curve for transits, we first need to normalize and flatten the full observation. This can be performed on a stitched light curve. For more information about combining multiple observations of the same target, please see the companion tutorial on combining multiple quarters of *Kepler* data with Lightkurve." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 442 }, "executionInfo": { "elapsed": 72582, "status": "ok", "timestamp": 1601412555229, "user": { "displayName": "Susan Mullally", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GhoAkTlu5JCXqC32438ISJU86DPSZdvoBOLwtOQMfU=s64", "userId": "01921813910966567332" }, "user_tz": 240 }, "id": "V0XVebt-AM-4", "outputId": "29fd2769-0dcc-4700-9314-1fae68ccdd70" }, "outputs": [], "source": [ "search_result" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 405 }, "executionInfo": { "elapsed": 74448, "status": "ok", "timestamp": 1601412557102, "user": { "displayName": "Susan Mullally", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GhoAkTlu5JCXqC32438ISJU86DPSZdvoBOLwtOQMfU=s64", "userId": "01921813910966567332" }, "user_tz": 240 }, "id": "iXDKVb9aBBNx", "outputId": "d93fb7aa-bbd1-48a3-f3a9-e777770460e0" }, "outputs": [], "source": [ "# Flatten the light curve \n", "lc = lc_collection.stitch().flatten(window_length=901).remove_outliers()\n", "lc.plot();" ] }, { "cell_type": "markdown", "metadata": { "id": "c03Y0DPv-Csl" }, "source": [ "## 2. The Box Least Squares Method for Finding Transiting Planets" ] }, { "cell_type": "markdown", "metadata": { "id": "Bz1vMoZWTQRm" }, "source": [ "The most common method used to identify transiting exoplanets is the Box Least Squares (BLS) periodogram analysis. BLS works by modeling a transit using an upside-down top hat with four parameters: period, duration, depth, and reference time. These can be seen in the figure below, from the [astropy.timeseries](https://docs.astropy.org/en/stable/timeseries/) implementation of BLS.\n", "\n", "\"Box\n", "\n", "These parameters are then optimized by minimizing the square difference between the BLS transit model and the observation. For more information about BLS, please see the [Astropy documentation](https://docs.astropy.org/en/stable/timeseries/bls.html).\n", "\n", "Lightkurve has two types of periodogram available to anaylze periodic trends in light curves:\n", "* `LombScarglePeriodogram`\n", "* `BoxLeastSquaresPeriodogram`\n", "\n", "Please see the companion tutorial on how to create periodograms and identify significant peaks for an example of the `LombScarglePeriodogram`." ] }, { "cell_type": "markdown", "metadata": { "id": "QWoWOLfELCTX" }, "source": [ "## 3. Searching for Transiting Planets in a *Kepler* Light Curve Using BLS\n", "\n", "To create a `BoxLeastSquaresPeriodogram`, use the `LightCurve` method [to_periodogram](https://docs.lightkurve.org/reference/api/lightkurve.LightCurve.to_periodogram.html?highlight=to_periodogram), and pass in the string `'bls'` to specify the type of periodogram object you want to create. This method also optionally takes an array of periods (in days) to search, which we will set from 1–20 days to limit our search to short-period planets. We do so using the [numpy.linspace](https://numpy.org/doc/stable/reference/generated/numpy.linspace.html) function." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 390 }, "executionInfo": { "elapsed": 81201, "status": "ok", "timestamp": 1601412563862, "user": { "displayName": "Susan Mullally", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GhoAkTlu5JCXqC32438ISJU86DPSZdvoBOLwtOQMfU=s64", "userId": "01921813910966567332" }, "user_tz": 240 }, "id": "iLOVr_ZuRP2n", "outputId": "abef2286-e635-4663-b1f5-a6950d76ceda" }, "outputs": [], "source": [ "import numpy as np\n", "# Create array of periods to search\n", "period = np.linspace(1, 20, 10000)\n", "# Create a BLSPeriodogram\n", "bls = lc.to_periodogram(method='bls', period=period, frequency_factor=500);\n", "bls.plot();" ] }, { "cell_type": "markdown", "metadata": { "id": "a-8gU6D2A7a6" }, "source": [ "The plot above shows the power, or the likelihood of the BLS fit, for each of the periods in the array we passed in. This plot shows a handful of high-power peaks at discrete periods, which is a good sign that a transit has been identified. The highest power spike shows the most likely period, while the lower power spikes are fractional harmonics of the period, for example, 1/2, 1/3, 1/4, etc. \n", "\n", "We can pull out the most likely BLS parameters by taking their values at maximum power — we will refer to this transiting object as \"planet b.\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 37 }, "executionInfo": { "elapsed": 81197, "status": "ok", "timestamp": 1601412563864, "user": { "displayName": "Susan Mullally", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GhoAkTlu5JCXqC32438ISJU86DPSZdvoBOLwtOQMfU=s64", "userId": "01921813910966567332" }, "user_tz": 240 }, "id": "3c24rWxnR7_M", "outputId": "fdc82ff2-19ab-4809-cf43-77676daa5a40" }, "outputs": [], "source": [ "planet_b_period = bls.period_at_max_power\n", "planet_b_t0 = bls.transit_time_at_max_power\n", "planet_b_dur = bls.duration_at_max_power\n", "\n", "# Check the value for period\n", "planet_b_period" ] }, { "cell_type": "markdown", "metadata": { "id": "4rlYrX_tLjRu" }, "source": [ "To confirm that this period and transit time (epoch) correspond to a transit signal, we can phase-fold the light curve using these values and plot it." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 405 }, "executionInfo": { "elapsed": 82802, "status": "ok", "timestamp": 1601412565475, "user": { "displayName": "Susan Mullally", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GhoAkTlu5JCXqC32438ISJU86DPSZdvoBOLwtOQMfU=s64", "userId": "01921813910966567332" }, "user_tz": 240 }, "id": "KOM3l2NbSDft", "outputId": "173ae47e-b646-43d3-cab1-fa8f24302249" }, "outputs": [], "source": [ "ax = lc.fold(period=planet_b_period, epoch_time=planet_b_t0).scatter()\n", "ax.set_xlim(-5, 5);" ] }, { "cell_type": "markdown", "metadata": { "id": "QpfdGLSoMDUb" }, "source": [ "The phase-folded light curve shows a strong transit signal with the identified period and transit time of maximum BLS power." ] }, { "cell_type": "markdown", "metadata": { "id": "IhdPdcMOSRYy" }, "source": [ "## 4. Retrieving a Transit Model and Cadence Mask" ] }, { "cell_type": "markdown", "metadata": { "id": "Yj6Oym9HMMvw" }, "source": [ "The BLS periodogram has features that make it possible to search for multiple planets in the same system. If we want to identify additional transit signals, it will be much more convenient if we first remove the previously identified signal. This will prevent the high-power periodicity of the first planet, planet b, from dominating the BLS periodogram, and will allow us to find lower signal-to-noise ratio (SNR) transits.\n", "\n", "We can create a cadence mask for the light curve using the transit parameters from the `BoxLeastSquaresPeriodogram`." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "l03MOLu3Nm1J" }, "outputs": [], "source": [ "# Create a cadence mask using the BLS parameters\n", "planet_b_mask = bls.get_transit_mask(period=planet_b_period, \n", " transit_time=planet_b_t0, \n", " duration=planet_b_dur)" ] }, { "cell_type": "markdown", "metadata": { "id": "gh0XVIJ4OBSu" }, "source": [ "Now, we can create a masked version of the light curve to search for additional transit signals. The light curve is shown below, with masked cadences marked in red." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 405 }, "executionInfo": { "elapsed": 88300, "status": "ok", "timestamp": 1601412570982, "user": { "displayName": "Susan Mullally", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GhoAkTlu5JCXqC32438ISJU86DPSZdvoBOLwtOQMfU=s64", "userId": "01921813910966567332" }, "user_tz": 240 }, "id": "l_vzNQZwOKI0", "outputId": "7a50a3b5-a962-45c0-fab3-c59ba3fe5f2f" }, "outputs": [], "source": [ "masked_lc = lc[~planet_b_mask]\n", "ax = masked_lc.scatter();\n", "lc[planet_b_mask].scatter(ax=ax, c='r', label='Masked');" ] }, { "cell_type": "markdown", "metadata": { "id": "S7SJfPWnOqE7" }, "source": [ "We can also create a BLS model to visualize the transit fit. This returns a `LightCurve` object with the BLS model in the flux column." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "QptjZH66OwR1" }, "outputs": [], "source": [ "# Create a BLS model using the BLS parameters\n", "planet_b_model = bls.get_transit_model(period=planet_b_period, \n", " transit_time=planet_b_t0, \n", " duration=planet_b_dur)" ] }, { "cell_type": "markdown", "metadata": { "id": "qzfYLeCTPKjD" }, "source": [ "We can plot this over the folded light curve to confirm that it accurately represents the transit." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 405 }, "executionInfo": { "elapsed": 89329, "status": "ok", "timestamp": 1601412572021, "user": { "displayName": "Susan Mullally", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GhoAkTlu5JCXqC32438ISJU86DPSZdvoBOLwtOQMfU=s64", "userId": "01921813910966567332" }, "user_tz": 240 }, "id": "rHqMZmfYSX1E", "outputId": "00d53e85-ce58-44fc-e2be-7fc629642582" }, "outputs": [], "source": [ "ax = lc.fold(planet_b_period, planet_b_t0).scatter()\n", "planet_b_model.fold(planet_b_period, planet_b_t0).plot(ax=ax, c='r', lw=2)\n", "ax.set_xlim(-5, 5);" ] }, { "cell_type": "markdown", "metadata": { "id": "goco294YUFjs" }, "source": [ "## 5. Identifying Additional Transiting Planet Signals in the Same Light Curve" ] }, { "cell_type": "markdown", "metadata": { "id": "OQboGya1PZF-" }, "source": [ "Now that we have created a light curve with the first identified planet masked out, we can search the remaining light curve for additional transit signals. Here, we search for long-period planets by increasing our range of periods to 1–300 days." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 431 }, "executionInfo": { "elapsed": 96255, "status": "ok", "timestamp": 1601412578953, "user": { "displayName": "Susan Mullally", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GhoAkTlu5JCXqC32438ISJU86DPSZdvoBOLwtOQMfU=s64", "userId": "01921813910966567332" }, "user_tz": 240 }, "id": "MSUsDbMJUM-y", "outputId": "6d2b2bf8-2e57-4232-f3b8-257c94571b26" }, "outputs": [], "source": [ "period = np.linspace(1, 300, 10000)\n", "bls = masked_lc.to_periodogram('bls', period=period, frequency_factor=500)\n", "bls.plot();" ] }, { "cell_type": "markdown", "metadata": { "id": "4GJ7WfRR31lT" }, "source": [ "While no peaks in this BLS periodogram display a power as high as the previous transit signal, there is a definite peak near ~240 days. We can pull out the corresponding period and transit time to check the signal." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 37 }, "executionInfo": { "elapsed": 96253, "status": "ok", "timestamp": 1601412578957, "user": { "displayName": "Susan Mullally", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GhoAkTlu5JCXqC32438ISJU86DPSZdvoBOLwtOQMfU=s64", "userId": "01921813910966567332" }, "user_tz": 240 }, "id": "YVhdUd32P0Sx", "outputId": "6bae3db5-2a2e-48ba-fb02-a490a85727d2" }, "outputs": [], "source": [ "planet_c_period = bls.period_at_max_power\n", "planet_c_t0 = bls.transit_time_at_max_power\n", "planet_c_dur = bls.duration_at_max_power\n", "\n", "# Check the value for period\n", "planet_c_period" ] }, { "cell_type": "markdown", "metadata": { "id": "xbk7G1in4NPm" }, "source": [ "We can again plot the phase-folded light curve to examine the transit." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 405 }, "executionInfo": { "elapsed": 102368, "status": "ok", "timestamp": 1601412585079, "user": { "displayName": "Susan Mullally", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GhoAkTlu5JCXqC32438ISJU86DPSZdvoBOLwtOQMfU=s64", "userId": "01921813910966567332" }, "user_tz": 240 }, "id": "6FKmoM70UOl3", "outputId": "dbba469e-0edb-4f8d-c1b5-be123b256ebe" }, "outputs": [], "source": [ "ax = masked_lc.fold(planet_c_period, planet_c_t0).scatter()\n", "masked_lc.fold(planet_c_period, planet_c_t0).bin(.1).plot(ax=ax, c='r', lw=2, \n", " label='Binned Flux')\n", "ax.set_xlim(-5, 5);" ] }, { "cell_type": "markdown", "metadata": { "id": "ebk1C7aa4ctu" }, "source": [ "This signal is lower SNR because there are fewer transits due to the longer period, and the shallower depth implies that the planet is smaller. To help see the transit more clearly, we have overplotted the binned flux, combining consecutive points taken over a span of 0.1 days.\n", "\n", "We have now successfully identified two planets in the same system! We can use the BLS models to visualize the transit timing in the light curve." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "SRngiK4vQNWv" }, "outputs": [], "source": [ "planet_c_model = bls.get_transit_model(period=planet_c_period, \n", " transit_time=planet_c_t0, \n", " duration=planet_c_dur)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 405 }, "executionInfo": { "elapsed": 105743, "status": "ok", "timestamp": 1601412588463, "user": { "displayName": "Susan Mullally", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GhoAkTlu5JCXqC32438ISJU86DPSZdvoBOLwtOQMfU=s64", "userId": "01921813910966567332" }, "user_tz": 240 }, "id": "XEXsEtfHQOE8", "outputId": "5486451f-9f6a-48c4-c7c9-262510efaa00" }, "outputs": [], "source": [ "ax = lc.scatter();\n", "planet_b_model.plot(ax=ax, c='dodgerblue', label='Planet b Transit Model');\n", "planet_c_model.plot(ax=ax, c='r', label='Planet c Transit Model');" ] }, { "cell_type": "markdown", "metadata": { "id": "ow66EyEhRZ98" }, "source": [ "## 6. Using the Interactive BLS Periodogram in Lightkurve" ] }, { "cell_type": "markdown", "metadata": { "id": "0UwgAQO45MIR" }, "source": [ "Lightkurve also has a tool that enables you to interactively perform a BLS search. A quick demo of this feature is shown below. \n", "\n", "To use the [LightCurve.interact_bls()](https://docs.lightkurve.org/reference/api/lightkurve.LightCurve.interact_bls.html?highlight=lightcurve%20interact_bls#lightkurve.LightCurve.interact_bls) method, zoom in on peaks in the BLS periodogram using the interactive plotting tools. To improve the fit, you can change the transit duration. The phase-folded light curve panel in the top right and the full light curve below it will automatically update to plot the highest power BLS model. The BLS parameters with highest power are noted in the bottom right of the figure." ] }, { "cell_type": "markdown", "metadata": { "id": "q-Xkjz6sKwlx" }, "source": [ "![interact_bls() demo animation](../1-getting-started/interact-screenshots/interact_bls.gif)" ] }, { "cell_type": "markdown", "metadata": { "id": "aG4fgysD_Brp" }, "source": [ "## About this Notebook\n", "\n", "**Authors:** Nicholas Saunders (nksaun@hawaii.edu)\n", "\n", "**Updated On:** 2020-09-28" ] }, { "cell_type": "markdown", "metadata": { "id": "MptPsdBQ_Qju" }, "source": [ "## Citing Lightkurve and Astropy\n", "\n", "If you use `lightkurve` or its dependencies in your published research, please cite the authors. Click the buttons below to copy BibTeX entries to your clipboard." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 151 }, "executionInfo": { "elapsed": 105740, "status": "ok", "timestamp": 1601412588467, "user": { "displayName": "Susan Mullally", "photoUrl": "https://lh3.googleusercontent.com/a-/AOh14GhoAkTlu5JCXqC32438ISJU86DPSZdvoBOLwtOQMfU=s64", "userId": "01921813910966567332" }, "user_tz": 240 }, "id": "1khvwNHx_QDz", "outputId": "1a696184-e00e-4286-8b8b-f8a665305138" }, "outputs": [], "source": [ "lk.show_citation_instructions()" ] }, { "cell_type": "markdown", "metadata": { "id": "ZhdRVU3B_Zn2" }, "source": [ "\"Space\n" ] } ], "metadata": { "colab": { "collapsed_sections": [], "name": "Identifying a transiting planet signal in Kepler or TESS light curves", "provenance": [ { "file_id": "https://github.com/KeplerGO/lightkurve/blob/master/docs/source/tutorials/04-how-to-remove-tess-scattered-light-using-regressioncorrector.ipynb", "timestamp": 1599958717967 } ] }, "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.10" } }, "nbformat": 4, "nbformat_minor": 4 }