gwBOB.BOB_utils module
- class gwBOB.BOB_utils.BOB[source]
Bases:
objectConstruct Backwards-One-Body waveforms.
Typical workflow:
bob = BOB() bob.initialize_with_sxs_data(“SXS:BBH:0305”) # or initialize_with_cce_data / initialize_with_NR_mode bob.what_should_BOB_create = “news” # or “psi4”, “strain_using_news”, etc. (see valid_choices()) bob.optimize_Omega0 = True # optional t, y = bob.construct_BOB()
Internally, state is grouped into six dataclasses (see
gwBOB/_state.py) accessed transparently via property delegation:_remnant: physics constants (mf, chif, Omega_ISCO, Omega_QNM, w_r, tau, l, m, …)_data: NR waveform timeseries (psi4_data, news_data, strain_data, …)_wf_config: waveform construction knobs (what_to_create, t0, Phi_0, minf_t0, …)_fit_config: fit/optimization knobs (optimize_Omega0, optimize_t0, start_fit_before_tpeak, …)_runtime: derived state recomputed on every mode switch (data, tp, Ap, t, t_tp_tau, …)_fit_result: fit outputs (fitted_t0, fitted_Omega0, fit_failed)
Every documented public attribute (e.g.
bob.tp,bob.Omega_0,bob.optimize_Omega0,bob.fitted_Omega0) is reachable via a@propertythat reads/writes through to the relevant container.__slots__is enabled so attribute typos raiseAttributeErrorinstead of silently creating a new attribute.Claude Code: See DESIGN_state_split.md for the architectural rationale.
- property Ap
- property M_tot
- property NR_based_on_BOB_ts
- property Omega_0
- property Omega_ISCO
- property Omega_QNM
- property Phi_0
- property auto_switch_to_numerical_integration
- property chif
- property chif_with_sign
- construct_BOB(N=2)[source]
Construct the BOB timeseries.
Dispatches to
construct_BOB_minf_t0(whenminf_t0is True) orconstruct_BOB_finite_t0(otherwise), then performs a phase alignment against the NR data and stores the resampled NR result inself.NR_based_on_BOB_tsfor plotting / comparison.- Parameters:
N (int) – Number of terms in the series expansion used for “strain_using_news” / “strain_using_psi4” integration. Ignored for direct (non-integrated) modes. Be careful: very large N can cause memory pressure.
- Returns:
(t, y) where t is the time array and y is the complex BOB waveform array.
- Return type:
tuple of (np.ndarray, np.ndarray)
- construct_BOB_current_quadrupole_naturally(perform_phase_alignment_first=False, lm_Omega0=None, lmm_Omega0=None)[source]
Construct the current quadrupole wave
I_lm = (i / sqrt(2)) * (h_lm - (-1)^|m| * conj(h_l,-m))
by building the (l, +m) and (l, -m) modes with BOB first, then combining.
- Parameters:
perform_phase_alignment_first (bool) – Whether to phase-align the (l, ±m) BOB modes against NR before combining (vs. aligning only the final current wave). Currently unused — see body.
lm_Omega0 (float, optional) – Override the initial-condition frequency for the (l, +m) BOB construction.
lmm_Omega0 (float, optional) – Override the initial-condition frequency for the (l, -m) BOB construction.
- Returns:
(union_ts, BOB_current_wave) — the time grid (union of the two mode grids) and the complex current-quadrupole waveform on it.
- Return type:
tuple of (np.ndarray, np.ndarray)
- construct_BOB_finite_t0(N)[source]
This function is used to construct the BOB for a finite t0 value.
- Parameters:
N (int) – Number of terms to use in the series if “strain_using_news” is used
- Returns:
BOB timeseries
- Return type:
Kuibit Timeseries
- construct_BOB_mass_quadrupole_naturally(perform_phase_alignment_first=False, lm_Omega0=None, lmm_Omega0=None)[source]
Construct the mass quadrupole wave
I_lm = (1 / sqrt(2)) * (h_lm + (-1)^|m| * conj(h_l,-m))
by building the (l, +m) and (l, -m) modes with BOB first, then combining.
- Parameters:
perform_phase_alignment_first (bool) – Whether to phase-align the (l, ±m) BOB modes against NR before combining (vs. aligning only the final mass wave). Currently unused — see body.
lm_Omega0 (float, optional) – Override the initial-condition frequency for the (l, +m) BOB construction.
lmm_Omega0 (float, optional) – Override the initial-condition frequency for the (l, -m) BOB construction.
- Returns:
(union_ts, BOB_mass_wave) — the time grid (union of the two mode grids) and the complex mass-quadrupole waveform on it.
- Return type:
tuple of (np.ndarray, np.ndarray)
- construct_BOB_minf_t0(N)[source]
This function is used to construct BOB taking t0 to be -infinity.
- Parameters:
N (int) – Number of terms to use in the series if “strain_using_news” is used
- Returns:
BOB timeseries
- Return type:
Kuibit Timeseries
- construct_NR_mass_and_current_quadrupole(what_to_create)[source]
Build the NR mass and current quadrupole waveforms from the loaded (l, ±m) modes via:
I_current = (i / sqrt(2)) * (h_lm - (-1)^|m| * conj(h_l,-m)) I_mass = (1 / sqrt(2)) * (h_lm + (-1)^|m| * conj(h_l,-m))
- Parameters:
what_to_create (str) – Which NR data to combine — one of “psi4”, “news”, “strain”.
- Returns:
(NR_current, NR_mass) — note the order: current first, mass second.
- Return type:
tuple of (kuibit_ts, kuibit_ts)
- property current_quadrupole_data
- property data
- property end_fit_after_tpeak
- fit_Omega0()[source]
Optimize the initial angular frequency Omega_0 by fitting BOB’s analytic frequency to the NR frequency over the configured fit window. Only valid for the t0 = -infinity flavor.
On success, writes the optimized value to
self.Omega_0. On failure (any exception duringcurve_fit), setsself.fit_failed = Trueand writesself.Omega_0 = self.Omega_ISCO.Side effect: if
end_fit_after_tpeakexceedsend_after_tpeak, the former is silently lowered to match. (Claude Code: See code_review §2 P5 E9 — flagged for future cleanup.)- Raises:
ValueError – If
minf_t0is False (usefit_t0for finite t0).
- property fit_failed
- fit_omega(x, Omega_0)[source]
Optimizer callback for
fit_Omega0— used byscipy.optimize.curve_fit.Mutates
self.Omega_0to the trial value, evaluates the analytic BOB frequency for the currently selected mode, and returns the frequency array sliced to the fit window. The mutation ofself.Omega_0is a known fragility (Claude Code: see code_review §2 P9 / DESIGN_stage3.md “Deferred work”); for now the caller is expected to overwriteself.Omega_0with the optimized value aftercurve_fitreturns.- Parameters:
x (np.ndarray) – Time samples (passed by
curve_fit; not actually used inside, sinceself.tprovides the time grid).Omega_0 (float) – Trial initial angular frequency.
- Returns:
BOB frequency evaluated at
self.t[start:end]for the configured fit window.- Return type:
np.ndarray
- fit_t0()[source]
Optimize the initial time t0 by grid search.
For each candidate t0, Omega_0 is fixed from the NR frequency at that time, and the squared residual against the BOB frequency is computed (via
fit_t0_only). On completion,self.t0,self.t0_tp_tau,self.Omega_0,self.fitted_t0,self.fitted_Omega0are all updated.Implementation note: a grid search is preferred to a least-squares fit because (1) each t0 is linked to a discrete Omega_0 with a finite timestep, (2) LSQ can get trapped in local minima even with a good initial guess, and (3) since this is a 1-D fit, brute-force is fast.
Use this when
minf_t0is False. For t0 = -infinity, usefit_Omega0instead.
- fit_t0_and_Omega0()[source]
Joint optimization of the initial time (t0) and initial frequency (Omega_0).
Not yet implemented. An experimental differential-evolution + curve_fit approach lived here previously but was unreliable; see git history if you want to revive it.
- fit_t0_and_omega(x, t0, Omega_0)[source]
Optimizer callback for joint t0 + Omega_0 fitting via
curve_fit.Currently UNCALLED: its only caller was the body of
fit_t0_and_Omega0, which was retired in favor ofraise NotImplementedError. Kept for future reuse if joint fitting is reimplemented.Mutates
self.Omega_0,self.t0,self.t0_tp_tauto the trial values. Same impurity caveat asfit_omega.- Parameters:
x (np.ndarray) – Time samples (passed by
curve_fit).t0 (float) – Trial initial time.
Omega_0 (float) – Trial initial angular frequency.
- Returns:
BOB frequency evaluated on the fit window. On evaluation failure, returns a flat array of 1e10 to signal a bad residual to the optimizer.
- Return type:
np.ndarray
- fit_t0_only(t00, freq_data)[source]
Optimizer callback for
fit_t0— used byscipy.optimize.brute.For each candidate t0, fixes Omega_0 from the NR frequency at that time and returns the squared residual. Mutates
self.t0,self.t0_tp_tau,self.Omega_0(same impurity caveat as the other fit callbacks).- Parameters:
t00 (np.ndarray) – Single-element array containing the trial t0 (
brutepasses parameters as arrays).freq_data (kuibit_ts) – NR (orbital) frequency timeseries — already divided by
|m|soyis big Omega.
- Returns:
Sum of squared residuals between BOB and NR frequencies on the configured fit window.
- Return type:
float
- property fitted_Omega0
- property fitted_t0
- property full_psi4_data
- property full_strain_data
- get_correct_Phi_and_Omega()[source]
Return the BOB phase and frequency arrays for the currently selected mode.
Dispatches to the correct
BOB_terms.BOB_<flavor>_phase[_finite_t0]function based onwhat_should_BOB_createandminf_t0.Note: even in the X_using_Y cases (e.g., strain_using_news), the analytic news-frequency term is used because the BOB amplitude is constructed to best describe the news; using the strain frequency for Omega_0 optimization on these cases would be unphysical.
- Returns:
(Phi, Omega) — phase and angular frequency arrays evaluated on the time grid
self.t.- Return type:
tuple of (np.ndarray, np.ndarray)
- Raises:
ValueError – If
what_should_BOB_createis not one of the supported flavors.
- get_news_data(**kwargs)[source]
Return the NR news timeseries (computed as d/dt of the strain) for an arbitrary (l, m) mode.
Same restrictions as
get_psi4_data: only the requested(l, m)and(l, -m)modes are available unlessload_all_modes=Trueat init.- kwargs:
l (int): l index (defaults to
self.l). m (int): m index (defaults toself.m).
- Returns:
(t, y) of the requested news mode.
- Return type:
tuple of (np.ndarray, np.ndarray)
- get_psi4_data(**kwargs)[source]
Return the NR psi4 timeseries for an arbitrary (l, m) mode.
Defaults to the (l, m) mode specified during initialization. Pass
l=...and/orm=...as keyword arguments to retrieve a different mode.With
load_all_modes=Falseat init (the default), only the requested(l, m)and(l, -m)modes are stored — calls for other modes raiseAttributeError. Passload_all_modes=Truetoinitialize_with_*if you need arbitrary mode access (uses much more memory). Afterinitialize_with_NR_mode, only the single mode passed in is ever available.- kwargs:
l (int): l index (defaults to
self.l). m (int): m index (defaults toself.m).
- Returns:
(t, y) of the requested psi4 mode.
- Return type:
tuple of (np.ndarray, np.ndarray)
- get_strain_data(**kwargs)[source]
Return the NR strain timeseries for an arbitrary (l, m) mode.
Same restrictions as
get_psi4_data: only the requested(l, m)and(l, -m)modes are available unlessload_all_modes=Trueat init.- kwargs:
l (int): l index (defaults to
self.l). m (int): m index (defaults toself.m).
- Returns:
(t, y) of the requested strain mode.
- Return type:
tuple of (np.ndarray, np.ndarray)
- get_t_isco()[source]
This function is used to get the time of the ISCO of the waveform.
- Parameters:
None
- Returns:
Time of ISCO of the waveform
- Return type:
float
- property h_L2_norm_tp
- initialize_with_NR_mode(t_NR, y_psi4, y_strain, mf, chif, l=2, m=2, w_r=-1, tau=-1, verbose=False)[source]
This function is used to initialize the BOB with NR data. Currently this function only supports the input of one (s=-2,l,m) mode.
- Parameters:
t_NR (array) – timeseries of NR psi4 data
y_psi4 (array) – values of NR psi4 data
y_strain (array) – values of NR strain data
mf (float) – final mass of the system
chif (array) – final spin of the system
l (int) – Mode number
m (int) – Mode number
w_r (float) – Angular frequency of the mode
tau (float) – Damping time of the mode
verbose (bool) – Whether to print verbose output
- initialize_with_cce_data(cce_id, l=2, m=2, perform_superrest_transformation=False, inertial_to_coprecessing_transformation=False, provide_own_abd=None, resample_dt=0.1, verbose=False, load_all_modes=False)[source]
This function is used to initialize the BOB with CCE data.
- Parameters:
cce_id (str) – CCE id of the simulation (https://data.black-holes.org/waveforms/extcce_catalog.html)
l (int) – Mode number
m (int) – Mode number
perform_superrest_transformation (bool) – Whether to perform a superrest transformation
inertial_to_coprecessing_transformation (bool) – Whether to perform an inertial to coprecessing transformation
provide_own_abd (scri.Abd) – Use a user passed in scri abd object (maybe useful if the user has specific pre-processing requirements)
resample_dt (float) – Resampling time step
verbose (bool) – Whether to print verbose output
load_all_modes (bool) – If True, retain the full multi-mode interpolated strain and psi4 arrays so that
get_*_data(l, m)can return arbitrary modes after init. Default is False (memory-efficient): only the requested(l, m)and(l, -m)modes are retained. Claude Code: SeeMEMORY.mdfor measurements.
- initialize_with_sxs_data(sxs_id, l=2, m=2, download=True, resample_dt=0.1, verbose=False, inertial_to_coprecessing_transformation=False, load_all_modes=False)[source]
This function is used to initialize the BOB with SXS data.
Memory: by default, this method extracts the requested
(l, m)and(l, -m)modes from the un-interpolated waveform first and resamples only those two modes to the dense uniform grid. This drops the init peak from ~1.2 GB to ~700 MB on SXS:BBH:2325. The original slow path (interpolate all ~77 modes, then slice) is still used whenload_all_modes=Trueorinertial_to_coprecessing_transformation=True, since both require the full multi-mode object. Claude Code: see peak_memory_fix.md for the rollout history.- Parameters:
sxs_id (str) – SXS id of the simulation
l (int) – Mode number
m (int) – Mode number
download (bool) – Whether to download the data
resample_dt (float) – Resampling time step
verbose (bool) – Whether to print verbose output
inertial_to_coprecessing_transformation (bool) – Whether to perform inertial to coprecessing transformation. Forces the slow init path (rotation is a multi-mode operation).
load_all_modes (bool) – If True, retain the full multi-mode interpolated strain and psi4 arrays so that
get_psi4_data(l, m)/get_news_data(l, m)/get_strain_data(l, m)can return arbitrary modes after init. Default is False (memory-efficient): only the requested(l, m)and(l, -m)modes are retained, dropping ~110 MB / BOB instance for SXS:BBH:2325.load_all_modes=Truealso forces the slow init path. Claude Code: SeeMEMORY.mdfor measured costs and parallel-init implications.
- property l
- property m
- property mass_quadrupole_data
- property metadata
- property mf
- property minf_t0
- property news_Ap
- property news_data
- property news_mm_data
- property news_tp
- property optimize_Omega0
- property optimize_t0
Return whether t0 optimization is requested.
- property optimize_t0_and_Omega0
Return whether joint t0 + Omega_0 optimization is requested.
- property perform_final_amplitude_rescaling
- property perform_final_time_alignment
- property psi4_Ap
- property psi4_data
- property psi4_mm_data
- property psi4_tp
- property resample_dt
- residual_t0_and_omega(p, t_freq, y_freq)[source]
Optimizer callback for joint t0 + Omega_0 fitting via
scipy.optimize.differential_evolution.Currently UNCALLED: its only caller was the body of
fit_t0_and_Omega0, which was retired in favor ofraise NotImplementedError. Kept for future reuse if joint fitting is reimplemented.Mutates
self.Omega_0,self.t0,self.t0_tp_tauto the trial values. Same impurity caveat as the other fit callbacks.- Parameters:
p (tuple of (float, float)) – Trial parameters (t0, Omega_0).
t_freq (np.ndarray) – Time array of the NR frequency reference.
y_freq (np.ndarray) – NR frequency values aligned with
t_freq.
- Returns:
Sum of squared residuals between the BOB-predicted and NR frequencies over the configured fit window.
- Return type:
float
- property set_end_after_tpeak
Return the configured end time relative to tpeak.
- property set_initial_time
Return the configured initial time t0 (in code units relative to peak).
- property set_start_before_tpeak
Return the configured start time relative to tpeak.
- property start_fit_before_tpeak
- property strain_Ap
- property strain_data
- property strain_mm_data
- property strain_scri_wm
- property strain_tp
- property strain_wm
- property sxs_id
- property t
- property t0
- property t0_tp_tau
- property t_tp_tau
- property tau
- property tp
- property use_strain_for_Omega0_optimization
- property use_strain_for_t0_optimization
- valid_choices()[source]
Print the valid choices for what_should_BOB_create.
Derived from the dispatch tables (_SIMPLE_MODES, _QUADRUPOLE_MODES) so this listing and the setter cannot drift apart.
- property w_r
- property what_is_BOB_building
- property what_should_BOB_create
Returns what BOB should create