band_model_uncertainties = 2.5 * np.log10(filter_defs[:, 2].astype(float)) phot_band_cols = filter_defs[:, 3].astype(str) e_phot_band_cols = filter_defs[:, 4].astype(str) # Scale factor for synthetic colour residuals phot_scale_fac = 20 # Stars to treat as equal mass binaries whose single star flux should be halved unresolved_equal_mass_binary_list = ["5724250571514167424"] unresolved_equal_mass_binary_mag_diff = 0.75 # Literature information (including photometry) info_cat_path = "data/{}_info.tsv".format(cat_label) info_cat = utils.load_info_cat( info_cat_path, in_paper=True, only_observed=True, unresolved_equal_mass_binary_list=unresolved_equal_mass_binary_list, ) only_fit_info_cat_stars = True # Initialise settings for each band band_settings_b = { "inst_res_pow": 3000, "wl_min": 3500, "wl_max": 5700, "n_px": 2858, "wl_per_px": 0.77, "wl_broadening": 0.77, "arm": "b", "grid": "B3000",
"""Script to generate all paper figures and tables """ import plumage.plotting as pplt import plumage.utils as utils import plumage.spectra as spec import plumage.paper as paper spec_path = "spectra" # Import literature info for both standards and TESS targets std_info = utils.load_info_cat("data/std_info.tsv") tic_info = utils.load_info_cat("data/tess_info.tsv") # Load results tables for both standards and TESS targets obs_std = utils.load_fits_obs_table("std", path="spectra") obs_tess = utils.load_fits_obs_table("tess", path="spectra") # Load spectra and results for standards spec_std_b, spec_std_r, obs_std = utils.load_fits("std", path=spec_path) bad_px_masks_std_b = utils.load_fits_image_hdu("bad_px", "std", arm="b") bad_px_masks_std_r = utils.load_fits_image_hdu("bad_px", "std", arm="r") synth_std_b = utils.load_fits_image_hdu("synth", "std", arm="b") synth_std_r = utils.load_fits_image_hdu("synth", "std", arm="r") synth_std_lit_b = utils.load_fits_image_hdu("synth_lit", "std", arm="b") synth_std_lit_r = utils.load_fits_image_hdu("synth_lit", "std", arm="r") # Load spectra and results for TESS targets spec_tess_b, spec_tess_r, obs_tess = utils.load_fits("tess", path=spec_path) bad_px_masks_tess_b = utils.load_fits_image_hdu("bad_px", "tess", arm="b") bad_px_masks_tess_r = utils.load_fits_image_hdu("bad_px", "tess", arm="r") synth_tess_b = utils.load_fits_image_hdu("synth", "tess", arm="b")
import plumage.plotting as pplt import astropy.constants as const # Timing start_time = datetime.now() # ----------------------------------------------------------------------------- # Setup # ----------------------------------------------------------------------------- label = "tess" spec_path = "spectra" # Load in literature info for our stars tic_info = utils.load_info_cat( remove_fp=True, only_observed=True, use_mann_code_for_masses=True, ).reset_index() tic_info.set_index("TIC", inplace=True) # Load NASA ExoFOP info on TOIs toi_info = utils.load_exofop_toi_cat(do_ctoi_merge=True) # Load in info on observations and fitting results observations = utils.load_fits_table( "OBS_TAB", label, path=spec_path, ) # Choose binning, and import light curves to fit with
# Import spec_std_b, spec_std_r, obs_std = utils.load_fits("std_fluxed", path=spec_path) #synth_std_b = utils.load_fits_image_hdu("synth", "std", arm="b") #synth_std_r = utils.load_fits_image_hdu("synth", "std", arm="r") synth_std_lit_b = utils.load_fits_image_hdu("synth_lit", "std_fluxed", arm="b") synth_std_lit_r = utils.load_fits_image_hdu("synth_lit", "std_fluxed", arm="r") # Mask to only those with literature synthetic spectra mask = ~np.isnan(np.sum(synth_std_lit_b, axis=1)) spec_std_b = spec_std_b[mask] spec_std_r = spec_std_r[mask] obs_std = obs_std[mask] synth_std_lit_b = synth_std_lit_b[mask] synth_std_lit_r = synth_std_lit_r[mask] std_info = utils.load_info_cat("data/std_info.tsv") obs_std = obs_std.join(std_info, "source_id", how="inner", rsuffix="_") star_dict = { 134:("Teff~3192, logg~5.08, [FeH]~-0.02, Gl 447 (3796072592206250624)", "phoenix/lte032-5.0-0.0a+0.0.BT-Settl.7", "phoenix/lte032.0-5.0-0.0a+0.0.BT-Settl.spec.7"), 97:("Teff~3261 logg~4.95, [Fe/H]~0.16, GJ 3379 (3316364602541746048)", "", "",), 4:("Teff~3298 logg~4.83, [Fe/H]~0.17, Gl 876 (2603090003484152064)", "", "",), 23:("Teff~3530, logg~4.78, [FeH]~+0.35, Gl 849 (2627117287488522240)", "phoenix/lte035-5.0+0.3a+0.0.BT-Settl.7",
"""Script to generate synthetic spectra at the literature values for stellar standards. """ import numpy as np import plumage.utils as utils import plumage.synthetic as synth import plumage.spectra as spec from astropy import constants as const from scipy.interpolate import InterpolatedUnivariateSpline as ius label = "std" spec_path = "spectra" std_info = utils.load_info_cat("data/std_info.tsv", in_paper=True) spectra_b, spectra_r, observations = utils.load_fits(label, path=spec_path) # Initlise empty arrays to hold synthetic spectra at lit params all_synth_lit_b = [] all_synth_lit_r = [] # Intitialise wavelength scale values band_settings_b = { "inst_res_pow":3000, "wl_min":3500, "wl_max":5700, "n_px":2858, "wl_per_px":0.77, "wl_broadening":0.77, "arm":"b", "grid":"B3000", }
"""Script to download and save complete lightcurves for all TOIs """ import numpy as np import plumage.utils as utils import plumage.transits as transit # Binning factor. Note that we're assuming a minimum cadence of 2 mins, so # extended mission data will get binned to at least that level bin_fac = 4 # Import catalogue of TESS info tess_info = utils.load_info_cat( remove_fp=True, only_observed=True, use_mann_code_for_masses=False, do_extinction_correction=False,) # Load ExoFOP info efi = utils.load_exofop_toi_cat() all_lightcurves = [] unmatched_tics = [] sector_list = [] for star_i, (source_id, star) in enumerate(tess_info.iterrows()): print("\nDownloading lightcurve {}/{} for TIC {}".format( star_i+1, len(tess_info), star["TIC"])) # Download light curve for current star try: lc, sectors = transit.download_lc_all_sectors(
# Polynomial order of the fitted offset function offset_poly_order = 1 # Whether to apply an additional linear correction to the residuals apply_correction = True # Whether to plot remaining residual trend plot_resid_trend = False # ----------------------------------------------------------------------------- # Import and setup # ----------------------------------------------------------------------------- # Import CPM info cpm_info = utils.load_info_cat( "data/cpm_info.tsv", clean=False, allow_alt_plx=True, use_mann_code_for_masses=False, do_extinction_correction=False,) # Only keep reliable pairs cpm_info = cpm_info[cpm_info["included"] == "yes"] if use_only_aaa_2mass: cpm_info = cpm_info[cpm_info["Qflg"] == "AAA"] if rule_out_gaia_dups: cpm_info = cpm_info[cpm_info["dup"] == 0] if apply_ruwe_cut: cpm_info = cpm_info[cpm_info["ruwe"] < 1.4]
def make_table_ld_coeff( break_row=64, label="tess", info_cat=None, ): """Make the final results table to display the angular diameters and derived fundamental parameters. Parameters ---------- break_row: int Which row to break table 1 at and start table 2. """ # Load in observations, TIC, and TOI info observations = utils.load_fits_table("OBS_TAB", label, path="spectra") if info_cat is None: info_cat = utils.load_info_cat( remove_fp=True, in_paper=True, only_observed=True, use_mann_code_for_masses=True, ) if label == "tess": id_col = "TIC" else: id_col = "Gaia DR2" comb_info = observations.join(info_cat, "source_id", rsuffix="_info", how="inner") comb_info.sort_values("teff_synth", inplace=True) cols = OrderedDict([ (id_col, ""), (r"$a_1$", ""), (r"$a_2$", ""), (r"$a_3$", ""), (r"$a_4$", ""), ]) header = [] header_1 = [] header_2 = [] table_rows = [] footer = [] notes = [] # Construct the header of the table header.append("\\begin{table}") header.append("\\centering") #header.append("\\label{tab:ld_coeff}") header.append("\\begin{tabular}{%s}" % ("c" * len(cols))) header.append("\hline") header.append((("%s & " * len(cols))[:-2] + r"\\") % tuple(cols.keys())) header.append((("%s & " * len(cols))[:-2] + r"\\") % tuple(cols.values())) header.append("\hline") # Now add the separate info for the two tables header_1 = header.copy() caption = ("Nonlinear limb darkening coefficients from " "\citet{claret_limb_2017}") header_1.insert(2, "\\caption{{{}}}".format(caption)) header_1.insert(3, "\\label{tab:ld_coeff}") header_2 = header.copy() header_2.insert(2, "\\contcaption{Limb darkening coefficients}") # Populate the table for every science target for star_i, star in comb_info.iterrows(): table_row = "" # Step through column by column if label == "tess": table_row += "%s & " % star["TIC"] else: table_row += "%s & " % star.name # Coefficients table_row += r"{:0.3f} & ".format(star["ldc_a1"]) table_row += r"{:0.3f} & ".format(star["ldc_a2"]) table_row += r"{:0.3f} & ".format(star["ldc_a3"]) table_row += r"{:0.3f} ".format(star["ldc_a4"]) table_rows.append(table_row + r"\\") # Finish the table footer.append("\hline") footer.append("\end{tabular}") footer.append("\\end{table}") # Write the table/s break_rows = np.arange(break_row, len(comb_info), break_row) low_row = 0 for table_i, break_row in enumerate(break_rows): if table_i == 0: header = header_1 else: header = header_2 table_x = header + table_rows[low_row:break_row] + footer + notes np.savetxt("paper/table_ldc_{}_{:0.0f}.tex".format(label, table_i), table_x, fmt="%s") low_row = break_row # Do final part table if low_row < len(comb_info): table_i += 1 table_x = header_2 + table_rows[low_row:] + footer + notes np.savetxt("paper/table_ldc_{}_{:0.0f}.tex".format(label, table_i), table_x, fmt="%s")
def make_table_targets( break_row=45, tess_info=None, ): """Make the LaTeX table to summarise the target information. Parameters ---------- break_row: int Which row to break table 1 at and start table 2. """ # Load in the TESS target info if tess_info is None: tess_info = utils.load_info_cat(remove_fp=True, only_observed=True, in_paper=True) tess_info.sort_values("G_mag", inplace=True) cols = OrderedDict([("TOI$^a$", ""), ("TIC$^b$", ""), ("2MASS$^c$", ""), ("Gaia DR2$^d$", ""), ("RA$^d$", "(hh mm ss.ss)"), ("DEC$^d$", "(dd mm ss.ss)"), ("$G^d$", "(mag)"), ("${B_p-R_p}^d$", "(mag)"), ("Plx$^d$", "(mas)"), ("ruwe$^d$", ""), ("E($B-V$)", ""), (r"N$_{\rm pc}^e$", "")]) header = [] header_1 = [] header_2 = [] table_rows = [] footer = [] notes = [] # Construct the header of the table header.append("\\begin{landscape}") header.append("\\begin{table}") header.append("\\centering") header.append("\\begin{tabular}{%s}" % ("c" * len(cols))) header.append("\hline") header.append((("%s & " * len(cols))[:-2] + r"\\") % tuple(cols.keys())) header.append((("%s & " * len(cols))[:-2] + r"\\") % tuple(cols.values())) header.append("\hline") # Now add the separate info for the two tables header_1 = header.copy() header_1.insert(3, "\\caption{Science targets}") header_1.insert(4, "\\label{tab:science_targets}") header_2 = header.copy() header_2.insert(3, "\\contcaption{Science targets}") # Populate the table for every science target for star_i, star in tess_info.iterrows(): table_row = "" # Only continue if both observed and not FP if star["observed"] == "yes" and star["TFOPWG Disposition"] == "FP": continue # Format RA and DEC ra_hr = np.floor(star["ra"] / 15) ra_min = np.floor((star["ra"] / 15 - ra_hr) * 60) ra_sec = ((star["ra"] / 15 - ra_hr) * 60 - ra_min) * 60 ra = "{:02.0f} {:02.0f} {:05.2f}".format(ra_hr, ra_min, ra_sec) dec_deg = np.floor(star["dec"]) dec_min = np.floor((star["dec"] - dec_deg) * 60) dec_sec = ((star["dec"] - dec_deg) * 60 - dec_min) * 60 dec = "{:+02.0f} {:02.0f} {:05.2f}".format(dec_deg, dec_min, dec_sec) # Step through column by column table_row += "%s & " % int(star["TOI"]) table_row += "%s & " % star["TIC"] #table_row += "%s & " % star["TOI"] table_row += "%s & " % star["2mass"] table_row += "%s & " % star_i table_row += "%s & " % ra table_row += "%s & " % dec table_row += "%0.2f & " % star["G_mag"] table_row += "%0.2f & " % star["Bp-Rp"] table_row += r"%0.2f $\pm$ %0.2f & " % (star["plx"], star["e_plx"]) table_row += "%0.1f & " % star["ruwe"] table_row += "%0.2f & " % star["ebv"] table_row += "%i " % star["n_pc"] # Replace any nans with '-' table_rows.append(table_row.replace("nan", "-") + r"\\") # Finish the table footer.append("\\hline") footer.append("\\end{tabular}") footer_2 = footer.copy() # Add notes section with references notes.append("\\begin{minipage}{\linewidth}") notes.append("\\vspace{0.1cm}") notes.append("\\textbf{Notes:} $^a$ TESS Object of Interest ID, " "$^b$ TESS Input Catalogue ID " "\citep{stassun_tess_2018, stassun_revised_2019}," "$^c$2MASS \citep{skrutskie_two_2006}, " "$^c$Gaia \citep{brown_gaia_2018} - " " note that Gaia parallaxes listed here have been " "corrected for the zeropoint offset, " "$^d$Number of candidate planets, NASA Exoplanet Follow-up " "Observing Program for TESS \\\\") notes.append("\\end{minipage}") notes.append("\\end{table}") notes.append("\\end{landscape}") footer_2.append("\\end{table}") footer_2.append("\\end{landscape}") # Write the tables table_1 = header_1 + table_rows[:break_row] + footer + notes table_2 = header_2 + table_rows[break_row:] + footer_2 # Write the table np.savetxt("paper/table_targets_1.tex", table_1, fmt="%s") np.savetxt("paper/table_targets_2.tex", table_2, fmt="%s")
def make_table_final_results( break_row=45, label="tess", logg_col="logg_synth", exp_scale=-12, info_cat=None, do_activity_crossmatch=False, ): """Make the final results table to display the angular diameters and derived fundamental parameters. Parameters ---------- break_row: int Which row to break table 1 at and start table 2. """ # Load in observations, TIC, and TOI info observations = utils.load_fits_table("OBS_TAB", label, path="spectra") # Crossmatch with activity if do_activity_crossmatch: observations = utils.merge_activity_table_with_obs( observations, label, fix_missing_source_id=True) if info_cat is None: info_cat = utils.load_info_cat( remove_fp=True, in_paper=True, only_observed=True, use_mann_code_for_masses=True, ) if label == "tess": id_col = "TIC" caption = "Final results for TESS candidate exoplanet hosts" else: id_col = "Gaia DR2" caption = "Final results for cool dwarf standards" comb_info = observations.join(info_cat, "source_id", rsuffix="_info", how="inner") comb_info.sort_values("teff_synth", inplace=True) cols = OrderedDict([ ("TOI", ""), (id_col, ""), (r"$T_{\rm eff}$", "(K)"), (r"$\log g$", ""), (r"[Fe/H]", ""), (r"$M$", "($M_\odot$)"), (r"$R$", "($R_\odot$)"), (r"$m_{\rm bol}$", ""), (r"$f_{\rm bol}$", r"{{\footnotesize(10$^{%i}\,$ergs s$^{-1}$ cm $^{-2}$)}}" % exp_scale), #(r"$L$", "($L_\odot$)"), (r"EW(H$\alpha$)", r"\SI{}{\angstrom}"), (r"$\log R^{'}_{\rm HK}$", ""), ]) # Pop activity keys if making standards if label != "tess": cols.pop("TOI") cols.pop(r"EW(H$\alpha$)") cols.pop(r"$\log R^{'}_{\rm HK}$") header = [] header_1 = [] header_2 = [] table_rows = [] footer = [] notes = [] # Construct the header of the table header.append("\\begin{table*}") header.append("\\centering") header.append("\\begin{tabular}{%s}" % ("c" * len(cols))) header.append("\hline") header.append((("%s & " * len(cols))[:-2] + r"\\") % tuple(cols.keys())) header.append((("%s & " * len(cols))[:-2] + r"\\") % tuple(cols.values())) header.append("\hline") # Now add the separate info for the two tables header_1 = header.copy() header_1.insert(2, "\\label{{tab:final_results_{}}}".format(label)) header_1.insert(2, "\\caption{{{}}}".format(caption)) header_2 = header.copy() header_2.insert(2, "\\contcaption{{{}}}".format(caption)) # Populate the table for every science target for star_i, star in comb_info.iterrows(): # Check to make sure this star has results if np.isnan(star["teff_synth"]): print("Skipping", star_i) continue table_row = "" # Step through column by column if label == "tess": table_row += "%s & " % int(star["TOI"]) table_row += "%s & " % star["TIC"] else: table_row += "%s & " % star.name # Temperature table_row += r"{:0.0f} $\pm$ {:0.0f} & ".format( star["teff_synth"], star["e_teff_synth"]) table_row += r"{:0.2f} $\pm$ {:0.2f} &".format( star[logg_col], star["e_{}".format(logg_col)]) # Photometric [Fe/H] if np.isnan(star["phot_feh"]): table_row += "- &" else: table_row += r"{:0.2f} &".format(star["phot_feh"]) # Mass and radius table_row += r"{:0.3f} $\pm$ {:0.3f} &".format(star["mass_m19"], star["e_mass_m19"]) table_row += r"{:0.3f} $\pm$ {:0.3f} &".format(star["radius"], star["e_radius"]) # Bolometric magnitude table_row += r"{:0.2f} $\pm$ {:0.2f} &".format(star["mbol_synth"], star["e_mbol_synth"]) # For fbol representation, split mantissa and exponent table_row += r"{:5.1f} $\pm$ {:0.1f} &".format( star["fbol"] / 10**exp_scale, star["e_fbol"] / 10**exp_scale) # Luminosity #table_row += r"{:0.3f} $\pm$ {:0.3f} & ".format( #star["L_star"], star["e_L_star"]) # H alpha and logR`HK if do_activity_crossmatch and label == "tess": table_row += r"{:0.2f} & ".format(star["EW(Ha)"]) table_row += r"{:0.2f} ".format(star["logR'HK"]) elif label == "tess": table_row += r"{:0.2f} & ".format(np.nan) table_row += r"{:0.2f} ".format(np.nan) # Not writing activity columns, remove & else: table_row = table_row[:-2] # Get rid of nans, append table_rows.append(table_row.replace("nan", "-") + r"\\") # Finish the table footer.append("\hline") footer.append("\end{tabular}") footer.append("\\end{table*}") # Write the table/s break_rows = np.arange(break_row, len(comb_info), break_row) low_row = 0 for table_i, break_row in enumerate(break_rows): if table_i == 0: header = header_1 else: header = header_2 table_x = header + table_rows[low_row:break_row] + footer + notes np.savetxt("paper/table_final_results_{}_{:0.0f}.tex".format( label, table_i), table_x, fmt="%s") low_row = break_row # Do final part table if low_row < len(comb_info): table_i += 1 table_x = header_2 + table_rows[low_row:] + footer + notes np.savetxt("paper/table_final_results_{}_{:0.0f}.tex".format( label, table_i), table_x, fmt="%s")
[1.15, 1.05, 0, 0, 0, 2, 1.2, 1.05, 1.05, 1.05]) band_model_uncertainties[~np.isfinite(band_model_uncertainties)] = 0 # Bp, Rp, J, H, K, v, g, r, i, z phot_mask = np.array([0, 1, 1, 1, 1, 0, 0, 1, 1, 1]).astype(bool) filters = filters[phot_mask] phot_band_cols = phot_band_cols[phot_mask] e_phot_band_cols = e_phot_band_cols[phot_mask] band_model_uncertainties = band_model_uncertainties[phot_mask] # Scale factor for synthetic colour residuals phot_scale_fac = 1 # Literature information (including photometry) info_cat_path = "data/{}_info.tsv".format(label) info_cat = utils.load_info_cat(info_cat_path, only_observed=True) skymapper_phot = pd.read_csv("data/rains_all_gaia_ids_matchfinal.csv", sep=",", dtype={"source_id": str}, header=0) skymapper_phot.set_index("source_id", inplace=True) info_cat = info_cat.join(skymapper_phot, "source_id", how="inner", rsuffix="_") # Mask for testing #mask = np.isfinite(info_cat["i_psf"]) #info_cat = info_cat[mask] # Initialise settings for each band band_settings_b = {