Load Hyperfit functions and interpolator¶
(Please update to the latest version of jaxqualin
to avoid errors!)
In this example we will call the hyperfit functions (listed in the jaxqualin
paper) and corresponding interpolators to estimate the amplitudes and phases of different modes, as a function of the binary black hole simulation parameters.
The hyperfit polynomial terms and interpolation data might be updated in future versions of the paper.
Import functions¶
from jaxqualin.data import (download_hyperfit_data,
download_interpolate_data,
make_hyper_fit_functions,
make_interpolators)
Download data¶
By default, the download functions compares the local version of the data with the one hosted on this webpage.
If the online one is newer, it will be downloaded and the local version will be overriden.
Use overwrite = 'force'
to force overwrite, and never
to avoid overwriting.
download_hyperfit_data()
download_interpolate_data()
Downloading data file from https://mhycheung.github.io/jaxqualin/data/hyperfit_functions_latest.json to /home/markc/Jaxqualin/docs/notebooks/.jaxqualin_cache/data/hyperfit_functions_latest.json Downloading data file from https://mhycheung.github.io/jaxqualin/data/interpolate_data_latest.json to /home/markc/Jaxqualin/docs/notebooks/.jaxqualin_cache/data/interpolate_data_latest.json
Make hyperfit functions and interpolators¶
Now we convert the downloaded data into functions and interpolators that we can easily call.
hyperfit_functions = make_hyper_fit_functions()
hyper_interpolators = make_interpolators()
Estimating the amplitude and phase¶
We can estimate the amplitude and phase for a set of progenitor parameters $(\eta, \chi_+, \chi_-)$. All is well if the hyperfit and interpolation returns similar results.
mode_name = '2.2.1'
eta, chi_p, chi_m = 0.2, 0.1, 0.4
A_fit = hyperfit_functions[mode_name]['A'](eta, chi_p, chi_m)
A_interp = hyper_interpolators[mode_name]['A'](eta, chi_p, chi_m)
phi_fit = hyperfit_functions[mode_name]['phi'](eta, chi_p, chi_m)
phi_interp = hyper_interpolators[mode_name]['phi'](eta, chi_p, chi_m)
print(f'A_fit: {A_fit:.5f}, A_interp: {A_interp:.5f}')
print(f'phi_fit: {phi_fit:.5f}, phi_interp: {phi_interp:.5f}')
A_fit: 3.46540, A_interp: 3.52040 phi_fit: 4.46984, phi_interp: 4.53029
The interpolator returns nan
if the requested point is outside of the convex hull of the interpolation data.
This can be used to check whether the hyperfit is extrapolating at the point, because the fit is trained with the same data used to construct the interpolator.
If the point is not covered by the convex hull, it could be because no simulations in the SXS catalog cover that region of the parameter space, or the mode amplitude is too weak (such that the mode extraction procedure missed the mode).
eta, chi_p, chi_m = 0.1, 0.9, -0.9
A_fit = hyperfit_functions[mode_name]['A'](eta, chi_p, chi_m)
A_interp = hyper_interpolators[mode_name]['A'](eta, chi_p, chi_m)
phi_fit = hyperfit_functions[mode_name]['phi'](eta, chi_p, chi_m)
phi_interp = hyper_interpolators[mode_name]['phi'](eta, chi_p, chi_m)
print(f'A_fit: {A_fit:.5f}, A_interp: {A_interp:.5f}')
print(f'phi_fit: {phi_fit:.5f}, phi_interp: {phi_interp:.5f}')
A_fit: 10.37139, A_interp: nan phi_fit: 6.87546, phi_interp: nan
When the hyperfit and interpolation returns significantly different results, care should be taken. The mode amplitude might be too small for the hyperfit to work accurately, and the results in these regions of parameter space should at most be used as an order of magnitude estimation. In fact, the hyperfit amplitude could even be negative, if the mode amplitude is too low.
mode_name = '-2.2.0'
eta, chi_p, chi_m = 0.2, -0.1, 0.4
A_fit = hyperfit_functions[mode_name]['A'](eta, chi_p, chi_m)
A_interp = hyper_interpolators[mode_name]['A'](eta, chi_p, chi_m)
phi_fit = hyperfit_functions[mode_name]['phi'](eta, chi_p, chi_m)
phi_interp = hyper_interpolators[mode_name]['phi'](eta, chi_p, chi_m)
print(f'A_fit: {A_fit:.5e}, A_interp: {A_interp:.5e}')
print(f'phi_fit: {phi_fit:.5f}, phi_interp: {phi_interp:.5f}')
A_fit: 7.61902e-05, A_interp: 1.32367e-04 phi_fit: 5.68904, phi_interp: 5.76627
We can also interpolate the fluctuation of the mode amplitude and phase when they were extracted with our procedure
dA_interp = hyper_interpolators[mode_name]['dA'](eta, chi_p, chi_m)
dphi_interp = hyper_interpolators[mode_name]['dphi'](eta, chi_p, chi_m)
print(f'dA_interp: {dA_interp:.5e}, dphi_interp: {dphi_interp:.5f}')
dA_interp: 2.87685e-05, dphi_interp: 0.23975
Changing parameterization¶
By specifying PN = False
, we can use the $(q, \chi_1, \chi_2)$ parameterization instead of $(\eta, \chi_+, \chi_-)$
hyperfit_functions = make_hyper_fit_functions(PN = False)
hyper_interpolators = make_interpolators(PN = False)
mode_name = '2.2.1'
q, chi_1, chi_2 = 2.3, 0.2, -0.2
A_fit = hyperfit_functions[mode_name]['A'](q, chi_1, chi_2)
A_interp = hyper_interpolators[mode_name]['A'](q, chi_1, chi_2)
phi_fit = hyperfit_functions[mode_name]['phi'](q, chi_1, chi_2)
phi_interp = hyper_interpolators[mode_name]['phi'](q, chi_1, chi_2)
print(f'A_fit: {A_fit:.5f}, A_interp: {A_interp:.5f}')
print(f'phi_fit: {phi_fit:.5f}, phi_interp: {phi_interp:.5f}')
A_fit: 3.35743, A_interp: 3.38756 phi_fit: 4.53457, phi_interp: 4.58072