tglc 0.6.4__tar.gz → 0.6.6__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tglc
3
- Version: 0.6.4
3
+ Version: 0.6.6
4
4
  Summary: TESS-Gaia Light Curve
5
5
  Home-page: https://github.com/TeHanHunter/TESS_Gaia_Light_Curve
6
6
  Author: Te Han
@@ -8,9 +8,21 @@ Author-email: tehanhunter@gmail.com
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.8
11
+ Requires-Python: >=3.8, <3.13
12
12
  Description-Content-Type: text/x-rst
13
13
  License-File: LICENSE
14
+ Requires-Dist: astropy>=5.1
15
+ Requires-Dist: astroquery==0.4.7
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
+ Requires-Dist: seaborn
14
26
 
15
27
  ==================================
16
28
  Introduction
@@ -18,6 +30,7 @@ Introduction
18
30
 
19
31
  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.
20
32
 
33
+
21
34
  ==================================
22
35
  Usage
23
36
  ==================================
@@ -4,6 +4,7 @@ Introduction
4
4
 
5
5
  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.
6
6
 
7
+
7
8
  ==================================
8
9
  Usage
9
10
  ==================================
@@ -6,7 +6,7 @@ with open("README.rst", "r", encoding="utf-8") as fh:
6
6
  long_description = fh.read()
7
7
  setuptools.setup(
8
8
  name="tglc",
9
- version='0.6.4',
9
+ version='0.6.6',
10
10
  author="Te Han",
11
11
  author_email="tehanhunter@gmail.com",
12
12
  description="TESS-Gaia Light Curve",
@@ -18,9 +18,9 @@ setuptools.setup(
18
18
  "License :: OSI Approved :: MIT License",
19
19
  "Operating System :: OS Independent",
20
20
  ],
21
- install_requires=['astropy>=5.1', 'astroquery', 'matplotlib', 'numpy', 'oauthlib', 'requests', 'scipy',
22
- 'threadpoolctl', 'tqdm', 'wheel', 'wotan'],
21
+ install_requires=['astropy>=5.1', 'astroquery==0.4.7', 'matplotlib', 'numpy', 'oauthlib', 'requests', 'scipy',
22
+ 'threadpoolctl', 'tqdm', 'wheel', 'wotan', 'seaborn'],
23
23
  packages=setuptools.find_packages(include=['tglc', 'tglc.*']),
24
- python_requires=">=3.8",
24
+ python_requires=">=3.8, <3.13",
25
25
  include_package_data=True
26
26
  )
@@ -0,0 +1,3 @@
1
+ __version__ = "0.6.6"
2
+ __author__ = 'Te Han, Timothy Brandt'
3
+ __credits__ = 'University of California, Santa Barbara'
@@ -191,16 +191,19 @@ def fit_lc(A, source, star_info=None, x=0., y=0., star_num=0, factor=2, psf_size
191
191
  coord = np.arange(size ** 2).reshape(size, size)
192
192
  index = np.array(coord[down:up, left:right]).flatten()
193
193
  A_cut = np.zeros((len(index), np.shape(A)[1]))
194
+ A_target = np.zeros((len(index), np.shape(A)[1]))
194
195
  for i in range(len(index)):
195
196
  A_ = np.zeros(np.shape(A)[-1])
196
197
  star_pos = np.where(star_info_num[0] == index[i])[0]
197
198
  A_[star_info_num[1][star_pos]] = star_info_num[2][star_pos]
199
+ A_target[i] = A_
198
200
  A_cut[i] = A[index[i], :] - A_
199
201
  aperture = np.zeros((len(source.time), len(index)))
200
202
  for j in range(len(source.time)):
201
203
  aperture[j] = np.array(source.flux[j][down:up, left:right]).flatten() - np.dot(A_cut, e_psf[j])
202
204
  aperture = aperture.reshape((len(source.time), up - down, right - left))
203
- # np.save(f'_residual_{source.sector}.npy', aperture)
205
+ target_5x5 = (np.dot(A_target, np.nanmedian(e_psf, axis=0)).reshape(cut_size, cut_size))
206
+ field_stars_5x5 = (np.dot(A_cut, np.nanmedian(e_psf, axis=0)).reshape(cut_size, cut_size))
204
207
 
205
208
  # psf_lc
206
209
  over_size = psf_size * factor + 1
@@ -262,7 +265,7 @@ def fit_lc(A, source, star_info=None, x=0., y=0., star_num=0, factor=2, psf_size
262
265
  portion = np.nansum(psf_shape[:, 4:7, 4:7]) / np.nansum(psf_shape)
263
266
  # print(np.nansum(psf_shape[:, 5, 5]) / np.nansum(psf_shape))
264
267
  # np.save(f'toi-5344_psf_{source.sector}.npy', psf_shape)
265
- return aperture, psf_lc, y - down, x - left, portion
268
+ return aperture, psf_lc, y - down, x - left, portion, target_5x5, field_stars_5x5
266
269
 
267
270
 
268
271
  def fit_lc_float_field(A, source, star_info=None, x=np.array([]), y=np.array([]), star_num=0, factor=2, psf_size=11,
@@ -86,7 +86,7 @@ def convert_gaia_id(catalogdata_tic):
86
86
  FROM gaiadr3.dr2_neighbourhood
87
87
  WHERE dr2_source_id IN {gaia_ids}
88
88
  """
89
- gaia_array = np.array(catalogdata_tic['GAIA'])
89
+ gaia_array = np.array([str(item) for item in catalogdata_tic['GAIA']], dtype=object)
90
90
  gaia_array = gaia_array[gaia_array != 'None']
91
91
  # np.save('gaia_array.npy', gaia_array)
92
92
  segment = (len(gaia_array) - 1) // 10000
@@ -14,12 +14,14 @@ from astroquery.mast import Catalogs
14
14
  import astropy.units as u
15
15
  from astropy.coordinates import SkyCoord
16
16
  from astroquery.mast import Tesscut
17
+ import sys
18
+ import warnings
17
19
  # Tesscut._service_api_connection.TIMEOUT = 6000
18
-
19
20
  # warnings.simplefilter('ignore', UserWarning)
20
21
  from threadpoolctl import ThreadpoolController, threadpool_limits
21
22
  import numpy as np
22
-
23
+ import seaborn as sns
24
+ import itertools
23
25
  controller = ThreadpoolController()
24
26
 
25
27
 
@@ -40,10 +42,6 @@ def tglc_lc(target='TIC 264468702', local_directory='', size=90, save_aper=True,
40
42
  os.makedirs(local_directory + f'lc/', exist_ok=True)
41
43
  os.makedirs(local_directory + f'epsf/', exist_ok=True)
42
44
  os.makedirs(local_directory + f'source/', exist_ok=True)
43
- if first_sector_only:
44
- sector = 'first'
45
- elif last_sector_only:
46
- sector = 'last'
47
45
  print(f'Target: {target}')
48
46
  target_ = Catalogs.query_object(target, radius=42 * 0.707 / 3600, catalog="Gaia", version=2)
49
47
  if len(target_) == 0:
@@ -77,7 +75,7 @@ def tglc_lc(target='TIC 264468702', local_directory='', size=90, save_aper=True,
77
75
  elif first_sector_only:
78
76
  print(f'Only processing the first sector the target is observed in: Sector {sector_table["sector"][0]}.')
79
77
  print('Downloading Data from MAST and Gaia ...')
80
-
78
+ sector = sector_table["sector"][0]
81
79
  source = ffi_cut(target=target, size=size, local_directory=local_directory, sector=sector,
82
80
  limit_mag=limit_mag, transient=transient) # sector
83
81
  source.select_sector(sector=source.sector_table['sector'][0])
@@ -86,6 +84,7 @@ def tglc_lc(target='TIC 264468702', local_directory='', size=90, save_aper=True,
86
84
  elif last_sector_only:
87
85
  print(f'Only processing the last sector the target is observed in: Sector {sector_table["sector"][-1]}.')
88
86
  print('Downloading Data from MAST and Gaia ...')
87
+ sector = sector_table["sector"][-1]
89
88
  source = ffi_cut(target=target, size=size, local_directory=local_directory, sector=sector,
90
89
  limit_mag=limit_mag, transient=transient) # sector
91
90
  source.select_sector(sector=source.sector_table['sector'][-1])
@@ -296,47 +295,58 @@ def plot_pf_lc(local_directory=None, period=None, mid_transit_tbjd=None, kind='c
296
295
  plt.close(fig)
297
296
 
298
297
 
299
- def plot_contamination(local_directory=None, gaia_dr3=None):
300
- files = glob(f'{local_directory}lc/*.fits')
298
+ def plot_contamination(local_directory=None, gaia_dr3=None, ymin=None, ymax=None, pm_years=3000):
299
+ sns.set(rc={'font.family': 'serif', 'font.serif': 'DejaVu Serif', 'font.size': 12,
300
+ 'axes.edgecolor': '0.2', 'axes.labelcolor': '0.', 'xtick.color': '0.', 'ytick.color': '0.',
301
+ 'axes.facecolor': '0.95', 'grid.color': '0.9'})
302
+ files = glob(f'{local_directory}lc/*{gaia_dr3}*.fits')
301
303
  os.makedirs(f'{local_directory}plots/', exist_ok=True)
302
304
  for i in range(len(files)):
303
305
  with fits.open(files[i], mode='denywrite') as hdul:
304
306
  sector = hdul[0].header['SECTOR']
307
+ q = [a and b for a, b in
308
+ zip(list(hdul[1].data['TESS_flags'] == 0), list(hdul[1].data['TGLC_flags'] == 0))]
309
+ if ymin is None and ymax is None:
310
+ ymin = np.nanmin(hdul[1].data['cal_aper_flux'][q]) - 0.01
311
+ ymax = np.nanmax(hdul[1].data['cal_aper_flux'][q]) + 0.01
305
312
  with open(glob(f'{local_directory}source/*_{sector}.pkl')[0], 'rb') as input_:
306
313
  source = pickle.load(input_)
307
314
  source.select_sector(sector=sector)
308
315
  star_num = np.where(source.gaia['DESIGNATION'] == f'Gaia DR3 {gaia_dr3}')
309
- plt.imshow(source.flux[0], origin='lower')
310
- plt.show()
311
- plt.close()
312
- # print(source.gaia[891])
313
- # print(source.gaia[star_num])
314
- nearby_stars = np.argsort(
316
+
317
+ distances = np.sqrt(
315
318
  (source.gaia[f'sector_{sector}_x'][:500] - source.gaia[star_num][f'sector_{sector}_x']) ** 2 +
316
- (source.gaia[f'sector_{sector}_y'][:500] - source.gaia[star_num][f'sector_{sector}_y']) ** 2)[0:5]
317
- # print(f'sector = {source.sector}')
319
+ (source.gaia[f'sector_{sector}_y'][:500] - source.gaia[star_num][f'sector_{sector}_y']) ** 2)
320
+
321
+ # Find closest 5 stars (6-self) or those within 5 pixels
322
+ nearby_stars = np.argsort(distances)[:6]
323
+ nearby_stars = nearby_stars[distances[nearby_stars] <= 5]
318
324
  star_x = source.gaia[star_num][f'sector_{sector}_x'][0]
319
325
  star_y = source.gaia[star_num][f'sector_{sector}_y'][0]
320
326
  max_flux = np.nanmax(
321
- np.nanmedian(source.flux[:, round(star_y) - 2:round(star_y) + 3, round(star_x) - 2:round(star_x) + 3],
322
- axis=0))
323
- fig = plt.figure(constrained_layout=False, figsize=(15, 5))
324
- gs = fig.add_gridspec(5, 16)
325
- gs.update(wspace=0.1, hspace=0.1)
326
- ax0 = fig.add_subplot(gs[:5, :5])
327
+ np.nanmedian(
328
+ source.flux[:, round(star_y) - 2:round(star_y) + 3, round(star_x) - 2:round(star_x) + 3],
329
+ axis=0))
330
+ fig = plt.figure(constrained_layout=False, figsize=(20, 12))
331
+ gs = fig.add_gridspec(21, 10)
332
+ gs.update(wspace=0.03, hspace=0.1)
333
+ ax0 = fig.add_subplot(gs[:10, :3])
327
334
  ax0.imshow(np.median(source.flux, axis=0), cmap='RdBu', vmin=-max_flux, vmax=max_flux, origin='lower')
328
-
329
- ax0.scatter(source.gaia[f'sector_{sector}_x'][:500], source.gaia[f'sector_{sector}_y'][:500], s=50,
330
- c='r', label='background stars')
331
- ax0.scatter(source.gaia[f'sector_{sector}_x'][nearby_stars],
332
- source.gaia[f'sector_{sector}_y'][nearby_stars], s=50,
335
+ ax0.set_xlabel('x pixel')
336
+ ax0.set_ylabel('y pixel')
337
+ ax0.scatter(star_x, star_y, s=300, c='r', marker='*', label='target star')
338
+ ax0.scatter(source.gaia[f'sector_{sector}_x'][:500], source.gaia[f'sector_{sector}_y'][:500], s=30,
333
339
  c='r', label='background stars')
340
+ ax0.scatter(source.gaia[f'sector_{sector}_x'][nearby_stars[nearby_stars != star_num[0][0]]],
341
+ source.gaia[f'sector_{sector}_y'][nearby_stars[nearby_stars != star_num[0][0]]],
342
+ s=30, c='r', edgecolor='black', linewidth=1, label='background stars')
343
+ ax0.grid(False)
334
344
  for l in range(len(nearby_stars)):
335
345
  index = np.where(
336
346
  source.tic['dr3_source_id'] == int(source.gaia['DESIGNATION'][nearby_stars[l]].split(' ')[-1]))
337
347
  gaia_targets = source.gaia
338
348
  median_time = np.median(source.time)
339
- interval = (median_time - 388.5) / 365.25 + 3000
349
+ interval = (median_time - 388.5) / 365.25 + pm_years
340
350
  ra = gaia_targets['ra'][nearby_stars[l]]
341
351
  dec = gaia_targets['dec'][nearby_stars[l]]
342
352
  if not np.isnan(gaia_targets['pmra'][nearby_stars[l]]):
@@ -352,43 +362,37 @@ def plot_contamination(local_directory=None, gaia_dr3=None):
352
362
  y_gaia - source.gaia[f'sector_{sector}_y'][nearby_stars[l]],
353
363
  width=0.02, color='r', edgecolor=None, head_width=0.1)
354
364
  try:
355
- ax0.text(source.gaia[f'sector_{sector}_x'][nearby_stars[l]] - 0.1,
356
- source.gaia[f'sector_{sector}_y'][nearby_stars[l]] + 0.3,
357
- f'TIC {int(source.tic["TIC"][index])}', rotation=90)
358
- except kindError:
359
- ax0.text(source.gaia[f'sector_{sector}_x'][nearby_stars[l]] - 0.1,
360
- source.gaia[f'sector_{sector}_y'][nearby_stars[l]] + 0.2,
361
- f'{source.gaia[f"DESIGNATION"][nearby_stars[l]]}', rotation=90)
362
- ax0.scatter(star_x, star_y, s=300, c='r', marker='*', label='target star')
365
+ txt = ax0.text(source.gaia[f'sector_{sector}_x'][nearby_stars[l]] + 0.5,
366
+ source.gaia[f'sector_{sector}_y'][nearby_stars[l]] - 0.05,
367
+ f'TIC {int(source.tic["TIC"][index])}', size=7)
368
+
369
+ except TypeError:
370
+ designation = source.gaia[f"DESIGNATION"][nearby_stars[l]]
371
+ formatted_text = '\n'.join([designation[i:i + 15] for i in range(0, len(designation), 15)])
363
372
 
364
- # ax0.legend()
373
+ txt = ax0.text(source.gaia[f'sector_{sector}_x'][nearby_stars[l]] + 0.5,
374
+ source.gaia[f'sector_{sector}_y'][nearby_stars[l]] - 0.05,
375
+ formatted_text, size=7)
365
376
  ax0.set_xlim(round(star_x) - 5.5, round(star_x) + 5.5)
366
377
  ax0.set_ylim(round(star_y) - 5.5, round(star_y) + 5.5)
367
- ax0.set_title(f'TIC_{hdul[0].header["TICID"]}_sector_{hdul[0].header["SECTOR"]:04d}')
368
- ax0.vlines(round(star_x) - 2.5, round(star_y) - 2.5, round(star_y) + 2.5, colors='k')
369
- ax0.vlines(round(star_x) + 2.5, round(star_y) - 2.5, round(star_y) + 2.5, colors='k')
370
- ax0.hlines(round(star_y) - 2.5, round(star_x) - 2.5, round(star_x) + 2.5, colors='k')
371
- ax0.hlines(round(star_y) + 2.5, round(star_x) - 2.5, round(star_x) + 2.5, colors='k')
372
- # for j in range(5):
373
- # for k in range(5):
374
- # ax_ = fig.add_subplot(gs[(4 - j), (5 + k)])
375
- # ax_.patch.set_facecolor('C0')
376
- # ax_.patch.set_alpha(max(0, np.median(source.flux[:, round(star_y) - 2 + j, round(star_x) - 2 + k]) / max_flux))
377
- # cal_lc, trend = flatten(hdul[1].data['time'],
378
- # source.flux[:, round(star_y) - 2 + j, round(star_x) - 2 + k],
379
- # window_length=1, method='biweight', return_trend=True)
380
- # ax_.plot(hdul[1].data['time'], cal_lc, '.k', ms=1, label='center pixel')
381
-
382
- t_, y_, x_ = np.shape(hdul[0].data)
378
+ ax0.set_title(f'TIC_{hdul[0].header["TICID"]}_Sector_{hdul[0].header["SECTOR"]:04d}')
379
+ ax0.vlines(round(star_x) - 2.5, round(star_y) - 2.5, round(star_y) + 2.5, colors='k', lw=1.2)
380
+ ax0.vlines(round(star_x) + 2.5, round(star_y) - 2.5, round(star_y) + 2.5, colors='k', lw=1.2)
381
+ ax0.hlines(round(star_y) - 2.5, round(star_x) - 2.5, round(star_x) + 2.5, colors='k', lw=1.2)
382
+ ax0.hlines(round(star_y) + 2.5, round(star_x) - 2.5, round(star_x) + 2.5, colors='k', lw=1.2)
383
+ try:
384
+ t_, y_, x_ = np.shape(hdul[0].data)
385
+ except ValueError:
386
+ warnings.warn('Light curves need to have the primary hdu. Set save_aperture=True when producing the light curve to enable this plot.')
387
+ sys.exit()
383
388
  max_flux = np.max(
384
389
  np.median(source.flux[:, int(star_y) - 2:int(star_y) + 3, int(star_x) - 2:int(star_x) + 3], axis=0))
390
+ arrays = []
385
391
  for j in range(y_):
386
392
  for k in range(x_):
387
- ax_ = fig.add_subplot(gs[(4 - j), (6 + 2 * k):(8 + 2 * k)])
388
- ax_.patch.set_facecolor('C0')
393
+ ax_ = fig.add_subplot(gs[(19 - 2 * j):(21 - 2 * j), (2 * k):(2 + 2 * k)])
394
+ ax_.patch.set_facecolor('#4682B4')
389
395
  ax_.patch.set_alpha(min(1, max(0, 5 * np.nanmedian(hdul[0].data[:, j, k]) / max_flux)))
390
- q = [a and b for a, b in
391
- zip(list(hdul[1].data['TESS_flags'] == 0), list(hdul[1].data['TGLC_flags'] == 0))]
392
396
 
393
397
  _, trend = flatten(hdul[1].data['time'][q],
394
398
  hdul[0].data[:, j, k][q] - np.nanmin(hdul[0].data[:, j, k][q]) + 1000,
@@ -396,18 +400,68 @@ def plot_contamination(local_directory=None, gaia_dr3=None):
396
400
  cal_aper = (hdul[0].data[:, j, k][q] - np.nanmin(
397
401
  hdul[0].data[:, j, k][q]) + 1000 - trend) / np.nanmedian(
398
402
  hdul[0].data[:, j, k][q]) + 1
399
- # ax_.plot(hdul[1].data['time'][q], cal_aper, '.k', ms=0.5)
400
- ax_.plot(hdul[1].data['time'][q], hdul[0].data[:, j, k][q], '.k', ms=0.5)
401
- # ax_.set_ylim(0.7, 1.3)
403
+ if 1 <= j <= 3 and 1 <= k <= 3:
404
+ arrays.append(cal_aper)
405
+ ax_.plot(hdul[1].data['time'][q], cal_aper, '.k', ms=0.5)
406
+ # ax_.plot(hdul[1].data['time'][q], hdul[0].data[:, j, k][q], '.k', ms=0.5)
407
+ ax_.set_ylim(ymin, ymax)
408
+ ax_.set_xlabel('TBJD')
409
+ ax_.set_ylabel('')
402
410
  if j != 0:
403
411
  ax_.set_xticklabels([])
412
+ ax_.set_xlabel('')
404
413
  if k != 0:
405
414
  ax_.set_yticklabels([])
406
-
407
- plt.savefig(f'{local_directory}plots/contamination_sector_{hdul[0].header["SECTOR"]:04d}.pdf',
408
- dpi=300)
409
- plt.close()
410
-
415
+ if j == 2 and k == 0:
416
+ ax_.set_ylabel('Normalized and detrended Flux of each pixel')
417
+
418
+ combinations = itertools.combinations(arrays, 2)
419
+ median_abs_diffs = []
420
+ for arr_a, arr_b in combinations:
421
+ abs_diff = np.abs(arr_a - arr_b)
422
+ median_diff = np.median(abs_diff)
423
+ median_abs_diffs.append(median_diff)
424
+ median_abs_diffs = np.array(median_abs_diffs)
425
+ iqr = np.percentile(median_abs_diffs, 75) - np.percentile(median_abs_diffs, 25)
426
+ print(f"Interquartile Range (IQR): {iqr}")
427
+ std_dev = np.std(median_abs_diffs)
428
+ print(f"Standard Deviation: {std_dev}")
429
+ ax1 = fig.add_subplot(gs[:10, 4:7])
430
+ ax1.hist(median_abs_diffs, color='k', edgecolor='k', facecolor='none', rwidth=0.8, linewidth=2)
431
+ ax1.set_box_aspect(1)
432
+ ax1.set_title(f'Distribution of the MADs among combinations of the center 3*3 pixels')
433
+ ax1.set_xlabel('MAD between combinations of center 3*3 pixel fluxes')
434
+ ax1.set_ylabel('Counts')
435
+ text_ax = fig.add_axes([0.71, 0.9, 0.3, 0.3]) # [left, bottom, width, height] in figure coordinates
436
+ text_ax.axis('off') # Turn off axis lines, ticks, etc.
437
+ text_ax.text(0., 0., f"Gaia DR3 {gaia_dr3} \n"
438
+ f" ←← TESS SPOC FFI and TIC/Gaia stars with proper motions. \n"
439
+ f" Arrows show Gaia proper motion after {pm_years} years. \n"
440
+ f" ← Histogram of the MADs between 3*3 pixel fluxes. \n"
441
+ f" ↓ Fluxes of each pixels after contaminations are removed. \n"
442
+ f" The fluxes are normalized and detrended. The background \n"
443
+ f" color shows the pixel brightness after the decontamination. \n"
444
+ f"\n"
445
+ f"How to interpret these plots: \n"
446
+ f" If the signals you are interested in (i.e. transits, \n"
447
+ f" eclipses, variable stars) show similar amplitudes in \n"
448
+ f" all (especially the center 3*3) pixels, then the star \n"
449
+ f" is likely to be the source. The median absolute \n"
450
+ f" differences (MADs) taken between all combinations \n"
451
+ f" of the center pixel fluxes are shown in the histogram \n"
452
+ f" for a quantititive comparison to other possible sources. \n"
453
+ f" The star with smaller distribution width (IQR or \n"
454
+ f" STD) is more likely to be the source of the signal. \n"
455
+ f"\n"
456
+ f"Interquartile Range (IQR): {iqr:05f} \n"
457
+ f"Standard Deviation: {std_dev:05f}", transform=text_ax.transAxes, ha='left',
458
+ va='top')
459
+ plt.subplots_adjust(top=.98, bottom=0.05, left=0.05, right=0.95)
460
+ plt.savefig(
461
+ f'{local_directory}plots/contamination_sector_{hdul[0].header["SECTOR"]:04d}_Gaia_DR3_{gaia_dr3}.pdf',
462
+ dpi=300)
463
+ # plt.savefig(f'{local_directory}plots/contamination_sector_{hdul[0].header["SECTOR"]:04d}_Gaia_DR3_{gaia_dr3}.png',
464
+ # dpi=600)
411
465
 
412
466
  def plot_epsf(local_directory=None):
413
467
  files = glob(f'{local_directory}epsf/*.npy')
@@ -458,7 +512,7 @@ def get_tglc_lc(tics=None, method='query', server=1, directory=None, prior=None)
458
512
 
459
513
  if __name__ == '__main__':
460
514
  tics = [16005254]
461
- directory = f'/home/tehan/data/'
515
+ directory = f'/Users/tehan/Downloads/'
462
516
  os.makedirs(directory, exist_ok=True)
463
517
  get_tglc_lc(tics=tics, method='query', server=1, directory=directory)
464
518
  # plot_lc(local_directory=f'{directory}TIC {tics[0]}/', kind='cal_aper_flux')
@@ -20,7 +20,7 @@ warnings.simplefilter('always', UserWarning)
20
20
  def lc_output(source, local_directory='', index=0, time=None, psf_lc=None, cal_psf_lc=None, aper_lc=None,
21
21
  cal_aper_lc=None, bg=None, tess_flag=None, tglc_flag=None, cadence=None, aperture=None,
22
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):
23
+ local_bg=None, save_aper=False, portion=1, prior=None, transient=None, target_5x5=None, field_stars_5x5=None):
24
24
  """
25
25
  lc output to .FITS file in MAST HLSP standards
26
26
  :param tglc_flag: np.array(), required
@@ -82,6 +82,13 @@ def lc_output(source, local_directory='', index=0, time=None, psf_lc=None, cal_p
82
82
  primary_hdu = fits.PrimaryHDU(aperture)
83
83
  else:
84
84
  primary_hdu = fits.PrimaryHDU()
85
+ # Simulated star images based on ePSF, used to estimate contamination ratio and others
86
+ image_data = np.zeros((3, 5, 5))
87
+ image_data[0] = target_5x5
88
+ image_data[1] = field_stars_5x5
89
+ # This is the pixel-wise contamination ratio
90
+ image_data[2] = field_stars_5x5/target_5x5
91
+ image_hdu = fits.ImageHDU(data=image_data)
85
92
 
86
93
  primary_hdu.header = fits.Header(cards=[
87
94
  fits.Card('SIMPLE', True, 'conforms to FITS standard'),
@@ -116,6 +123,7 @@ def lc_output(source, local_directory='', index=0, time=None, psf_lc=None, cal_p
116
123
  fits.Card('GAIA_bp', gaia_bp, 'Gaia DR3 bp band magnitude'),
117
124
  fits.Card('GAIA_rp', gaia_rp, 'Gaia DR3 rp band magnitude'),
118
125
  fits.Card('RAWFLUX', raw_flux, 'median flux of raw FFI'),
126
+ fits.Card('CONTAMRT', round(np.nansum(field_stars_5x5[1:4,1:4])/np.nansum(target_5x5[1:4,1:4]), 9), 'contamination ratio of default 3*3 aperture'),
119
127
  fits.Card('CALIB', 'TGLC', 'pipeline used for image calibration')])
120
128
  if save_aper:
121
129
  primary_hdu.header.comments['NAXIS1'] = "Time (hdul[1].data['time'])"
@@ -190,13 +198,14 @@ def lc_output(source, local_directory='', index=0, time=None, psf_lc=None, cal_p
190
198
  if type(prior) == float:
191
199
  table_hdu.header.append(('PRIOR', prior, 'prior of field stars'), end=True)
192
200
 
193
- hdul = fits.HDUList([primary_hdu, table_hdu])
201
+ hdul = fits.HDUList([primary_hdu, table_hdu, image_hdu])
194
202
  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',
203
+ f'{local_directory}hlsp_tglc_tess_ffi_gaiaid-{objid}-s{source.sector:04d}-cam{source.camera}-ccd{source.ccd}_tess_v2_llc.fits',
196
204
  overwrite=True)
197
205
  return
198
206
 
199
207
 
208
+
200
209
  def epsf(source, psf_size=11, factor=2, local_directory='', target=None, cut_x=0, cut_y=0, sector=0,
201
210
  limit_mag=16, edge_compression=1e-4, power=1.4, name=None, save_aper=False, no_progress_bar=False, prior=None):
202
211
  """
@@ -310,7 +319,7 @@ def epsf(source, psf_size=11, factor=2, local_directory='', target=None, cut_x=0
310
319
  fit_lc_float_field(A, source, star_info=star_info, x=x_round, y=y_round, star_num=i, e_psf=e_psf,
311
320
  near_edge=near_edge, prior=prior)
312
321
  else:
313
- aperture, psf_lc, star_y, star_x, portion = \
322
+ aperture, psf_lc, star_y, star_x, portion, target_5x5, field_stars_5x5 = \
314
323
  fit_lc(A, source, star_info=star_info, x=x_round[i], y=y_round[i], star_num=i, e_psf=e_psf,
315
324
  near_edge=near_edge)
316
325
  aper_lc = np.sum(
@@ -359,4 +368,4 @@ def epsf(source, psf_size=11, factor=2, local_directory='', target=None, cut_x=0
359
368
  bg=background_, time=source.time, psf_lc=psf_lc, cal_psf_lc=cal_psf_lc, aper_lc=aper_lc,
360
369
  cal_aper_lc=cal_aper_lc, local_bg=local_bg, x_aperture=x_aperture[i],
361
370
  y_aperture=y_aperture[i], near_edge=near_edge, save_aper=save_aper, portion=portion,
362
- prior=prior, transient=source.transient)
371
+ prior=prior, transient=source.transient, target_5x5=target_5x5, field_stars_5x5=field_stars_5x5)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tglc
3
- Version: 0.6.4
3
+ Version: 0.6.6
4
4
  Summary: TESS-Gaia Light Curve
5
5
  Home-page: https://github.com/TeHanHunter/TESS_Gaia_Light_Curve
6
6
  Author: Te Han
@@ -8,9 +8,21 @@ Author-email: tehanhunter@gmail.com
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.8
11
+ Requires-Python: >=3.8, <3.13
12
12
  Description-Content-Type: text/x-rst
13
13
  License-File: LICENSE
14
+ Requires-Dist: astropy>=5.1
15
+ Requires-Dist: astroquery==0.4.7
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
+ Requires-Dist: seaborn
14
26
 
15
27
  ==================================
16
28
  Introduction
@@ -18,6 +30,7 @@ Introduction
18
30
 
19
31
  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.
20
32
 
33
+
21
34
  ==================================
22
35
  Usage
23
36
  ==================================
@@ -1,5 +1,5 @@
1
1
  astropy>=5.1
2
- astroquery
2
+ astroquery==0.4.7
3
3
  matplotlib
4
4
  numpy
5
5
  oauthlib
@@ -9,3 +9,4 @@ threadpoolctl
9
9
  tqdm
10
10
  wheel
11
11
  wotan
12
+ seaborn
@@ -1,3 +0,0 @@
1
- __version__ = "0.6.4"
2
- __author__ = 'Te Han, Timothy Brandt'
3
- __credits__ = 'University of California, Santa Barbara'
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes