Source code for simppler.utils

from __future__ import annotations

import numpy as np
from numpy.typing import ArrayLike


[docs] def time_to_phase( p: dict, t: ArrayLike, planet: int, double: bool = False ) -> np.ndarray: """Convert time to phase :param p: Dictionary mapping parameter names to values. Must contain a period ``per{planet}`` and time of conjunction ``tc{planet}``. :param t: Array of times :param planet: Integer index of the planet (base 1) :param double: Wehther the phase array should be doubled. Useful for plotting. """ per = p[f"per{planet}"] t0 = p[f"tc{planet}"] t = np.array(t) phase = (t - t0) % per / per if double: phase = np.concatenate([phase, phase + 1]) return phase
[docs] def bin_data( t: np.ndarray, rv: np.ndarray, erv: np.ndarray, nbins: int = 30 ) -> tuple[np.ndarray]: """Bin RV data The data is binned using a weighted average. Bins with less than 3 points are discarded. :param t: Times :param rv: RVs :param erv: RV uncertainties :param nbins: Number of bins to use """ # Compute bins n, bins = np.histogram(t, bins=nbins) bin_inds = np.digitize(t, bins) bin_centers = (bins[:-1] + bins[1:]) / 2 bin_means = np.array( [ np.average(rv[bin_inds == i], weights=1 / erv[bin_inds == i] ** 2) if np.any(bin_inds == i) else np.nan for i in range(1, nbins + 1) ] ) bin_stds = np.array( [ np.sqrt(1 / np.sum(1 / erv[bin_inds == i] ** 2)) if np.any(bin_inds == i) else np.nan for i in range(1, nbins + 1) ] ) # Discard bins with less than 3 pts nmask = n >= 3 bin_centers = bin_centers[nmask] bin_means = bin_means[nmask] bin_stds = bin_stds[nmask] return bin_centers, bin_means, bin_stds
[docs] def timeperi_to_timetrans(tp, per, ecc, omega, secondary=False): """ Convert Time of Periastron to Time of Transit Copied from RadVel (https://github.com/California-Planet-Search/radvel/blob/master/radvel/orbit.py) License: https://github.com/California-Planet-Search/radvel/blob/master/LICENSE Args: tp (float): time of periastron per (float): period [days] ecc (float): eccentricity omega (float): argument of peri (radians) secondary (bool): calculate time of secondary eclipse instead Returns: float: time of inferior conjunction (time of transit if system is transiting) """ try: if ecc >= 1: return tp except ValueError: pass if secondary: f = 3 * np.pi / 2 - omega # true anomaly during secondary eclipse ee = 2 * np.arctan( np.tan(f / 2) * np.sqrt((1 - ecc) / (1 + ecc)) ) # eccentric anomaly # ensure that ee is between 0 and 2*pi (always the eclipse AFTER tp) if isinstance(ee, np.float64): ee = ee + 2 * np.pi else: ee[ee < 0.0] = ee + 2 * np.pi else: f = np.pi / 2 - omega # true anomaly during transit ee = 2 * np.arctan( np.tan(f / 2) * np.sqrt((1 - ecc) / (1 + ecc)) ) # eccentric anomaly tc = tp + per / (2 * np.pi) * (ee - ecc * np.sin(ee)) # time of conjunction return tc
[docs] def timetrans_to_timeperi(tc, per, ecc, omega): """ Convert Time of Transit to Time of Periastron Passage Copied from RadVel (https://github.com/California-Planet-Search/radvel/blob/master/radvel/orbit.py) License: https://github.com/California-Planet-Search/radvel/blob/master/LICENSE Args: tc (float): time of transit per (float): period [days] ecc (float): eccentricity omega (float): longitude of periastron (radians) Returns: float: time of periastron passage """ try: if ecc >= 1: return tc except ValueError: pass f = np.pi / 2 - omega ee = 2 * np.arctan( np.tan(f / 2) * np.sqrt((1 - ecc) / (1 + ecc)) ) # eccentric anomaly tp = tc - per / (2 * np.pi) * (ee - ecc * np.sin(ee)) # time of periastron return tp