#!/usr/bin/env python """Vazquez-Semadeni referee item (i): accelerating-SFR ensemble bias. In global hierarchical collapse (GHC) the volume-averaged massive-star birthrate B(t) rises with time. The steady-state estimator identifies the observed ratio R_obs = N_emb/N_OB with the lifetime ratio tau_emb/. But: N_emb(now) = B(now) * tau_emb (currently forming) N_OB(now) = int_{now-tMS}^{now} B(t') dt' (accumulated on MS) so R_obs = B(now) tau_emb / int B dt', while the true steady-state ratio is tau_emb/. The bias bias = R_obs / R_true = B(now) / int_{now-}^{now} B dt' is >1 for any rising B: the estimator OVERstates tau_emb, i.e. the true luminous embedded phase is even shorter. We quantify the factor with a small ensemble MC over the acceleration timescale and the mean MS lifetime, and cross-check against the independently measured local OB overdensity (Quintana et al. 2026). """ import numpy as np rng = np.random.default_rng(20260719) N = 200000 # Exponential accelerating birthrate B(t) = B0 exp(t / tau_acc). # tau_acc: GHC/local free-fall driven; molecular-cloud assembly a few Myr. # Spread 2-10 Myr covers slow (near-steady) to fast acceleration. tau_acc = rng.uniform(2.0, 10.0, N) # Myr # for the L>1e5 population (IMF-weighted, from sec:clock) ~4.3 Myr, # allow 3.5-5.0 to fold lifetime-model spread. tMS = rng.uniform(3.5, 5.0, N) # Myr x = tMS / tau_acc bias = x / (1.0 - np.exp(-x)) # >=1 always; ->1 as x->0 q = np.percentile(bias, [2.5, 16, 50, 84, 97.5]) print("=== accelerating-SFR bias on tau_emb (R_obs/R_true) ===") print(f"bias median {q[2]:.2f} 68% [{q[1]:.2f}-{q[3]:.2f}] " f"95% [{q[0]:.2f}-{q[4]:.2f}]") # Corrected timescale: measured tau_emb = 7e4 yr (rho=61) is an overestimate. tau_meas = 7.0e4 tc = tau_meas / bias qc = np.percentile(tc, [16, 50, 84]) print(f"corrected tau_emb from 7e4 yr: median {qc[1]:.2e} " f"68% [{qc[0]:.2e}-{qc[2]:.2e}] yr") # Cross-check: the bias should not exceed the measured local OB overdensity, # which directly bounds B(now)/. Quintana+2026 give the # local volume ~1.3-2x overdense vs its long-term average. overdens = np.array([1.3, 2.0]) print(f"independent bound from OB overdensity B(now)/: {overdens} " f"-> consistent with MC bias (median {q[2]:.2f})") # Fraction of ensemble with bias in the 1.3-2.0 'expected' band: frac = np.mean((bias > 1.2) & (bias < 2.1)) print(f"fraction of ensemble with bias in 1.2-2.1: {frac:.2f}")