def get_celerite_matrices(self, x, diag, **kwargs): x = tt.as_tensor_variable(x) diag = tt.as_tensor_variable(diag) ar, cr, ac, bc, cc, dc = self.coefficients a = diag + tt.sum(ar) + tt.sum(ac) arg = dc[None, :] * x[:, None] cos = tt.cos(arg) sin = tt.sin(arg) z = tt.zeros_like(x) U = tt.concatenate( ( ar[None, :] + z[:, None], ac[None, :] * cos + bc[None, :] * sin, ac[None, :] * sin - bc[None, :] * cos, ), axis=1, ) V = tt.concatenate( (tt.ones_like(ar)[None, :] + z[:, None], cos, sin), axis=1, ) c = tt.concatenate((cr, cc, cc)) return c, a, U, V
def __init__(self, min_radius, max_radius): self.min_radius = tt.as_tensor_variable(min_radius) self.max_radius = tt.as_tensor_variable(max_radius) # Compute Ar from Espinoza self.dr = self.max_radius - self.min_radius denom = 2 + self.min_radius + self.max_radius self.Ar = self.dr / denom
def test_get_aor_from_transit_duration(): duration = 0.12 period = 10.1235 b = 0.34 ror = 0.06 r_star = 0.7 dv = tt.as_tensor_variable(duration) aor, jac = get_aor_from_transit_duration(dv, period, b, ror) assert np.allclose(theano.grad(aor, dv).eval(), jac.eval()) for orbit in [ KeplerianOrbit(period=period, t0=0.0, b=b, a=r_star * aor, r_star=r_star), KeplerianOrbit( period=period, t0=0.0, b=b, duration=duration, r_star=r_star, ror=ror, ), ]: x, y, z = orbit.get_planet_position(0.5 * duration) assert np.allclose(tt.sqrt(x**2 + y**2).eval(), r_star * (1 + ror)) x, y, z = orbit.get_planet_position(-0.5 * duration) assert np.allclose(tt.sqrt(x**2 + y**2).eval(), r_star * (1 + ror)) x, y, z = orbit.get_planet_position(period + 0.5 * duration) assert np.allclose(tt.sqrt(x**2 + y**2).eval(), r_star * (1 + ror))
def dot(self, x, diag, y): x = tt.as_tensor_variable(x) y = tt.as_tensor_variable(y) is_vector = False if y.ndim == 1: is_vector = True y = y[:, None] if y.ndim != 2: raise ValueError("'y' can only be a vector or matrix") c, a, U, V = self.get_celerite_matrices(x, diag) z = y * a[:, None] z += ops.matmul_lower(x, c, U, V, y)[0] z += ops.matmul_upper(x, c, U, V, y)[0] if is_vector: return z[:, 0] return z
def test_jacobians(): duration = 0.12 period = 10.1235 b = 0.34 ror = 0.06 r_star = 0.7 dv = tt.as_tensor_variable(duration) orbit = KeplerianOrbit(period=period, t0=0.0, b=b, duration=dv, r_star=r_star, ror=ror) assert np.allclose( orbit.jacobians["duration"]["a"].eval(), theano.grad(orbit.a, dv).eval(), ) assert np.allclose( orbit.jacobians["duration"]["a_planet"].eval(), theano.grad(orbit.a_planet, dv).eval(), ) assert np.allclose( orbit.jacobians["duration"]["a_star"].eval(), theano.grad(orbit.a_star, dv).eval(), ) assert np.allclose( orbit.jacobians["duration"]["rho_star"].eval(), theano.grad(orbit.rho_star, dv).eval(), ) bv = tt.as_tensor_variable(b) orbit = KeplerianOrbit(period=period, t0=0.0, b=bv, a=orbit.a, r_star=r_star, ror=ror) assert np.allclose( orbit.jacobians["b"]["cos_incl"].eval(), theano.grad(orbit.cos_incl, bv).eval(), )
def __init__(self, *, sigma, period, Q0, dQ, f, **kwargs): self.sigma = tt.as_tensor_variable(sigma).astype("float64") self.period = tt.as_tensor_variable(period).astype("float64") self.Q0 = tt.as_tensor_variable(Q0).astype("float64") self.dQ = tt.as_tensor_variable(dQ).astype("float64") self.f = tt.as_tensor_variable(f).astype("float64") self.amp = self.sigma ** 2 / (1 + self.f) # One term with a period of period Q1 = 0.5 + self.Q0 + self.dQ w1 = 4 * np.pi * Q1 / (self.period * tt.sqrt(4 * Q1 ** 2 - 1)) S1 = self.amp / (w1 * Q1) # Another term at half the period Q2 = 0.5 + self.Q0 w2 = 8 * np.pi * Q2 / (self.period * tt.sqrt(4 * Q2 ** 2 - 1)) S2 = self.f * self.amp / (w2 * Q2) super().__init__( SHOTerm(S0=S1, w0=w1, Q=Q1), SHOTerm(S0=S2, w0=w2, Q=Q2), **kwargs )
def test_approx_transit_depth(): u = np.array([0.3, 0.2]) lc = LimbDarkLightCurve(u[0], u[1]) for b, delta in [ (np.float64(0.5), np.float64(0.01)), (np.array([0.1, 0.9]), np.array([0.1, 0.5])), (np.array([0.1, 0.9, 0.3]), np.array([0.1, 0.5, 0.0234])), ]: dv = tt.as_tensor_variable(delta) ror, jac = lc.get_ror_from_approx_transit_depth(dv, b, jac=True) _check_quad(u, b, delta, ror.eval()) assert np.allclose(theano.grad(tt.sum(ror), dv).eval(), jac.eval())
class SHOTerm(Term): __doc__ = base_terms.SHOTerm.__doc__ __parameter_spec__ = base_terms.SHOTerm.__parameter_spec__ @base_terms.handle_parameter_spec( lambda x: tt.as_tensor_variable(x).astype("float64") ) def __init__(self, *, eps=1e-5, **kwargs): self.eps = tt.as_tensor_variable(eps).astype("float64") super().__init__(**kwargs) def overdamped(self): Q = self.Q f = tt.sqrt(tt.maximum(1.0 - 4.0 * Q ** 2, self.eps)) empty = tt.zeros(0, dtype=self.dtype) return ( 0.5 * self.S0 * self.w0 * Q * tt.stack([1.0 + 1.0 / f, 1.0 - 1.0 / f]), 0.5 * self.w0 / Q * tt.stack([1.0 - f, 1.0 + f]), empty, empty, empty, empty, ) def underdamped(self): Q = self.Q f = tt.sqrt(tt.maximum(4.0 * Q ** 2 - 1.0, self.eps)) a = self.S0 * self.w0 * Q c = 0.5 * self.w0 / Q empty = tt.zeros(0, dtype=self.dtype) return ( empty, empty, tt.stack([a]), tt.stack([a / f]), tt.stack([c]), tt.stack([c * f]), ) def get_coefficients(self): m = self.Q < 0.5 return [ ifelse(m, a, b) for a, b in zip(self.overdamped(), self.underdamped()) ]
def get_value(self, t): t = tt.as_tensor_variable(t).astype("float64") tp = t - self.lag proxy_val = _interp( tp, self.times, self.values, ) if self.tau_scan == 0: # no lifetime, nothing else to do return self.amp * proxy_val tau = self.tau0 if self.tau_harm is not None: tau_cs = self.tau_harm.get_value(t + self.t_adj) tau += tau_cs proxy_val += self._lt_corr(tp, tau) return self.amp * proxy_val
def __init__( self, ptimes, pvalues, amp, lag=0., tau0=0., tau_harm=None, tau_scan=0, days_per_time_unit=365.25, ): # data self.times = tt.as_tensor_variable(ptimes).astype("float64") self.values = tt.as_tensor_variable(pvalues).astype("float64") # parameters self.amp = tt.as_tensor_variable(amp).astype("float64") self.days_per_time_unit = tt.as_tensor_variable(days_per_time_unit).astype("float64") self.lag = tt.as_tensor_variable(lag / days_per_time_unit).astype("float64") self.tau0 = tt.as_tensor_variable(tau0).astype("float64") self.tau_harm = tau_harm self.tau_scan = tau_scan dt = 1.0 bs = np.arange(dt, tau_scan + dt, dt) / days_per_time_unit self.bs = tt.as_tensor_variable(bs).astype("float64") self.dt = tt.as_tensor_variable(dt).astype("float64") # Makes "(m)jd" and "jyear" compatible for the lifetime # seasonal variation. The julian epoch (the default) # is slightly offset with respect to (modified) julian days. self.t_adj = 0. if self.days_per_time_unit == 1: # discriminate between julian days and modified julian days, # 1.8e6 is year 216 in julian days and year 6787 in # modified julian days. It should be pretty safe to judge on # that for most use cases. if self.times[0] > 1.8e6: # julian days self.t_adj = 13. else: # modified julian days self.t_adj = -44.25 self.t_adj = tt.as_tensor_variable(self.t_adj).astype("float64")
def __init__(self, ror=None, **kwargs): if ror is None: raise ValueError("missing required parameter 'ror'") self.ror = tt.as_tensor_variable(ror) kwargs["transform"] = kwargs.pop("transform", tr.ImpactParameterTransform(self.ror)) try: shape = kwargs.get("shape", self.ror.distribution.shape) except AttributeError: shape = None if shape is None: testval = 0.5 else: testval = 0.5 + np.zeros(shape) kwargs["shape"] = shape kwargs["testval"] = kwargs.pop("testval", testval) super(ImpactParameter, self).__init__(**kwargs)
def get_value(self, t): t = tt.as_tensor_variable(t).astype("float64") tau_cs = tt.zeros(t.shape[:-1], dtype="float64") for h in self.harmonics: tau_cs += h.get_value(t) return tt.maximum(self.lower, tau_cs)
def __init__(self, *, eps=1e-5, **kwargs): self.eps = tt.as_tensor_variable(eps).astype("float64") super().__init__(**kwargs)
def logp(self, value): return tt.zeros_like(tt.as_tensor_variable(value))
def compute_gradient(self, t): t = tt.as_tensor_variable(t).astype("float64") dcos = tt.cos(self.omega * t) dsin = tt.sin(self.omega * t) df = 2 * np.pi * t * (self.sin * dcos - self.cos * dsin) return (df, dcos, dsin)
def asarray(a, dtype=None, order=None): if dtype is None: dtype = aesara.config.floatX return tt.as_tensor_variable(a).astype(dtype)
def __init__(self, freq, cos, sin): self.omega = tt.as_tensor_variable(2 * np.pi * freq).astype("float64") self.cos = tt.as_tensor_variable(cos).astype("float64") self.sin = tt.as_tensor_variable(sin).astype("float64")
def get_value(self, t): t = tt.as_tensor_variable(t).astype("float64") return ( self.cos * tt.cos(self.omega * t) + self.sin * tt.sin(self.omega * t) )
def as_tensor_variable(x, dtype="float64", **kwargs): t = tt.as_tensor_variable(x, **kwargs) if dtype is None: return t return t.astype(dtype)
def get_value(self, t): t = tt.as_tensor_variable(t).astype("float64") v = tt.zeros(t.shape[:-1], dtype="float64") for m in self.models: v += m.get_value(t) return v
def __init__(self, *, a, b, c, d, **kwargs): self.a = tt.as_tensor_variable(a).astype("float64") self.b = tt.as_tensor_variable(b).astype("float64") self.c = tt.as_tensor_variable(c).astype("float64") self.d = tt.as_tensor_variable(d).astype("float64") super().__init__(**kwargs)
def _as_tensor(self, tensor): return tt.as_tensor_variable(tensor).astype("float64")
def __init__(self, harmonics, lower=0.): if not hasattr(harmonics, "getitem"): harmonics = [harmonics] self.harmonics = harmonics self.lower = tt.as_tensor_variable(lower).astype("float64")
def __init__(self, term, delta, **kwargs): self.term = term self.delta = tt.as_tensor_variable(delta).astype("float64") super().__init__(**kwargs)
def get_value(self, t): t = tt.as_tensor_variable(t).astype("float64") return self.amp * tt.sin(self.omega * t + self.phase)
def __init__(self, freq, amp, phase): self.omega = tt.as_tensor_variable(2 * np.pi * freq).astype("float64") self.amp = tt.as_tensor_variable(amp).astype("float64") self.phase = tt.as_tensor_variable(phase).astype("float64")
def __init__(self, ror): self.one_plus_ror = 1 + tt.as_tensor_variable(ror)
def compute_gradient(self, t): t = tt.as_tensor_variable(t).astype("float64") damp = tt.sin(self.omega * t + self.phase) dphi = self.amp * tt.cos(self.omega * t + self.phase) df = 2 * np.pi * t * dphi return (df, damp, dphi)
def __init__(self, *, sigma, rho, eps=0.01, **kwargs): self.sigma = tt.as_tensor_variable(sigma).astype("float64") self.rho = tt.as_tensor_variable(rho).astype("float64") self.eps = tt.as_tensor_variable(eps).astype("float64") super().__init__(**kwargs)