def process_light_curve(all_time, all_flux): """Removes low-frequency variability from a light curve. Args: all_time: A list of numpy arrays; the time values of the raw light curve. all_flux: A list of numpy arrays corresponding to the time arrays in all_time. Returns: time: 1D NumPy array; the time values of the light curve. flux: 1D NumPy array; the normalized flux values of the light curve. """ # Split on gaps. all_time, all_flux = util.split(all_time, all_flux, gap_width=0.75) # Fit a piecewise-cubic spline with default arguments. spline = kepler_spline.fit_kepler_spline(all_time, all_flux, verbose=False)[0] # Concatenate the piecewise light curve and spline. time = np.concatenate(all_time) flux = np.concatenate(all_flux) spline = np.concatenate(spline) # In rare cases the piecewise spline contains NaNs in places the spline could # not be fit. We can't normalize those points if the spline isn't defined # there. Instead we just remove them. finite_i = np.isfinite(spline) if not np.all(finite_i): time = time[finite_i] flux = flux[finite_i] spline = spline[finite_i] # "Flatten" the light curve (remove low-frequency variability) by dividing by # the spline. flux /= spline return time, flux
def process(self, inputs): """Processes a single light curve.""" raw_lc = inputs["raw_light_curve"] all_time = [ np.array(s.time, dtype=np.float64) for s in raw_lc.segments ] all_flux = [ np.array(s.flux, dtype=np.float64) for s in raw_lc.segments ] length_raw = sum([len(t) for t in all_time]) # Remove events. events_to_remove = inputs.pop("events_to_remove", []) if events_to_remove: all_time, all_flux = util.remove_events( all_time, all_flux, events_to_remove, width_factor=self.remove_events_width_factor, include_empty_segments=False) if not all_time: return # Removed entire light curve. # Split on gaps. all_time, all_flux = util.split(all_time, all_flux, gap_width=self.gap_width) # Mask events. events_to_mask = inputs.pop("events_to_mask_for_spline", []) if events_to_mask: all_masked_time, all_masked_flux = util.remove_events( all_time, all_flux, events=events_to_mask, width_factor=self.remove_events_width_factor) else: all_masked_time = all_time all_masked_flux = all_flux # Fit normalization curve. if self.normalize_method == "spline": all_spline, metadata = kepler_spline.fit_kepler_spline( all_masked_time, all_masked_flux, **self.normalize_args) else: raise ValueError("Unrecognized normalize_method: {}".format( self.normalize_method)) # Interpolate the spline between the events removed. if events_to_mask: all_spline = util.interpolate_masked_spline( all_time, all_masked_time, all_spline) # Concatenate the results. time = np.concatenate(all_time) flux = np.concatenate(all_flux) norm_curve = np.concatenate(all_spline) # Initialize the output. light_curve = light_curve_pb2.LightCurve( length_raw=length_raw, spline_metadata=light_curve_pb2.SplineMetadata( bkspace=metadata.bkspace, bad_bkspaces=metadata.bad_bkspaces, likelihood_term=metadata.likelihood_term, penalty_term=metadata.penalty_term, bic=metadata.bic, masked_events=events_to_mask, **self.normalize_args), removed_events=events_to_remove) # If the normalization curve contains NaNs, we can't normalize those places. is_finite = np.isfinite(norm_curve) is_not_finite = np.logical_not(is_finite) if np.any(is_not_finite): light_curve.norm_curve_failures.time[:] = time[is_not_finite] light_curve.norm_curve_failures.flux[:] = flux[is_not_finite] time = time[is_finite] flux = flux[is_finite] norm_curve = norm_curve[is_finite] # Possibly remove outliers. if self.upward_outlier_sigma_cut or self.downward_outlier_sigma_cut: norm_flux = flux / norm_curve # We compute outliers on normalized flux. deviation = norm_flux - np.median(norm_flux) if self.upward_outlier_sigma_cut: is_upward_outlier = np.logical_not( robust_mean.robust_mean( deviation, cut=self.upward_outlier_sigma_cut)[2]) np.logical_and(is_upward_outlier, deviation > 0, out=is_upward_outlier) else: is_upward_outlier = np.zeros_like(deviation, dtype=np.bool) if self.downward_outlier_sigma_cut: is_downward_outlier = np.logical_not( robust_mean.robust_mean( deviation, cut=self.downward_outlier_sigma_cut)[2]) np.logical_and(is_downward_outlier, deviation < 0, out=is_downward_outlier) else: is_downward_outlier = np.zeros_like(deviation, dtype=np.bool) is_outlier = np.logical_or(is_upward_outlier, is_downward_outlier) is_not_outlier = np.logical_not(is_outlier) if np.any(is_outlier): light_curve.outliers_removed.time[:] = time[is_outlier] light_curve.outliers_removed.flux[:] = flux[is_outlier] light_curve.outliers_removed.norm_curve[:] = norm_curve[ is_outlier] time = time[is_not_outlier] flux = flux[is_not_outlier] norm_curve = norm_curve[is_not_outlier] # Fill the output. light_curve.light_curve.time[:] = time light_curve.light_curve.flux[:] = flux light_curve.light_curve.norm_curve[:] = norm_curve inputs[self.output_name] = light_curve yield inputs