How to save a LightCurve in FITS format?

Once you have detrended or altered a lightcurve in some way, you may want to save it as a FITS file. This allows you to easily share the file with your collaborators or submit your lightcurves as a MAST High Level Science Product (HLSP). Lightkurve provides a to_fits() method which will easily convert your LightCurve object into a fits file.

Below is a brief demostration showing how to_fits() works.

Note: if you are considering contributing a HLSP you may want to read the guidelines for contributing fits files. These include which fits headers are required/suggested for your HLSP to be accepted.

Example: editing and writing a lightcurve

First we'll obtain a random Kepler lightcurve from MAST.

In [1]:
from lightkurve import search_lightcurvefile
lcf = search_lightcurvefile('KIC 757076', quarter=3).download()

Now we'll make some edits to the lightcurve. Below we use the PDCSAP flux from MAST, remove NaN values and clip out any outliers.

In [2]:
lc = lcf.PDCSAP_FLUX.remove_nans().remove_outliers()
lc.scatter();

Now we can use the to_fits method to save the lightcurve to a file called output.fits.

In [3]:
lc.to_fits(path='output.fits', overwrite=True)

Let's take a look at the file and check that it behaved as we expect

In [4]:
from astropy.io import fits
hdu = fits.open('output.fits')
type(hdu)
Out[4]:
astropy.io.fits.hdu.hdulist.HDUList
In [5]:
hdu.info()
Filename: output.fits
No.    Name      Ver    Type      Cards   Dimensions   Format
  0  PRIMARY       1 PrimaryHDU      25   ()      
  1  LIGHTCURVE    1 BinTableHDU     28   4133R x 7C   [D, E, E, J, K, D, D]   

hdu is a set of astropy.io.fits objects, which is what we would expect. Lets take a look at the header of the first extension.

In [6]:
hdu[0].header
Out[6]:
SIMPLE  =                    T / conforms to FITS standards                     
BITPIX  =                    8 / array data type                                
NAXIS   =                    0 / number of array dimensions                     
EXTEND  =                    T / file contains extensions                       
NEXTEND =                    2 / number of standard extensions                  
EXTNAME = 'PRIMARY '           / name of extension                              
EXTVER  =                    1 / extension version number (not format version)  
ORIGIN  = 'Unofficial data product' / institution responsible for file          
DATE    = '2019-09-19'         / file creation date.                            
CREATOR = 'lightkurve.LightCurve.to_fits()' / pipeline job and program used t   
TELESCOP= 'KEPLER  '           / telescope                                      
INSTRUME= 'Kepler Photometer'  / detector type                                  
OBJECT  = '757076  '           / string version of target id                    
KEPLERID=               757076 / unique Kepler target identifier                
CHANNEL =                   56 / CCD channel                                    
RADESYS = 'ICRS    '           / reference frame of celestial coordinates       
RA_OBJ  =            291.03872 / [deg] right ascension                          
DEC_OBJ =             36.59813 / [deg] declination                              
EQUINOX =                 2000 / equinox of celestial coordinate system         
PROCVER = '1.1.1   '                                                            
MISSION = 'Kepler  '                                                            
DATE-OBS= '2009-09-18T17:53:34.165'                                             
QUARTER =                    3                                                  
CHECKSUM= 'ZpfMaoeKToeKZoeK'   / HDU checksum updated 2019-09-19T15:46:38       
DATASUM = '0       '           / data unit checksum updated 2019-09-19T15:46:38 

Looks like it has all the correct information about the target. What about the second extension?

In [7]:
hdu[1].header
Out[7]:
XTENSION= 'BINTABLE'           / binary table extension                         
BITPIX  =                    8 / array data type                                
NAXIS   =                    2 / number of array dimensions                     
NAXIS1  =                   44 / length of dimension 1                          
NAXIS2  =                 4133 / length of dimension 2                          
PCOUNT  =                    0 / number of group parameters                     
GCOUNT  =                    1 / number of groups                               
TFIELDS =                    7 / number of table fields                         
TTYPE1  = 'TIME    '                                                            
TFORM1  = 'D       '                                                            
TUNIT1  = 'bkjd    '                                                            
TTYPE2  = 'FLUX    '                                                            
TFORM2  = 'E       '                                                            
TUNIT2  = 'counts  '                                                            
TTYPE3  = 'FLUX_ERR'                                                            
TFORM3  = 'E       '                                                            
TUNIT3  = 'counts  '                                                            
TTYPE4  = 'CADENCENO'                                                           
TFORM4  = 'J       '                                                            
TTYPE5  = 'SAP_QUALITY'                                                         
TFORM5  = 'K       '                                                            
TTYPE6  = 'MOM_CENTR1'                                                          
TFORM6  = 'D       '                                                            
TTYPE7  = 'MOM_CENTR2'                                                          
TFORM7  = 'D       '                                                            
EXTNAME = 'LIGHTCURVE'                                                          
CHECKSUM= 'U9FAU695U6CAU695'   / HDU checksum updated 2019-09-19T15:46:38       
DATASUM = '390244549'          / data unit checksum updated 2019-09-19T15:46:38 

This extension has 7 columns, TIME, FLUX, FLUX_ERR, SAP_QUALITY, CADENCENO, MOM_CENTR1, and MOM_CENTR2. What if we wanted to add new keywords to our fits file? HLSP products require some extra keywords. Let's add some keywords to explain who made the data, and what our HLSP is.

In [8]:
lc.to_fits(path='output.fits',
             overwrite=True,
             HLSPLEAD='Kepler/K2 GO office',
             HLSPNAME='TUTORIAL',
             CITATION='HEDGES2018')
In [9]:
hdu = fits.open('output.fits')
In [10]:
hdu[0].header
Out[10]:
SIMPLE  =                    T / conforms to FITS standards                     
BITPIX  =                    8 / array data type                                
NAXIS   =                    0 / number of array dimensions                     
EXTEND  =                    T / file contains extensions                       
NEXTEND =                    2 / number of standard extensions                  
EXTNAME = 'PRIMARY '           / name of extension                              
EXTVER  =                    1 / extension version number (not format version)  
ORIGIN  = 'Unofficial data product' / institution responsible for file          
DATE    = '2019-09-19'         / file creation date.                            
CREATOR = 'lightkurve.LightCurve.to_fits()' / pipeline job and program used t   
TELESCOP= 'KEPLER  '           / telescope                                      
INSTRUME= 'Kepler Photometer'  / detector type                                  
OBJECT  = '757076  '           / string version of target id                    
KEPLERID=               757076 / unique Kepler target identifier                
CHANNEL =                   56 / CCD channel                                    
RADESYS = 'ICRS    '           / reference frame of celestial coordinates       
RA_OBJ  =            291.03872 / [deg] right ascension                          
DEC_OBJ =             36.59813 / [deg] declination                              
EQUINOX =                 2000 / equinox of celestial coordinate system         
PROCVER = '1.1.1   '                                                            
HLSPLEAD= 'Kepler/K2 GO office'                                                 
HLSPNAME= 'TUTORIAL'                                                            
CITATION= 'HEDGES2018'                                                          
MISSION = 'Kepler  '                                                            
DATE-OBS= '2009-09-18T17:53:34.165'                                             
QUARTER =                    3                                                  
CHECKSUM= '6aHd6V9Z6ZEb6Z9Z'   / HDU checksum updated 2019-09-19T15:46:39       
DATASUM = '0       '           / data unit checksum updated 2019-09-19T15:46:39 

Now our new keywords are included in the primary header! What about if we want to add more data columns to our fits file? We can simply add data columns in the same way. Let's add the data quality to our fits file.

In [11]:
demo_vector = lc.fold(1.23456789).phase
demo_vector
Out[11]:
array([-0.49992399, -0.49952132, -0.49932792, ...,  0.49923243,
        0.49957413,  0.49988861])
In [12]:
lc.to_fits(path='output.fits',
             overwrite=True,
             HLSPLEAD='Kepler/K2 GO office',
             HLSPNAME='TUTORIAL',
             CITATION='HEDGES2018',
             DEMO_COLUMN=demo_vector)
In [13]:
hdu = fits.open('output.fits')
In [14]:
hdu[1].data.columns
Out[14]:
ColDefs(
    name = 'TIME'; format = 'D'; unit = 'bkjd'
    name = 'FLUX'; format = 'E'; unit = 'counts'
    name = 'FLUX_ERR'; format = 'E'; unit = 'counts'
    name = 'CADENCENO'; format = 'J'
    name = 'DEMO_COLUMN'; format = 'D'
    name = 'SAP_QUALITY'; format = 'K'
    name = 'MOM_CENTR1'; format = 'D'
    name = 'MOM_CENTR2'; format = 'D'
)

The vector is populated as a data column in the HDU extension. Once all your lightcurves are saved as fits files and you have a README file, you can consider submitting your data products to MAST.