Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Tests

on:
push:
branches: [master]
pull_request:

jobs:
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install dependencies
run: |
pip install lalsuite pycbc pytest black
pip install -e .

- name: Run tests
run: pytest tests/ -v
38 changes: 13 additions & 25 deletions esigmapy/blend.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Copyright (C) 2023 Kartikey Sharma, Prayush Kumar
#
"""Master function to hybridise any complex timeseries using the 'frequency' as a user input,
"""Master function to hybridise any complex timeseries using the 'frequency' as a user input,
specifically to be used for gravitational waveform hybridisation, fine-tuned for a single mode.
"""

Expand Down Expand Up @@ -100,17 +100,13 @@ def align_in_phase(
align_merger_to_inspiral=True,
):
if len(inspiral) == 0:
raise IOError(
f"""You passed an inspiral waveform of zero length, to align
with merger-ringdown!"""
)
raise IOError(f"""You passed an inspiral waveform of zero length, to align
with merger-ringdown!""")
if (t2_index_insp + 1 - t1_index_insp) < 1:
raise IOError(
f"""You have passed a very narrow window for the inspiral
raise IOError(f"""You have passed a very narrow window for the inspiral
waveform's hybridization. As per your input, the inspiral
waveform from index {t1_index_insp} to {t2_index_insp + 1}
should be used to attach merger-ringdown"""
)
should be used to attach merger-ringdown""")

# Function alignes the two waveforms using the phase, optimised over the attachment region
# m from l,m mode
Expand Down Expand Up @@ -237,10 +233,8 @@ def blend_modes(
Set this to True to enable logging output.
"""
if frq_width <= 0:
raise IOError(
f"""You are trying to blend over a frequency window of
negative length (= {frq_width}Hz). Fix this."""
)
raise IOError(f"""You are trying to blend over a frequency window of
negative length (= {frq_width}Hz). Fix this.""")
if blend_using_avg_orbital_frequency:
if len(inspiral_orbital_frequency) != len(inspiral_modes[mode_to_align_by]):
raise IOError(
Expand Down Expand Up @@ -327,14 +321,12 @@ def blend_modes(
inspiral_orbital_frequency, (frq_attach + frq_width / 2) / em
)
if verbose > 1:
print(
f"""Hybridizing using orbital frequency. Frequency
print(f"""Hybridizing using orbital frequency. Frequency
{frq_attach + frq_width / 2}Hz found at {t2_index_insp}.
The same frequency would have been found at index
{find_last_value_location_in_series(frq_insp[(el, em)],
frq_attach + frq_width / 2)} of mode frequency evolution.
"""
)
""")
else:
t2_index_insp = find_last_value_location_in_series(
frq_insp[(el, em)], frq_attach + frq_width / 2
Expand All @@ -344,17 +336,13 @@ def blend_modes(
t1_index_insp = t2_index_insp - (t2_index_mr - t1_index_mr)

if verbose > 4:
print(
f"""In the merger-ringdown waveform, the hybridization frequency window
print(f"""In the merger-ringdown waveform, the hybridization frequency window
[{frq_attach - frq_width / 2}, {frq_attach + frq_width / 2}]
was found at indices [{t1_index_mr}, {t2_index_mr}]
"""
)
print(
f"""In the inspiral waveform, the same window is to be found at
""")
print(f"""In the inspiral waveform, the same window is to be found at
indices [{t1_index_insp}, {t2_index_insp}.]
"""
)
""")
"""
Theoretically, we NEED a timeshift to align the waveforms in frequency.
Instead of shifting one of the two waveforms for alignment, we are defining
Expand Down
71 changes: 24 additions & 47 deletions esigmapy/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ def get_inspiral_esigma_modes(

if f_ref < f_lower:
ref_idx = np.searchsorted(
(retval[1].data.data ** 1.5) / ((mass1 + mass2) * lal.MTSUN_SI * np.pi),
(retval[1].data.data**1.5) / ((mass1 + mass2) * lal.MTSUN_SI * np.pi),
f_lower,
)
new_len = len(retval[0].data.data) - ref_idx
Expand Down Expand Up @@ -535,10 +535,8 @@ def _get_transition_frequency_window(
# frequency, towards the end of waveform

if verbose > 4:
print(
f"""Transition frequency found at index {transition_idx}
in the orbital frequency array of length {len(orbital_freq)}"""
)
print(f"""Transition frequency found at index {transition_idx}
in the orbital frequency array of length {len(orbital_freq)}""")

if blend_using_avg_orbital_frequency:
# We integrate `orbital_freq` to obtain `orbital_phase`
Expand Down Expand Up @@ -640,11 +638,9 @@ def _get_transition_frequency_window(
)

if verbose > 4:
print(
f"""The transition is to happen in a window from
print(f"""The transition is to happen in a window from
frequencies: [{orbital_freq[window_start_idx]}, {orbital_freq[transition_idx]}]Hz,
between indices: [{window_start_idx}, {transition_idx}]"""
)
between indices: [{window_start_idx}, {transition_idx}]""")
else:
raise RuntimeError(
"""We should never reach here. Did you set a non-bool value for the
Expand Down Expand Up @@ -772,22 +768,16 @@ def get_imr_esigma_modes(
"""
check_available_mr_approximants(merger_ringdown_approximant)
if (mean_anomaly is None) and (coa_phase is None):
raise IOError(
f"""Please specify one of the phase angles, either of
`mean_anomaly` or `coa_phase`."""
)
raise IOError(f"""Please specify one of the phase angles, either of
`mean_anomaly` or `coa_phase`.""")
if blend_aligning_merger_to_inspiral and (mean_anomaly is None):
raise IOError(
f"""If you want to attach ESIGMA inspiral to merger, by
raise IOError(f"""If you want to attach ESIGMA inspiral to merger, by
phase shifting merger to inspiral, please specify the
phase angle `mean_anomaly`"""
)
phase angle `mean_anomaly`""")
if (not blend_aligning_merger_to_inspiral) and (coa_phase is None):
raise IOError(
f"""If you want to attach ESIGMA inspiral to merger, by
raise IOError(f"""If you want to attach ESIGMA inspiral to merger, by
phase shifting inspiral to merger, please specify the
phase angle `coa_phase`"""
)
phase angle `coa_phase`""")
if mean_anomaly is None:
mean_anomaly = 0
if coa_phase is None:
Expand All @@ -807,13 +797,11 @@ def get_imr_esigma_modes(
set(available_inspiral_orbital_params)
)
if return_orbital_params_user != set(return_orbital_params):
print(
f"""Warning: You requested the following list of orbital
print(f"""Warning: You requested the following list of orbital
parameters to be returned: {return_orbital_params}, but we reduce it to
{return_orbital_params_user} as we only have the evolution of the following
parameters available with us: {available_inspiral_orbital_params}.
"""
)
""")
elif not return_orbital_params:
return_orbital_params = []
return_orbital_params_user = False
Expand Down Expand Up @@ -871,26 +859,21 @@ def get_imr_esigma_modes(
raise RuntimeError(
f"""The inspiral modes do not contain the primary
desired {mode_to_align_by} multipole. It currently holds only the following:
{modes_inspiral_numpy.keys()}"""
)
{modes_inspiral_numpy.keys()}""")

orbital_eccentricity = retval[-2]["e"]
# Throw error if eccentricity at the end of inspiral is definitely unsafe
if orbital_eccentricity[-1] > ECCENTRICITY_LEVEL_ISCO_ERROR:
raise IOError(
f"""ERROR: You entered a very large initial eccentricity
raise IOError(f"""ERROR: You entered a very large initial eccentricity
{eccentricity}. The orbital eccentricity at the end of inspiral was
{orbital_eccentricity[-1]}. The merger-ringdown attachment with a
quasicircular will be questionable."""
)
quasicircular will be questionable.""")
# Warn user if eccentricity at the end of inspiral is potentially unsafe
if orbital_eccentricity[-1] > ECCENTRICITY_LEVEL_ISCO_WARNING and verbose:
print(
f"""WARNING: You entered a very large initial eccentricity
print(f"""WARNING: You entered a very large initial eccentricity
{eccentricity}. The orbital eccentricity at the end of inspiral was
{orbital_eccentricity[-1]}. The merger-ringdown attachment with a quasicircular
model might be affected."""
)
model might be affected.""")

if (f_window_mr_transition is None) or failsafe or (verbose > 1):
if blend_using_avg_orbital_frequency:
Expand All @@ -914,14 +897,12 @@ def get_imr_esigma_modes(
modes_inspiral_numpy[mode_to_align_by]
)
mode_frequency = esigmapy.blend.compute_frequency(mode_phase, delta_t)
print(
f"""DEBUG: Orbital freq at end of inspiral is {orbital_frequency[-1]}Hz,
print(f"""DEBUG: Orbital freq at end of inspiral is {orbital_frequency[-1]}Hz,
mode-{mode_to_align_by} freq at the end of inspiral is {mode_frequency[-1]}Hz, max and min
mode-{mode_to_align_by} frequencies are {np.max(mode_frequency)}Hz and
{np.min(mode_frequency)}Hz, and the transition frequency (of {mode_to_align_by}-mode)
requested is {f_mr_transition}Hz, which should be less than the maximum freq of
{mode_to_align_by}-mode: {mode_frequency.max()}Hz."""
)
{mode_to_align_by}-mode: {mode_frequency.max()}Hz.""")
return (
modes_inspiral_numpy,
mode_phase,
Expand All @@ -940,12 +921,10 @@ def get_imr_esigma_modes(
mode_frequency = esigmapy.blend.compute_frequency(mode_phase, delta_t)
if mode_frequency.max() < f_mr_transition:
if verbose:
print(
f"""FAILSAFE: Maximum orbital freq during inspiral is
print(f"""FAILSAFE: Maximum orbital freq during inspiral is
{orbital_frequency.max()}Hz, and max frequency of {mode_to_align_by}-mode is
{mode_frequency.max()}Hz, so we are resetting transition frequency from
{f_mr_transition}Hz to {mode_frequency.max()}Hz."""
)
{f_mr_transition}Hz to {mode_frequency.max()}Hz.""")
f_mr_transition = mode_frequency.max()

# If the user does not provide the width of hybridization window (
Expand Down Expand Up @@ -1026,12 +1005,10 @@ def get_imr_esigma_modes(
verbose=verbose,
)
except Exception as exc:
print(
f"""Inspiral + MergerRingdown attachment failed. Its very likely
print(f"""Inspiral + MergerRingdown attachment failed. Its very likely
that you entered a very large initial eccentricity {eccentricity}. The orbital
eccentricity at the end of inspiral was {orbital_eccentricity[-1]}
"""
)
""")
raise exc
modes_imr_numpy = retval[0]

Expand Down
3 changes: 1 addition & 2 deletions esigmapy/legacy.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Copyright (C) 2023 Prayush Kumar
#
"""Legacy code to calibrate transition/attachment of inspiral and merger-ringdown
"""
"""Legacy code to calibrate transition/attachment of inspiral and merger-ringdown"""


class FitMOmegaIMRAttachmentNonSpinning:
Expand Down
42 changes: 14 additions & 28 deletions esigmapy/surrogate/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,13 +422,11 @@ def get_imr_esigmasur_mode(
set(available_inspiral_orbital_params)
)
if return_orbital_params_user != set(return_orbital_params):
print(
f"""Warning: You requested the following list of orbital
print(f"""Warning: You requested the following list of orbital
parameters to be returned: {return_orbital_params}, but we reduce it to
{return_orbital_params_user} as we only have the evolution of the following
parameters available with us: {available_inspiral_orbital_params}.
"""
)
""")
elif not return_orbital_params:
return_orbital_params = []
return_orbital_params_user = False
Expand Down Expand Up @@ -475,29 +473,23 @@ def get_imr_esigmasur_mode(
modes_inspiral_numpy = retval[-1]

if mode_to_align_by not in modes_inspiral_numpy:
raise RuntimeError(
f"""The inspiral modes do not contain the primary
raise RuntimeError(f"""The inspiral modes do not contain the primary
desired {mode_to_align_by} multipole. It currently holds only the following:
{modes_inspiral_numpy.keys()}"""
)
{modes_inspiral_numpy.keys()}""")

orbital_eccentricity = retval[-2]["e"]
# Throw error if eccentricity at the end of inspiral is definitely unsafe
if orbital_eccentricity[-1] > ECCENTRICITY_LEVEL_ISCO_ERROR:
raise IOError(
f"""ERROR: You entered a very large reference eccentricity
raise IOError(f"""ERROR: You entered a very large reference eccentricity
{reference_eccentricity}. The orbital eccentricity at the end of inspiral was
{orbital_eccentricity[-1]}. The merger-ringdown attachment with a
quasicircular will be questionable."""
)
quasicircular will be questionable.""")
# Warn user if eccentricity at the end of inspiral is potentially unsafe
if orbital_eccentricity[-1] > ECCENTRICITY_LEVEL_ISCO_WARNING and verbose:
print(
f"""WARNING: You entered a very large reference eccentricity
print(f"""WARNING: You entered a very large reference eccentricity
{reference_eccentricity}. The orbital eccentricity at the end of inspiral was
{orbital_eccentricity[-1]}. The merger-ringdown attachment with a quasicircular
model might be affected."""
)
model might be affected.""")

if (f_window_mr_transition is None) or failsafe or (verbose > 1):
if blend_using_avg_orbital_frequency:
Expand All @@ -521,14 +513,12 @@ def get_imr_esigmasur_mode(
modes_inspiral_numpy[mode_to_align_by]
)
mode_frequency = esigmapy.blend.compute_frequency(mode_phase, delta_t)
print(
f"""DEBUG: Orbital freq at end of inspiral is {orbital_frequency[-1]}Hz,
print(f"""DEBUG: Orbital freq at end of inspiral is {orbital_frequency[-1]}Hz,
mode-{mode_to_align_by} freq at the end of inspiral is {mode_frequency[-1]}Hz, max and min
mode-{mode_to_align_by} frequencies are {np.max(mode_frequency)}Hz and
{np.min(mode_frequency)}Hz, and the transition frequency (of {mode_to_align_by}-mode)
requested is {f_mr_transition}Hz, which should be less than the maximum freq of
{mode_to_align_by}-mode: {mode_frequency.max()}Hz."""
)
{mode_to_align_by}-mode: {mode_frequency.max()}Hz.""")
return (
modes_inspiral_numpy,
mode_phase,
Expand All @@ -547,12 +537,10 @@ def get_imr_esigmasur_mode(
mode_frequency = esigmapy.blend.compute_frequency(mode_phase, delta_t)
if mode_frequency.max() < f_mr_transition:
if verbose:
print(
f"""FAILSAFE: Maximum orbital freq during inspiral is
print(f"""FAILSAFE: Maximum orbital freq during inspiral is
{orbital_frequency.max()}Hz, and max frequency of {mode_to_align_by}-mode is
{mode_frequency.max()}Hz, so we are resetting transition frequency from
{f_mr_transition}Hz to {mode_frequency.max()}Hz."""
)
{f_mr_transition}Hz to {mode_frequency.max()}Hz.""")
f_mr_transition = mode_frequency.max()

# If the user does not provide the width of hybridization window (
Expand Down Expand Up @@ -633,12 +621,10 @@ def get_imr_esigmasur_mode(
verbose=verbose,
)
except Exception as exc:
print(
f"""Inspiral + MergerRingdown attachment failed. Its very likely
print(f"""Inspiral + MergerRingdown attachment failed. Its very likely
that you entered a very large reference eccentricity {reference_eccentricity}. The orbital
eccentricity at the end of inspiral was {orbital_eccentricity[-1]}
"""
)
""")
raise exc
modes_imr_numpy = retval[0]

Expand Down
Loading