Describe the bug
When convert_to_lal_binary_neutron_star_parameters receives a parameter dictionary containing both the component tidal deformabilities (lambda_1 and lambda_2) and the derived tidal parameters (lambda_tilde and delta_lambda_tilde), it reconstructs and overwrites the existing component values from the derived representation. Due to floating-point round-off, this conversion can change an explicitly supplied lambda_1 = 0.0 into a very small negative value.
I think this occurs during run_sampler post-processing because coversion_function=conversion_function=bilby.gw.conversion.generate_all_bns_parameters is applied to the injection parameters twice. The first call adds lambda_tilde and delta_lambda_tilde and the second call passes the filled dictionary back through convert_to_lal_binary_neutron_star_parameters, triggering the overwrite.
In my case, the (NSBH) injection specified:
lambda_1 = 0.0
lambda_2 = 1097.4026147742702
The sampler completed successfully and produced posterior samples. During post-processing, Bilby converted the injection parameters a second time. Since the first conversion had added lambda_tilde and delta_lambda_tilde, the second conversion reconstructed the component tidal deformabilities from those derived quantities. Due to floating-point round-off, the reconstructed value was approximately:
LALSimulation printed this as:
and rejected the waveform because tidal deformabilities are required to be non-negative.
This appears to be caused by the following logic in convert_to_lal_binary_neutron_star_parameters:
if 'delta_lambda_tilde' in converted_parameters.keys():
converted_parameters['lambda_1'], converted_parameters['lambda_2'] =\
lambda_tilde_delta_lambda_tilde_to_lambda_1_lambda_2(
converted_parameters['lambda_tilde'],
parameters['delta_lambda_tilde'],
converted_parameters['mass_1'],
converted_parameters['mass_2'])
elif 'lambda_tilde' in converted_parameters.keys():
converted_parameters['lambda_1'], converted_parameters['lambda_2'] =\
lambda_tilde_to_lambda_1_lambda_2(
converted_parameters['lambda_tilde'],
converted_parameters['mass_1'],
converted_parameters['mass_2'])
These lines overwrite lambda_1 and lambda_2 even when both component values are already present and valid.
To Reproduce
A minimal reproducer:
import bilby
parameters = {
"mass_1": 7.320188129088971,
"mass_2": 1.4957247709090036,
"lambda_1": 0.0,
"lambda_2": 1097.4026147742702,
}
first_conversion = bilby.gw.conversion.generate_all_bns_parameters(
parameters
)
print("After first conversion:")
print("lambda_1 =", repr(first_conversion["lambda_1"]))
print("lambda_2 =", repr(first_conversion["lambda_2"]))
print("lambda_tilde =", repr(first_conversion["lambda_tilde"]))
print(
"delta_lambda_tilde =",
repr(first_conversion["delta_lambda_tilde"]),
)
second_conversion, _ = (
bilby.gw.conversion.convert_to_lal_binary_neutron_star_parameters(
first_conversion
)
)
print("After second conversion:")
print("lambda_1 =", repr(second_conversion["lambda_1"]))
print("lambda_2 =", repr(second_conversion["lambda_2"]))
For the values above, the second conversion produces a value close to:
lambda_1 = -2.45587692656649e-14
In my run, the relevant runtime sequence was:
bilby INFO : Rejection sampling nested samples to obtain 6335 posterior samples
bilby INFO : Sampling time: 1 day, 3:24:28.088555
bilby WARNING : Result.save_to_file called with extension=True. This will default to json, and ignore the extension from the filename.
The failure then occurred after sampling.
Error message
XLAL Error - XLALStoreTidalParametersFromLambdas (LALSimIMRPhenomXHM_tidal.c:71): Tidal deformabilities cannot be negative. Value in LALDict are lambda1 = -0.000000, lambda2 = 1097.402615.
XLAL Error - XLALStoreTidalParametersFromLambdas (LALSimIMRPhenomXHM_tidal.c:71): Invalid argument
XLAL Error - IMRPhenomXSetWaveformVariables (LALSimIMRPhenomX_internals.c:306): Failed to set tidal parameters from lambdas.
XLAL Error - IMRPhenomXSetWaveformVariables (LALSimIMRPhenomX_internals.c:306): Internal function call failed: Invalid argument
XLAL Error - XLALSimIMRPhenomXHMFrequencySequence (LALSimIMRPhenomXHM.c:1785): Error: IMRPhenomXSetWaveformVariables failed.
XLAL Error - XLALSimIMRPhenomXHMFrequencySequence (LALSimIMRPhenomXHM.c:1785): Internal function call failed: Invalid argument
XLAL Error - XLALSimInspiralChooseFDWaveformSequence (LALSimInspiralWaveformCache.c:1710): Internal function call failed: Invalid argument
Traceback (most recent call last):
File "/ligo/home/ligo.org/ish.gupta/Projects/nsbh_hom/tests/test1/phenom-nsbh/run_1/ECC/runs/run_1/run.py", line 199, in <module>
result = bilby.run_sampler(
^^^^^^^^^^^^^^^^^^
File "/scratch2/ligo.org/ish.gupta/conda-envs/nsbh-hom/src/bilby/bilby/core/sampler/__init__.py", line 358, in run_sampler
result.injection_parameters = conversion_function(
^^^^^^^^^^^^^^^^^^^^
File "/scratch2/ligo.org/ish.gupta/conda-envs/nsbh-hom/src/bilby/bilby/gw/conversion.py", line 1758, in generate_all_bns_parameters
output_sample = _generate_all_cbc_parameters(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/scratch2/ligo.org/ish.gupta/conda-envs/nsbh-hom/src/bilby/bilby/gw/conversion.py", line 1653, in _generate_all_cbc_parameters
compute_per_detector_log_likelihoods(
File "/scratch2/ligo.org/ish.gupta/conda-envs/nsbh-hom/src/bilby/bilby/gw/conversion.py", line 2317, in compute_per_detector_log_likelihoods
samples = likelihood.compute_per_detector_log_likelihood(samples)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/scratch2/ligo.org/ish.gupta/conda-envs/nsbh-hom/src/bilby/bilby/gw/likelihood/base.py", line 482, in compute_per_detector_log_likelihood
self.waveform_generator.frequency_domain_strain(parameters)
File "/scratch2/ligo.org/ish.gupta/conda-envs/nsbh-hom/src/bilby/bilby/gw/waveform_generator.py", line 135, in frequency_domain_strain
return self._calculate_strain(model=self.frequency_domain_source_model,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/scratch2/ligo.org/ish.gupta/conda-envs/nsbh-hom/src/bilby/bilby/gw/waveform_generator.py", line 197, in _calculate_strain
model_strain = self._strain_from_model(model_data_points, model, parameters, xp=xp)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/scratch2/ligo.org/ish.gupta/conda-envs/nsbh-hom/src/bilby/bilby/gw/waveform_generator.py", line 214, in _strain_from_model
return model(model_data_points, **parameters)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/scratch2/ligo.org/ish.gupta/conda-envs/nsbh-hom/src/bilby/bilby/gw/source.py", line 795, in lal_binary_neutron_star_relative_binning
return _base_waveform_frequency_sequence(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/scratch2/ligo.org/ish.gupta/conda-envs/nsbh-hom/src/bilby/bilby/gw/source.py", line 1125, in _base_waveform_frequency_sequence
h_plus, h_cross = lalsim_SimInspiralChooseFDWaveformSequence(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/scratch2/ligo.org/ish.gupta/conda-envs/nsbh-hom/src/bilby/bilby/gw/utils.py", line 743, in lalsim_SimInspiralChooseFDWaveformSequence
return SimInspiralChooseFDWaveformSequence(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: Internal function call failed: Invalid argument
Expected behavior
When both lambda_1 and lambda_2 are already present and non-None, Bilby should preserve those component values.
Derived quantities such as lambda_tilde and delta_lambda_tilde should not take precedence over explicitly supplied component tidal deformabilities during a subsequent conversion.
Suggested solution (optional)
Only reconstruct lambda_1 and lambda_2 from the combined tidal quantities when valid component lambdas are not already available.
For example:
have_component_lambdas = all(
key in converted_parameters
and converted_parameters[key] is not None
for key in ("lambda_1", "lambda_2")
)
if (
"delta_lambda_tilde" in converted_parameters
and not have_component_lambdas
):
converted_parameters["lambda_1"], converted_parameters["lambda_2"] = (
lambda_tilde_delta_lambda_tilde_to_lambda_1_lambda_2(
converted_parameters["lambda_tilde"],
converted_parameters["delta_lambda_tilde"],
converted_parameters["mass_1"],
converted_parameters["mass_2"],
)
)
elif (
"lambda_tilde" in converted_parameters
and not have_component_lambdas
):
converted_parameters["lambda_1"], converted_parameters["lambda_2"] = (
lambda_tilde_to_lambda_1_lambda_2(
converted_parameters["lambda_tilde"],
converted_parameters["mass_1"],
converted_parameters["mass_2"],
)
)
This would:
- Preserve explicitly available
lambda_1 and lambda_2.
- Reconstruct component lambdas from
lambda_tilde and delta_lambda_tilde only when the component representation is unavailable.
Environment
- Bilby version:
2.8.0.dev60+g28fca2270
- Installation method: source installation inside a Conda environment
- Python version: 3.11
- Dynesty version: 3.0.0
- LAL version: 7.6.1.1
- LALSimulation version: 6.1.0.1
- Waveform approximant:
IMRPhenomXHM_NSBH (private repo)
- Source model:
bilby.gw.source.lal_binary_neutron_star_relative_binning
Describe the bug
When
convert_to_lal_binary_neutron_star_parametersreceives a parameter dictionary containing both the component tidal deformabilities (lambda_1andlambda_2) and the derived tidal parameters (lambda_tildeanddelta_lambda_tilde), it reconstructs and overwrites the existing component values from the derived representation. Due to floating-point round-off, this conversion can change an explicitly suppliedlambda_1 = 0.0into a very small negative value.I think this occurs during
run_samplerpost-processing becausecoversion_function=conversion_function=bilby.gw.conversion.generate_all_bns_parametersis applied to the injection parameters twice. The first call addslambda_tildeanddelta_lambda_tildeand the second call passes the filled dictionary back throughconvert_to_lal_binary_neutron_star_parameters, triggering the overwrite.In my case, the (NSBH) injection specified:
The sampler completed successfully and produced posterior samples. During post-processing, Bilby converted the injection parameters a second time. Since the first conversion had added
lambda_tildeanddelta_lambda_tilde, the second conversion reconstructed the component tidal deformabilities from those derived quantities. Due to floating-point round-off, the reconstructed value was approximately:LALSimulation printed this as:
and rejected the waveform because tidal deformabilities are required to be non-negative.
This appears to be caused by the following logic in
convert_to_lal_binary_neutron_star_parameters:These lines overwrite
lambda_1andlambda_2even when both component values are already present and valid.To Reproduce
A minimal reproducer:
For the values above, the second conversion produces a value close to:
In my run, the relevant runtime sequence was:
The failure then occurred after sampling.
Error message
Expected behavior
When both
lambda_1andlambda_2are already present and non-None, Bilby should preserve those component values.Derived quantities such as
lambda_tildeanddelta_lambda_tildeshould not take precedence over explicitly supplied component tidal deformabilities during a subsequent conversion.Suggested solution (optional)
Only reconstruct
lambda_1andlambda_2from the combined tidal quantities when valid component lambdas are not already available.For example:
This would:
lambda_1andlambda_2.lambda_tildeanddelta_lambda_tildeonly when the component representation is unavailable.Environment
2.8.0.dev60+g28fca2270IMRPhenomXHM_NSBH(private repo)bilby.gw.source.lal_binary_neutron_star_relative_binning