Using the to_fits and read_generic_lightcurve functions#
Learning Goals#
By the end of this tutorial you will:
Learn how to create a LightCurve object.
Save the LightCurve object as a fits file using the
`to_fits<https://lightkurve.github.io/lightkurve/reference/api/lightkurve.LightCurve.to_fits.html?highlight=to_fits#lightkurve.LightCurve.to_fits>`__ function.Read in the same FITs file using the
`read_generic_lightcurve<lightkurve/lightkurve>`__ function.
Introduction#
The intent of the tutorial is to illustrate how one might use data from any mission (not just Kepler, K2, or TESS) and analize it within Lightkurve.
Imports#
This tutorial requires:
[15]:
%matplotlib inline
import lightkurve as lk
import matplotlib.pyplot as plt
import numpy as np
from astropy.time import Time
import astropy.units as u
1: Creating our lightcurve data and our LightCurve Object#
First we will create some fake lightcurve data to use as an example and convert this into a LightCurve Object. You could also download a LightCurve Object via using `search_lightcurve <https://lightkurve.github.io/lightkurve/reference/api/lightkurve.search_lightcurve.html?highlight=search_lightcurve#lightkurve.search_lightcurve>`__ and
`download() <https://lightkurve.github.io/lightkurve/reference/api/lightkurve.SearchResult.download.html?highlight=download#lightkurve.SearchResult.download>`__ if you wish, but for now we will create our simple data set.
[16]:
#Create the time values and specify the format
time_values = Time(np.linspace(2458000, 2458000 + 10, 100), format='jd')
#Create the flux and flux error values
flux_values = np.sin(time_values.value * 0.5) + 1000
flux_err_values = np.full_like(flux_values, 0.01, dtype=np.float32)
#Specify the flux units
unit_flux = u.electron/u.second
Using this data set we then use the LightCurve function to create our object and look at the data.
[17]:
#Create the LightCurve object and look
my_lc = lk.LightCurve(time=time_values, flux=flux_values * unit_flux, flux_err=flux_err_values * unit_flux)
my_lc
[17]:
| time | flux | flux_err |
|---|---|---|
| electron / s | electron / s | |
| Time | float64 | float32 |
| 2458000.0 | 1000.4536549054471 | 0.009999999776482582 |
| 2458000.101010101 | 1000.4080866165767 | 0.009999999776482582 |
| 2458000.202020202 | 1000.3614776178835 | 0.009999999776482582 |
| 2458000.303030303 | 1000.3139467722524 | 0.009999999776482582 |
| 2458000.404040404 | 1000.2656152941383 | 0.009999999776482582 |
| 2458000.505050505 | 1000.2166064391281 | 0.009999999776482582 |
| 2458000.606060606 | 1000.1670451904844 | 0.009999999776482582 |
| 2458000.707070707 | 1000.1170579401942 | 0.009999999776482582 |
| 2458000.8080808083 | 1000.066772166409 | 0.009999999776482582 |
| ... | ... | ... |
| 2458009.1919191917 | 1000.8324444376836 | 0.009999999776482582 |
| 2458009.292929293 | 1000.859356363695 | 0.009999999776482582 |
| 2458009.393939394 | 1000.8840767435362 | 0.009999999776482582 |
| 2458009.494949495 | 1000.9065425349794 | 0.009999999776482582 |
| 2458009.595959596 | 1000.9266964453594 | 0.009999999776482582 |
| 2458009.696969697 | 1000.9444870778121 | 0.009999999776482582 |
| 2458009.797979798 | 1000.9598690624119 | 0.009999999776482582 |
| 2458009.898989899 | 1000.9728031716038 | 0.009999999776482582 |
| 2458010.0 | 1000.9832564206663 | 0.009999999776482582 |
We can now access the column values directly as an attribute of the object.
[18]:
my_lc.flux
[18]:
We can also plot the data.
[19]:
my_lc.plot()
[19]:
<Axes: xlabel='Time [JD]', ylabel='Flux [$\\mathrm{e^{-}\\,s^{-1}}$]'>
Additional meta data or keyword arguments may be added via a dictionary as part of LightCurve function.
For example we could define the mission and the telescope we obtained the data from via the following:
[20]:
my_lc.meta['TELESCOP'] = "MY_FAKE_TELESCOPE"
my_lc.meta['MISSION'] = "MY_FAKE_MISSION"
print(my_lc.meta['TELESCOP'], my_lc.meta['MISSION'])
MY_FAKE_TELESCOPE MY_FAKE_MISSION
2: Saving the LightCurve Object as a FITS file#
We can now convert our object into a FITS file using the to_fits function. For this we simply need to state the file name and path. Be sure to state if you want your file to be overwritten or not using either False or True.
[21]:
output_filename = './my_custom_lightcurve.fits'
my_lc.to_fits(output_filename, overwrite=True)
f"LightCurve saved to {output_filename}"
[21]:
'LightCurve saved to ./my_custom_lightcurve.fits'
Note we can also add information to our fits file using an extra_data dictionary. Defined extra keywords or columns would then be included in the FITS file. Keywords would be stroed in the primary header and np.array data as columns in the 1st extension. As an example let’s add an “ORIGIN” keyword which will indicate where got our data from.
[22]:
extra_data = {"ORIGIN": "Tutorial"}
We can then overwrite our old file and add this so when we read it in, it will be there.
[23]:
my_lc.to_fits(output_filename, overwrite=True, **extra_data)
[23]:
[<astropy.io.fits.hdu.image.PrimaryHDU object at 0x1687bb440>, <astropy.io.fits.hdu.table.BinTableHDU object at 0x16890c2f0>]
3: Reading in a FITS file#
We can now use the read_generic_lightcurve funtion to read in our FITS file as a LightCurve Object. To do this we must specify the file and the relevent columns for our data.
[24]:
read_lc = lk.io.generic.read_generic_lightcurve(filename='./my_custom_lightcurve.fits', time_column="time", flux_column="flux", flux_err_column="flux_err", time_format="jd")
We can now query the object as done previously.
[25]:
read_lc
[25]:
| time | flux | flux_err |
|---|---|---|
| electron / s | electron / s | |
| Time | float32 | float32 |
| 2458000.0 | 1000.4536743164062 | 0.009999999776482582 |
| 2458000.101010101 | 1000.4080810546875 | 0.009999999776482582 |
| 2458000.202020202 | 1000.3614501953125 | 0.009999999776482582 |
| 2458000.303030303 | 1000.31396484375 | 0.009999999776482582 |
| 2458000.404040404 | 1000.265625 | 0.009999999776482582 |
| 2458000.505050505 | 1000.2166137695312 | 0.009999999776482582 |
| 2458000.606060606 | 1000.1670532226562 | 0.009999999776482582 |
| 2458000.707070707 | 1000.1170654296875 | 0.009999999776482582 |
| 2458000.8080808083 | 1000.0667724609375 | 0.009999999776482582 |
| ... | ... | ... |
| 2458009.1919191917 | 1000.8324584960938 | 0.009999999776482582 |
| 2458009.292929293 | 1000.859375 | 0.009999999776482582 |
| 2458009.393939394 | 1000.8840942382812 | 0.009999999776482582 |
| 2458009.494949495 | 1000.9065551757812 | 0.009999999776482582 |
| 2458009.595959596 | 1000.9266967773438 | 0.009999999776482582 |
| 2458009.696969697 | 1000.9444580078125 | 0.009999999776482582 |
| 2458009.797979798 | 1000.9598388671875 | 0.009999999776482582 |
| 2458009.898989899 | 1000.9727783203125 | 0.009999999776482582 |
| 2458010.0 | 1000.9832763671875 | 0.009999999776482582 |
[26]:
read_lc.flux
[26]:
[27]:
read_lc.plot()
[27]:
<Axes: xlabel='Time [JD]', ylabel='Flux [$\\mathrm{e^{-}\\,s^{-1}}$]'>
We can even check the meta data to make sure our telescope, mission, and origin information was saved correctly.
[28]:
read_lc.meta
[28]:
{'EXTNAME': 'PRIMARY',
'CHECKSUM': 'AaAiBX9ZAaAfAU7Z',
'DATASUM': '0',
'SIMPLE': True,
'BITPIX': 8,
'NAXIS': 0,
'EXTEND': True,
'NEXTEND': 2,
'EXTVER': 1,
'ORIGIN': 'Tutorial',
'DATE': '2026-03-04',
'CREATOR': 'lightkurve.LightCurve.to_fits()',
'TELESCOP': 'MY_FAKE_TELESCOPE',
'INSTRUME': None,
'OBJECT': None,
'RADESYS': 'ICRS',
'RA_OBJ': None,
'DEC_OBJ': None,
'EQUINOX': 2000.0,
'PROCVER': '2.5.2dev',
'MISSION': 'MY_FAKE_MISSION',
'LABEL': None,
'RA': None,
'DEC': None,
'FILENAME': './my_custom_lightcurve.fits',
'FLUX_ORIGIN': 'lightkurve.LightCurve.to_fits()'}
We now know how to create a LightCurve Object, save it as a FITS file, and read in a FITS file as a LightCurve Object.