tglc 0.6.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tglc/__init__.py +3 -0
- tglc/background_mask/__init__.py +0 -0
- tglc/background_mask/median_mask.fits +0 -0
- tglc/effective_psf.py +484 -0
- tglc/ffi.py +376 -0
- tglc/ffi_cut.py +279 -0
- tglc/lc_plot.py +2662 -0
- tglc/mast.py +116 -0
- tglc/quick_lc.py +526 -0
- tglc/run.py +95 -0
- tglc/source_output.py +85 -0
- tglc/target_lightcurve.py +362 -0
- tglc-0.6.5.dist-info/LICENSE +21 -0
- tglc-0.6.5.dist-info/METADATA +80 -0
- tglc-0.6.5.dist-info/RECORD +17 -0
- tglc-0.6.5.dist-info/WHEEL +5 -0
- tglc-0.6.5.dist-info/top_level.txt +1 -0
tglc/run.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# export OPENBLAS_NUM_THREADS=1
|
|
2
|
+
# export MKL_NUM_THREADS=1
|
|
3
|
+
# export NUMEXPR_NUM_THREADS=1
|
|
4
|
+
# export OMP_NUM_THREADS=1
|
|
5
|
+
# https://dev.to/kapilgorve/set-environment-variable-in-windows-and-wsl-linux-in-terminal-3mg4
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
|
|
9
|
+
os.environ["OPENBLAS_NUM_THREADS"] = "1"
|
|
10
|
+
os.environ["MKL_NUM_THREADS"] = "1"
|
|
11
|
+
os.environ["NUMEXPR_NUM_THREADS"] = "1"
|
|
12
|
+
os.environ["OMP_NUM_THREADS"] = "1"
|
|
13
|
+
|
|
14
|
+
import pickle
|
|
15
|
+
import numpy as np
|
|
16
|
+
import matplotlib.pyplot as plt
|
|
17
|
+
import multiprocessing
|
|
18
|
+
|
|
19
|
+
from astropy.io import fits
|
|
20
|
+
from tglc.target_lightcurve import epsf
|
|
21
|
+
from multiprocessing import Pool
|
|
22
|
+
from functools import partial
|
|
23
|
+
from glob import glob
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def lc_per_cut(i, camccd='', local_directory=''):
|
|
27
|
+
cut_x = i // 14
|
|
28
|
+
cut_y = i % 14
|
|
29
|
+
with open(f'{local_directory}source/{camccd}/source_{cut_x:02d}_{cut_y:02d}.pkl', 'rb') as input_:
|
|
30
|
+
source = pickle.load(input_)
|
|
31
|
+
epsf(source, psf_size=11, factor=2, cut_x=cut_x, cut_y=cut_y, sector=source.sector, power=1.4,
|
|
32
|
+
local_directory=local_directory, limit_mag=16, save_aper=False, no_progress_bar=True)
|
|
33
|
+
# residual =
|
|
34
|
+
# np.save(f'/home/tehan/cosmos/MKI/Roland/{cut_x:02d}_{cut_y:02d}.npy', residual)
|
|
35
|
+
# fig = plt.figure(constrained_layout=False, figsize=(8, 8))
|
|
36
|
+
# gs = fig.add_gridspec(2, 2)
|
|
37
|
+
# gs.update(wspace=0.4, hspace=0.2)
|
|
38
|
+
# wcs = source.wcs
|
|
39
|
+
# ax0 = fig.add_subplot(gs[0:2, 0:2], projection=wcs)
|
|
40
|
+
# ax0.imshow(residual, origin='bottom')
|
|
41
|
+
# ax0.coords['pos.eq.ra'].set_axislabel('Right Ascension')
|
|
42
|
+
# ax0.coords['pos.eq.ra'].set_axislabel_position('l')
|
|
43
|
+
# ax0.coords['pos.eq.ra'].set_ticklabel(rotation=90)
|
|
44
|
+
# ax0.coords['pos.eq.dec'].set_axislabel('Declination')
|
|
45
|
+
# ax0.coords['pos.eq.dec'].set_axislabel_position('b')
|
|
46
|
+
# ax0.coords.grid(color='k', ls='dotted')
|
|
47
|
+
# ax0.tick_params(axis='x', labelbottom=True)
|
|
48
|
+
# ax0.tick_params(axis='y', labelleft=True)
|
|
49
|
+
# ax0.set_title(f'Sector 42 Camera 1 CCD 1, cut {cut_x:02d}_{cut_y:02d}, cadence {source.cadence[2817]}, time {source.time[2817]}')
|
|
50
|
+
# plt.savefig(f'/home/tehan/cosmos/MKI/Roland/figs/{cut_x:02d}_{cut_y:02d}.png')
|
|
51
|
+
|
|
52
|
+
def lc_per_ccd(camccd='1-1', local_directory=''):
|
|
53
|
+
os.makedirs(f'{local_directory}epsf/{camccd}/', exist_ok=True)
|
|
54
|
+
with Pool() as p:
|
|
55
|
+
p.map(partial(lc_per_cut, camccd=camccd, local_directory=local_directory), range(196))
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def plot_epsf(sector=1, camccd='', local_directory=''):
|
|
59
|
+
fig = plt.figure(constrained_layout=False, figsize=(20, 9))
|
|
60
|
+
gs = fig.add_gridspec(14, 30)
|
|
61
|
+
gs.update(wspace=0.05, hspace=0.05)
|
|
62
|
+
for i in range(196):
|
|
63
|
+
cut_x = i // 14
|
|
64
|
+
cut_y = i % 14
|
|
65
|
+
psf = np.load(f'{local_directory}epsf/{camccd}/epsf_{cut_x:02d}_{cut_y:02d}_sector_{sector}_{camccd}.npy')
|
|
66
|
+
cmap = 'bone'
|
|
67
|
+
if np.isnan(psf).any():
|
|
68
|
+
cmap = 'inferno'
|
|
69
|
+
ax = fig.add_subplot(gs[13 - cut_y, cut_x])
|
|
70
|
+
ax.imshow(psf[0, :23 ** 2].reshape(23, 23), cmap=cmap, origin='lower')
|
|
71
|
+
ax.set_yticklabels([])
|
|
72
|
+
ax.set_xticklabels([])
|
|
73
|
+
ax.tick_params(axis='x', bottom=False)
|
|
74
|
+
ax.tick_params(axis='y', left=False)
|
|
75
|
+
input_files = glob(f'{local_directory}ffi/*{camccd}-????-?_ffic.fits')
|
|
76
|
+
with fits.open(input_files[0], mode='denywrite') as hdul:
|
|
77
|
+
flux = hdul[1].data[0:2048, 44:2092]
|
|
78
|
+
ax_1 = fig.add_subplot(gs[:, 16:])
|
|
79
|
+
ax_1.imshow(np.log10(flux), origin='lower')
|
|
80
|
+
fig.text(0.25, 0.08, 'CUT X (0-13)', ha='center')
|
|
81
|
+
fig.text(0.09, 0.5, 'CUT Y (0-13)', va='center', rotation='vertical')
|
|
82
|
+
fig.suptitle(f'ePSF for sector:{sector} camera-ccd:{camccd}', x=0.5, y=0.92, size=20)
|
|
83
|
+
plt.savefig(f'{local_directory}log/epsf_sector_{sector}_{camccd}.png', bbox_inches='tight', dpi=300)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
if __name__ == '__main__':
|
|
87
|
+
print("Number of cpu : ", multiprocessing.cpu_count())
|
|
88
|
+
sector = 1
|
|
89
|
+
local_directory = f'/home/tehan/data/sector{sector:04d}/'
|
|
90
|
+
for i in range(16):
|
|
91
|
+
name = f'{1 + i // 4}-{1 + i % 4}'
|
|
92
|
+
lc_per_ccd(camccd=name, local_directory=local_directory)
|
|
93
|
+
plot_epsf(sector=sector, camccd=name, local_directory=local_directory)
|
|
94
|
+
# name = f'1-3'
|
|
95
|
+
# lc_per_cut(169, camccd=name, local_directory=local_directory)
|
tglc/source_output.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
os.environ["OPENBLAS_NUM_THREADS"] = "8"
|
|
4
|
+
os.environ["MKL_NUM_THREADS"] = "8"
|
|
5
|
+
os.environ["NUMEXPR_NUM_THREADS"] = "8"
|
|
6
|
+
os.environ["OMP_NUM_THREADS"] = "8"
|
|
7
|
+
import glob
|
|
8
|
+
from tglc.ffi import *
|
|
9
|
+
from multiprocessing import Pool
|
|
10
|
+
from functools import partial
|
|
11
|
+
import logging
|
|
12
|
+
import warnings
|
|
13
|
+
import astroquery
|
|
14
|
+
import matplotlib.pyplot as plt
|
|
15
|
+
|
|
16
|
+
logging.getLogger(astroquery.__name__).setLevel(logging.ERROR)
|
|
17
|
+
warnings.simplefilter('ignore', UserWarning)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def median_mask(sector_num=26):
|
|
21
|
+
mask = np.ones((sector_num, 16, 2048))
|
|
22
|
+
for i in range(sector_num):
|
|
23
|
+
for j in range(16):
|
|
24
|
+
mask[i, j] = np.load(
|
|
25
|
+
f'/mnt/c/users/tehan/desktop/mask/mask_sector{i + 1:04d}_cam{1 + j // 4}_ccd{1 + j % 4}.npy')
|
|
26
|
+
plt.figure(figsize=(10, 3))
|
|
27
|
+
plt.imshow(mask[i], origin='lower', aspect=30)
|
|
28
|
+
plt.colorbar()
|
|
29
|
+
plt.title(f'sector_{i + 1}')
|
|
30
|
+
plt.xlabel(f'column')
|
|
31
|
+
plt.ylabel(f'camera-ccd')
|
|
32
|
+
plt.savefig(f'/mnt/c/users/tehan/desktop/mask/fig/sector_{i + 1}.png', dpi=300)
|
|
33
|
+
plt.close()
|
|
34
|
+
med_mask = np.nanmedian(mask, axis=0)
|
|
35
|
+
|
|
36
|
+
plt.figure(figsize=(10, 3))
|
|
37
|
+
plt.imshow(med_mask, origin='lower', aspect=30, vmin=np.min(np.nonzero(med_mask)), vmax=np.max(med_mask))
|
|
38
|
+
plt.colorbar()
|
|
39
|
+
plt.xlabel(f'column')
|
|
40
|
+
plt.ylabel(f'camera-ccd')
|
|
41
|
+
plt.title(f'median_mask_first_{sector_num}_sectors')
|
|
42
|
+
plt.savefig(f'/mnt/c/users/tehan/desktop/mask/fig/median_mask_primary.png', dpi=300)
|
|
43
|
+
plt.close()
|
|
44
|
+
hdu = fits.PrimaryHDU(med_mask)
|
|
45
|
+
hdu.writeto('/mnt/c/users/tehan/desktop/mask/median_mask.fits')
|
|
46
|
+
return med_mask
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def cut_ffi_(i, sector=1, size=150, local_directory=''):
|
|
50
|
+
ffi(camera=1 + i // 4, ccd=1 + i % 4, sector=sector, size=size, local_directory=local_directory,
|
|
51
|
+
producing_mask=False)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def ffi_to_source(sector=1, local_directory=''):
|
|
55
|
+
"""
|
|
56
|
+
Cut calibrated FFI to source.pkl
|
|
57
|
+
:param sector: int, required
|
|
58
|
+
TESS sector number
|
|
59
|
+
:param local_directory: string, required
|
|
60
|
+
output directory
|
|
61
|
+
"""
|
|
62
|
+
os.makedirs(f'{local_directory}lc/', exist_ok=True)
|
|
63
|
+
os.makedirs(f'{local_directory}epsf/', exist_ok=True)
|
|
64
|
+
os.makedirs(f'{local_directory}ffi/', exist_ok=True)
|
|
65
|
+
os.makedirs(f'{local_directory}source/', exist_ok=True)
|
|
66
|
+
os.makedirs(f'{local_directory}log/', exist_ok=True)
|
|
67
|
+
os.makedirs(f'{local_directory}mask/', exist_ok=True)
|
|
68
|
+
|
|
69
|
+
with Pool(1) as p:
|
|
70
|
+
p.map(partial(cut_ffi_, sector=sector, size=150, local_directory=local_directory), range(16))
|
|
71
|
+
|
|
72
|
+
# for i in range(16):
|
|
73
|
+
# ffi(camera=1 + i // 4, ccd=1 + i % 4, sector=sector, size=150, local_directory=local_directory)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
if __name__ == '__main__':
|
|
77
|
+
sector = 56
|
|
78
|
+
ffi_to_source(sector=sector, local_directory=f'/home/tehan/data/sector{sector:04d}/')
|
|
79
|
+
# med_mask = median_mask(sector_num=26)
|
|
80
|
+
# ffi_to_source(sector=sector, local_directory=f'/pdo/users/tehan/sector{sector:04d}/')
|
|
81
|
+
# files = glob.glob(f'/home/tehan/data/sector{sector:04d}/source/*/source_00_00.pkl')
|
|
82
|
+
# for i in range(len(files)):
|
|
83
|
+
# with open(files[i], 'rb') as input_:
|
|
84
|
+
# source = pickle.load(input_)
|
|
85
|
+
# print(np.min(np.diff(source.cadence)), files[i])
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
# export OPENBLAS_NUM_THREADS=1
|
|
2
|
+
# https://dev.to/kapilgorve/set-environment-variable-in-windows-and-wsl-linux-in-terminal-3mg4
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import warnings
|
|
6
|
+
import numpy as np
|
|
7
|
+
import numpy.ma as ma
|
|
8
|
+
import tglc
|
|
9
|
+
import matplotlib.pyplot as plt
|
|
10
|
+
from astropy.io import fits
|
|
11
|
+
from tqdm import trange
|
|
12
|
+
from os.path import exists
|
|
13
|
+
from tglc.effective_psf import get_psf, fit_psf, fit_lc, fit_lc_float_field, bg_mod
|
|
14
|
+
from tglc.ffi import Source
|
|
15
|
+
from tglc.ffi_cut import Source_cut
|
|
16
|
+
|
|
17
|
+
warnings.simplefilter('always', UserWarning)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def lc_output(source, local_directory='', index=0, time=None, psf_lc=None, cal_psf_lc=None, aper_lc=None,
|
|
21
|
+
cal_aper_lc=None, bg=None, tess_flag=None, tglc_flag=None, cadence=None, aperture=None,
|
|
22
|
+
cut_x=None, cut_y=None, star_x=2, star_y=2, x_aperture=None, y_aperture=None, near_edge=False,
|
|
23
|
+
local_bg=None, save_aper=False, portion=1, prior=None, transient=None):
|
|
24
|
+
"""
|
|
25
|
+
lc output to .FITS file in MAST HLSP standards
|
|
26
|
+
:param tglc_flag: np.array(), required
|
|
27
|
+
TGLC quality flags
|
|
28
|
+
:param source: tglc.ffi_cut.Source or tglc.ffi_cut.Source_cut, required
|
|
29
|
+
Source or Source_cut object
|
|
30
|
+
:param local_directory: string, required
|
|
31
|
+
output directory
|
|
32
|
+
:param index: int, required
|
|
33
|
+
star index
|
|
34
|
+
:param time: list, required
|
|
35
|
+
epochs of FFI
|
|
36
|
+
:param lc: list, required
|
|
37
|
+
ePSF light curve fluxes
|
|
38
|
+
:param cal_lc: list, required
|
|
39
|
+
ePSF light curve fluxes, detrended
|
|
40
|
+
:param cadence: list, required
|
|
41
|
+
list of cadences of TESS FFI
|
|
42
|
+
:return:
|
|
43
|
+
"""
|
|
44
|
+
if transient is None:
|
|
45
|
+
objid = [int(s) for s in (source.gaia[index]['DESIGNATION']).split() if s.isdigit()][0]
|
|
46
|
+
else:
|
|
47
|
+
objid = transient[0]
|
|
48
|
+
source_path = f'{local_directory}hlsp_tglc_tess_ffi_gaiaid-{objid}-s{source.sector:04d}-cam{source.camera}-ccd{source.ccd}_tess_v1_llc.fits'
|
|
49
|
+
source_exists = exists(source_path)
|
|
50
|
+
# if source_exists and (os.path.getsize(source_path) > 0):
|
|
51
|
+
# print('LC exists, please (re)move the file if you wish to overwrite.')
|
|
52
|
+
# return
|
|
53
|
+
if np.isnan(source.gaia[index]['phot_bp_mean_mag']) or ma.is_masked(source.gaia[index]['phot_bp_mean_mag']):
|
|
54
|
+
gaia_bp = 'NaN'
|
|
55
|
+
else:
|
|
56
|
+
gaia_bp = source.gaia[index]['phot_bp_mean_mag']
|
|
57
|
+
if np.isnan(source.gaia[index]['phot_rp_mean_mag']) or ma.is_masked(source.gaia[index]['phot_rp_mean_mag']):
|
|
58
|
+
gaia_rp = 'NaN'
|
|
59
|
+
else:
|
|
60
|
+
gaia_rp = source.gaia[index]['phot_rp_mean_mag']
|
|
61
|
+
psf_err = 1.4826 * np.nanmedian(np.abs(psf_lc - np.nanmedian(psf_lc)))
|
|
62
|
+
if np.isnan(psf_err):
|
|
63
|
+
psf_err = 'NaN'
|
|
64
|
+
aper_err = 1.4826 * np.nanmedian(np.abs(aper_lc - np.nanmedian(aper_lc)))
|
|
65
|
+
if np.isnan(aper_err):
|
|
66
|
+
aper_err = 'NaN'
|
|
67
|
+
cal_psf_err = 1.4826 * np.nanmedian(np.abs(cal_psf_lc - np.nanmedian(cal_psf_lc)))
|
|
68
|
+
if np.isnan(cal_psf_err):
|
|
69
|
+
cal_psf_err = 'NaN'
|
|
70
|
+
cal_aper_err = 1.4826 * np.nanmedian(np.abs(cal_aper_lc - np.nanmedian(cal_aper_lc)))
|
|
71
|
+
if np.isnan(cal_aper_err):
|
|
72
|
+
cal_aper_err = 'NaN'
|
|
73
|
+
try:
|
|
74
|
+
ticid = str(source.tic['TIC'][np.where(source.tic['dr3_source_id'] == objid)][0])
|
|
75
|
+
except:
|
|
76
|
+
ticid = ''
|
|
77
|
+
try:
|
|
78
|
+
raw_flux = np.nanmedian(source.flux[:, star_y, star_x])
|
|
79
|
+
except:
|
|
80
|
+
raw_flux = None
|
|
81
|
+
if save_aper:
|
|
82
|
+
primary_hdu = fits.PrimaryHDU(aperture)
|
|
83
|
+
else:
|
|
84
|
+
primary_hdu = fits.PrimaryHDU()
|
|
85
|
+
|
|
86
|
+
primary_hdu.header = fits.Header(cards=[
|
|
87
|
+
fits.Card('SIMPLE', True, 'conforms to FITS standard'),
|
|
88
|
+
fits.Card('EXTEND', True),
|
|
89
|
+
fits.Card('NEXTEND', 1, 'number of standard extensions'),
|
|
90
|
+
fits.Card('EXTNAME', 'PRIMARY', 'name of extension'),
|
|
91
|
+
fits.Card('EXTDATA', 'aperture', 'decontaminated FFI cut for aperture photometry'),
|
|
92
|
+
fits.Card('EXTVER', 1, 'extension version'),
|
|
93
|
+
fits.Card('TIMESYS', 'TDB', 'TESS Barycentric Dynamical Time'),
|
|
94
|
+
fits.Card('BUNIT', 'e-/s', 'flux unit'),
|
|
95
|
+
fits.Card('STAR_X', x_aperture, 'star x position in cut'),
|
|
96
|
+
fits.Card('STAR_Y', y_aperture, 'star y position in cut'),
|
|
97
|
+
fits.Card('COMMENT', 'hdul[0].data[:,star_y,star_x]=lc'),
|
|
98
|
+
fits.Card('ORIGIN', 'UCSB/TGLC', 'institution responsible for creating this file'),
|
|
99
|
+
fits.Card('TELESCOP', 'TESS', 'telescope'),
|
|
100
|
+
fits.Card('INSTRUME', 'TESS Photometer', 'detector type'),
|
|
101
|
+
fits.Card('FILTER', 'TESS', 'the filter used for the observations'),
|
|
102
|
+
fits.Card('OBJECT', source.gaia[index]['DESIGNATION'], 'string version of Gaia DR3 ID'),
|
|
103
|
+
fits.Card('GAIADR3', objid, 'integer version of Gaia DR3 ID'),
|
|
104
|
+
fits.Card('TICID', ticid, 'TESS Input Catalog ID'),
|
|
105
|
+
fits.Card('SECTOR', source.sector, 'observation sector'),
|
|
106
|
+
fits.Card('CAMERA', source.camera, 'camera No.'),
|
|
107
|
+
fits.Card('CCD', source.ccd, 'CCD No.'),
|
|
108
|
+
fits.Card('CUT_x', cut_x, 'FFI cut x index'),
|
|
109
|
+
fits.Card('CUT_y', cut_y, 'FFI cut y index'),
|
|
110
|
+
fits.Card('CUTSIZE', source.size, 'FFI cut size'),
|
|
111
|
+
fits.Card('RADESYS', 'ICRS', 'reference frame of celestial coordinates'),
|
|
112
|
+
fits.Card('RA_OBJ', source.gaia[index]['ra'], '[deg] right ascension, J2000'),
|
|
113
|
+
fits.Card('DEC_OBJ', source.gaia[index]['dec'], '[deg] declination, J2000'),
|
|
114
|
+
fits.Card('TESSMAG', source.gaia[index]['tess_mag'], 'TESS magnitude, fitted by Gaia DR3 bands'),
|
|
115
|
+
fits.Card('GAIA_G', source.gaia[index]['phot_g_mean_mag'], 'Gaia DR3 g band magnitude'),
|
|
116
|
+
fits.Card('GAIA_bp', gaia_bp, 'Gaia DR3 bp band magnitude'),
|
|
117
|
+
fits.Card('GAIA_rp', gaia_rp, 'Gaia DR3 rp band magnitude'),
|
|
118
|
+
fits.Card('RAWFLUX', raw_flux, 'median flux of raw FFI'),
|
|
119
|
+
fits.Card('CALIB', 'TGLC', 'pipeline used for image calibration')])
|
|
120
|
+
if save_aper:
|
|
121
|
+
primary_hdu.header.comments['NAXIS1'] = "Time (hdul[1].data['time'])"
|
|
122
|
+
primary_hdu.header.comments['NAXIS2'] = 'x size of cut'
|
|
123
|
+
primary_hdu.header.comments['NAXIS3'] = 'y size of cut'
|
|
124
|
+
|
|
125
|
+
t_start = source.time[0]
|
|
126
|
+
t_stop = source.time[-1]
|
|
127
|
+
if source.sector < 27: # primary
|
|
128
|
+
exposure_time = 1800
|
|
129
|
+
elif source.sector < 56: # first extended
|
|
130
|
+
exposure_time = 600
|
|
131
|
+
else: # second extended
|
|
132
|
+
exposure_time = 200
|
|
133
|
+
c1 = fits.Column(name='time', array=np.array(time), format='D')
|
|
134
|
+
c2 = fits.Column(name='psf_flux', array=np.array(psf_lc), format='E') # psf factor
|
|
135
|
+
# c3 = fits.Column(name='psf_flux_err',
|
|
136
|
+
# array=1.4826 * np.median(np.abs(psf_lc - np.median(psf_lc))) * np.ones(len(psf_lc)), format='E')
|
|
137
|
+
c4 = fits.Column(name='aperture_flux', array=aper_lc / portion, format='E')
|
|
138
|
+
# c5 = fits.Column(name='aperture_flux_err',
|
|
139
|
+
# array=1.4826 * np.median(np.abs(aper_lc - np.median(aper_lc))) * np.ones(len(aper_lc)), format='E')
|
|
140
|
+
c6 = fits.Column(name='cal_psf_flux', array=np.array(cal_psf_lc), format='E')
|
|
141
|
+
# c7 = fits.Column(name='cal_psf_flux_err',
|
|
142
|
+
# array=1.4826 * np.median(np.abs(cal_psf_lc - np.median(cal_psf_lc))) * np.ones(len(cal_psf_lc)),
|
|
143
|
+
# format='E')
|
|
144
|
+
c8 = fits.Column(name='cal_aper_flux', array=np.array(cal_aper_lc), format='E')
|
|
145
|
+
# c9 = fits.Column(name='cal_aper_flux_err',
|
|
146
|
+
# array=1.4826 * np.median(np.abs(cal_aper_lc - np.median(cal_aper_lc))) * np.ones(len(cal_aper_lc)),
|
|
147
|
+
# format='E')
|
|
148
|
+
c10 = fits.Column(name='background', array=bg, format='E') # add tilt
|
|
149
|
+
c11 = fits.Column(name='cadence_num', array=np.array(cadence), format='J') # 32 bit int
|
|
150
|
+
c12 = fits.Column(name='TESS_flags', array=np.array(tess_flag), format='I') # 16 bit int
|
|
151
|
+
c13 = fits.Column(name='TGLC_flags', array=tglc_flag, format='I')
|
|
152
|
+
table_hdu = fits.BinTableHDU.from_columns([c1, c2, c4, c6, c8, c10, c11, c12, c13])
|
|
153
|
+
table_hdu.header.append(('INHERIT', 'T', 'inherit the primary header'), end=True)
|
|
154
|
+
table_hdu.header.append(('EXTNAME', 'LIGHTCURVE', 'name of extension'), end=True)
|
|
155
|
+
table_hdu.header.append(('EXTVER', 1, 'extension version'), # TODO: version?
|
|
156
|
+
end=True)
|
|
157
|
+
table_hdu.header.append(('TELESCOP', 'TESS', 'telescope'), end=True)
|
|
158
|
+
table_hdu.header.append(('INSTRUME', 'TESS Photometer', 'detector type'), end=True)
|
|
159
|
+
table_hdu.header.append(('FILTER', 'TESS', 'the filter used for the observations'), end=True)
|
|
160
|
+
table_hdu.header.append(('OBJECT', source.gaia[index]['DESIGNATION'], 'string version of Gaia DR3 ID'),
|
|
161
|
+
end=True)
|
|
162
|
+
table_hdu.header.append(('GAIADR3', objid, 'integer version of GaiaDR3 designation'), end=True)
|
|
163
|
+
table_hdu.header.append(('RADESYS', 'ICRS', 'reference frame of celestial coordinates'), end=True)
|
|
164
|
+
table_hdu.header.append(('RA_OBJ', source.gaia[index]['ra'], '[deg] right ascension, J2000'), end=True)
|
|
165
|
+
table_hdu.header.append(('DEC_OBJ', source.gaia[index]['dec'], '[deg] declination, J2000'), end=True)
|
|
166
|
+
table_hdu.header.append(('TIMEREF', 'SOLARSYSTEM', 'barycentric correction applied to times'), end=True)
|
|
167
|
+
table_hdu.header.append(('TASSIGN', 'SPACECRAFT', 'where time is assigned'), end=True)
|
|
168
|
+
table_hdu.header.append(('BJDREFI', 2457000, 'integer part of BJD reference date'), end=True)
|
|
169
|
+
table_hdu.header.append(('BJDREFR', 0.0, 'fraction of the day in BJD reference date'), end=True)
|
|
170
|
+
table_hdu.header.append(('TIMESYS', 'TDB', 'TESS Barycentric Dynamical Time'), end=True)
|
|
171
|
+
table_hdu.header.append(('TIMEUNIT', 'd', 'time unit for TIME'), end=True)
|
|
172
|
+
# table_hdu.header.append(('BUNIT', 'e-/s', 'psf_flux unit'), end=True)
|
|
173
|
+
table_hdu.header.append(('TELAPS', t_stop - t_start, '[d] TSTOP-TSTART'), end=True)
|
|
174
|
+
table_hdu.header.append(('TSTART', t_start, '[d] observation start time in TBJD'), end=True)
|
|
175
|
+
table_hdu.header.append(('TSTOP', t_stop, '[d] observation end time in TBJD'), end=True)
|
|
176
|
+
table_hdu.header.append(('MJD_BEG', t_start + 56999.5, '[d] start time in barycentric MJD'), end=True)
|
|
177
|
+
table_hdu.header.append(('MJD_END', t_stop + 56999.5, '[d] end time in barycentric MJD'), end=True)
|
|
178
|
+
table_hdu.header.append(('TIMEDEL', (t_stop - t_start) / len(source.time), '[d] time resolution of data'),
|
|
179
|
+
end=True)
|
|
180
|
+
table_hdu.header.append(('XPTIME', exposure_time, '[s] exposure time'), end=True)
|
|
181
|
+
table_hdu.header.append(('PSF_ERR', psf_err, '[e-/s] PSF flux error'), end=True)
|
|
182
|
+
table_hdu.header.append(('APER_ERR', aper_err, '[e-/s] aperture flux error'), end=True)
|
|
183
|
+
table_hdu.header.append(('CPSF_ERR', cal_psf_err, '[e-/s] calibrated PSF flux error'), end=True)
|
|
184
|
+
table_hdu.header.append(('CAPE_ERR', cal_aper_err, '[e-/s] calibrated aperture flux error'), end=True)
|
|
185
|
+
table_hdu.header.append(('NEAREDGE', near_edge, 'distance to edges of FFI <= 2'), end=True)
|
|
186
|
+
table_hdu.header.append(('LOC_BG', local_bg, '[e-/s] locally modified background'), end=True)
|
|
187
|
+
table_hdu.header.append(('COMMENT', "TRUE_BG = hdul[1].data['background'] + LOC_BG"), end=True)
|
|
188
|
+
table_hdu.header.append(('WOTAN_WL', 1, 'wotan detrending window length'), end=True)
|
|
189
|
+
table_hdu.header.append(('WOTAN_MT', 'biweight', 'wotan detrending method'), end=True)
|
|
190
|
+
if type(prior) == float:
|
|
191
|
+
table_hdu.header.append(('PRIOR', prior, 'prior of field stars'), end=True)
|
|
192
|
+
|
|
193
|
+
hdul = fits.HDUList([primary_hdu, table_hdu])
|
|
194
|
+
hdul.writeto(
|
|
195
|
+
f'{local_directory}hlsp_tglc_tess_ffi_gaiaid-{objid}-s{source.sector:04d}-cam{source.camera}-ccd{source.ccd}_tess_v1_llc.fits',
|
|
196
|
+
overwrite=True)
|
|
197
|
+
return
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def epsf(source, psf_size=11, factor=2, local_directory='', target=None, cut_x=0, cut_y=0, sector=0,
|
|
201
|
+
limit_mag=16, edge_compression=1e-4, power=1.4, name=None, save_aper=False, no_progress_bar=False, prior=None):
|
|
202
|
+
"""
|
|
203
|
+
User function that unites all necessary steps
|
|
204
|
+
:param source: TGLC.ffi_cut.Source or TGLC.ffi_cut.Source_cut, required
|
|
205
|
+
Source or Source_cut object
|
|
206
|
+
:param factor: int, optional
|
|
207
|
+
effective PSF oversampling factor
|
|
208
|
+
:param local_directory: string, required
|
|
209
|
+
output directory
|
|
210
|
+
:param sector: int, required
|
|
211
|
+
TESS sector number
|
|
212
|
+
:param limit_mag: int, required
|
|
213
|
+
upper limiting magnitude of the lightcurves that are outputted.
|
|
214
|
+
:param edge_compression: float, optional
|
|
215
|
+
parameter for edge compression
|
|
216
|
+
:param power: float, optional
|
|
217
|
+
power for weighting bright stars' contribution to the fit. 1 means same contribution from all stars,
|
|
218
|
+
<1 means emphasizing dimmer stars
|
|
219
|
+
:return:
|
|
220
|
+
"""
|
|
221
|
+
if target is None:
|
|
222
|
+
target = f'{cut_x:02d}_{cut_y:02d}'
|
|
223
|
+
A, star_info, over_size, x_round, y_round = get_psf(source, psf_size=psf_size, factor=factor,
|
|
224
|
+
edge_compression=edge_compression)
|
|
225
|
+
lc_directory = f'{local_directory}lc/{source.camera}-{source.ccd}/'
|
|
226
|
+
epsf_loc = f'{local_directory}epsf/{source.camera}-{source.ccd}/epsf_{target}_sector_{sector}_{source.camera}-{source.ccd}.npy'
|
|
227
|
+
if type(source) == Source_cut:
|
|
228
|
+
bg_dof = 3
|
|
229
|
+
lc_directory = f'{local_directory}lc/'
|
|
230
|
+
epsf_loc = f'{local_directory}epsf/epsf_{target}_sector_{sector}.npy'
|
|
231
|
+
else:
|
|
232
|
+
bg_dof = 6
|
|
233
|
+
os.makedirs(lc_directory, exist_ok=True)
|
|
234
|
+
# sim_image = np.dot(A[:source.size ** 2, :], fit_psf(A, source, over_size, power=power, time=2817).T)
|
|
235
|
+
# # residual = np.abs(source.flux[2817].flatten() - sim_image)
|
|
236
|
+
# residual = source.flux[2817].flatten() - sim_image
|
|
237
|
+
# return residual.reshape((source.size, source.size))
|
|
238
|
+
|
|
239
|
+
epsf_exists = exists(epsf_loc)
|
|
240
|
+
if epsf_exists:
|
|
241
|
+
e_psf = np.load(epsf_loc)
|
|
242
|
+
print(f'Loaded ePSF {target} from directory. ')
|
|
243
|
+
else:
|
|
244
|
+
e_psf = np.zeros((len(source.time), over_size ** 2 + bg_dof))
|
|
245
|
+
for i in trange(len(source.time), desc='Fitting ePSF', disable=no_progress_bar):
|
|
246
|
+
e_psf[i] = fit_psf(A, source, over_size, power=power, time=i)
|
|
247
|
+
if np.isnan(e_psf).any():
|
|
248
|
+
warnings.warn(
|
|
249
|
+
f"TESS FFI cut includes Nan values. Please shift the center of the cutout to remove Nan near edge. Target: {target}")
|
|
250
|
+
np.save(epsf_loc, e_psf)
|
|
251
|
+
# contamination_8 = np.dot(A[:source.size ** 2, :], e_psf[0].T)
|
|
252
|
+
# np.save('/mnt/c/users/tehan/desktop/7654/contamination_8_.npy', contamination_8)
|
|
253
|
+
# TODO: quality use which background?
|
|
254
|
+
background = np.dot(A[:source.size ** 2, -bg_dof:], e_psf[:, -bg_dof:].T)
|
|
255
|
+
quality_raw = np.zeros(len(source.time), dtype=np.int16)
|
|
256
|
+
sigma = 1.4826 * np.nanmedian(np.abs(e_psf[:, -1] - np.nanmedian(e_psf[:, -1])))
|
|
257
|
+
quality_raw[abs(e_psf[:, -1] - np.nanmedian(e_psf[:, -1])) >= 3 * sigma] += 1
|
|
258
|
+
index_1 = np.where(np.array(source.quality) == 0)[0]
|
|
259
|
+
index_2 = np.where(quality_raw == 0)[0]
|
|
260
|
+
index = np.intersect1d(index_1, index_2)
|
|
261
|
+
if type(source) == Source_cut:
|
|
262
|
+
in_frame = np.where(np.invert(np.isnan(source.flux[0])))
|
|
263
|
+
x_left = np.min(in_frame[1]) - 0.5
|
|
264
|
+
x_right = source.size - np.max(in_frame[1]) + 0.5
|
|
265
|
+
y_left = np.min(in_frame[0]) - 0.5
|
|
266
|
+
y_right = source.size - np.max(in_frame[0]) + 0.5
|
|
267
|
+
else:
|
|
268
|
+
x_left = 1.5 if cut_x != 0 else -0.5
|
|
269
|
+
x_right = 2.5 if cut_x != 13 else 0.5
|
|
270
|
+
y_left = 1.5 if cut_y != 0 else -0.5
|
|
271
|
+
y_right = 2.5 if cut_y != 13 else 0.5
|
|
272
|
+
|
|
273
|
+
num_stars = np.array(source.gaia['tess_mag']).searchsorted(limit_mag, 'right')
|
|
274
|
+
x_aperture = source.gaia[f'sector_{source.sector}_x'] - np.maximum(0, x_round - 2)
|
|
275
|
+
y_aperture = source.gaia[f'sector_{source.sector}_y'] - np.maximum(0, y_round - 2)
|
|
276
|
+
|
|
277
|
+
start = 0
|
|
278
|
+
end = num_stars
|
|
279
|
+
if name is not None:
|
|
280
|
+
try:
|
|
281
|
+
start = int(np.where(source.gaia['DESIGNATION'] == 'Gaia DR3 ' +
|
|
282
|
+
str(source.tic['dr3_source_id'][np.where(source.tic['TIC'] == name)][0]))[0][0])
|
|
283
|
+
end = start + 1
|
|
284
|
+
except:
|
|
285
|
+
try:
|
|
286
|
+
start = int(np.where(source.gaia['DESIGNATION'] == name)[0][0])
|
|
287
|
+
end = start + 1
|
|
288
|
+
except IndexError:
|
|
289
|
+
print(
|
|
290
|
+
f'Target not found in the requested sector (Sector {sector}). This can be caused by a lack of Gaia '
|
|
291
|
+
f'ID or an incomplete TESS to Gaia crossmatch table. Please check whether the output light curve Gaia'
|
|
292
|
+
f' DR3 ID agrees with your target.')
|
|
293
|
+
start = 0
|
|
294
|
+
end = 1
|
|
295
|
+
for i in trange(start, end, desc='Fitting lc', disable=no_progress_bar):
|
|
296
|
+
if x_left <= x_round[i] < source.size - x_right and y_left <= y_round[i] < source.size - y_right:
|
|
297
|
+
if type(source) == Source:
|
|
298
|
+
x_left = 1.5
|
|
299
|
+
x_right = 2.5
|
|
300
|
+
y_left = 1.5
|
|
301
|
+
y_right = 2.5
|
|
302
|
+
if x_left + 2 <= x_round[i] < source.size - (x_right + 2) and y_left + 2 <= y_round[i] < source.size - (
|
|
303
|
+
y_right + 2):
|
|
304
|
+
near_edge = False
|
|
305
|
+
else:
|
|
306
|
+
near_edge = True
|
|
307
|
+
|
|
308
|
+
if type(prior) == float or type(prior) == np.float64:
|
|
309
|
+
aperture, psf_lc, star_y, star_x, portion = \
|
|
310
|
+
fit_lc_float_field(A, source, star_info=star_info, x=x_round, y=y_round, star_num=i, e_psf=e_psf,
|
|
311
|
+
near_edge=near_edge, prior=prior)
|
|
312
|
+
else:
|
|
313
|
+
aperture, psf_lc, star_y, star_x, portion = \
|
|
314
|
+
fit_lc(A, source, star_info=star_info, x=x_round[i], y=y_round[i], star_num=i, e_psf=e_psf,
|
|
315
|
+
near_edge=near_edge)
|
|
316
|
+
aper_lc = np.sum(
|
|
317
|
+
aperture[:, max(0, star_y - 1):min(5, star_y + 2), max(0, star_x - 1):min(5, star_x + 2)],
|
|
318
|
+
axis=(1, 2))
|
|
319
|
+
if source.sector < 27: # primary
|
|
320
|
+
exposure_time = 1800
|
|
321
|
+
elif source.sector < 56: # first extended
|
|
322
|
+
exposure_time = 600
|
|
323
|
+
else: # second extended
|
|
324
|
+
exposure_time = 200
|
|
325
|
+
saturated_arg_aper = np.where(aper_lc > 1e5 * 9 * 2e5 / exposure_time) # saturation is 2e5 e-
|
|
326
|
+
aper_lc[saturated_arg_aper] = np.nan
|
|
327
|
+
saturated_arg_psf = np.where(psf_lc > 1e5 * 9 * 2e5 / exposure_time)
|
|
328
|
+
psf_lc[saturated_arg_psf] = np.nan
|
|
329
|
+
|
|
330
|
+
local_bg, aper_lc, psf_lc, cal_aper_lc, cal_psf_lc = bg_mod(source, q=index, portion=portion,
|
|
331
|
+
psf_lc=psf_lc,
|
|
332
|
+
aper_lc=aper_lc,
|
|
333
|
+
near_edge=near_edge, star_num=i)
|
|
334
|
+
background_ = background[x_round[i] + source.size * y_round[i], :]
|
|
335
|
+
quality = np.zeros(len(source.time), dtype=np.int16)
|
|
336
|
+
sigma = 1.4826 * np.nanmedian(np.abs(background_ - np.nanmedian(background_)))
|
|
337
|
+
quality[abs(background_ - np.nanmedian(background_)) >= 5 * sigma] += 1
|
|
338
|
+
# if cut_x == 7:
|
|
339
|
+
# lc_directory = f'{local_directory}lc/{source.camera}-{source.ccd}_extra/'
|
|
340
|
+
# os.makedirs(lc_directory, exist_ok=True)
|
|
341
|
+
if np.isnan(aper_lc).all():
|
|
342
|
+
continue
|
|
343
|
+
else:
|
|
344
|
+
if type(source) == Source:
|
|
345
|
+
# if cut_x >= 7:
|
|
346
|
+
# lc_directory = f'{local_directory}lc/{source.camera}-{source.ccd}_extra/'
|
|
347
|
+
lc_output(source, local_directory=lc_directory, index=i,
|
|
348
|
+
tess_flag=source.quality, cut_x=cut_x, cut_y=cut_y, cadence=source.cadence,
|
|
349
|
+
aperture=aperture.astype(np.float32), star_y=y_round[i], star_x=x_round[i], tglc_flag=quality,
|
|
350
|
+
bg=background_, time=source.time, psf_lc=psf_lc, cal_psf_lc=cal_psf_lc, aper_lc=aper_lc,
|
|
351
|
+
cal_aper_lc=cal_aper_lc, local_bg=local_bg, x_aperture=x_aperture[i],
|
|
352
|
+
y_aperture=y_aperture[i], near_edge=near_edge, save_aper=save_aper, portion=portion,
|
|
353
|
+
prior=prior)
|
|
354
|
+
else:
|
|
355
|
+
lc_output(source, local_directory=lc_directory, index=i,
|
|
356
|
+
tess_flag=source.quality, cut_x=cut_x, cut_y=cut_y, cadence=source.cadence,
|
|
357
|
+
aperture=aperture.astype(np.float32), star_y=y_round[i], star_x=x_round[i],
|
|
358
|
+
tglc_flag=quality,
|
|
359
|
+
bg=background_, time=source.time, psf_lc=psf_lc, cal_psf_lc=cal_psf_lc, aper_lc=aper_lc,
|
|
360
|
+
cal_aper_lc=cal_aper_lc, local_bg=local_bg, x_aperture=x_aperture[i],
|
|
361
|
+
y_aperture=y_aperture[i], near_edge=near_edge, save_aper=save_aper, portion=portion,
|
|
362
|
+
prior=prior, transient=source.transient)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Te Han
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: tglc
|
|
3
|
+
Version: 0.6.5
|
|
4
|
+
Summary: TESS-Gaia Light Curve
|
|
5
|
+
Home-page: https://github.com/TeHanHunter/TESS_Gaia_Light_Curve
|
|
6
|
+
Author: Te Han
|
|
7
|
+
Author-email: tehanhunter@gmail.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/x-rst
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: astropy >=5.1
|
|
15
|
+
Requires-Dist: astroquery
|
|
16
|
+
Requires-Dist: matplotlib
|
|
17
|
+
Requires-Dist: numpy
|
|
18
|
+
Requires-Dist: oauthlib
|
|
19
|
+
Requires-Dist: requests
|
|
20
|
+
Requires-Dist: scipy
|
|
21
|
+
Requires-Dist: threadpoolctl
|
|
22
|
+
Requires-Dist: tqdm
|
|
23
|
+
Requires-Dist: wheel
|
|
24
|
+
Requires-Dist: wotan
|
|
25
|
+
|
|
26
|
+
==================================
|
|
27
|
+
Introduction
|
|
28
|
+
==================================
|
|
29
|
+
|
|
30
|
+
TESS-Gaia Light Curve (`TGLC <https://archive.stsci.edu/hlsp/tglc>`_) is a dataset of TESS full-frame image light curves publicly available via the MAST portal. It is fitted with effective PSF and decontaminated with Gaia DR3 and achieved percent-level photometric precision down to 16th TESS magnitude! It unlocks astrophysics to a vast number of dim stars below 12th TESS magnitude. A package called tglc is pip-installable for customized light curve fits.
|
|
31
|
+
|
|
32
|
+
==================================
|
|
33
|
+
Usage
|
|
34
|
+
==================================
|
|
35
|
+
There are four fluxes in each FITS file: aperture flux, PSF flux, calibrated aperture flux, and calibrated PSF flux.
|
|
36
|
+
If you are uncertain which to use:
|
|
37
|
+
|
|
38
|
+
* Calibrated psf flux is better in **deblending** targets. Use this if you need to deblend a target near a variable source. The best deblending can be achieved with tglc package by setting a non-zero prior. It also gives the more accurate **transit depth** in most cases, especially when fitting with an optimized prior.
|
|
39
|
+
* Calibrated aperture flux usually has slightly **higher SNR**. The transit depth (or variation amplitude), however, can be imperfect since the normalization depends on the PSF fitting which is imperfect. This imperfection can be minimized by using a bigger aperture than the default aperture (3*3). One need to use the tglc package and set tglc_lc(save_aper=True) to access the 5*5 aperture. In the presence of a bright but "constant" contamination (several magnitudes brighter), the calibrated aperture flux is better in removing the constant contamination.
|
|
40
|
+
* The aperture flux and PSF flux are not detrended or normalized. Use this if you are doing stellar variability science with long baseline. Or, if the detrending is not optimal (default detrending has a window length of 1 day; see Known Problems below), start with the aperture flux or PSF flux and detrend carefully!
|
|
41
|
+
* **If you are uncertain, start with calibrated aperture flux!**
|
|
42
|
+
|
|
43
|
+
The `tutorial <tutorial/TGLC_tutorial.ipynb>`_ shows the syntaxes and differences among these light curves in several examples.
|
|
44
|
+
|
|
45
|
+
==================================
|
|
46
|
+
Data Access
|
|
47
|
+
==================================
|
|
48
|
+
There are three data access methods:
|
|
49
|
+
|
|
50
|
+
* MAST Portal: Easiest for acquiring light curves for a few stars. However, new sectors are updated relatively slowly.
|
|
51
|
+
* MAST bulk download: Best for downloading light curves for all stars (<16 TESS magnitude) in a sectors.
|
|
52
|
+
* tglc package: Capable of producing similar quality light curves for any sector and any star with custom options.
|
|
53
|
+
|
|
54
|
+
MAST Portal/bulk download
|
|
55
|
+
----------------------------
|
|
56
|
+
The easiest usage requires no package installation. Simply follow the `TGLC HLSP page <https://archive.stsci.edu/hlsp/tglc>`_ to download light curves from MAST or use `MAST Portal <https://mast.stsci.edu/portal/Mashup/Clients/Mast/Portal.html>`_. Light curves are being fitted sector by sector and will be available on MAST gradually. MAST hosts all Gaia DR3 stars down to 16th magnitude. Each .fits file includes PSF and aperture light curves and their calibrated versions.
|
|
57
|
+
|
|
58
|
+
MAST available sectors: `sector worklist <https://docs.google.com/spreadsheets/d/1FhHElWb1wmx9asWiZecAJ2umN0-P_aXn55OBVB34_rg/edit?usp=sharing>`_
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
tglc package
|
|
62
|
+
----------------------------
|
|
63
|
+
Users can also fit light curves using the package tglc. Using tglc, one can specify a region, sector(s), and customized aperture shape if needed. It can also allow all field stars to float by assigning Gaussian priors, which can help decontaminate variable field stars. tglc is currently only available for linux. Run::
|
|
64
|
+
|
|
65
|
+
pip install tglc
|
|
66
|
+
|
|
67
|
+
for the latest tglc release. After installation, follow the `tutorial <tutorial/TGLC_tutorial.ipynb>`_ to fit light curves. If there is a problem, please leave a comment in the Issues section to help us improve. Thank you!
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
==================================
|
|
71
|
+
Known Problems
|
|
72
|
+
==================================
|
|
73
|
+
There are several imperfections we noticed in the MAST TGLC light curves and tglc package:
|
|
74
|
+
|
|
75
|
+
* If the star is very dim (~< 15 Tmag) near a variable source, it can make the aperture and/or PSF light curve negative for some cadences. The detrending algorithm could malfunction and result in bad cal_aper_flux and/or cal_psf_flux. This is now fixed for tglc package, but this problem remains for the primary mission light curves published on MAST. Please detrend again if necessary. The extended mission light curves on MAST will not be affected. This is a very rare scenario, but could be important.
|
|
76
|
+
|
|
77
|
+
==================================
|
|
78
|
+
Reference
|
|
79
|
+
==================================
|
|
80
|
+
If you find the TGLC light curves or the tglc package useful in your research, please cite `our paper <https://iopscience.iop.org/article/10.3847/1538-3881/acaaa7>`_ published on the Astronomical Journal.
|