def main(inf, outf, config): with open(inf, "r", newline="") as f: cadns, times, fluxs = utils.csv_column_read(f, FIELDS, casts=CASTS, start=config.start, end=config.end) # Do the thing. times, fluxs = highpass(times, fluxs, config) utils.csv_column_write(outf, [cadns, times, fluxs], FIELDS)
def main(inf, outf, config): with open(inf, "r", newline="") as inf: cadns, times, fluxs = utils.csv_column_read(inf, FIELDS, start=config.start, end=config.end, casts=CASTS) # Decorrelate flux. fluxs, _ = decorrelate_data(config.tp, times, fluxs) utils.csv_column_write(outf, [cadns, times, fluxs], FIELDS)
def plot_fft(fig, config): CASTS = [float, float] FIELDS = ["frequency", config.pgtype] # Iterate over all inputs. nfiles = len(config.ifiles) for i, ifile in enumerate(config.ifiles): # Get the periodogram information. with open(ifile, "r", newline="") as f: fx, fy = utils.csv_column_read(f, FIELDS, casts=CASTS) # Create a latex axis. ax = utils.latexify(fig.add_subplot("%d%d%d" % (nfiles, 1, i + 1))) # Plot the periodogram. ax.plot(fx, fy, color="k", linestyle="-", marker="None") ax.set_axisbelow(True) ax.set_xlabel("Frequency ($\mu$Hz)") # Make sure the axis names are correct. if config.pgtype == "amplitude": ax.set_ylabel("Amplitude (ppm)") elif config.pgtype == "psd": ax.set_ylabel("PSD (ppm$^2$ $\mu$Hz$^{-1}$)") if config.maxx > config.minx >= 0: ax.set_xlim([config.minx, config.maxx]) if config.maxy > config.miny >= 0: ax.set_ylim([config.miny, config.maxy]) plt.legend() fig.tight_layout()
def main(inf, outf, config): with open(inf, "r", newline="") as inf: cadns, times, fluxs = utils.csv_column_read(inf, FIELDS, start=config.start, end=config.end, casts=CASTS) # To PPM. fluxs = (fluxs / fluxs.mean() - 1) * 1e6 utils.csv_column_write(outf, [cadns, times, fluxs], FIELDS)
def main(inf, outf, config): with open(inf, "r", newline="") as f: times, fluxs = utils.csv_column_read(f, FIELDS, casts=CASTS, start=config.start, end=config.end) fx, fy = utils.lombscargle_amplitude(times, fluxs, mult=config.mult, upper=config.upper) # Output the FFT. utils.csv_column_write(outf, [fx, fy], ["frequency", "amplitude"])
def main(inf, outf, config): with open(inf, "r", newline="") as inf: cadns, times, fluxs = utils.csv_column_read(inf, FIELDS, start=config.start, end=config.end, casts=CASTS) # Remove outliers. filt = reject_outliers(times, fluxs, config) cadns = cadns[filt] times = times[filt] fluxs = fluxs[filt] utils.csv_column_write(outf, [cadns, times, fluxs], FIELDS)
def main(inf, outf, config): FIELDS = ["frequency", "amplitude"] CASTS = [float, float] with open(inf, "r", newline="") as f: fx, fy = utils.csv_column_read(f, FIELDS, casts=CASTS) # Do the thing. fx, fy = utils.raw_to_psd(fx, fy, config.variance) # Output the PSD. FIELDS[1] = "psd" utils.csv_column_write(outf, [fx, fy], FIELDS)
def plot_echelle(config, fig, ifile): CASTS = [float, float] FIELDS = ["frequency", config.pgtype] if config.deltanu is None: raise NotImplementedError("∆𝜈 autocorrelation not implemented") # Get the cadence information. with open(ifile, "r", newline="") as f: fx, fy = utils.csv_column_read(f, FIELDS, casts=CASTS) # Filter start and end. filt = numpy.ones_like(fx, dtype=bool) if config.start is not None: filt &= fx >= config.start * config.deltanu if config.end is not None: filt &= fx <= (config.end + 1) * config.deltanu fx = fx[filt] fy = fy[filt] # Convert from power to amplitude. if config.pgtype == "psd": pass #fy *= numpy.diff(fx).mean() #fy **= 0.5 #pass # Convert to wrapped echelle. fx += config.off fx %= config.deltanu # Sort the arrays. sfilt = numpy.argsort(fx) fx = fx[sfilt] fy = fy[sfilt] # Smooth using a Savgol filter. #itp = scipy.interpolate.interp1d(fx, fy, kind='linear') #fy = scipy.signal.savgol_filter(itp(fx), config.width, 6) win = scipy.signal.boxcar(config.width) fy = scipy.signal.convolve(fy, win, mode="same") # Plot. ax = utils.latexify(fig.add_subplot(111)) ax.plot(fx, fy, color="r") ax.set_ylabel("PSD (ppm$^2$$\mu$Hz$^{-1}$)") ax.set_xlabel("Frequency mod %s ($\mu$Hz)" % (config.deltanu,)) plt.legend() fig.tight_layout()
def main(files, outf, config): TIME = [] FLUX = [] # We split the filename into <fname>[:<start>:<end>]. for fname in files: start = 0 end = -1 # Allow slices in fnames. if ":" in fname: fname, start, end = fname.split(":") # Float. start = float(start) end = float(end) # Open file. with open(fname, "r", newline="") as f: times, fluxs = utils.csv_column_read(f, FIELDS, casts=CASTS) # Times. offset = times - times.min() # Allow negative slices. if end < 0: end = offset.max() + (end + 1) # Filter. filt = (start <= offset) & (offset <= end) times = times[filt] fluxs = fluxs[filt] # Append. TIME = numpy.append(TIME, times) FLUX = numpy.append(FLUX, fluxs) # Fake the cadence numbers. CADN = numpy.arange(TIME.shape[0]) + 1 # We need to sort by the time. This is a bit of a pain, because the operation # of "sorting rows" isn't a thing in numpy. We need to switch out to Python # lists. tosort = numpy.array([TIME, FLUX]).T tosort = sorted(list(tosort), key=lambda arr: arr[0]) TIME, FLUX = numpy.array(tosort).T utils.csv_column_write(outf, [CADN, TIME, FLUX], ["cadence"] + FIELDS)
def main(inf, outf, config): with open(inf, "r", newline="") as f: cadns, times, fluxs = utils.csv_column_read(f, FIELDS, casts=CASTS, start=config.start, end=config.end) diffs = numpy.diff(times).copy() assert(numpy.all(diffs >= 0)) for idx, gap in zip(*numpy.where(diffs > config.width), diffs[diffs > config.width]): # We only remove the gap to the scale of the median. gap -= gap % numpy.median(diffs) # Remove the gap. This isn't a concurrent modification because the diffs aren't views. times[idx+1:] -= gap # Output the FFT. utils.csv_column_write(outf, [cadns, times, fluxs], FIELDS)
def main(files, outf, config): # Cadences. cadns = [] times = [] fluxs = [] for fname in files: with open(fname, "r", newline="") as f: # Get CSV. _cadn, _time, _flux = utils.csv_column_read(f, FIELDS, casts=CASTS, start=config.start, end=config.end) # Convert to numpy arrays. cadns.append(_cadn) times.append(_time) fluxs.append(_flux) # Get unique set. inter = cadns[0] for cadn in cadns[1:]: inter = np.intersect1d(inter, cadn) # Filter out each array. for i, cadn in enumerate(cadns): filt = np.in1d(cadn, inter) cadns[i] = cadns[i][filt] times[i] = times[i][filt] fluxs[i] = fluxs[i][filt] # Convert filtered version to arrays (now everything is the same shape). cadns = np.median(cadns, axis=0) times = np.median(times, axis=0) fluxs = np.array(fluxs, dtype=float) # Combine the flux values. fluxs = config.reduce(fluxs) utils.csv_column_write(outf, [cadns, times, fluxs], FIELDS)
def plot_echelle(config, fig, ifile): CASTS = [float, float] FIELDS = ["frequency", config.pgtype] if config.deltanu is None: raise NotImplementedError("∆𝜈 autocorrelation not implemented") # Get the cadence information. with open(ifile, "r", newline="") as f: fx, fy = utils.csv_column_read(f, FIELDS, casts=CASTS) # Filter start and end. filt = numpy.ones_like(fx, dtype=bool) if config.start is not None: filt &= fx >= config.start * config.deltanu if config.end is not None: filt &= fx <= (config.end + 1) * config.deltanu fx = fx[filt] fy = fy[filt] # Convert from power to amplitude. if config.pgtype == "psd": pass #fy *= numpy.diff(fx).mean() #fy **= 0.5 # First we bin the transform. width = config.smoothwidth bins = int(fx.ptp() // width) newfy = numpy.zeros(bins) for i in range(bins): rnge = (i*width <= fx) & (fx < (i+1)*width) newfy[i] = fy[rnge].sum() fy = newfy fx = numpy.linspace(fx.min(), fx.max(), bins) # Then we compute the grid sizes. delta = numpy.diff(fx).mean() rows = int(fx.ptp() // config.deltanu) cols = int(config.deltanu // delta) # Fill in the grid from the binned data. grid = numpy.zeros([rows, cols]) for y, _ in enumerate(grid): grid[y,...] = fy[y*cols:(y+1)*cols] ax = utils.latexify(fig.add_subplot(111)) #ax.imshow(-grid, cmap="gray", interpolation="nearest", origin="bottom") #ax.imshow(grid, cmap="viridis", interpolation="nearest", origin="bottom") ax.pcolormesh(grid, cmap="viridis") #ax.pcolormesh(-grid, cmap="gray") #ax.xaxis.set_ticks(numpy.arange) ax.xaxis.set_ticks ax.set_xlim([0, config.deltanu]) ax.xaxis.set_ticks(numpy.arange(*ax.get_xlim(), step=20)) ax.xaxis.set_ticks(numpy.arange(*ax.get_xlim(), step=5), minor=True) ax.set_ylim([config.start, config.end-config.start]) ax.yaxis.set_ticks(numpy.arange(*ax.get_ylim(), step=1)+1) #ax.yaxis.set_ticks(numpy.arange(*ax.get_ylim(), step=0.25), minor=True) #ax.set_ylabel("Frequency ($\mu$Hz)") ax.set_ylabel("Mode Order") ax.set_xlabel("Frequency mod %s ($\mu$Hz)" % (config.deltanu,)) plt.legend() fig.tight_layout()
def main(inf, outf, config): with open(inf, "r", newline="") as f: times, fluxs = utils.csv_column_read(f, FIELDS, casts=CASTS, start=config.start, end=config.end) # Output the variance. print(fluxs.var(), file=outf)
def plot_lc(config, fig, ifile): # Get the cadence information. with open(ifile, "r", newline="") as f: times, fluxs = utils.csv_column_read(f, FIELDS, casts=CASTS, start=config.start, end=config.end) # Times and fluxes. xs = times ys = fluxs # Convert flux to ppm. #ys = ys / ys.mean() - 1 #ys *= 1e6 # Figure out time-related offsets. offset = np.min(times) xs -= offset if config.timestamp is not None: config.timestamp -= offset if config.fft: fx, fy = utils.lombscargle_amplitude(xs, ys, upper=config.high_freq) if config.fftout: with open(config.fftout, "w", newline="") as f: utils.csv_column_write(f, [fx, fy], ["frequency", "amplitude"]) fx, fy = utils.raw_to_psd(fx, fy, fluxs.var()) if config.lc: if config.period is not None: # TODO: We should allow for showing more than one phase. xs = (xs % config.period) / config.period xs = (xs + config.phase) % 1.0 # Bin the folded phase plot by taking the average of ranges. if config.bins is not None: size = 1.0 / config.bins nys = np.zeros(config.bins) for i in range(config.bins): rnge = (i*size <= xs) & (xs < (i+1)*size) nys[i] = np.median(ys[rnge]) ys = nys xs = np.arange(config.bins) * size # Replication. xs = np.tile(xs, config.width) + np.repeat(np.arange(config.width), xs.shape[0]) ys = np.tile(ys, config.width) if config.fft and config.lc: ax1 = utils.latexify(fig.add_subplot(211)) else: ax1 = utils.latexify(fig.add_subplot(111)) if config.lc: if not (config.period or config.bins): ax1.plot(xs, ys, color="0.5", linestyle="-", marker="None") #ax1.plot(xs, ys, color="k", linestyle="None", marker="+", label=r"Kepler/K2 Halo Photometry") ax1.set_xlabel("Time ($d$)") else: # TODO: We should overlay a binned version. if config.timestamp is not None: predicted = (config.timestamp % config.period) / config.period predicted = (predicted + config.phase) % 1.0 ax1.xaxis.set_ticks(predicted + np.arange(config.width), minor=True) ax1.xaxis.grid(True, which="minor", color="r", linestyle="--", linewidth=2) ax1.plot(xs, ys, color="0.5", linestyle="None", marker="o", label=r"Kepler/K2 Halo Photometry") ax1.set_xlabel("Phase") ax1.set_ylabel(r"Intensity (ppm)") if config.lc and config.title: ax1.set_title(r"Light Curve [%s] # %s" % (description(config), config.comment or "")) if config.fft: if config.lc: ax2 = utils.latexify(fig.add_subplot(212)) else: ax2 = ax1 ax2.plot(fx, fy, color="k", linestyle="-", marker="None") #ax2.xaxis.set_ticks(np.arange(*ax2.get_xlim(), step=1)) #ax2.xaxis.set_ticks(np.arange(*ax2.get_xlim(), step=0.25), minor=True) #ax2.xaxis.grid(True, which="major", color="k", linestyle="--") #ax2.xaxis.grid(True, which="minor", color="k", linestyle=":") ax2.set_axisbelow(True) #ax2.set_xlabel("Frequency ($d^{-1}$)") ax2.set_xlabel("Frequency ($\mu$Hz)") #ax2.set_ylabel("Amplitude (ppm)") ax2.set_ylabel("PDF (ppm$^2$ $\mu$Hz$^{-1}$)") if config.maxx > config.minx: ax2.set_xlim([config.minx, config.maxx]) if config.maxy > config.miny: ax2.set_ylim([config.miny, config.maxy]) plt.legend() fig.tight_layout()