How to recover the first TESS planet candidate with Lightkurve?

Recently, the first public pixel data from the TESS mission have become available from the data archive at MAST. This tutorial demonstrates how the Lightkurve Python package can be used to read in these data and create your own TESS light curves with different aperture masks.

Below is a quick tutorial on how to get started using Lightkurve and TESS data. We'll use the nearby, bright target Pi Mensae (ID 261136679), around which the mission team recently discovered a short period planet candidate on a 6.27 day orbit. See the pre-print paper by Huang et al (2018) for more details.

TESS data is stored in a binary file format which is documented in the TESS Science Data Products Description Document. Lightkurve provides a TessTargetPixelFile class which allows you to interact with the data easily.

In [0]:
!pip install lightkurve
import lightkurve
Collecting lightkurve
  Downloading https://files.pythonhosted.org/packages/c5/2e/537e5d6f23021750668103bca4b0ce6fc45fe4cf0942a8a313de46c22b63/lightkurve-1.1.1.tar.gz (474kB)
     |████████████████████████████████| 481kB 2.8MB/s 
Requirement already satisfied: numpy>=1.11 in /usr/local/lib/python3.6/dist-packages (from lightkurve) (1.16.4)
Requirement already satisfied: astropy>=1.3 in /usr/local/lib/python3.6/dist-packages (from lightkurve) (3.0.5)
Requirement already satisfied: scipy>=0.19.0 in /usr/local/lib/python3.6/dist-packages (from lightkurve) (1.3.1)
Requirement already satisfied: matplotlib>=1.5.3 in /usr/local/lib/python3.6/dist-packages (from lightkurve) (3.0.3)
Collecting astroquery>=0.3.9 (from lightkurve)
  Downloading https://files.pythonhosted.org/packages/61/50/a7a08f9e54d7d9d97e69433cd88231e1ad2901811c9d1ae9ac7ccaef9396/astroquery-0.3.9.tar.gz (4.2MB)
     |████████████████████████████████| 4.2MB 37.0MB/s 
Collecting oktopus (from lightkurve)
  Downloading https://files.pythonhosted.org/packages/2d/6e/7b7e11442ff70286c22614d200f6145f83528dc6c99fec0982665e25c8d3/oktopus-0.1.2.tar.gz
Requirement already satisfied: bs4 in /usr/local/lib/python3.6/dist-packages (from lightkurve) (0.0.1)
Requirement already satisfied: requests in /usr/local/lib/python3.6/dist-packages (from lightkurve) (2.21.0)
Requirement already satisfied: tqdm in /usr/local/lib/python3.6/dist-packages (from lightkurve) (4.28.1)
Requirement already satisfied: pandas in /usr/local/lib/python3.6/dist-packages (from lightkurve) (0.24.2)
Collecting uncertainties (from lightkurve)
  Downloading https://files.pythonhosted.org/packages/2a/c2/babbe5b16141859dd799ed31c03987100a7b6d0ca7c0ed4429c96ce60fdf/uncertainties-3.1.2.tar.gz (232kB)
     |████████████████████████████████| 235kB 40.0MB/s 
Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib>=1.5.3->lightkurve) (1.1.0)
Requirement already satisfied: python-dateutil>=2.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib>=1.5.3->lightkurve) (2.5.3)
Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib>=1.5.3->lightkurve) (2.4.2)
Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.6/dist-packages (from matplotlib>=1.5.3->lightkurve) (0.10.0)
Collecting keyring>=4.0 (from astroquery>=0.3.9->lightkurve)
  Downloading https://files.pythonhosted.org/packages/6e/b3/b4d443d2e30c00cdb73612426222172182e54359545cfb17774792619e49/keyring-19.0.2-py2.py3-none-any.whl
Requirement already satisfied: beautifulsoup4>=4.3.2 in /usr/local/lib/python3.6/dist-packages (from astroquery>=0.3.9->lightkurve) (4.6.3)
Requirement already satisfied: html5lib>=0.999 in /usr/local/lib/python3.6/dist-packages (from astroquery>=0.3.9->lightkurve) (1.0.1)
Requirement already satisfied: autograd in /usr/local/lib/python3.6/dist-packages (from oktopus->lightkurve) (1.3)
Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /usr/local/lib/python3.6/dist-packages (from requests->lightkurve) (3.0.4)
Requirement already satisfied: urllib3<1.25,>=1.21.1 in /usr/local/lib/python3.6/dist-packages (from requests->lightkurve) (1.24.3)
Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/dist-packages (from requests->lightkurve) (2019.6.16)
Requirement already satisfied: idna<2.9,>=2.5 in /usr/local/lib/python3.6/dist-packages (from requests->lightkurve) (2.8)
Requirement already satisfied: pytz>=2011k in /usr/local/lib/python3.6/dist-packages (from pandas->lightkurve) (2018.9)
Requirement already satisfied: setuptools in /usr/local/lib/python3.6/dist-packages (from kiwisolver>=1.0.1->matplotlib>=1.5.3->lightkurve) (41.0.1)
Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.6/dist-packages (from python-dateutil>=2.1->matplotlib>=1.5.3->lightkurve) (1.12.0)
Collecting secretstorage; sys_platform == "linux" (from keyring>=4.0->astroquery>=0.3.9->lightkurve)
  Downloading https://files.pythonhosted.org/packages/82/59/cb226752e20d83598d7fdcabd7819570b0329a61db07cfbdd21b2ef546e3/SecretStorage-3.1.1-py3-none-any.whl
Requirement already satisfied: entrypoints in /usr/local/lib/python3.6/dist-packages (from keyring>=4.0->astroquery>=0.3.9->lightkurve) (0.3)
Requirement already satisfied: webencodings in /usr/local/lib/python3.6/dist-packages (from html5lib>=0.999->astroquery>=0.3.9->lightkurve) (0.5.1)
Requirement already satisfied: future>=0.15.2 in /usr/local/lib/python3.6/dist-packages (from autograd->oktopus->lightkurve) (0.16.0)
Collecting cryptography (from secretstorage; sys_platform == "linux"->keyring>=4.0->astroquery>=0.3.9->lightkurve)
  Downloading https://files.pythonhosted.org/packages/97/18/c6557f63a6abde34707196fb2cad1c6dc0dbff25a200d5044922496668a4/cryptography-2.7-cp34-abi3-manylinux1_x86_64.whl (2.3MB)
     |████████████████████████████████| 2.3MB 35.4MB/s 
Collecting jeepney (from secretstorage; sys_platform == "linux"->keyring>=4.0->astroquery>=0.3.9->lightkurve)
  Downloading https://files.pythonhosted.org/packages/0a/4c/ef880713a6c6d628869596703167eab2edf8e0ec2d870d1089dcb0901b81/jeepney-0.4.1-py3-none-any.whl (60kB)
     |████████████████████████████████| 61kB 19.9MB/s 
Collecting asn1crypto>=0.21.0 (from cryptography->secretstorage; sys_platform == "linux"->keyring>=4.0->astroquery>=0.3.9->lightkurve)
  Downloading https://files.pythonhosted.org/packages/ea/cd/35485615f45f30a510576f1a56d1e0a7ad7bd8ab5ed7cdc600ef7cd06222/asn1crypto-0.24.0-py2.py3-none-any.whl (101kB)
     |████████████████████████████████| 102kB 25.2MB/s 
Requirement already satisfied: cffi!=1.11.3,>=1.8 in /usr/local/lib/python3.6/dist-packages (from cryptography->secretstorage; sys_platform == "linux"->keyring>=4.0->astroquery>=0.3.9->lightkurve) (1.12.3)
Requirement already satisfied: pycparser in /usr/local/lib/python3.6/dist-packages (from cffi!=1.11.3,>=1.8->cryptography->secretstorage; sys_platform == "linux"->keyring>=4.0->astroquery>=0.3.9->lightkurve) (2.19)
Building wheels for collected packages: lightkurve, astroquery, oktopus, uncertainties
  Building wheel for lightkurve (setup.py) ... done
  Created wheel for lightkurve: filename=lightkurve-1.1.1-cp36-none-any.whl size=495117 sha256=22f99fb7c31fbf5aacf663a1579e39856e3a0e6f3877a82f90ea9f8bde1cccda
  Stored in directory: /root/.cache/pip/wheels/85/da/fb/c1498ed5d32ab0adeb94e45e85d025845e5602f93ae5c8f627
  Building wheel for astroquery (setup.py) ... done
  Created wheel for astroquery: filename=astroquery-0.3.9-cp36-none-any.whl size=3247933 sha256=2554f9d6d9804d8d80487a5a8a311f85aa0f63cda788a816de626263da6b1688
  Stored in directory: /root/.cache/pip/wheels/8a/d1/1e/4124d9ef35e2bbfbaa284c97dd49d9babbab42d966c4bea190
  Building wheel for oktopus (setup.py) ... done
  Created wheel for oktopus: filename=oktopus-0.1.2-cp36-none-any.whl size=12781 sha256=58cbee19ae50f7cf189f51d91fd75af6baf7408d0459d02de16739e74d225b2a
  Stored in directory: /root/.cache/pip/wheels/9b/90/81/098fc66ee56166d63c9a8fc0a9672ae7b3423396a588ec952a
  Building wheel for uncertainties (setup.py) ... done
  Created wheel for uncertainties: filename=uncertainties-3.1.2-cp36-none-any.whl size=96455 sha256=2ab2d9acec2d3ad4d9b48fabca4d8841186c3c6bd0aa747949f36887af39df48
  Stored in directory: /root/.cache/pip/wheels/d9/d3/0e/5b0b743a8abd50373705427438456da5dc2621891138d7a618
Successfully built lightkurve astroquery oktopus uncertainties
Installing collected packages: asn1crypto, cryptography, jeepney, secretstorage, keyring, astroquery, oktopus, uncertainties, lightkurve
Successfully installed asn1crypto-0.24.0 astroquery-0.3.9 cryptography-2.7 jeepney-0.4.1 keyring-19.0.2 lightkurve-1.1.1 oktopus-0.1.2 secretstorage-3.1.1 uncertainties-3.1.2
In [0]:
from lightkurve import TessTargetPixelFile
tpf = TessTargetPixelFile('https://archive.stsci.edu/hlsps/tess-data-alerts/hlsp_tess-data-alerts_tess_phot_00261136679-s01_tess_v1_tp.fits')
Downloading https://archive.stsci.edu/hlsps/tess-data-alerts/hlsp_tess-data-alerts_tess_phot_00261136679-s01_tess_v1_tp.fits [Done]

TessTargetPixelFile's have many helpful methods and attributes. For example, you can access basic meta data on the target easily:

In [0]:
tpf.mission
Out[0]:
'TESS'
In [0]:
tpf.targetid  # TESS Input Catalog (TIC) Identifier
Out[0]:
261136679
In [0]:
tpf.sector  # TESS Observation Sector
Out[0]:
1
In [0]:
tpf.camera  # TESS Camera Number
Out[0]:
4
In [0]:
tpf.ccd  # TESS CCD Number
Out[0]:
2

We might want to plot the data, we can do this with the plot() method. You can add the keyword aperture_mask to plot an aperture on top of the image. In this case we've used the pipeline_mask which is stored in the original .fits file, but you can use any aperture you like.

In [0]:
%matplotlib inline
tpf.plot(aperture_mask=tpf.pipeline_mask);
In [0]:
tpf.plot()
Out[0]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f90e467eac8>

If you want to access the original fits file that generated the data you can use the hdu attribute of the tpf. This will return an astropy.io.fits object, for example

In [0]:
tpf.hdu
Out[0]:
[<astropy.io.fits.hdu.image.PrimaryHDU object at 0x7f90eaa9a7f0>, <astropy.io.fits.hdu.table.BinTableHDU object at 0x7f90ea078860>, <astropy.io.fits.hdu.image.ImageHDU object at 0x7f90ea0a1d30>, <astropy.io.fits.hdu.table.BinTableHDU object at 0x7f90e1ae5c18>]

You can access each extension and the data inside it in the same way you'd use astropy.io.fits. If you want to access data held in the TPF, such as the time of the observations, you can do that easily by using

In [0]:
tpf.time
Out[0]:
array([1325.29698328, 1325.29837215, 1325.29976102, ..., 1353.17292214,
       1353.17431099, 1353.17569985])

This returns the time in units of days counted since Julian Day 2457000.

You can access the corresponding flux values using

In [0]:
tpf.flux
Out[0]:
array([[[  -1.3825388,  -37.66533  ,  -91.830536 , ..., -108.04645  ,
         -103.54175  , -134.1816   ],
        [-135.68407  , -125.30367  , -112.52773  , ..., -113.03839  ,
         -122.92997  , -131.28302  ],
        [-147.63722  , -142.73625  , -134.99854  , ..., -101.330734 ,
         -114.31767  , -121.03055  ],
        ...,
        [-138.13503  , -137.8448   , -146.29425  , ...,  -77.273094 ,
         -105.22347  , -135.82652  ],
        [-142.20255  , -139.6766   , -147.65201  , ..., -118.81814  ,
         -129.52805  , -130.46175  ],
        [-133.71326  , -134.32669  , -148.82013  , ..., -127.16725  ,
          -90.90953  , -112.974434 ]],

       [[  -3.390986 ,  -47.140965 ,  -90.53796  , ..., -106.87563  ,
         -108.55464  , -136.6413   ],
        [-133.7175   , -125.38933  , -114.30842  , ..., -115.82087  ,
         -125.8608   , -132.87209  ],
        [-147.48918  , -142.87836  , -138.43767  , ..., -103.16773  ,
         -116.372955 , -119.86726  ],
        ...,
        [-138.81976  , -138.86803  , -146.27737  , ...,  -78.0859   ,
         -107.27506  , -136.54706  ],
        [-139.40416  , -141.568    , -148.46045  , ..., -122.45605  ,
         -127.82529  , -132.05716  ],
        [-131.66135  , -135.35051  , -150.45163  , ..., -128.91386  ,
          -88.85448  , -111.716286 ]],

       [[  -3.5488758,  -47.50886  ,  -95.015564 , ..., -110.717064 ,
         -108.882744 , -137.5612   ],
        [-137.84918  , -126.03129  , -115.643364 , ..., -114.72093  ,
         -126.24343  , -133.79109  ],
        [-147.31683  , -145.31314  , -137.13574  , ..., -105.026146 ,
         -116.6999   , -122.60661  ],
        ...,
        [-141.17563  , -140.43784  , -149.25896  , ...,  -78.849335 ,
         -108.58714  , -138.34416  ],
        [-140.01288  , -142.26175  , -148.14075  , ..., -126.20568  ,
         -129.13695  , -132.04318  ],
        [-132.21141  , -138.6819   , -146.84227  , ..., -131.71007  ,
          -93.29626  , -116.47916  ]],

       ...,

       [[  15.500299 ,  -32.484245 ,  -88.58714  , ...,  -99.75848  ,
          -93.617775 , -129.5383   ],
        [-122.93883  , -117.40679  , -105.49079  , ..., -108.75932  ,
         -120.350716 , -129.25839  ],
        [-143.43176  , -138.72139  , -131.21268  , ...,  -97.953094 ,
         -113.65763  , -118.00191  ],
        ...,
        [-130.2462   , -133.78702  , -140.91888  , ...,  -68.20146  ,
          -99.546646 , -132.0319   ],
        [-137.01523  , -137.3937   , -141.48993  , ..., -112.68788  ,
         -125.11879  , -128.38521  ],
        [-125.543655 , -129.38873  , -144.37961  , ..., -122.12083  ,
          -89.26432  , -107.87084  ]],

       [[  18.095486 ,  -34.98728  ,  -91.17793  , ...,  -99.494095 ,
          -93.221954 , -128.76079  ],
        [-124.04631  , -116.41686  , -102.980415 , ..., -107.50661  ,
         -119.95467  , -127.54848  ],
        [-142.71834  , -138.71126  , -129.78357  , ...,  -98.722206 ,
         -112.27363  , -119.09576  ],
        ...,
        [-131.34     , -131.13364  , -141.24506  , ...,  -71.29033  ,
          -98.11233  , -129.48041  ],
        [-134.56529  , -136.50882  , -140.93579  , ..., -114.41215  ,
         -122.87399  , -129.40953  ],
        [-126.638466 , -132.9018   , -142.17902  , ..., -123.72011  ,
          -89.90764  , -108.07525  ]],

       [[  14.83668  ,  -38.491974 ,  -89.118706 , ..., -104.50926  ,
          -98.43293  , -133.46823  ],
        [-129.66971  , -120.571465 , -107.0652   , ..., -110.490425 ,
         -121.109955 , -126.844826 ],
        [-146.30688  , -139.21913  , -132.79062  , ...,  -99.678925 ,
         -112.38672  , -118.37381  ],
        ...,
        [-133.21715  , -132.51721  , -141.62198  , ...,  -73.295105 ,
         -100.20323  , -132.46454  ],
        [-138.18147  , -138.7651   , -144.7824   , ..., -116.421265 ,
         -125.88614  , -129.6993   ],
        [-126.65554  , -130.70747  , -144.31444  , ..., -124.7908   ,
          -86.73392  , -112.15379  ]]], dtype=float32)

Flux is a numpy.ndarray with a shape of (TIME x PIXELS x PIXELS). If you want to access just the first frame you can use

In [0]:
tpf.flux[0]
Out[0]:
array([[-1.38253880e+00, -3.76653290e+01, -9.18305359e+01,
        -1.29922272e+02, -1.45692978e+02, -1.35893311e+02,
        -9.54683685e+01, -8.85729370e+01, -1.08046448e+02,
        -1.03541748e+02, -1.34181595e+02],
       [-1.35684067e+02, -1.25303673e+02, -1.12527733e+02,
        -1.35690414e+02, -1.45928650e+02, -1.27757614e+02,
        -6.09818077e+01, -7.37526398e+01, -1.13038391e+02,
        -1.22929970e+02, -1.31283020e+02],
       [-1.47637222e+02, -1.42736252e+02, -1.34998535e+02,
        -1.41663147e+02, -1.40064377e+02, -1.18161720e+02,
        -5.37216644e+01, -6.23722382e+01, -1.01330734e+02,
        -1.14317673e+02, -1.21030548e+02],
       [-1.49992447e+02, -1.43351776e+02, -1.39589264e+02,
        -1.37442719e+02, -1.31207718e+02, -9.68078690e+01,
        -1.37817793e+01, -3.41951828e+01, -7.66406403e+01,
        -8.33256989e+01, -8.85187225e+01],
       [-1.37578445e+02, -1.28364151e+02, -1.26376915e+02,
        -1.21656555e+02, -1.14596848e+02, -5.06528702e+01,
         7.68901138e+01,  4.60617752e+01,  2.71646519e+01,
         3.94530640e+01, -2.65274410e+01],
       [-1.36808558e+01,  3.27203102e+01,  5.92592163e+01,
         3.10102577e+01,  1.12594862e+01,  1.24587753e+02,
         3.30445312e+02,  3.36818207e+02,  4.67378265e+02,
         2.58437531e+02,  5.39367867e+00],
       [ 3.06964386e+02,  5.08380646e+02,  6.83612305e+02,
         6.75774414e+02,  6.43811035e+02,  8.33415833e+02,
         1.27430811e+03,  1.84799011e+03,  1.48316943e+03,
         3.57677521e+02, -2.22004585e+01],
       [ 7.54239929e+02,  1.21837598e+03,  1.75272681e+03,
         2.08298779e+03,  2.50489863e+04,  6.54504688e+04,
         6.99400781e+03,  7.02737646e+03,  1.77507739e+03,
         2.59077271e+02, -1.98949337e+01],
       [ 1.11253564e+03,  2.07831738e+03,  3.65158667e+03,
         5.48250391e+03,  1.00965391e+05,  1.02543531e+05,
         4.09393594e+04,  9.44738086e+03,  1.42760950e+03,
         3.31844025e+02,  5.17090683e+01],
       [ 1.02698645e+03,  2.25617969e+03,  5.54376465e+03,
         2.46261230e+04,  1.03035734e+05,  1.04624336e+05,
         6.53138633e+04,  7.71915039e+03,  1.35093494e+03,
         3.36992310e+02, -3.54690289e+00],
       [ 7.21791382e+02,  1.66756409e+03,  3.87029858e+03,
         2.42247129e+04,  1.03909016e+05,  1.06053984e+05,
         4.83635586e+04,  4.23504346e+03,  1.32237488e+03,
         3.16208466e+02, -6.57367096e+01],
       [ 4.29120178e+02,  1.26064551e+03,  3.15358057e+03,
         1.05985273e+04,  1.02944805e+05,  1.05321906e+05,
         1.19889746e+04,  3.39063574e+03,  1.40142529e+03,
         4.15249512e+02, -3.48390923e+01],
       [ 1.72348724e+02,  7.88590881e+02,  2.23820068e+03,
         4.44562012e+03,  5.58241680e+04,  1.03319727e+05,
         5.61203809e+03,  2.66727393e+03,  1.30703625e+03,
         4.99335266e+02,  4.71602020e+01],
       [ 2.69907742e+01,  3.23401794e+02,  9.99374329e+02,
         1.78104407e+03,  2.04844604e+03,  3.67428320e+04,
         2.80467065e+03,  1.85512500e+03,  1.18081396e+03,
         6.49496826e+02,  1.00554329e+02],
       [-7.98464050e+01,  9.25059509e+01,  3.26399536e+02,
         6.55647888e+02,  9.57525818e+02,  1.18310132e+03,
         1.39609094e+03,  1.17153650e+03,  1.15672314e+03,
         7.71616577e+02,  5.45056877e+01],
       [-1.13249367e+02, -6.13406181e+01,  5.93428993e+01,
         1.54688034e+02,  3.48396606e+02,  5.27463257e+02,
         6.76866699e+02,  6.34336426e+02,  5.01662018e+02,
         3.01781311e+02, -2.48897457e+01],
       [-8.82987518e+01, -1.17512108e+02, -9.47615585e+01,
        -3.40316010e+01,  4.28901634e+01,  1.52270020e+02,
         2.72233185e+02,  2.77604492e+02,  1.88234268e+02,
         4.79093513e+01, -6.75118103e+01],
       [-8.60586777e+01, -1.14533005e+02, -1.38196228e+02,
        -1.20548019e+02, -7.74374313e+01, -3.44268494e+01,
         3.27217293e+01,  4.88377647e+01,  1.26917982e+01,
        -5.03569221e+01, -1.11872086e+02],
       [-1.38135025e+02, -1.37844803e+02, -1.46294250e+02,
        -1.46713867e+02, -1.37058548e+02, -1.05716675e+02,
        -6.76952667e+01, -5.82716599e+01, -7.72730942e+01,
        -1.05223473e+02, -1.35826523e+02],
       [-1.42202545e+02, -1.39676605e+02, -1.47652008e+02,
        -1.50885605e+02, -1.49152878e+02, -1.39763824e+02,
        -1.17666542e+02, -1.09747162e+02, -1.18818138e+02,
        -1.29528046e+02, -1.30461746e+02],
       [-1.33713257e+02, -1.34326691e+02, -1.48820129e+02,
        -1.51972229e+02, -1.49277893e+02, -1.45098679e+02,
        -1.30031540e+02, -1.21871094e+02, -1.27167252e+02,
        -9.09095306e+01, -1.12974434e+02]], dtype=float32)

These values are in units electrons per second.

Building Light Curves from TPFs

We can use the to_lightcurve() method to turn this TPF into a light curve using Simple Aperture Photometry. This will put an aperture on the target, and sum up the flux in all the pixels inside the aperture.

The default for to_lightcurve() is to use the mask generated by the TESS pipeline.

In [0]:
lc = tpf.to_lightcurve()

Now we can use the plot function to take a look at the data.

In [0]:
lc.errorbar();

This looks pretty good, but maybe we can improve things by creating a new aperture.

In [0]:
import numpy as np

# Create a median image of the source over time
median_image = np.nanmedian(tpf.flux, axis=0)

# Select pixels which are brighter than the 85th percentile of the median image
aperture_mask = median_image > np.nanpercentile(median_image, 85)

# Plot that aperture
tpf.plot(aperture_mask=aperture_mask);
In [0]:
lc = tpf.to_lightcurve(aperture_mask=aperture_mask)
In [0]:
lc.errorbar();

There's a long term trend in this dataset, which we can remove with a simple smoothing filter. You can use the lc.flatten() method to apply and divide the Savitzky-Golay smoothing filter. Here we'll use a window_length of 1001 cadences, which is roughly a 5% of the full length of the light curve.

In [0]:
# Number of cadences in the full light curve
print(lc.time.shape)
(18104,)
In [0]:
flat_lc = lc.flatten(window_length=1001)
flat_lc.errorbar();

The light curve looks much flatter. Unfortunately there is a portion of the light curve that is very noisy, due to a jitter in the TESS spacecraft. We can remove this simply by masking the light curve. First we'll select the times that had the jitter.

In [0]:
# Flag the times that are good quality
mask = (flat_lc.time < 1346) | (flat_lc.time > 1350)

Then we can just clip those times out.

In [0]:
masked_lc = flat_lc[mask]
masked_lc.errorbar();

We can use Lightkurve to plot these two light curves over each other to see the difference.

In [0]:
# First define the `matplotlib.pyplot.axes`
ax = flat_lc.errorbar()

# Pass that axis to the next plot
masked_lc.errorbar(ax=ax);

This looks much better. Now we might want to clip out some outliers from the light curve. We can do that with a simple lightkurve function remove_outliers()

In [0]:
clipped_lc = masked_lc.remove_outliers(sigma=6)
clipped_lc.errorbar();

It's a little hard to see these data because of the plotting style. Let's use a scatter plot instead. We can do this with the lc.scatter() method. This method works in the same way that matplotlib.pyplot.scatter works, and takes in the same keyword arguments.

In [0]:
clipped_lc.scatter(s=0.1);

We can also add errorbars using the lc.errorbar() method.

In [0]:
ax = clipped_lc.scatter(s=0.1)
clipped_lc.errorbar(ax=ax, alpha=0.2);  # alpha determines the transparency

Finally let's use lightkurve to fold the data at the exoplanet orbital period and see if we can see the transit.

In [0]:
folded_lc = clipped_lc.fold(period=6.27, t0=1325.504)
folded_lc.errorbar();

It looks like there's something there, but it's hard to see. Let's bin the light curve to reduce the number of points, but also reduce the uncertainty of those points.

In [0]:
binned_lc = folded_lc.bin(binsize=10)  # Average 10 points per bin
binned_lc.errorbar();

And now we can see the transit of Pi Men c!

Note that you can actually do all these steps in just a few lines:

In [0]:
lc = tpf.to_lightcurve(aperture_mask=aperture_mask).flatten(window_length=1001)
lc = lc[(lc.time < 1346) | (lc.time > 1350)]
lc.remove_outliers(sigma=6).fold(period=6.27, t0=1325.504).bin(binsize=10).errorbar();

Comparing two apertures

In the above tutorial we used our own aperture instead of the pipeline aperture. Let's compare the results from using these two different apertures.

In [0]:
# Use the default
lc = tpf.to_lightcurve(aperture_mask=tpf.pipeline_mask).flatten(window_length=1001)
lc = lc[(lc.time < 1346) | (lc.time > 1350)].remove_outliers(6).fold(period=6.27, t0=1325.504).bin(10)

# Use a custom aperture
custom_lc = tpf.to_lightcurve(aperture_mask=aperture_mask).flatten(window_length=1001)
custom_lc = custom_lc[(custom_lc.time < 1346) | (custom_lc.time > 1350)].remove_outliers(6).fold(period=6.27, t0=1325.504).bin(10)
In [0]:
ax = lc.errorbar(label='Default aperture')
custom_lc.errorbar(ax=ax, label='Custom aperture');

The importance of using different aperture masks is clearly visible in the figure above. Note however that the data archive at MAST also contains lightcurve products which have more advanced systematics removal methods applied. We will explore those in a future tutorial!