Spaces:
Sleeping
Sleeping
| # app.py — Rendered Frame Theory — Cosmology & Gravity Lab (Full Rewrite, Baseline Tuned) | |
| # Author: Liam Grinstead | |
| # | |
| # Unified RFT lab for cosmology, gravity, black holes and observer physics. | |
| # All modules are driven by the same coherence operator: | |
| # U_RFT = Phi * Gamma * R * (1 - Xi) * Psi | |
| # | |
| # This code and all underlying RFT constructs are protected by UK copyright | |
| # law and the Berne Convention. You are free to *use* this lab, explore, | |
| # and build understanding, but you are not permitted to weaponise RFT, | |
| # nor to commercially exploit the underlying framework, field equations | |
| # or operators without written permission from the author. | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| import gradio as gr | |
| import pandas as pd | |
| import hashlib | |
| import json | |
| # Optional cosmology backend for angular-diameter distances | |
| try: | |
| from astropy.cosmology import FlatLambdaCDM | |
| from astropy import units as u | |
| COSMO = FlatLambdaCDM(H0=70, Om0=0.3) | |
| ASTROPY_AVAILABLE = True | |
| except Exception: | |
| ASTROPY_AVAILABLE = False | |
| COSMO = None | |
| # ============================================================ | |
| # PHYSICAL CONSTANTS | |
| # ============================================================ | |
| G = 6.67430e-11 # m^3 / (kg s^2) | |
| c = 2.99792458e8 # m/s | |
| M_sun = 1.98847e30 # kg | |
| kpc = 3.085677581e19 # m | |
| Mpc = 3.085677581e22 # m | |
| # Astrophysical units for disk sim | |
| G_KPC = 4.3009e-6 # kpc (km/s)^2 / Msun | |
| MYR_TO_S = 3.15576e13 # seconds in 1 Myr | |
| KPC_TO_KM = 3.0857e16 # km in 1 kpc | |
| # ============================================================ | |
| # GLOBAL DEFAULTS (COHERENCE FIELD) — RFT BASELINE | |
| # ============================================================ | |
| COHERENCE_DEFAULTS = { | |
| "Phi": 3.55, # phase / amplification | |
| "Gamma": 3.4e-4, # recursion scale | |
| "R": 1.55, # curvature gain | |
| "Xi": 0.61, # susceptibility (0 inert, 1 collapse) | |
| "Psi": 1.54 # observer phase weight | |
| } | |
| # ============================================================ | |
| # PROVENANCE LOGGING (SEALED) | |
| # ============================================================ | |
| PROV = [] | |
| PROV_FILE = "rft_cosmology_provenance.jsonl" | |
| def log_prov(module, inputs, outputs): | |
| """ | |
| Append a sealed provenance record in memory and to disk. | |
| Each record is SHA-512 hashed over its core fields. | |
| """ | |
| stamp = pd.Timestamp.utcnow().isoformat() | |
| base = { | |
| "module": module, | |
| "timestamp": stamp, | |
| "inputs": inputs, | |
| "outputs": outputs, | |
| } | |
| payload = json.dumps(base, sort_keys=True, default=str) | |
| base["sha512"] = hashlib.sha512(payload.encode("utf-8")).hexdigest() | |
| PROV.append(base) | |
| try: | |
| with open(PROV_FILE, "a", encoding="utf-8") as f: | |
| f.write(json.dumps(base) + "\n") | |
| except Exception: | |
| # HF sandbox may disallow writes; keep in-memory log regardless | |
| pass | |
| def prov_refresh(): | |
| if not PROV: | |
| return pd.DataFrame(columns=["module", "timestamp", "inputs", "outputs", "sha512"]) | |
| return pd.DataFrame(PROV) | |
| # ============================================================ | |
| # COHERENCE HELPERS | |
| # ============================================================ | |
| def coherence_derived(Phi, Gamma, R, Xi, Psi): | |
| """ | |
| Compute core derived quantities from the global coherence field: | |
| U_RFT, Phi*Gamma, Gamma_eff, r_BAO, ell_n, z-mappings. | |
| """ | |
| PhiGamma = Phi * Gamma | |
| U = Phi * Gamma * R * (1.0 - Xi) * Psi | |
| # Effective recursion (Gamma_eff) from BAO / CMB docs | |
| Gamma_eff = Gamma * (1.0 + Phi * (1.0 - np.exp(-Gamma))) | |
| # BAO scale (arbitrary units; mapping to Mpc is handled externally) | |
| if Gamma_eff <= 0: | |
| r_bao = np.nan | |
| ells = [np.nan, np.nan, np.nan] | |
| else: | |
| r_bao = np.pi / np.sqrt(Gamma_eff) | |
| ells = [int(round(n * np.pi * np.sqrt(Gamma_eff))) for n in (1, 2, 3)] | |
| # Two redshift mappings | |
| z_eff_exp = np.exp(PhiGamma) - 1.0 | |
| z_factor = 1.0 / (1.0 + PhiGamma) if (1.0 + PhiGamma) != 0 else np.nan | |
| return { | |
| "U_RFT": float(U), | |
| "PhiGamma": float(PhiGamma), | |
| "Gamma_eff": float(Gamma_eff), | |
| "r_BAO": float(r_bao), | |
| "ell_1": float(ells[0]), | |
| "ell_2": float(ells[1]), | |
| "ell_3": float(ells[2]), | |
| "z_eff_exp": float(z_eff_exp), | |
| "z_compression_factor": float(z_factor), | |
| } | |
| # ============================================================ | |
| # MODULE 1: COHERENCE DASHBOARD | |
| # ============================================================ | |
| def coherence_dashboard(Phi, Gamma, R, Xi, Psi, z_obs_demo): | |
| derived = coherence_derived(Phi, Gamma, R, Xi, Psi) | |
| # Apply compression mapping to a demo observed redshift | |
| if not np.isnan(derived["z_compression_factor"]): | |
| z_rft = (1.0 + z_obs_demo) * derived["z_compression_factor"] - 1.0 | |
| else: | |
| z_rft = np.nan | |
| text = ( | |
| f"U_RFT = {derived['U_RFT']:.4e}\n" | |
| f"Phi*Gamma = {derived['PhiGamma']:.4e}\n" | |
| f"Gamma_eff = {derived['Gamma_eff']:.4e}\n" | |
| f"r_BAO (arb) = {derived['r_BAO']:.3f}\n" | |
| f"CMB-like peaks: ell_1={derived['ell_1']:.1f}, ell_2={derived['ell_2']:.1f}, ell_3={derived['ell_3']:.1f}\n" | |
| f"Exp redshift mapping: 1+z = exp(Phi*Gamma) ⇒ z_eff ≈ {derived['z_eff_exp']:.3e}\n" | |
| f"Compression mapping on z_obs={z_obs_demo:.2f}: z_RFT ≈ {z_rft:.3f}" | |
| ) | |
| # BAO / Gamma_eff curve | |
| Gamma_vals = np.linspace(max(Gamma * 0.2, 1e-6), Gamma * 5.0 if Gamma > 0 else 1e-3, 200) | |
| Gamma_eff_vals = Gamma_vals * (1.0 + Phi * (1.0 - np.exp(-Gamma_vals))) | |
| r_bao_vals = np.pi / np.sqrt(np.maximum(Gamma_eff_vals, 1e-12)) | |
| fig, ax = plt.subplots(figsize=(5, 4)) | |
| ax.plot(Gamma_eff_vals, r_bao_vals, label="r_BAO(Γ_eff)") | |
| if derived["Gamma_eff"] > 0: | |
| ax.scatter([derived["Gamma_eff"]], [derived["r_BAO"]], color="red", zorder=5, label="Current") | |
| ax.set_xlabel("Gamma_eff") | |
| ax.set_ylabel("r_BAO (arb)") | |
| ax.set_title("BAO Scale vs Effective Coherence") | |
| ax.grid(True, alpha=0.3) | |
| ax.legend() | |
| fig.tight_layout() | |
| log_prov( | |
| "Coherence dashboard", | |
| {"Phi": Phi, "Gamma": Gamma, "R": R, "Xi": Xi, "Psi": Psi, "z_obs_demo": z_obs_demo}, | |
| {**derived, "z_RFT_demo": float(z_rft)} | |
| ) | |
| return text, fig | |
| # ============================================================ | |
| # MODULE 2: ANALYTIC ROTATION CURVES | |
| # ============================================================ | |
| def rotation_curves_analytic(M_disk_solar, M_bulge_solar, R_d_kpc, Phi, Gamma, R, Xi, Psi): | |
| derived = coherence_derived(Phi, Gamma, R, Xi, Psi) | |
| PhiGamma = derived["PhiGamma"] | |
| r = np.linspace(0.1, 50.0, 400) # kpc | |
| # Simple exponential disk + bulge | |
| M_disk = M_disk_solar * M_sun * (1.0 - np.exp(-r / R_d_kpc)) | |
| M_bulge = M_bulge_solar * M_sun * (1.0 - np.exp(-r / (0.3 * R_d_kpc))) | |
| M_tot = M_disk + M_bulge | |
| v_baryon = np.sqrt(G * M_tot / (r * kpc)) / 1000.0 # km/s | |
| scale = np.sqrt(max(PhiGamma, 0.0)) | |
| v_rft = v_baryon * (scale if np.isfinite(scale) else 1.0) | |
| fig, ax = plt.subplots(figsize=(6, 4)) | |
| ax.plot(r, v_baryon, label="Baryons only", color="tab:blue") | |
| ax.plot(r, v_rft, label=f"RFT amplified (√(Phi*Gamma)≈{scale:.3f})", color="tab:orange") | |
| ax.axhspan(220, 240, color="grey", alpha=0.15, label="220–240 km/s band") | |
| ax.set_xlabel("Radius r (kpc)") | |
| ax.set_ylabel("v_rot (km/s)") | |
| ax.set_title("Galaxy Rotation Curve — Baryons vs RFT Amplification") | |
| ax.grid(True, alpha=0.3) | |
| ax.legend() | |
| fig.tight_layout() | |
| log_prov( | |
| "Rotation curves (analytic)", | |
| {"M_disk": M_disk_solar, "M_bulge": M_bulge_solar, "R_d": R_d_kpc, | |
| "Phi": Phi, "Gamma": Gamma, "R": R, "Xi": Xi, "Psi": Psi}, | |
| {"PhiGamma": PhiGamma, "scale": float(scale)} | |
| ) | |
| return fig | |
| # ============================================================ | |
| # MODULE 3: RFT GRAVITY DISK SIM (N-BODY TOY) | |
| # ============================================================ | |
| M_central_disk = 1.2e11 # Msun | |
| M_disk_total = 6.0e10 # Msun | |
| N_particles_disk = 300 | |
| m_particle_disk = M_disk_total / N_particles_disk | |
| softening_kpc = 0.1 | |
| def disk_compute_accel(positions, masses, model, a0_val): | |
| """ | |
| Compute accelerations for the disk N-body sim under Newton or RFT gravity. | |
| Uses a softened point-mass potential + central mass. Self-terms on the | |
| diagonal are set to a large finite value, not inf, to keep numerics stable. | |
| """ | |
| x = positions[:, 0] | |
| y = positions[:, 1] | |
| N = positions.shape[0] | |
| dx = x[:, None] - x[None, :] | |
| dy = y[:, None] - y[None, :] | |
| r2 = dx*dx + dy*dy + softening_kpc**2 | |
| # Self terms: large finite number instead of infinity | |
| idx = np.arange(N) | |
| r2[idx, idx] = 1e10 | |
| inv_r = 1.0 / np.sqrt(r2) | |
| inv_r3 = inv_r / r2 | |
| ax_dd = -G_KPC * np.sum(masses[None, :] * dx * inv_r3, axis=1) | |
| ay_dd = -G_KPC * np.sum(masses[None, :] * dy * inv_r3, axis=1) | |
| r2_c = x*x + y*y + softening_kpc**2 | |
| r_c = np.sqrt(r2_c) | |
| gN_c = G_KPC * M_central_disk / r2_c | |
| if model == "newton": | |
| g_c = gN_c | |
| elif model == "rft": | |
| # RFT deformation: g_RFT = 0.5( gN + sqrt(gN^2 + 4 gN a0) ) | |
| g_c = 0.5 * (gN_c + np.sqrt(gN_c**2 + 4.0 * gN_c * a0_val)) | |
| else: | |
| raise ValueError("model must be 'newton' or 'rft'") | |
| ax_c = -g_c * x / r_c | |
| ay_c = -g_c * y / r_c | |
| ax_total = ax_dd + ax_c | |
| ay_total = ay_dd + ay_c | |
| ax_km_s2 = ax_total / KPC_TO_KM | |
| ay_km_s2 = ay_total / KPC_TO_KM | |
| return np.stack([ax_km_s2, ay_km_s2], axis=1) | |
| def disk_init(r_min=2.0, r_max=20.0, seed=42): | |
| rng = np.random.default_rng(int(seed)) | |
| u = rng.random(N_particles_disk) | |
| r = np.sqrt(r_min**2 + (r_max**2 - r_min**2) * u) | |
| theta = 2.0 * np.pi * rng.random(N_particles_disk) | |
| x = r * np.cos(theta) | |
| y = r * np.sin(theta) | |
| positions = np.stack([x, y], axis=1) | |
| M_enc = M_central_disk + M_disk_total * (r / r.max()) | |
| gN = G_KPC * M_enc / r**2 | |
| v_circ = np.sqrt(r * gN) | |
| vx = -v_circ * np.sin(theta) | |
| vy = v_circ * np.cos(theta) | |
| velocities = np.stack([vx, vy], axis=1) | |
| return positions, velocities | |
| def disk_leapfrog(model, n_steps, dt_myr, a0_val): | |
| positions, velocities = disk_init() | |
| masses = np.full(N_particles_disk, m_particle_disk) | |
| dt_s = dt_myr * MYR_TO_S | |
| acc = disk_compute_accel(positions, masses, model=model, a0_val=a0_val) | |
| velocities += 0.5 * acc * dt_s | |
| for _ in range(int(n_steps)): | |
| positions += (velocities * dt_s) / KPC_TO_KM | |
| acc = disk_compute_accel(positions, masses, model=model, a0_val=a0_val) | |
| velocities += acc * dt_s | |
| return positions, velocities | |
| def disk_rotation_curve(positions, velocities, n_bins): | |
| x = positions[:, 0] | |
| y = positions[:, 1] | |
| vx = velocities[:, 0] | |
| vy = velocities[:, 1] | |
| r = np.sqrt(x*x + y*y) | |
| with np.errstate(divide="ignore", invalid="ignore"): | |
| inv_r = np.where(r > 0, 1.0 / r, 0.0) | |
| tx = -y * inv_r | |
| ty = x * inv_r | |
| v_t = vx * tx + vy * ty | |
| r_min = 2.0 | |
| r_max = 40.0 | |
| bins = np.linspace(r_min, r_max, n_bins + 1) | |
| idx = np.digitize(r, bins) | |
| r_centers = [] | |
| v_means = [] | |
| for b in range(1, n_bins + 1): | |
| mask = idx == b | |
| if np.any(mask): | |
| r_centers.append(r[mask].mean()) | |
| v_means.append(np.mean(np.abs(v_t[mask]))) | |
| return np.array(r_centers), np.array(v_means) | |
| def rft_disk_module(Phi, Gamma, R, Xi, Psi, n_steps, dt_myr, n_bins): | |
| derived = coherence_derived(Phi, Gamma, R, Xi, Psi) | |
| # Tie a0 to Gamma_eff: scale around 2500 (km/s)^2/kpc at Gamma_eff ~ 1e-4 | |
| Gamma_eff = max(derived["Gamma_eff"], 1e-6) | |
| a0_val = 2500.0 * (Gamma_eff / 1.0e-4) | |
| posN, velN = disk_leapfrog(model="newton", n_steps=n_steps, dt_myr=dt_myr, a0_val=a0_val) | |
| posR, velR = disk_leapfrog(model="rft", n_steps=n_steps, dt_myr=dt_myr, a0_val=a0_val) | |
| rN, vN = disk_rotation_curve(posN, velN, n_bins=n_bins) | |
| rR, vR = disk_rotation_curve(posR, velR, n_bins=n_bins) | |
| # Rotation curves | |
| fig_rc, ax = plt.subplots(figsize=(6, 4)) | |
| ax.plot(rN, vN, "o--", label="Newton (baryons only)") | |
| ax.plot(rR, vR, "o-", label="RFT gravity (Γ_eff-linked)") | |
| ax.axvspan(10, 40, color="grey", alpha=0.1, label="10–40 kpc") | |
| ax.axhspan(220, 240, color="orange", alpha=0.1, label="220–240 km/s") | |
| ax.set_xlabel("Radius r (kpc)") | |
| ax.set_ylabel("v_rot (km/s)") | |
| ax.set_title("Toy Galaxy Disk: Newton vs RFT") | |
| ax.grid(True, alpha=0.3) | |
| ax.legend() | |
| fig_rc.tight_layout() | |
| # Spatial distribution | |
| fig_xy, axes = plt.subplots(1, 2, figsize=(9, 4), sharex=True, sharey=True) | |
| axes[0].scatter(posN[:, 0], posN[:, 1], s=4, alpha=0.7) | |
| axes[0].set_title("Newton disk (final)") | |
| axes[0].set_xlabel("x (kpc)") | |
| axes[0].set_ylabel("y (kpc)") | |
| axes[0].grid(True, alpha=0.3) | |
| axes[0].set_aspect("equal", "box") | |
| axes[1].scatter(posR[:, 0], posR[:, 1], s=4, alpha=0.7, color="tab:orange") | |
| axes[1].set_title("RFT disk (final)") | |
| axes[1].set_xlabel("x (kpc)") | |
| axes[1].grid(True, alpha=0.3) | |
| axes[1].set_aspect("equal", "box") | |
| fig_xy.tight_layout() | |
| log_prov( | |
| "RFT disk sim", | |
| {"Phi": Phi, "Gamma": Gamma, "R": R, "Xi": Xi, "Psi": Psi, | |
| "n_steps": int(n_steps), "dt_myr": float(dt_myr), "n_bins": int(n_bins), | |
| "a0_val": float(a0_val)}, | |
| {"note": "Newton vs RFT disk rotation curves linked to Gamma_eff"} | |
| ) | |
| return fig_rc, fig_xy | |
| # ============================================================ | |
| # MODULE 4: LENSING KAPPA MAPS | |
| # ============================================================ | |
| def sigma_crit_full(Ds_m, Dl_m, Dls_m): | |
| return (c**2 / (4.0 * np.pi * G)) * (Ds_m / (Dl_m * Dls_m)) | |
| def gaussian_surface_density(x_m, y_m, M_kg, sigma_m): | |
| r2 = x_m**2 + y_m**2 | |
| return (M_kg / (2.0 * np.pi * sigma_m**2)) * np.exp(-r2 / (2.0 * sigma_m**2)) | |
| def plummer_surface_density(x_m, y_m, M_kg, a_m): | |
| R2 = x_m**2 + y_m**2 | |
| return (M_kg / (np.pi * a_m**2)) * (1.0 + R2 / a_m**2) ** (-2) | |
| def kappa_map_module(D_s_Mpc, D_l_Mpc, M_l_solar, scale_val, scale_unit, | |
| profile, Phi, Gamma, R, Xi, Psi): | |
| derived = coherence_derived(Phi, Gamma, R, Xi, Psi) | |
| PhiGamma = derived["PhiGamma"] | |
| if ASTROPY_AVAILABLE: | |
| z_s = (D_s_Mpc * u.Mpc).to(u.m).value / (3000.0 * Mpc) | |
| z_l = (D_l_Mpc * u.Mpc).to(u.m).value / (3000.0 * Mpc) | |
| Ds_m = COSMO.angular_diameter_distance(z_s).to(u.m).value | |
| Dl_m = COSMO.angular_diameter_distance(z_l).to(u.m).value | |
| Dls_m = COSMO.angular_diameter_distance_z1z2(z_l, z_s).to(u.m).value | |
| else: | |
| Ds_m = D_s_Mpc * Mpc | |
| Dl_m = D_l_Mpc * Mpc | |
| Dls_m = max((D_s_Mpc - D_l_Mpc), 1e-3) * Mpc | |
| sigcrit = sigma_crit_full(Ds_m, Dl_m, Dls_m) | |
| scale_m = scale_val * (kpc if scale_unit == "kpc" else Mpc) | |
| Sigma_func = gaussian_surface_density if profile == "Gaussian" else plummer_surface_density | |
| span = 4.0 * scale_m | |
| grid = np.linspace(-span, span, 200) | |
| XX, YY = np.meshgrid(grid, grid) | |
| Sigma = Sigma_func(XX, YY, M_l_solar * M_sun, scale_m) | |
| kappa_b = Sigma / sigcrit | |
| kappa_rft = kappa_b * PhiGamma | |
| fig, ax = plt.subplots(figsize=(5, 4)) | |
| im = ax.imshow( | |
| kappa_rft, | |
| origin="lower", | |
| extent=[grid.min() / Mpc, grid.max() / Mpc, grid.min() / Mpc, grid.max() / Mpc], | |
| cmap="viridis", | |
| aspect="equal" | |
| ) | |
| ax.set_xlabel("x (Mpc)") | |
| ax.set_ylabel("y (Mpc)") | |
| ax.set_title(f"κ_RFT map — {profile}, ΦΓ={PhiGamma:.3e}") | |
| fig.colorbar(im, ax=ax, label="κ_RFT") | |
| fig.tight_layout() | |
| log_prov( | |
| "Lensing kappa map", | |
| {"D_s_Mpc": D_s_Mpc, "D_l_Mpc": D_l_Mpc, "M_l_solar": M_l_solar, | |
| "scale_val": scale_val, "scale_unit": scale_unit, "profile": profile, | |
| "Phi": Phi, "Gamma": Gamma, "R": R, "Xi": Xi, "Psi": Psi}, | |
| {"PhiGamma": PhiGamma} | |
| ) | |
| return fig | |
| # ============================================================ | |
| # MODULE 5: BAO + CMB HARMONICS | |
| # ============================================================ | |
| def bao_cmb_module(Phi, Gamma, R, Xi, Psi): | |
| derived = coherence_derived(Phi, Gamma, R, Xi, Psi) | |
| Gamma_eff = max(derived["Gamma_eff"], 1e-6) | |
| PhiGamma = derived["PhiGamma"] | |
| k = np.linspace(0.01, 0.5, 400) | |
| D_A = 1.0 # arbitrary units; only shapes matter | |
| P = (k**-1.0) * (1.0 + PhiGamma * np.cos(k * D_A / np.sqrt(Gamma_eff))) | |
| fig, ax = plt.subplots(figsize=(6, 4)) | |
| ax.plot(k, P, label="P_RFT(k)") | |
| ax.set_xlabel("k (arb)") | |
| ax.set_ylabel("P_RFT(k) (arb)") | |
| ax.set_title("RFT Recursion Spectrum — BAO / CMB Toy") | |
| ax.grid(True, alpha=0.3) | |
| ax.legend() | |
| fig.tight_layout() | |
| peaks = (derived["ell_1"], derived["ell_2"], derived["ell_3"]) | |
| log_prov( | |
| "BAO + CMB toy", | |
| {"Phi": Phi, "Gamma": Gamma, "R": R, "Xi": Xi, "Psi": Psi}, | |
| {"Gamma_eff": Gamma_eff, "r_BAO": derived["r_BAO"], "ells": peaks} | |
| ) | |
| summary = f"Gamma_eff={Gamma_eff:.4e}, r_BAO≈{derived['r_BAO']:.3f}, peaks ell_n≈{peaks}" | |
| return fig, summary | |
| # ============================================================ | |
| # MODULE 6: REDSHIFT CURVES | |
| # ============================================================ | |
| def redshift_module(Phi, Gamma, R, Xi, Psi): | |
| derived = coherence_derived(Phi, Gamma, R, Xi, Psi) | |
| PhiGamma = derived["PhiGamma"] | |
| z_factor = derived["z_compression_factor"] | |
| z_obs = np.linspace(0.0, 3.0, 300) | |
| if np.isfinite(z_factor): | |
| z_rft = (1.0 + z_obs) * z_factor - 1.0 | |
| else: | |
| z_rft = np.full_like(z_obs, np.nan) | |
| z_exp = np.full_like(z_obs, derived["z_eff_exp"]) | |
| fig, ax = plt.subplots(figsize=(6, 4)) | |
| ax.plot(z_obs, z_obs, label="z (FRW metric)", linestyle="--") | |
| ax.plot(z_obs, z_rft, label="z_RFT (compression mapping)") | |
| ax.plot(z_obs, z_exp, label="z_RFT (exp ΦΓ, constant)") | |
| ax.set_xlabel("z_obs (bare)") | |
| ax.set_ylabel("z_rendered") | |
| ax.set_title("RFT Redshift Mappings") | |
| ax.grid(True, alpha=0.3) | |
| ax.legend() | |
| fig.tight_layout() | |
| log_prov( | |
| "Redshift curves", | |
| {"Phi": Phi, "Gamma": Gamma, "R": R, "Xi": Xi, "Psi": Psi}, | |
| {"PhiGamma": PhiGamma, "z_factor": z_factor, "z_eff_exp": derived["z_eff_exp"]} | |
| ) | |
| return fig | |
| # ============================================================ | |
| # MODULE 7: BLACK HOLES & LISA COHERENCE CREST | |
| # ============================================================ | |
| def bh_lisa_module(M_bh_solar, Phi, Gamma, R, Xi, Psi): | |
| derived = coherence_derived(Phi, Gamma, R, Xi, Psi) | |
| U = derived["U_RFT"] | |
| M_bh = M_bh_solar * M_sun | |
| R_s = 2.0 * G * M_bh / c**2 | |
| R_rft = R_s * U | |
| # Toy coherence crest and frequency drift | |
| t = np.linspace(-1.0, 1.0, 400) # normalized time around merger | |
| sigma = 0.3 | |
| PhiGamma0 = derived["PhiGamma"] | |
| crest = PhiGamma0 * np.exp(-t**2 / (2.0 * sigma**2)) | |
| dPhiGamma_dt = -(t / (sigma**2)) * crest | |
| delta_f = dPhiGamma_dt / (2.0 * np.pi) | |
| f0 = 10.0 # mHz baseline | |
| f_gr = f0 * (1.0 + 0.3 * t) | |
| f_rft = f_gr + delta_f | |
| fig, ax = plt.subplots(figsize=(6, 4)) | |
| ax.plot(t, f_gr, label="GR-like chirp (toy)") | |
| ax.plot(t, f_rft, label="RFT chirp with coherence crest") | |
| ax.set_xlabel("Time (arb, around merger)") | |
| ax.set_ylabel("Frequency (mHz, arb)") | |
| ax.set_title("LISA-band Frequency Drift from Coherence Crest (Toy)") | |
| ax.grid(True, alpha=0.3) | |
| ax.legend() | |
| fig.tight_layout() | |
| info = ( | |
| f"R_S (Schwarzschild) ≈ {R_s:.3e} m\n" | |
| f"U_RFT ≈ {U:.3e}\n" | |
| f"R_RFT = U_RFT * R_S ≈ {R_rft:.3e} m" | |
| ) | |
| log_prov( | |
| "BH + LISA crest toy", | |
| {"M_bh_solar": M_bh_solar, "Phi": Phi, "Gamma": Gamma, "R": R, "Xi": Xi, "Psi": Psi}, | |
| {"R_S": float(R_s), "R_RFT": float(R_rft)} | |
| ) | |
| return info, fig | |
| # ============================================================ | |
| # MODULE 8: OBSERVER FIELD & COLLAPSE | |
| # ============================================================ | |
| def observer_module(kappa_obs, Xi_baseline, lambda_obs, Phi, Gamma, R, Xi_slider, Psi): | |
| # Xi_total = Xi_baseline + lambda_obs * kappa_obs + Xi_slider | |
| Xi_total = Xi_baseline + lambda_obs * kappa_obs + Xi_slider | |
| Xi_total = float(Xi_total) | |
| derived = coherence_derived(Phi, Gamma, R, Xi_total, Psi) | |
| collapse_rate = Phi * Gamma * Xi_total * Psi | |
| collapsed = Xi_total >= 1.0 | |
| t = np.linspace(0.0, 1.0, 200) | |
| Xi_t = Xi_baseline + lambda_obs * kappa_obs * np.exp(-5.0 * (t - 0.6)**2) + Xi_slider | |
| rate_t = Phi * Gamma * Xi_t * Psi | |
| fig, ax1 = plt.subplots(figsize=(6, 4)) | |
| ax1.plot(t, Xi_t, label="Ξ(t)", color="tab:blue") | |
| ax1.axhline(1.0, color="grey", linestyle="--", label="Collapse threshold") | |
| ax1.set_xlabel("Time (arb)") | |
| ax1.set_ylabel("Ξ(t)") | |
| ax1.grid(True, alpha=0.3) | |
| ax2 = ax1.twinx() | |
| ax2.plot(t, rate_t, label="λ_RFT(t)", color="tab:orange", alpha=0.8) | |
| ax2.set_ylabel("Collapse drive λ_RFT(t)") | |
| lines, labels = ax1.get_legend_handles_labels() | |
| lines2, labels2 = ax2.get_legend_handles_labels() | |
| ax1.legend(lines + lines2, labels + labels2, loc="upper left") | |
| fig.tight_layout() | |
| status = "Collapse triggered (Ξ ≥ 1)" if collapsed else "No collapse (Ξ < 1)" | |
| text = ( | |
| f"Ξ_total ≈ {Xi_total:.3f}\n" | |
| f"Instantaneous collapse drive λ_RFT ≈ {collapse_rate:.3e}\n" | |
| f"Status: {status}" | |
| ) | |
| log_prov( | |
| "Observer field", | |
| {"kappa_obs": kappa_obs, "Xi_baseline": Xi_baseline, "lambda_obs": lambda_obs, | |
| "Phi": Phi, "Gamma": Gamma, "R": R, "Xi_slider": Xi_slider, "Psi": Psi}, | |
| {"Xi_total": Xi_total, "collapse_rate": float(collapse_rate), "collapsed": bool(collapsed)} | |
| ) | |
| return text, fig | |
| # ============================================================ | |
| # GRADIO UI | |
| # ============================================================ | |
| with gr.Blocks(title="Rendered Frame Theory — Cosmology & Gravity Lab") as demo: | |
| gr.Markdown( | |
| "# Rendered Frame Theory — Cosmology & Gravity Lab\n" | |
| "This lab exposes core RFT cosmology and gravity modules, all driven by the same\n" | |
| "coherence operator $U_{\\rm RFT} = \\Phi\\,\\Gamma\\,\\mathcal{R}\\,(1-\\Xi)\\,\\Psi$.\n" | |
| "You can inspect the mathematics, run case studies, and see exactly how a single\n" | |
| "coherence field reshapes rotation curves, lensing, redshift, black holes,\n" | |
| "and observer-linked collapse." | |
| ) | |
| # Global coherence parameters shared by all modules (RFT baseline) | |
| with gr.Accordion("Global Coherence Field (Φ, Γ, ℛ, Ξ, Ψ)", open=True): | |
| with gr.Row(): | |
| Phi = gr.Slider(0.1, 5.0, value=COHERENCE_DEFAULTS["Phi"], step=0.05, label="Φ (phase / amplification)") | |
| Gamma = gr.Slider(1e-5, 5e-4, value=COHERENCE_DEFAULTS["Gamma"], step=1e-5, label="Γ (recursion scale)") | |
| R = gr.Slider(0.5, 2.0, value=COHERENCE_DEFAULTS["R"], step=0.01, label="ℛ (curvature gain)") | |
| Xi = gr.Slider(0.0, 0.9, value=COHERENCE_DEFAULTS["Xi"], step=0.01, label="Ξ (susceptibility)") | |
| Psi = gr.Slider(0.1, 2.0, value=COHERENCE_DEFAULTS["Psi"], step=0.01, label="Ψ (observer phase)") | |
| with gr.Tabs(): | |
| # HOW TO USE / EXPLANATION | |
| with gr.TabItem("How this lab works"): | |
| gr.Markdown( | |
| "## How this lab works\n\n" | |
| "**Global controls (top accordion)**\n\n" | |
| "- **Φ (phase / amplification)** — how strongly the coherence field amplifies\n" | |
| " gravity, lensing and redshift. Higher Φ means stronger RFT effects everywhere.\n" | |
| "- **Γ (recursion scale)** — sets the strength of the underlying recursion\n" | |
| " that generates BAO and CMB-like structure. It feeds into Γ_eff.\n" | |
| "- **ℛ (curvature gain)** — large-scale curvature gain; multiplies the whole\n" | |
| " coherence operator. Increasing ℛ boosts all cosmological deformations.\n" | |
| "- **Ξ (susceptibility)** — how close the system is to collapse. Ξ→1 suppresses\n" | |
| " U_RFT and pushes the model toward measurement / collapse.\n" | |
| "- **Ψ (observer phase)** — how strongly observers couple into the field.\n" | |
| " Higher Ψ tightens the link between coherence and what is rendered.\n\n" | |
| "**Tabs**\n\n" | |
| "- **Coherence dashboard** — shows the derived quantities from your current\n" | |
| " sliders: U_RFT, ΦΓ, Γ_eff, r_BAO, approximate CMB peaks and redshift mappings.\n" | |
| "- **Rotation curves (analytic)** — classic v(r) from baryons only (disk+bulge)\n" | |
| " versus an RFT-amplified curve using √(ΦΓ). This is the transparent\n" | |
| " \"one parameter replaces dark matter\" view.\n" | |
| "- **RFT gravity disk sim** — N-body toy galaxy disk. Same initial conditions,\n" | |
| " evolved once with Newtonian gravity, once with the RFT deformation g_RFT.\n" | |
| " You see both the rotation curves and the final disk shapes.\n" | |
| "- **Lensing κ maps** — surface-density κ maps for a lens, scaled by ΦΓ. This\n" | |
| " shows how RFT modifies apparent lensing without inventing invisible mass.\n" | |
| "- **BAO + CMB (toy)** — shows a toy RFT recursion spectrum P_RFT(k) and reports\n" | |
| " Γ_eff, r_BAO and approximate harmonic peaks ℓ_n.\n" | |
| "- **Redshift mapping** — compares FRW redshift z with two RFT mappings: an\n" | |
| " exponential mapping from ΦΓ and a compression mapping that rescales 1+z.\n" | |
| "- **Black holes & LISA crest (toy)** — shows how U_RFT rescales the Schwarzschild\n" | |
| " radius and imprints a small coherence crest on a toy LISA-band chirp.\n" | |
| "- **Observer field & collapse** — lets you dial observer coherence κ_obs and\n" | |
| " see when Ξ_total crosses 1 and drives collapse.\n" | |
| "- **Math & case notes** — static summary of the key equations and how they\n" | |
| " correspond to what you see in the plots.\n" | |
| "- **Legal & RFT licence** — states the copyright position and allowed use.\n" | |
| ) | |
| # Coherence dashboard | |
| with gr.TabItem("Coherence dashboard"): | |
| z_obs_demo = gr.Slider(0.0, 3.0, value=1.0, step=0.05, label="Demo observed redshift z_obs") | |
| dash_text = gr.Textbox(label="Derived quantities", lines=8) | |
| dash_plot = gr.Plot(label="BAO scale vs Γ_eff") | |
| dash_btn = gr.Button("Update coherence summary", variant="primary") | |
| dash_btn.click( | |
| coherence_dashboard, | |
| inputs=[Phi, Gamma, R, Xi, Psi, z_obs_demo], | |
| outputs=[dash_text, dash_plot] | |
| ) | |
| # Analytic rotation curves | |
| with gr.TabItem("Rotation curves (analytic)"): | |
| M_disk = gr.Slider(1e9, 2e11, value=6e10, step=1e9, label="Disk mass (M☉)") | |
| M_bulge = gr.Slider(1e9, 1e11, value=1e10, step=1e9, label="Bulge mass (M☉)") | |
| R_d = gr.Slider(0.5, 6.0, value=3.0, step=0.1, label="Disk scale length (kpc)") | |
| rot_plot = gr.Plot(label="Rotation curve") | |
| rot_btn = gr.Button("Compute rotation curves") | |
| rot_btn.click( | |
| rotation_curves_analytic, | |
| inputs=[M_disk, M_bulge, R_d, Phi, Gamma, R, Xi, Psi], | |
| outputs=[rot_plot] | |
| ) | |
| # Disk sim | |
| with gr.TabItem("RFT gravity disk sim"): | |
| n_steps_disk = gr.Slider(500, 5000, value=2500, step=250, label="Integration steps") | |
| dt_myr_disk = gr.Slider(0.05, 0.5, value=0.2, step=0.05, label="Timestep (Myr)") | |
| n_bins_disk = gr.Slider(5, 30, value=15, step=1, label="Bins for v_rot(r)") | |
| rc_plot = gr.Plot(label="Rotation curves: Newton vs RFT") | |
| xy_plot = gr.Plot(label="Final disk configuration") | |
| disk_btn = gr.Button("Run disk experiment") | |
| disk_btn.click( | |
| rft_disk_module, | |
| inputs=[Phi, Gamma, R, Xi, Psi, n_steps_disk, dt_myr_disk, n_bins_disk], | |
| outputs=[rc_plot, xy_plot] | |
| ) | |
| # Lensing | |
| with gr.TabItem("Lensing κ maps"): | |
| D_s = gr.Slider(500.0, 5000.0, value=3000.0, step=10.0, label="Source distance (Mpc)") | |
| D_l = gr.Slider(100.0, 2000.0, value=800.0, step=10.0, label="Lens distance (Mpc)") | |
| M_l = gr.Slider(1e12, 1e15, value=1e14, step=1e12, label="Lens mass (M☉)") | |
| scale_unit = gr.Dropdown(choices=["kpc", "Mpc"], value="Mpc", label="Scale unit") | |
| scale_val = gr.Slider(0.05, 0.5, value=0.15, step=0.01, label="Scale radius") | |
| profile = gr.Dropdown(choices=["Gaussian", "Plummer"], value="Plummer", label="Surface-density profile") | |
| kappa_plot = gr.Plot(label="κ_RFT map") | |
| def _scale_slider_update(unit): | |
| if unit == "kpc": | |
| return gr.Slider.update(minimum=50.0, maximum=300.0, value=150.0, step=5.0, label="Scale radius") | |
| else: | |
| return gr.Slider.update(minimum=0.05, maximum=0.5, value=0.15, step=0.01, label="Scale radius") | |
| scale_unit.change(_scale_slider_update, inputs=scale_unit, outputs=scale_val) | |
| kappa_btn = gr.Button("Compute κ_RFT map") | |
| kappa_btn.click( | |
| kappa_map_module, | |
| inputs=[D_s, D_l, M_l, scale_val, scale_unit, profile, Phi, Gamma, R, Xi, Psi], | |
| outputs=[kappa_plot] | |
| ) | |
| # BAO / CMB | |
| with gr.TabItem("BAO + CMB (toy)"): | |
| bao_plot = gr.Plot(label="P_RFT(k)") | |
| bao_text = gr.Textbox(label="Summary", lines=3) | |
| bao_btn = gr.Button("Compute recursion spectrum") | |
| bao_btn.click( | |
| bao_cmb_module, | |
| inputs=[Phi, Gamma, R, Xi, Psi], | |
| outputs=[bao_plot, bao_text] | |
| ) | |
| # Redshift | |
| with gr.TabItem("Redshift mapping"): | |
| redshift_plot = gr.Plot(label="z_RFT vs z_obs") | |
| redshift_btn = gr.Button("Compute redshift curves") | |
| redshift_btn.click( | |
| redshift_module, | |
| inputs=[Phi, Gamma, R, Xi, Psi], | |
| outputs=[redshift_plot] | |
| ) | |
| # Black holes | |
| with gr.TabItem("Black holes & LISA crest (toy)"): | |
| Mbh = gr.Slider(1e5, 1e9, value=4e6, step=1e5, label="BH mass (M☉)") | |
| bh_info = gr.Textbox(label="RFT radius", lines=3) | |
| bh_plot = gr.Plot(label="Frequency drift") | |
| bh_btn = gr.Button("Compute BH + LISA toy") | |
| bh_btn.click( | |
| bh_lisa_module, | |
| inputs=[Mbh, Phi, Gamma, R, Xi, Psi], | |
| outputs=[bh_info, bh_plot] | |
| ) | |
| # Observer / collapse | |
| with gr.TabItem("Observer field & collapse"): | |
| # Defaults chosen so Xi_total ≳ 1 at baseline | |
| kappa_obs = gr.Slider(0.0, 10.0, value=0.8, step=0.1, label="Observer coherence κ_obs") | |
| Xi_baseline = gr.Slider(0.0, 1.0, value=0.10, step=0.01, label="Ξ_baseline (environment)") | |
| lambda_obs = gr.Slider(0.0, 1.0, value=0.50, step=0.01, label="λ_obs (observer coupling)") | |
| Xi_slider = gr.Slider(0.0, 0.8, value=0.61, step=0.01, label="Extra Ξ control") | |
| obs_text = gr.Textbox(label="Collapse diagnostics", lines=4) | |
| obs_plot = gr.Plot(label="Ξ(t) and λ_RFT(t)") | |
| obs_btn = gr.Button("Evaluate observer field") | |
| obs_btn.click( | |
| observer_module, | |
| inputs=[kappa_obs, Xi_baseline, lambda_obs, Phi, Gamma, R, Xi_slider, Psi], | |
| outputs=[obs_text, obs_plot] | |
| ) | |
| # MATH & CASE NOTES | |
| with gr.TabItem("Math & case notes"): | |
| gr.Markdown( | |
| "## Core RFT cosmology mathematics (summary)\n\n" | |
| "**Global operator**\n\n" | |
| "- Coherence operator:\n" | |
| " \\[ U_{\\rm RFT} = \\Phi\\,\\Gamma\\,\\mathcal{R}\\,(1-\\Xi)\\,\\Psi. \\]\n" | |
| " This appears in black holes (R_RFT), observer collapse rates, and sets the\n" | |
| " global strength of the coherence field.\n\n" | |
| "- Pair combination:\n" | |
| " \\[ \\Phi\\Gamma = \\Phi \\cdot \\Gamma. \\]\n" | |
| " This controls redshift mappings, lensing amplification and analytic\n" | |
| " rotation-curve scaling.\n\n" | |
| "- Effective recursion for BAO/CMB:\n" | |
| " \\[ \\Gamma_{\\rm eff} = \\Gamma\\,\\big(1 + \\Phi(1 - e^{-\\Gamma})\\big). \\]\n" | |
| " From this we define a coherence BAO scale and toy CMB-like harmonic peaks:\n" | |
| " \\[ r_{\\rm BAO} = \\frac{\\pi}{\\sqrt{\\Gamma_{\\rm eff}}}, \\quad\n" | |
| " \\ell_n \\approx n\\,\\pi\\,\\sqrt{\\Gamma_{\\rm eff}}. \\]\n\n" | |
| "**Analytic rotation curves**\n\n" | |
| "- Baryonic rotation velocity:\n" | |
| " \\[ v_{\\rm bar}(r) = \\sqrt{\\frac{GM(r)}{r}}. \\]\n" | |
| "- RFT scaling used here:\n" | |
| " \\[ v_{\\rm RFT}(r) = v_{\\rm bar}(r)\\,\\sqrt{\\max(\\Phi\\Gamma,0)}. \\]\n" | |
| " In other words, dark matter is replaced by a coherence-driven tilt.\n\n" | |
| "**Disk N-body gravity (toy)**\n\n" | |
| "- Central gravitational field under RFT:\n" | |
| " \\[ g_{\\rm RFT} = \\tfrac{1}{2}\\left(g_N + \\sqrt{g_N^2 + 4 g_N a_0}\\right), \\]\n" | |
| " where \\(a_0\\) is tied to \\(\\Gamma_{\\rm eff}\\) and set near\n" | |
| " \\(2500\\,{\\rm (km/s)^2/kpc}\\) at a reference \\(\\Gamma_{\\rm eff}\\).\n\n" | |
| "**Lensing κ maps**\n\n" | |
| "- Baseline critical surface density:\n" | |
| " \\[ \\Sigma_{\\rm crit} = \\frac{c^2}{4\\pi G} \\frac{D_s}{D_l D_{ls}}. \\]\n" | |
| "- Surface-density profile \\(\\Sigma(x,y)\\) is chosen (Gaussian / Plummer),\n" | |
| " and the convergence is:\n" | |
| " \\[ \\kappa_{\\rm RFT} = \\frac{\\Sigma}{\\Sigma_{\\rm crit}}\\,(\\Phi\\Gamma). \\]\n\n" | |
| "**Redshift mappings**\n\n" | |
| "- Exponential mapping:\n" | |
| " \\[ 1 + z_{\\rm eff} = e^{\\Phi\\Gamma}. \\]\n" | |
| "- Compression mapping acting on observed z:\n" | |
| " \\[ 1 + z_{\\rm RFT} = (1 + z_{\\rm obs})\\,\\frac{1}{1+\\Phi\\Gamma}. \\]\n\n" | |
| "**Black holes and LISA coherence crest (toy)**\n\n" | |
| "- Classical Schwarzschild radius:\n" | |
| " \\[ R_S = \\frac{2GM}{c^2}. \\]\n" | |
| "- RFT-rescaled radius:\n" | |
| " \\[ R_{\\rm RFT} = U_{\\rm RFT}\\,R_S. \\]\n" | |
| "- Coherence crest is modeled as a temporary bump in \\(\\Phi\\Gamma(t)\\)\n" | |
| " that perturbs a GR-like frequency chirp in the LISA band.\n\n" | |
| "**Observer field and collapse**\n\n" | |
| "- Effective susceptibility including observers:\n" | |
| " \\[ \\Xi_{\\rm total} = \\Xi_{\\rm baseline} + \\lambda_{\\rm obs}\\,\\kappa_{\\rm obs} + \\Xi_{\\rm slider}. \\]\n" | |
| "- Collapse drive:\n" | |
| " \\[ \\lambda_{\\rm RFT} = \\Phi\\,\\Gamma\\,\\Xi_{\\rm total}\\,\\Psi. \\]\n" | |
| " When \\(\\Xi_{\\rm total} \\ge 1\\), the model flags a collapse event.\n\n" | |
| "These summaries are intentionally minimal; they are here so anyone using this\n" | |
| "space can see exactly what is being computed and how the global coherence\n" | |
| "field enters each module." | |
| ) | |
| # Provenance | |
| with gr.TabItem("Provenance"): | |
| prov_table = gr.Dataframe(headers=["module", "timestamp", "inputs", "outputs", "sha512"], wrap=True) | |
| prov_btn = gr.Button("Refresh provenance") | |
| prov_btn.click(prov_refresh, outputs=[prov_table]) | |
| # LEGAL / LICENCE | |
| with gr.TabItem("Legal & RFT licence"): | |
| gr.Markdown( | |
| "## Legal position and RFT licence (summary)\n\n" | |
| "- **Authorship**: Rendered Frame Theory (RFT), its coherence operators, field\n" | |
| " equations and applied models are authored by **Liam Grinstead**.\n\n" | |
| "- **Protection**: This work is protected under UK copyright law and the Berne\n" | |
| " Convention. All rights are reserved unless explicitly granted in writing.\n\n" | |
| "- **What you are allowed to do here**:\n" | |
| " - Use this space to explore, learn from, and critique RFT.\n" | |
| " - Plot, screenshot, and share results for **knowledge, education, and\n" | |
| " non-commercial research** (with appropriate attribution to the author).\n" | |
| " - Reference RFT in academic or scientific discussion, provided you cite the\n" | |
| " relevant public RFT papers / DOIs.\n\n" | |
| "- **What you are *not* allowed to do**:\n" | |
| " - Use RFT, its equations, or this lab to design or optimise **weapons or\n" | |
| " harmful systems**.\n" | |
| " - Lift the framework, operators, or code, rebrand them, and claim\n" | |
| " authorship or ownership.\n" | |
| " - Commercially exploit RFT (products, services, proprietary models,\n" | |
| " or derivative frameworks) **without explicit written permission** from\n" | |
| " the author.\n\n" | |
| "- **Intent**: RFT was created to break open the gatekeeping around cosmology\n" | |
| " and consciousness — not to hoard knowledge. This lab is deliberately public\n" | |
| " so that anyone can see how the model works. The non-negotiable line is\n" | |
| " that others do **not** get to weaponise this framework or privately profit\n" | |
| " from it while pretending it is theirs.\n\n" | |
| "If you wish to discuss legitimate collaborations, licensing, or formal\n" | |
| "research use, contact the author directly and reference this lab and the\n" | |
| "relevant RFT DOIs when you do so." | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() |