import warnings
import logging
import numpy as np
from altaipony.flarelc import FlareLightCurve
from lightkurve import (search_lightcurve,
search_targetpixelfile,
KeplerLightCurveFile,
TessLightCurveFile,
KeplerTargetPixelFile,
TessTargetPixelFile,
read)
LOG = logging.getLogger(__name__)
# ----------------------------------------------------------
# Read in data from MAST, either as LC (TESS, Kepler, K2) or TPF (K2)
# No reading in of Kepler or TESS TPFs as de-trending is not implemented for them.
[docs]def from_mast(targetid, mission, c=None, mode="LC", campaign=None, sector=None,
quarter=None, **kwargs):
"""Download light curve derived from
TPF or LC directly from MAST using the
great search functionality in lightkurve,
and construct a FlareLightCurve.
Parameters:
------------
targetid : str or int
TIC, EPIC or KIC ID
mission : str
"Kepler", "K2", or TESS"
c : int
quarter, campaign, or sector
mode : str
"TPF" or "LC", default is "LC"
kwargs : dict
Keyword arguments to pass to _from_mast_<mission>()
functions, like cadence ("short" or "long").
Return:
--------
FlareLightCurve
"""
warnings.warn("\nK2 functionality is deprecated and no longer maintained! It will be removed in version 3.0.")
if mission=="K2":
if mode == "LC":
warnings.warn("\nYou cannot do K2SC de-trending on a light curve only."
"Pass mode='TPF' to be able to run FLC.detrend('k2sc') later.")
if campaign != None:
c = campaign
return _from_mast_K2(targetid, mode, c, **kwargs)
elif mission == "Kepler":
if quarter != None:
c = quarter
return _from_mast_Kepler(targetid, c, **kwargs)
elif mission == "TESS":
if sector != None:
c = sector
return _from_mast_TESS(targetid, c, **kwargs)
return
def _from_mast_K2(targetid, mode, c, flux_type="PDCSAP_FLUX",
cadence="long", aperture_mask="default",
download_dir=None):
mission = "K2"
if mode == "TPF":
tpffilelist = search_targetpixelfile(targetid, mission=mission,
campaign=c, cadence=cadence)
tpf = tpffilelist.download(download_dir=download_dir)
if aperture_mask == "default":
aperture_mask = tpf.pipeline_mask
lc = tpf.to_lightcurve(aperture_mask=aperture_mask)
flc = _convert_TPF_to_FLC(tpf, lc)
return flc
elif mode == "LC":
flcfilelist = search_lightcurve(targetid, mission=mission,
campaign=c, cadence=cadence, author="K2")
return _handle_missions(flcfilelist, mission, flux_type,
cadence, download_dir, targetid,
c)
def _from_mast_Kepler(targetid, c, flux_type="PDCSAP_FLUX", cadence="long",
download_dir=None):
mission = "Kepler"
flcfilelist = search_lightcurve(targetid, mission=mission,
quarter=c, cadence=cadence)
return _handle_missions(flcfilelist, mission, flux_type,
cadence, download_dir, targetid,
c)
def _from_mast_TESS(targetid, c, flux_type="PDCSAP_FLUX", cadence="long",
download_dir=None, **kwargs):
mission = "TESS"
# print(targetid, mission, c, cadence, kwargs)
flcfilelist = search_lightcurve(targetid, mission=mission,
sector=c, cadence=cadence, **kwargs)
# print(flcfilelist)
return _handle_missions(flcfilelist, mission, flux_type,
cadence, download_dir, targetid,
c)
def _handle_missions(flcfilelist, mission, flux_type,
cadence, download_dir, targetid, c):
"""Handle the download in different missions.
Parameters:
-----------
flcfilelist : lightkurve.SearchResult
table of light curves that fit the query
mission : str
"TESS", "Kepler", or "K2"
flux_type : str
SAP_FLUX or PDCSAP_FLUX
cadence : str
short or long
download_dir : str
path to download to, defaults to lightkurve cache directory
targetid : str or int
queried target ID
c : int or list of ints or None
campaigns, quarter or sectors. If None is passed,
will return all available.
Return:
-------
FlareLightCurve
"""
missiondict = {"TESS":["sector","TLC"],
"K2":["campaign","KLC"],
"Kepler":["quarter","KLC"],}
S, origin = missiondict[mission]
if len(flcfilelist)==1:
lc = flcfilelist.download(download_dir=download_dir)
#lc = flcfile.get_lightcurve(flux_type)
flc = _convert_LC_to_FLC(lc, origin=origin)
return flc
elif len(flcfilelist)>1:
warnings.warn(f"Multiple TESS light curves for {targetid}"
f" in {S}(s) {c}. Downloading all to list.")
lclist = []
flcfiles = flcfilelist.download_all(download_dir=download_dir)
for flcfile in flcfiles:
# lc = flcfile.get_lightcurve(flux_type)
flc = _convert_LC_to_FLC(flcfile, origin=origin)
lclist.append(flc)
return lclist
# ----------------------------------------------------------
# ----------------------------------------------------------
# Read in local TPF (Kepler, K2, TESS) or LC (Kepler, K2, TESS, AltaiPony)
[docs]def from_path(path, mode, mission, **kwargs):
"""Construct a FlareLightCurve from
a local LC or TPF file. Also loads
AltaiPony-detrended light curves.
Parameters:
-------------
path : str
Path to local file.
mode : str
"LC", "TPF", "AltaiPony"
mission : str
"Kepler", "K2", "TESS"
kwargs : dict
Keyword arguments to pass to _from_path_<XXX>
functions
"""
if mode == "LC":
return _from_path_LC(path, mission, **kwargs)
elif mode == "TPF":
return _from_path_TPF(path, mission, **kwargs)
elif mode == "AltaiPony":
return _from_path_AltaiPony(path, **kwargs)
else:
raise KeyError("Invalid mode. Pass 'LC', 'TPF', or 'AltaiPony'.")
return
def _from_path_LC(path, mission, flux_type="PDCSAP_FLUX"):
origins = {"Kepler":"KLC", "K2":"KLC","TESS":"TLC"}
if ((mission == "Kepler") | (mission == "K2")):
lcf = KeplerLightCurveFile(path)
elif mission == "TESS":
lcf = TessLightCurveFile(path)
else:
raise KeyError("Invalid mission. Pass 'Kepler', 'K2', or 'TESS'.")
#lc = lcf.get_lightcurve(flux_type)
flc = _convert_LC_to_FLC(lcf, origin=origins[mission])
return flc
def _from_path_TPF(path, mission, aperture_mask="default"):
# origins = {"Kepler":"KLC", "K2":"KLC","TESS":"TLC"}
if ((mission == "Kepler") | (mission == "K2")):
tpf = KeplerTargetPixelFile(path)
elif mission == "TESS":
tpf = TessTargetPixelFile(path)
if aperture_mask == "default":
aperture_mask = tpf.pipeline_mask
lc = tpf.to_lightcurve(aperture_mask=aperture_mask)
flc = _convert_TPF_to_FLC(tpf, lc)
return flc
def _from_path_AltaiPony(path):
# rhdul = fits.open(path)
# attrs = dict()
# for k, v in rhdul[0].header.items():
# if str.lower(k) not in ['simple', 'bitpix', 'naxis', 'extend']:
# if str.lower(k) == "keplerid": #rename keplerid if it appears
# k = "targetid"
# attrs[str.lower(k)] = v
#
# for k in ['time', 'flux', 'flux_err', 'centroid_col',
# 'centroid_row', 'quality', 'cadenceno',
# 'detrended_flux', 'detrended_flux_err',
# 'quality_bitmask', 'saturation']:
# try:
# attrs[k] = rhdul[1].data[k].byteswap().newbyteorder()
# except KeyError:
# LOG.info("Warning: Keyword {} not in file.".format(k))
# continue
lc = read(path)
lc = lc[np.isfinite(lc.time.value) &
np.isfinite(lc.flux.value) &
np.isfinite(lc.cadenceno.value)]
# keys = dict([(key, lc[key].value) for key in lc.colnames[:3]])
# print(keys)
# flc = lc.FlareLightCurve(**keys, time_format=lc.time.format, meta=lc.meta)
# flc = FlareLightCurve(time=lc.time.value,
# flux=lc.flux.value,
# flux_err=lc.flux_err.value,
# pos_corr1=
# meta=lc.meta)
lc["detrended_flux"] = np.nan
lc["detrended_flux_err"] = np.nan
lc.__class__ = FlareLightCurve
lc._init_flare_table()
return lc
# ----------------------------------------------------------
# ----------------------------------------------------------
# Internal type conversion functions
def _convert_TPF_to_FLC(tpf, lc):
if "pos_corr1" not in lc.columns:
lc.pos_corr1 = lc.centroid_col
if "pos_corr2" not in lc.columns:
lc.pos_corr2 = lc.centroid_row
lc = lc[np.isfinite(lc.time.value) &
np.isfinite(lc.flux.value) &
np.isfinite(lc.pos_corr1.value) &
np.isfinite(lc.pos_corr2.value) &
np.isfinite(lc.cadenceno.value) ]
lc["detrended_flux"] = np.nan
lc["detrended_flux_err"] = np.nan
lc.meta['primary_header'] = tpf.hdu[0].header
lc.meta['data_header'] = tpf.hdu[1].header
lc.__class__ = FlareLightCurve
lc._init_flare_table()
lc._add_tpf_columns(tpf.flux.value, tpf.flux_err.value, tpf.pipeline_mask)
lc.origin = "TPF"
return lc
def _convert_LC_to_FLC(lc, origin=None, **kwargs):
lc = lc[np.isfinite(lc.time.value) &
np.isfinite(lc.flux.value) &
np.isfinite(lc.cadenceno.value)]
# lc["detrended_flux"] = np.nan
# lc["detrended_flux_err"] = np.nan
lc.__class__ = FlareLightCurve
lc._init_flare_table()
return lc
# ----------------------------------------------------------