def test_checkplot_with_multiple_same_pfmethods(): ''' This tests running the same period-finder for different period ranges. ''' outpath = os.path.join(os.path.dirname(LCPATH), 'test-checkplot.pkl') lcd, msg = hatlc.read_and_filter_sqlitecurve(LCPATH) gls_1 = periodbase.pgen_lsp(lcd['rjd'], lcd['aep_000'], lcd['aie_000'], startp=0.01, endp=0.1) gls_2 = periodbase.pgen_lsp(lcd['rjd'], lcd['aep_000'], lcd['aie_000'], startp=0.1, endp=300.0) pdm_1 = periodbase.stellingwerf_pdm(lcd['rjd'], lcd['aep_000'], lcd['aie_000'], startp=0.01, endp=0.1) pdm_2 = periodbase.stellingwerf_pdm(lcd['rjd'], lcd['aep_000'], lcd['aie_000'], startp=0.1, endp=300.0) assert isinstance(gls_1, dict) assert isinstance(gls_2, dict) assert isinstance(pdm_1, dict) assert isinstance(pdm_2, dict) cpf = checkplot.checkplot_pickle([gls_1, gls_2, pdm_1, pdm_2], lcd['rjd'], lcd['aep_000'], lcd['aie_000'], outfile=outpath, objectinfo=lcd['objectinfo']) assert os.path.exists(cpf) assert os.path.abspath(cpf) == os.path.abspath(outpath) cpd = _read_checkplot_picklefile(cpf) pfmethods = list(cpd['pfmethods']) assert len(pfmethods) == 4 assert '0-gls' in pfmethods assert '1-gls' in pfmethods assert '2-pdm' in pfmethods assert '3-pdm' in pfmethods
def test_checkplot_pickle_make(): ''' Tests if a checkplot pickle can be made. ''' outpath = os.path.join(os.path.dirname(LCPATH), 'test-checkplot.pkl') lcd, msg = hatlc.read_and_filter_sqlitecurve(LCPATH) gls = periodbase.pgen_lsp(lcd['rjd'], lcd['aep_000'], lcd['aie_000']) assert isinstance(gls, dict) assert_allclose(gls['bestperiod'], 1.54289477) pdm = periodbase.stellingwerf_pdm(lcd['rjd'], lcd['aep_000'], lcd['aie_000']) assert isinstance(pdm, dict) assert_allclose(pdm['bestperiod'], 3.08578956) cpf = checkplot.checkplot_pickle( [gls, pdm], lcd['rjd'], lcd['aep_000'], lcd['aie_000'], outfile=outpath, objectinfo=lcd['objectinfo'] ) assert os.path.exists(outpath)
def test_checkplot_pickle_update(): ''' Tests if a checkplot pickle can be made, read back, and updated. ''' outpath = os.path.join(os.path.dirname(LCPATH), 'test-checkplot.pkl') lcd, msg = hatlc.read_and_filter_sqlitecurve(LCPATH) gls = periodbase.pgen_lsp(lcd['rjd'], lcd['aep_000'], lcd['aie_000']) assert isinstance(gls, dict) assert_allclose(gls['bestperiod'], 1.54289477) pdm = periodbase.stellingwerf_pdm(lcd['rjd'], lcd['aep_000'], lcd['aie_000']) assert isinstance(pdm, dict) assert_allclose(pdm['bestperiod'], 3.08578956) # test write cpf = checkplot.checkplot_pickle( [gls, pdm], lcd['rjd'], lcd['aep_000'], lcd['aie_000'], outfile=outpath, objectinfo=lcd['objectinfo'] ) assert os.path.exists(outpath) # test read back cpd = checkplot._read_checkplot_picklefile(cpf) assert isinstance(cpd, dict) cpdkeys = set(list(cpd.keys())) testset = {'0-gls', '1-pdm', 'comments', 'externalplots', 'finderchart', 'magseries', 'neighbors', 'normmingap', 'normto', 'objectid', 'objectinfo', 'pfmethods', 'sigclip', 'signals', 'status', 'varinfo'} assert (testset - cpdkeys) == set() assert_allclose(cpd['0-gls']['bestperiod'], 1.54289477) assert_allclose(cpd['1-pdm']['bestperiod'], 3.08578956) # test update write to pickle cpd['comments'] = ('this is a test of the checkplot pickle ' 'update mechanism. this is only a test.') cpfupdated = checkplot.checkplot_pickle_update(cpf, cpd) cpdupdated = checkplot._read_checkplot_picklefile(cpfupdated) assert cpdupdated['comments'] == cpd['comments']
def do_period_finding_fitslc(lcpath, fluxap='TFA2', period_min=0.5, outdir=None): if not outdir: outdir = os.path.dirname(lcpath) outfile = os.path.basename(lcpath).replace('.fits', '_spdm_blsp_checkplot.png') outpath = os.path.join(outdir, outfile) if os.path.exists(outpath): print('found & skipped {}'.format(outpath)) return hdulist = fits.open(lcpath) hdr, lc = hdulist[0].header, hdulist[1].data times, mags, errs = (lc['TMID_BJD'], lc[fluxap], np.ones_like(lc[fluxap]) * np.nanmedian(lc[fluxap]) / 1000) #glsp = periodbase.pgen_lsp(times,mags,errs) spdm = periodbase.stellingwerf_pdm(times, mags, errs) blsp = periodbase.bls_parallel_pfind(times, mags, errs, startp=period_min, get_stats=False) objectinfo = {} keys = ['objectid', 'ra', 'decl', 'pmra', 'pmdecl', 'teff', 'gmag'] hdrkeys = [ 'Gaia-ID', 'RA[deg]', 'Dec[deg]', 'PM_RA[mas/yr]', 'PM_Dec[mas/year]', 'teff_val', 'phot_g_mean_mag' ] for k, hk in zip(keys, hdrkeys): if hk in hdr: objectinfo[k] = hdr[hk] else: objectinfo[k] = np.nan cp = checkplot.twolsp_checkplot_png(blsp, spdm, times, mags, errs, objectinfo=objectinfo, outfile=outpath, sigclip=[50., 5.], plotdpi=100, phasebin=3e-2, phasems=6.0, phasebinms=12.0, unphasedms=6.0) print('did {}'.format(outpath))
def test_pdm(): ''' Tests periodbase.stellingwerf_pdm. ''' lcd, msg = hatlc.read_and_filter_sqlitecurve(LCPATH) pdm = periodbase.stellingwerf_pdm(lcd['rjd'], lcd['aep_000'], lcd['aie_000']) assert isinstance(pdm, dict) assert_allclose(pdm['bestperiod'], 3.08578956)
def stellarvar_process_raw_lc(lcfile, mingap=0.5, windowsize=48 * 3): """ process raw lightcurve (IRM2) to show off stellar variability. turn it to relative flux units. stitch consistent normalization across orbits. (also, median filter with a BIG window). get the stellingwerf period and t0 as well. mingap (float): units of days return: time, whitened_flux, err_flux, flux, outdir, spdm """ if windowsize % 2 == 0: windowsize += 1 hdulist = fits.open(lcfile) data = hdulist[1].data time, mag, err_mag = data['TMID_BJD'], data['IRM2'], data['IRE2'] time, flux, err_flux = _get_flux_from_mags(time, mag, err_mag) # for detrending, need to split into orbits. get time groups, and filter # each one ngroups, groups = lcmath.find_lc_timegroups(time, mingap=mingap) assert ngroups == 2 tg_smooth_flux = [] for group in groups: #tg_smooth_flux.append( medfilt(flux[group], windowsize) ) tg_smooth_flux.append(savgol(flux[group], windowsize, polyorder=1)) flux_smooth = np.concatenate(tg_smooth_flux) func = interp1d(time, flux_smooth) flux_to_div = func(time) outdir = os.path.dirname(lcfile) divsavpath = os.path.join( outdir, 'DIVMODEL_{}.png'.format(os.path.basename(lcfile))) _divmodel_plot(time, flux, flux_to_div, divsavpath) whitened_flux = flux / flux_to_div spdm = periodbase.stellingwerf_pdm(time, whitened_flux, err_flux, magsarefluxes=True, nworkers=8) return time, whitened_flux, err_flux, flux, outdir, spdm
def allvar_periodogram_checkplot(a): ap = int(a['ap']) time, flux, err = a['STIME'], a[f'SPCA{ap}'], a[f'SPCAE{ap}'] spdm = periodbase.stellingwerf_pdm(time, flux, err, magsarefluxes=True, startp=0.05, endp=30, sigclip=5.0, nworkers=nworkers) lsp = periodbase.pgen_lsp(time, flux, err, magsarefluxes=True, startp=0.05, endp=30, autofreq=True, sigclip=5.0, nworkers=nworkers) objectinfo = {} keys = ['objectid', 'ra', 'decl', 'pmra', 'pmdecl', 'teff', 'gmag'] hdrkeys = [ 'Gaia-ID', 'RA_OBJ', 'DEC_OBJ', 'PM_RA[mas/yr]', 'PM_Dec[mas/year]', 'teff_val', 'phot_g_mean_mag' ] hdr = a['dtr_infos'][0][0] for k, hk in zip(keys, hdrkeys): if hk in hdr: objectinfo[k] = hdr[hk] else: objectinfo[k] = np.nan import matplotlib as mpl mpl.rcParams['axes.titlesize'] = 'xx-large' mpl.rcParams['axes.labelsize'] = 'xx-large' fig = checkplot.twolsp_checkplot_png(lsp, spdm, time, flux, err, magsarefluxes=True, objectinfo=objectinfo, varepoch='min', sigclip=None, plotdpi=100, phasebin=3e-2, phasems=6.0, phasebinms=14.0, unphasedms=6.0, figsize=(30, 24), returnfigure=True, circleoverlay=APSIZEDICT[ap] * 21, yticksize=20, trimylim=True) axs = fig.get_axes() for ax in axs: ax.get_yaxis().set_tick_params(which='both', direction='in', labelsize='xx-large') ax.get_xaxis().set_tick_params(which='both', direction='in', labelsize='xx-large') return fig, lsp, spdm, objectinfo
def main(checklcs=0, processlcs=0, makequadplot=0): wasp18file = ('../data/showoff_lightcurves/wasp18/' '4955371367334610048_llc.fits') blanco1files = glob('../data/showoff_lightcurves/blanco_1/*.fits') toifiles = glob('../data/showoff_lightcurves/toi_324/*.fits') toi324file = toifiles[0] if checklcs: check_lightcurve(wasp18file) for blanco1file in blanco1files: check_lightcurve(blanco1file) for toifile in toifiles: check_lightcurve(toifile) if processlcs: # retrieve the LC for # blanco_1/2320822863006024832_llc_spdm_blsp_checkplot.png fpath = [f for f in blanco1files if '2320822863006024832' in f][0] time, whitened_flux, err_flux, flux, outdir, spdm = ( stellarvar_process_raw_lc(fpath, windowsize=48 * 12)) period = spdm['bestperiod'] t0 = np.nanmedian(time) assert 0 # retrieve and clean wasp-18 (time, whitened_flux, err_flux, time_oot, flux_oot, err_flux_oot, flux, outdir) = (transit_process_raw_lc(wasp18file)) time, whitened_flux, err_flux = wasp18_fine_tuning( wasp18file, time, whitened_flux, err_flux, time_oot, flux_oot, err_flux_oot, outdir) trapd = get_trapd_given_timeseries(wasp18file, time, whitened_flux, err_flux) period, t0 = (trapd['fitinfo']['finalparams'][0], trapd['fitinfo']['finalparams'][1]) # ditto toi 324 (time, whitened_flux, err_flux, time_oot, flux_oot, err_flux_oot, flux, outdir) = (transit_process_raw_lc(toi324file, extra_maskfrac=0.3, windowsize=48)) time, whitened_flux, err_flux = toi_fine_tuning( toi324file, time, whitened_flux, err_flux, time_oot, flux_oot, err_flux_oot, outdir) trapd = get_trapd_given_timeseries(toi324file, time, whitened_flux, err_flux) if makequadplot: fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(6, 3)) # retrieve and clean wasp-18 datapklfile = '../data/showoff_lightcurves/wasp18/plot_data.pickle' if not os.path.exists(datapklfile): (time, whitened_flux, err_flux, time_oot, flux_oot, err_flux_oot, flux, outdir) = (transit_process_raw_lc(wasp18file, windowsize=48 * 2, extra_maskfrac=0.1)) time, whitened_flux, err_flux = wasp18_fine_tuning( wasp18file, time, whitened_flux, err_flux, time_oot, flux_oot, err_flux_oot, outdir) trapd = get_trapd_given_timeseries(wasp18file, time, whitened_flux, err_flux) period, t0 = (trapd['fitinfo']['finalparams'][0], trapd['fitinfo']['finalparams'][1]) outd = { 'time': time, 'flux': whitened_flux, 'period': period, 't0': t0 } with open(datapklfile, 'wb') as f: pickle.dump(outd, f, pickle.HIGHEST_PROTOCOL) print('dumped to {}'.format(datapklfile)) else: d = pickle.load(open(datapklfile, 'rb')) time = d['time'] whitened_flux = d['flux'] period = d['period'] t0 = d['t0'] plot_phase(time, whitened_flux, period, t0, axs[0, 0]) axs[0, 0].text(0.96, 0.06, 'P={:.2f}d'.format(period), transform=axs[0, 0].transAxes, ha='right', va='bottom') # ok now TOI 324 datapklfile = '../data/showoff_lightcurves/toi_324/plot_data.pickle' if not os.path.exists(datapklfile): (time, whitened_flux, err_flux, time_oot, flux_oot, err_flux_oot, flux, outdir) = (transit_process_raw_lc(toi324file, extra_maskfrac=0.3, windowsize=48)) time, whitened_flux, err_flux = toi_fine_tuning( toi324file, time, whitened_flux, err_flux, time_oot, flux_oot, err_flux_oot, outdir) trapd = get_trapd_given_timeseries(toi324file, time, whitened_flux, err_flux) period, t0 = (trapd['fitinfo']['finalparams'][0], trapd['fitinfo']['finalparams'][1]) outd = { 'time': time, 'flux': whitened_flux, 'period': period, 't0': t0 } with open(datapklfile, 'wb') as f: pickle.dump(outd, f, pickle.HIGHEST_PROTOCOL) print('dumped to {}'.format(datapklfile)) else: d = pickle.load(open(datapklfile, 'rb')) time = d['time'] whitened_flux = d['flux'] period = d['period'] t0 = d['t0'] plot_phase(time, whitened_flux, period, t0, axs[1, 0], s=5) axs[1, 0].text(0.96, 0.06, 'P={:.2f}d'.format(period), transform=axs[1, 0].transAxes, ha='right', va='bottom') # now the blanco-1 mega-rotator datapklfile = '../data/showoff_lightcurves/blanco_1/2320822863006024832_plot_data.pickle' if not os.path.exists(datapklfile): fpath = [f for f in blanco1files if '2320822863006024832' in f][0] time, whitened_flux, err_flux, flux, outdir, spdm = ( stellarvar_process_raw_lc(fpath, windowsize=48 * 12)) period = spdm['bestperiod'] t0 = np.nanmedian(time) outd = { 'time': time, 'flux': whitened_flux, 'period': period, 't0': t0 } with open(datapklfile, 'wb') as f: pickle.dump(outd, f, pickle.HIGHEST_PROTOCOL) print('dumped to {}'.format(datapklfile)) else: d = pickle.load(open(datapklfile, 'rb')) time = d['time'] whitened_flux = d['flux'] period = d['period'] t0 = d['t0'] plot_phase(time, whitened_flux, period, t0, axs[0, 1]) axs[0, 1].text(0.96, 0.94, 'P={:.2f}d'.format(period), transform=axs[0, 1].transAxes, ha='right', va='top') # finally, the rapid M dwarf rotator datapklfile = '../data/showoff_lightcurves/mdwarf_rotators/4742436853122727040_plot_data.pickle' if not os.path.exists(datapklfile): fpath = '../data/showoff_lightcurves/mdwarf_rotators/4742436853122727040_llc.fits' time, whitened_flux, err_flux, flux, outdir, _ = ( stellarvar_process_raw_lc(fpath, windowsize=48 * 12)) spdm = periodbase.stellingwerf_pdm(time, whitened_flux, err_flux, magsarefluxes=True, nworkers=8, startp=0.1, endp=0.2, stepsize=1e-4, autofreq=False) #the largest three flux points are visible outliers badfluxs = whitened_flux[np.argpartition(whitened_flux, -3)[-3:]] badinds = np.in1d(whitened_flux, badfluxs) okinds = ~badinds time = time[okinds] whitened_flux = whitened_flux[okinds] period = spdm['bestperiod'] t0 = np.nanmedian(time) outd = { 'time': time, 'flux': whitened_flux, 'period': period, 't0': t0 } with open(datapklfile, 'wb') as f: pickle.dump(outd, f, pickle.HIGHEST_PROTOCOL) print('dumped to {}'.format(datapklfile)) else: d = pickle.load(open(datapklfile, 'rb')) time = d['time'] whitened_flux = d['flux'] period = d['period'] t0 = d['t0'] plot_phase(time, whitened_flux, period, t0, axs[1, 1]) axs[1, 1].text(0.96, 0.06, 'P={:.2f}d'.format(period), transform=axs[1, 1].transAxes, ha='right', va='bottom') # TWEAK THINGS fig.text(0.5, 0, 'Phase', ha='center') fig.text(0, 0.5, 'Relative flux', va='center', rotation=90) fig.tight_layout(h_pad=0.1, w_pad=0.1) axs[0, 0].set_ylim((0.988, 1.001)) axs[0, 0].set_xlim((-0.7, 0.7)) axs[1, 0].set_ylim((0.970, 1.009)) axs[1, 0].set_xlim((-0.7, 0.7)) axs[0, 1].set_ylim((0.982, 1.018)) axs[0, 1].set_xlim((-1, 1)) axs[1, 1].set_ylim((0.93, 1.07)) axs[1, 1].set_xlim((-1, 1)) for ax in axs.flatten(): ax.yaxis.set_ticks_position('both') ax.xaxis.set_ticks_position('both') ax.get_yaxis().set_tick_params(which='both', direction='in') ax.get_xaxis().set_tick_params(which='both', direction='in') for tick in ax.xaxis.get_major_ticks(): tick.label.set_fontsize('small') for tick in ax.yaxis.get_major_ticks(): tick.label.set_fontsize('small') fig.tight_layout(h_pad=0.35, w_pad=0.85, pad=0.95) outpath = '../results/showoff_lightcurves/showoff_quadplot.png' fig.savefig(outpath, bbox_inches='tight', dpi=400) print('made {}'.format(outpath))
def test_checkplot_pickle_varepoch_handling(capsys): '''This tests the various different ways to give varepoch to checkplot_pickle. Uses the py.test capsys fixture to capture stdout and see if we reported the correct epoch being used. ''' outpath = os.path.join(os.path.dirname(LCPATH), 'test-checkplot.pkl') lcd, msg = hatlc.read_and_filter_sqlitecurve(LCPATH) gls = periodbase.pgen_lsp(lcd['rjd'], lcd['aep_000'], lcd['aie_000']) pdm = periodbase.stellingwerf_pdm(lcd['rjd'], lcd['aep_000'], lcd['aie_000']) assert isinstance(gls, dict) assert_allclose(gls['bestperiod'], 1.54289477) # 1. usual handling where epoch is None # should use min(times) as epoch all the time cpf = checkplot.checkplot_pickle( [gls, pdm], lcd['rjd'], lcd['aep_000'], lcd['aie_000'], outfile=outpath, objectinfo=lcd['objectinfo'], varepoch=None ) assert os.path.exists(outpath) # capture the stdout captured = capsys.readouterr() # see if we used the correct periods and epochs splitout = captured.out.split('\n') # plot output lines plotoutlines = [x for x in splitout if 'phased LC with period' in x] # these are the periods and epochs to match per line lookfor = ['gls phased LC with period 0: 1.542895, epoch: 56092.64056', 'gls phased LC with period 1: 0.771304, epoch: 56092.64056', 'gls phased LC with period 2: 0.514234, epoch: 56092.64056', 'pdm phased LC with period 0: 3.085790, epoch: 56092.64056', 'pdm phased LC with period 1: 1.542895, epoch: 56092.64056', 'pdm phased LC with period 2: 6.157824, epoch: 56092.64056'] for expected, plotline in zip(lookfor,plotoutlines): assert expected in plotline # 2. handle varepoch = 'min' cpf = checkplot.checkplot_pickle( [gls, pdm], lcd['rjd'], lcd['aep_000'], lcd['aie_000'], outfile=outpath, objectinfo=lcd['objectinfo'], varepoch='min' ) assert os.path.exists(outpath) # capture the stdout captured = capsys.readouterr() # see if we used the correct periods and epochs splitout = captured.out.split('\n') # plot output lines plotoutlines = [x for x in splitout if 'phased LC with period' in x] # these are the periods and epochs to match per line lookfor = ['gls phased LC with period 0: 1.542895, epoch: 56341.11968', 'gls phased LC with period 1: 0.771304, epoch: 56856.46618', 'gls phased LC with period 2: 0.514234, epoch: 56889.88470', 'pdm phased LC with period 0: 3.085790, epoch: 56828.62835', 'pdm phased LC with period 1: 1.542895, epoch: 56341.11968', 'pdm phased LC with period 2: 6.157824, epoch: 56154.33367'] for expected, plotline in zip(lookfor,plotoutlines): assert expected in plotline # 3. handle varepoch = some float cpf = checkplot.checkplot_pickle( [gls, pdm], lcd['rjd'], lcd['aep_000'], lcd['aie_000'], outfile=outpath, objectinfo=lcd['objectinfo'], varepoch=56000.5 ) assert os.path.exists(outpath) # capture the stdout captured = capsys.readouterr() # see if we used the correct periods and epochs splitout = captured.out.split('\n') # plot output lines plotoutlines = [x for x in splitout if 'phased LC with period' in x] # these are the periods and epochs to match per line lookfor = ['gls phased LC with period 0: 1.542895, epoch: 56000.50000', 'gls phased LC with period 1: 0.771304, epoch: 56000.50000', 'gls phased LC with period 2: 0.514234, epoch: 56000.50000', 'pdm phased LC with period 0: 3.085790, epoch: 56000.50000', 'pdm phased LC with period 1: 1.542895, epoch: 56000.50000', 'pdm phased LC with period 2: 6.157824, epoch: 56000.50000'] for expected, plotline in zip(lookfor,plotoutlines): assert expected in plotline # 4. handle varepoch = list of floats cpf = checkplot.checkplot_pickle( [gls, pdm], lcd['rjd'], lcd['aep_000'], lcd['aie_000'], outfile=outpath, objectinfo=lcd['objectinfo'], varepoch=[[56000.1,56000.2,56000.3], [56000.4,56000.5,56000.6]] ) assert os.path.exists(outpath) # capture the stdout captured = capsys.readouterr() # see if we used the correct periods and epochs splitout = captured.out.split('\n') # plot output lines plotoutlines = [x for x in splitout if 'phased LC with period' in x] # these are the periods and epochs to match per line lookfor = ['gls phased LC with period 0: 1.542895, epoch: 56000.10000', 'gls phased LC with period 1: 0.771304, epoch: 56000.20000', 'gls phased LC with period 2: 0.514234, epoch: 56000.30000', 'pdm phased LC with period 0: 3.085790, epoch: 56000.40000', 'pdm phased LC with period 1: 1.542895, epoch: 56000.50000', 'pdm phased LC with period 2: 6.157824, epoch: 56000.60000'] for expected, plotline in zip(lookfor,plotoutlines): assert expected in plotline
def _periodicity_analysis(hatid, times, mags, errs, normlcd, varperiod=None, isresidual=False): ''' Given times, magnitudes, and errors, run Phase Dispersion Minimization and Box Least Squares, then write the phase-folded LCs, periodograms, and header data to a checkplot pickle. Typically, in 03_EB_processing.py, mags will be (data+injected planet), or (data + injected planet - EB model). Args: hatid (str): HAT-XXX-XXXXXXX times (np.array): times of measurement (typically RJD) mags (np.array): measured magnitudes at observing times errs (np.array): measured error on mags normlcd: lightcurve dictionary from early reading / astrobase parsing Keyword Args: varperiod (float, default None): EB period, used to set upper and lower bounds of frequency search. isresidual (bool, default False): if `mags` is from residuals, use this. It will do a denser frequency search, at >~2x the EB period. Returns: nothing ''' #TODO: fix args, add docs if not varperiod: #injection has happened smallest_p = 0.5 cpwritepre = '../data/detachedEBs/injs/checkplot-inj-' elif isinstance(varperiod, float) and isresidual: smallest_p = varperiod * 2. + 0.1 cpwritepre = '../data/detachedEBs/injres/checkplot-injresiduals-' else: raise ValueError('smallest_p never properly assigned') biggest_p = min((times[-1] - times[0]) / 2.01, 100.) print('\nStellingwerf...\n') spdmp = periodbase.stellingwerf_pdm( times, mags, errs, autofreq=True, startp=smallest_p, endp=biggest_p, normalize=False, stepsize=1.0e-5, phasebinsize=0.03, mindetperbin=9, nbestpeaks=5, periodepsilon=0.1, # 0.1days sigclip=None, # no sigma clipping nworkers=None) varinfo = { 'objectisvar': True, 'vartags': None, 'varisperiodic': True, 'varperiod': spdmp['bestperiod'], 'varepoch': None } print('\nBLS...\n') blsp = periodbase.bls_parallel_pfind(times, mags, errs, startp=smallest_p, endp=biggest_p, stepsize=1.0e-5, mintransitduration=0.01, maxtransitduration=0.6, nphasebins=200, autofreq=False, nbestpeaks=5, periodepsilon=0.1, nworkers=None, sigclip=None) lspinfolist = [spdmp, blsp] cp = checkplot.checkplot_pickle(lspinfolist, times, mags, errs, nperiodstouse=3, objectinfo=normlcd['objectinfo'], varinfo=varinfo, findercmap='gray_r', normto='globalmedian', normmingap=4., outfile=cpwritepre + hatid + '.pkl.gz', sigclip=[10., -3.], varepoch='min', phasewrap=True, phasesort=True, phasebin=0.002, plotxlim=[-0.6, 0.6], plotdpi=150, returndict=False, pickleprotocol=3, greenhighlight=False, xgridlines=[-0.5, 0., 0.5]) #since we don't have easy checkplot_pickle to png written yet, use twolsp_checkplot_png #TODO: remove any png writing once happy with output if not varperiod: injpath = '../data/detachedEBs/plots/3_checkplot-inj-' elif isinstance(varperiod, float) and isresidual: injpath = '../data/detachedEBs/plots/5_checkplot-injresiduals-' else: raise ValueError('injpath never properly assigned') checkplot.twolsp_checkplot_png(spdmp, blsp, times, mags, errs, objectinfo=normlcd['objectinfo'], findercmap='gray_r', normto='globalmedian', normmingap=4., outfile=injpath + hatid + '.png', sigclip=[10., -3.], varepoch='min', phasewrap=True, phasesort=True, phasebin=0.002, plotxlim=[-0.6, 0.6], plotdpi=150) plt.close('all')
def periodicity_analysis(out, DSP_lim=None, field_id=None, DEBiL_write=False): ''' Given a specified field (e.g., G199), previous steps have created data/HATpipe/blsanalsums/cuts for that field and neighbors (imposing cuts on DSP_lim, Ntra_min, and NTV). They've also downloaded the appropriate LCs. Now rerun the periodicity analysis for these LCs (Box-Least-Squares and Stellingwerf Phase Dispersion Minimization), and make eb_checkplots for subsequent looking-at ("visual inspection"). Args: DEBiL_write (bool): whether to write a "name and best BLS period" file (in basically all use cases, not necessary). ''' assert type(field_id) == str print('\nBeginning periodicity analysis...\n\n') # File name format: HAT-199-0025234-V0-DR0-hatlc.sqlite.gz field_name = 'G' + field_id # e.g., 'G081' LC_read_path = '../data/LCs/' + field_name + '/' # where sqlitecurves already exist tail_str = '-V0-DR0-hatlc.sqlite.gz' # paths for LCs and EB checkplots LC_write_path = '../data/LCs_cut/' + field_name + '_' + str(DSP_lim) CP_write_path = '../data/CPs_cut/' + field_name + '_' + str(DSP_lim) for outpath in [ LC_write_path, LC_write_path + '/periodcut', LC_write_path + '/onedaycut', LC_write_path + '/shortcoveragecut', CP_write_path, CP_write_path + '/periodcut', CP_write_path + '/onedaycut', CP_write_path + '/shortcoveragecut' ]: if not os.path.isdir(outpath): os.makedirs(outpath) for ix, hatid in enumerate(out.index): if np.all(out.ix[hatid]['has_sqlc']): LC_cut_path = LC_write_path + '/' + hatid + tail_str LC_periodcut_path = LC_write_path + '/periodcut/' + hatid + tail_str LC_onedaycut_path = LC_write_path + '/onedaycut/' + hatid + tail_str LC_shortcoveragecut_path = LC_write_path + '/shortcoveragecut/' + hatid + tail_str CP_cut_path = CP_write_path + '/' + hatid + '.png' CP_periodcut_path = CP_write_path + '/periodcut/' + hatid + '.png' CP_onedaycut_path = CP_write_path + '/onedaycut/' + hatid + '.png' CP_shortcoveragecut_path = CP_write_path + '/shortcoveragecut/' + hatid + '.png' if (not os.path.exists(CP_cut_path)) \ and (not os.path.exists(CP_periodcut_path)) \ and (not os.path.exists(CP_onedaycut_path)) \ and (not os.path.exists(CP_shortcoveragecut_path)): # Get sqlitecurve data. obj_path = LC_read_path + hatid + tail_str lcd, msg = hatlc.read_and_filter_sqlitecurve(obj_path) # Make sure all observations are at the same zero-point. normlcd = hatlc.normalize_lcdict(lcd) # Select recommended EPD aperture with 'G' flag. (Alternate # approach: take the smallest aperture to minimize crowding). ap = next(iter(lcd['lcbestaperture']['ap'])) times = normlcd['rjd'][normlcd['aiq_' + ap] == 'G'] mags = normlcd['aep_' + ap][normlcd['aiq_' + ap] == 'G'] errs = normlcd['aie_' + ap][normlcd['aiq_' + ap] == 'G'] # Period analysis: Stellingwerf phase dispersion minimization # and rerun Box-Least-Squares. Range of interesting periods: # 0.5days-100days. BLS can only search for periods < half the # light curve observing baseline. (N.b. 100d signals are # basically always going to be stellar rotation) smallest_p = 0.5 biggest_p = min((times[-1] - times[0]) / 2.01, 100.) print('\nStellingwerf...\n') spdmp = periodbase.stellingwerf_pdm( times, mags, errs, autofreq=True, startp=smallest_p, endp=biggest_p, normalize=False, stepsize=1.0e-4, phasebinsize=0.05, mindetperbin=9, nbestpeaks=5, periodepsilon=0.1, # 0.1days sigclip=None, # no sigma clipping nworkers=None) print('\nBLS...\n') blsp = periodbase.bls_parallel_pfind( times, mags, errs, startp=smallest_p, endp=biggest_p, # don't search full timebase stepsize=1.0e-5, mintransitduration=0.01, # minimum transit length in phase maxtransitduration=0.7, # maximum transit length in phase nphasebins=200, autofreq=False, # figure out f0, nf, and df automatically nbestpeaks=5, periodepsilon=0.1, # 0.1 nworkers=None, sigclip=None) # Make and save checkplot to be looked at. cp = plotbase.make_eb_checkplot( spdmp, blsp, times, mags, errs, objectinfo=normlcd['objectinfo'], findercmap='gray_r', normto='globalmedian', normmingap=4.0, outfile=CP_cut_path, sigclip=None, varepoch='min', phasewrap=True, phasesort=True, phasebin=0.002, plotxlim=[-0.6, 0.6]) # Copy LCs with DSP>DSP_lim to /data/LCs_cut/G???_??/ if not os.path.exists(LC_cut_path): copyfile(obj_path, LC_cut_path) print('Copying {} -> {}\n'.format(obj_path, LC_cut_path)) #### CUTS #### maxperiod = 30. # days bestperiods = spdmp['nbestperiods'] + blsp['nbestperiods'] best3periods = spdmp['nbestperiods'][:3]+\ blsp['nbestperiods'][:3] bparr, b3parr = np.array(bestperiods), np.array(best3periods) minperiod = 0.5002 # days; else this harmonic of 1d happens proxto1d_s, proxto1d_m, proxto1d_b = 0.01, 0.015, 0.02 # days bestbls, bestspdm = blsp['bestperiod'], spdmp['bestperiod'] mindayscoverage = 3. cadence = 4. # minutes minnumpoints = mindayscoverage * 24 * 60 / cadence # (If 5 of the 6 best peaks are above max period (30 days)), OR # (If all of the SPDM peaks are above max period and the BLS # peaks are not, and all the BLS peaks less than the max period # are within 0.1days separate from e/other) OR # (The same, with BLS/SPDM switched), OR # (The difference between all SPDM is <0.1day and the # difference between all BLS is <0.1day) # # [n.b. latter broad-peak behavior happens b/c of stellar rotn] sb3parr = np.sort(b3parr) spdmn = np.array(spdmp['nbestperiods'][:3]) blsn = np.array(blsp['nbestperiods'][:3]) ps = 0.2 # peak_separation, days b3pint = b3parr[(b3parr < maxperiod) & ( b3parr > 2 * minperiod)] # interesting periods if npall(sb3parr[1:] > maxperiod) \ or \ ((npall(spdmn>maxperiod) and not npall(blsn>maxperiod)) and npall(abs(npdiff(blsn[blsn<maxperiod]))<ps)) \ or \ ((npall(blsn>maxperiod) and not npall(spdmn>maxperiod)) and npall(abs(npdiff(spdmn[spdmn<maxperiod]))<ps)) \ or \ (npall(abs(npdiff(spdmn))<ps) and npall(abs(npdiff(blsn))<ps)): os.rename(LC_cut_path, LC_periodcut_path) os.rename(CP_cut_path, CP_periodcut_path) # All 6 best peaks below max period (and above 1d) are within # 0.02days of a multiple of 1, OR # Both the BLS and SPDM max peak are within 0.015d of a # multiple of 1, OR # At least one of the best BLS&SPDM peaks are within 0.015d of one, # and of the remaining peaks > 1day, the rest are within 0.03days of # multiples of one. elif (npall(npisclose(npminimum(\ b3pint%1., abs((b3pint%1.)-1.)), 0., atol=proxto1d_b)))\ or \ ((npisclose(npminimum(\ bestbls%1., abs((bestbls%1.)-1.)), 0., atol=proxto1d_m)) and (npisclose(npminimum(\ bestspdm%1., abs((bestspdm%1.)-1.)), 0., atol=proxto1d_m)))\ or \ (\ (npisclose(abs(bestbls-1.), 0., atol=proxto1d_m) or npisclose(abs(bestspdm-1.), 0., atol=proxto1d_m)) and (npall(npisclose(npminimum(\ b3pint%1., abs((b3pint%1.)-1.)), 0., atol=proxto1d_m*2.)))\ ): os.rename(LC_cut_path, LC_onedaycut_path) os.rename(CP_cut_path, CP_onedaycut_path) # If there is not enough coverage. "Enough" means 3 days of # observations (at 4 minute cadence). elif len(mags) < minnumpoints: os.rename(LC_cut_path, LC_shortcoveragecut_path) os.rename(CP_cut_path, CP_shortcoveragecut_path) else: print('{:d}: {:s} or LC counterpart exists; continue.'.\ format(ix, CP_cut_path)) continue print('\nDone with periodicity analysis for {:s}.\n\n'.format(field_name)) if DEBiL_write: # Write DEBiL "input list" of HAT-IDs and periods. write_path = '../data/DEBiL_heads/' + field + '_DSP' + str( DSP_lim) + '.txt' if not os.path.exists(write_path): f_id = open(write_path, 'wb+') data = np.array([out.index, out['PERIOD']]) np.savetxt(f_id, data.T, fmt=['%15s', '%.6f']) f_id.close()