Skip to content
Merged
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
7 changes: 3 additions & 4 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
project = 'pycbc_wferrors_plugin'

import datetime

year = datetime.datetime.now().year
copyright = f'{year}, The PyCBC Team'
# copyright = '2025, Sumit Kumar and Max Melching and Frank Ohme'
Expand All @@ -29,15 +30,14 @@
'm2r2', # including markdown files
# 'sphinx_mdinclude', # including markdown files -> then comment m2r2 -> seems to work much better -> but not compatible with nbsphinx...
'nbsphinx',
'nbsphinx_link'
'nbsphinx_link',
]


templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']



# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

Expand All @@ -51,6 +51,5 @@
'collapse_navigation': False, # Makes navigation expandable
'sticky_navigation': True,
'navigation_depth': 4,
'titles_only': False
'titles_only': False,
}

30 changes: 18 additions & 12 deletions examples/notebooks/example_usage.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -66,8 +66,8 @@
" 'mass2': 20,\n",
" 'f_lower': 20,\n",
" 'f_final': 1024,\n",
" 'delta_f': 1/64,\n",
" 'delta_t': 1/2048,\n",
" 'delta_f': 1.0 / 64.0,\n",
" 'delta_t': 1.0 / 2048.0,\n",
" 'spin1z': 0,\n",
" 'spin2z': 0,\n",
" 'distance': 100,\n",
Expand Down Expand Up @@ -117,8 +117,8 @@
"wf_no_mod_params = {\n",
" 'modification_type': 'constant_shift',\n",
" 'error_in_phase': 'relative',\n",
" 'delta_amplitude': 0.,\n",
" 'delta_phase': 0.,\n",
" 'delta_amplitude': 0.0,\n",
" 'delta_phase': 0.0,\n",
"}\n",
"\n",
"hpf_no_mod, hcf_no_mod = get_fd_waveform(\n",
Expand Down Expand Up @@ -199,7 +199,7 @@
" 'modification_type': 'constant_shift',\n",
" 'error_in_phase': 'relative',\n",
" 'delta_amplitude': 0.1,\n",
" 'delta_phase': 0.,\n",
" 'delta_phase': 0.0,\n",
"}\n",
"\n",
"hpf_amp_mod, hcf_amp_mod = get_fd_waveform(\n",
Expand Down Expand Up @@ -246,7 +246,7 @@
"wf_phase_mod_params = {\n",
" 'modification_type': 'constant_shift',\n",
" 'error_in_phase': 'relative',\n",
" 'delta_amplitude': 0.,\n",
" 'delta_amplitude': 0.0,\n",
" 'delta_phase': 0.1,\n",
"}\n",
"\n",
Expand Down Expand Up @@ -350,7 +350,9 @@
"f_high_calibration = wf_params['f_final']\n",
"\n",
"n_wf_nodal_points = 10\n",
"wf_nodal_points = np.logspace(np.log10(f_low_calibration), np.log10(f_high_calibration), n_wf_nodal_points)\n",
"wf_nodal_points = np.logspace(\n",
" np.log10(f_low_calibration), np.log10(f_high_calibration), n_wf_nodal_points\n",
")\n",
"\n",
"\n",
"ampl_mean_err = 0.1\n",
Expand All @@ -360,8 +362,12 @@
"phase_stddev_err = 0.05\n",
"\n",
"np.random.seed(42)\n",
"delta_amplitude_arr = np.random.standard_normal(n_wf_nodal_points)*ampl_stddev_err + ampl_mean_err\n",
"delta_phase_arr = np.random.standard_normal(n_wf_nodal_points)*phase_stddev_err + phase_mean_err\n",
"delta_amplitude_arr = (\n",
" np.random.standard_normal(n_wf_nodal_points) * ampl_stddev_err + ampl_mean_err\n",
")\n",
"delta_phase_arr = (\n",
" np.random.standard_normal(n_wf_nodal_points) * phase_stddev_err + phase_mean_err\n",
")\n",
"\n",
"\n",
"wf_mod_spline_params = {\n",
Expand Down Expand Up @@ -519,8 +525,8 @@
" # t_gps=float(t_ref),\n",
")\n",
"\n",
"hf_ref = fp*hpf_ref + fc*hcf_ref\n",
"hf_mod_spline = fp*hpf_mod_spline + fc*hcf_mod_spline\n",
"hf_ref = fp * hpf_ref + fc * hcf_ref\n",
"hf_mod_spline = fp * hpf_mod_spline + fc * hcf_mod_spline\n",
"\n",
"\n",
"# from pycbc.waveform import apply_fseries_time_shift\n",
Expand Down
38 changes: 20 additions & 18 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

"""
setup.py file for waveform-errors from pycbc waveform plugin package
"""
Expand All @@ -10,29 +9,33 @@
'version_file': '_pycbc_wferrors_version.py',
'version_scheme': 'no-guess-dev',
'local_scheme': 'dirty-tag',
'fallback_version': '0.1.0'
'fallback_version': '0.1.0',
}


setup(
name = 'pycbc-wferrors',
use_scm_version = version_config,
description = 'An waveform plugin for systematic errors for PyCBC',
long_description = open('descr.rst').read(),
author = 'The PyCBC team',
author_email = 'sumit.kumar@aei.mpg.de',
url = 'http://www.pycbc.org/',
keywords = ['pycbc', 'signal processing', 'gravitational waves'],
setup_requires = [
name='pycbc-wferrors',
use_scm_version=version_config,
description='An waveform plugin for systematic errors for PyCBC',
long_description=open('descr.rst').read(),
author='The PyCBC team',
author_email='sumit.kumar@aei.mpg.de',
url='http://www.pycbc.org/',
keywords=['pycbc', 'signal processing', 'gravitational waves'],
setup_requires=[
'setuptools>=64',
'setuptools_scm>=8',
'wheel',
],
install_requires = ['pycbc'],
py_modules = ['wferrors'],
entry_points = {"pycbc.waveform.fd":["wferrors = wferrors:amplitude_phase_modification_fd",
"wferrors_2p = wferrors:amplitude_phase_modification_both_polarization_fd"]},
classifiers = [
install_requires=['pycbc'],
py_modules=['wferrors'],
entry_points={
"pycbc.waveform.fd": [
"wferrors = wferrors:amplitude_phase_modification_fd",
"wferrors_2p = wferrors:amplitude_phase_modification_both_polarization_fd",
]
},
classifiers=[
'Programming Language :: Python',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
Expand All @@ -57,6 +60,5 @@
'nbsphinx-link',
'lxml_html_clean', # Needed by nbsphinx
],

}
},
)
104 changes: 57 additions & 47 deletions wferrors.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@
def amplitude_phase_modification_fd(**kwds):
"""
This function applies the Amplitude-Phase modification, described in
Kumar, Melching, Ohme (2025), to the base waveform approximant in
Kumar, Melching, Ohme (2025), to the base waveform approximant in
frequency domain.

Input in kwds:
error_in_phase: 'relative' or 'absolute'
This argument specify the type of errors to be
applied.
baseline_approximant: FD approximant of the reference waveform model to
baseline_approximant: FD approximant of the reference waveform model to
modified.
modification_type: 'cubic_spline', 'cubic_spline_nodes', or 'constant_shift'
'cubic_spline': If this option is passed, the dictionary should
'cubic_spline': If this option is passed, the dictionary should
includes array of delta_amplitude, delta_phase, and nodal_points
'cubic_spline_nodes': When we specify this modification_type, the lower
and upper limits of the frequency should be given along with number
Expand Down Expand Up @@ -97,9 +97,9 @@ def amplitude_phase_modification_fd(**kwds):
+ delta_phase
)
elif dict_waveform_modification['modification_type'] == 'cubic_spline_nodes':
f_lower = (dict_waveform_modification.get('f_lower_wferror',
default=dict_waveform_modification['f_lower'])
)
f_lower = dict_waveform_modification.get(
'f_lower_wferror', default=dict_waveform_modification['f_lower']
)
f_high_wferror = dict_waveform_modification['f_high_wferror']
n_nodes_wferror = int(dict_waveform_modification['n_nodes_wferror'])
wf_nodal_points = numpy.logspace(
Expand Down Expand Up @@ -158,6 +158,7 @@ def amplitude_phase_modification_fd(**kwds):

return hp, hc


def amplitude_phase_modification_both_polarization_fd(**kwds):
"""Modify amplitude and phase of waveform polarizations in frequency domain."""

Expand All @@ -178,18 +179,14 @@ def amplitude_phase_modification_both_polarization_fd(**kwds):
delta_amplitude_plus_interp = CubicSpline(
wf_nodal_points, delta_amplitude_plus_arr
)
delta_phase_plus_interp = CubicSpline(
wf_nodal_points, delta_phase_plus_arr
)
delta_phase_plus_interp = CubicSpline(wf_nodal_points, delta_phase_plus_arr)

delta_amplitude_cross_arr = dict_waveform_modification['delta_amplitude_cross']
delta_phase_cross_arr = dict_waveform_modification['delta_phase_cross']
delta_amplitude_cross_interp = CubicSpline(
wf_nodal_points, delta_amplitude_cross_arr
)
delta_phase_cross_interp = CubicSpline(
wf_nodal_points, delta_phase_cross_arr
)
delta_phase_cross_interp = CubicSpline(wf_nodal_points, delta_phase_cross_arr)

# Modify amplitude and phase for Plus and Cross polarization
Am_plus = waveform.amplitude_from_frequencyseries(hp) * (
Expand Down Expand Up @@ -222,8 +219,12 @@ def amplitude_phase_modification_both_polarization_fd(**kwds):
delta_phase_cross = dict_waveform_modification['delta_phase_cross']

# Modify amplitude and phase for Plus and Cross polarization
Am_plus = waveform.amplitude_from_frequencyseries(hp) * (1 + delta_amplitude_plus)
Am_cross = waveform.amplitude_from_frequencyseries(hc) * (1 + delta_amplitude_cross)
Am_plus = waveform.amplitude_from_frequencyseries(hp) * (
1 + delta_amplitude_plus
)
Am_cross = waveform.amplitude_from_frequencyseries(hc) * (
1 + delta_amplitude_cross
)

if dict_waveform_modification['error_in_phase'] == 'relative':
Ph_plus = waveform.phase_from_frequencyseries(
Expand All @@ -233,40 +234,50 @@ def amplitude_phase_modification_both_polarization_fd(**kwds):
hc, remove_start_phase=False
) * (1 + delta_phase_cross)
elif dict_waveform_modification['error_in_phase'] == 'absolute':
Ph_plus = waveform.phase_from_frequencyseries(
hp, remove_start_phase=False
) + delta_phase_plus
Ph_cross = waveform.phase_from_frequencyseries(
hc, remove_start_phase=False
) + delta_phase_cross
Ph_plus = (
waveform.phase_from_frequencyseries(hp, remove_start_phase=False)
+ delta_phase_plus
)
Ph_cross = (
waveform.phase_from_frequencyseries(hc, remove_start_phase=False)
+ delta_phase_cross
)

elif modification_type == 'cubic_spline_nodes':
f_lower = (dict_waveform_modification.get('f_lower_wferror',
default=dict_waveform_modification['f_lower'])
)
f_lower = dict_waveform_modification.get(
'f_lower_wferror', default=dict_waveform_modification['f_lower']
)
f_high_wferror = dict_waveform_modification['f_high_wferror']
n_nodes_wferror = int(dict_waveform_modification['n_nodes_wferror'])

wf_nodal_points = numpy.logspace(
numpy.log10(f_lower), numpy.log10(f_high_wferror), n_nodes_wferror
)

delta_amplitude_plus_arr = numpy.hstack([
dict_waveform_modification[f'wferror_amplitude_plus_{i}']
for i in range(len(wf_nodal_points))
])
delta_phase_plus_arr = numpy.hstack([
dict_waveform_modification[f'wferror_phase_plus_{i}']
for i in range(len(wf_nodal_points))
])
delta_amplitude_cross_arr = numpy.hstack([
dict_waveform_modification[f'wferror_amplitude_cross_{i}']
for i in range(len(wf_nodal_points))
])
delta_phase_cross_arr = numpy.hstack([
dict_waveform_modification[f'wferror_phase_cross_{i}']
for i in range(len(wf_nodal_points))
])
delta_amplitude_plus_arr = numpy.hstack(
[
dict_waveform_modification[f'wferror_amplitude_plus_{i}']
for i in range(len(wf_nodal_points))
]
)
delta_phase_plus_arr = numpy.hstack(
[
dict_waveform_modification[f'wferror_phase_plus_{i}']
for i in range(len(wf_nodal_points))
]
)
delta_amplitude_cross_arr = numpy.hstack(
[
dict_waveform_modification[f'wferror_amplitude_cross_{i}']
for i in range(len(wf_nodal_points))
]
)
delta_phase_cross_arr = numpy.hstack(
[
dict_waveform_modification[f'wferror_phase_cross_{i}']
for i in range(len(wf_nodal_points))
]
)

delta_amplitude_plus_interp = CubicSpline(
wf_nodal_points, delta_amplitude_plus_arr
Expand All @@ -275,9 +286,7 @@ def amplitude_phase_modification_both_polarization_fd(**kwds):
delta_amplitude_cross_interp = CubicSpline(
wf_nodal_points, delta_amplitude_cross_arr
)
delta_phase_cross_interp = CubicSpline(
wf_nodal_points, delta_phase_cross_arr
)
delta_phase_cross_interp = CubicSpline(wf_nodal_points, delta_phase_cross_arr)

# Modify amplitude and phase for Plus and Cross polarization
Am_plus = waveform.amplitude_from_frequencyseries(hp) * (
Expand Down Expand Up @@ -306,10 +315,11 @@ def amplitude_phase_modification_both_polarization_fd(**kwds):
raise TypeError("Currently, no other modification are supported")

# Apply the correction to the base model
hp.data = numpy.vectorize(complex)(Am_plus * numpy.cos(Ph_plus),
Am_plus * numpy.sin(Ph_plus))
hc.data = numpy.vectorize(complex)(Am_cross * numpy.cos(Ph_cross),
Am_cross * numpy.sin(Ph_cross))
hp.data = numpy.vectorize(complex)(
Am_plus * numpy.cos(Ph_plus), Am_plus * numpy.sin(Ph_plus)
)
hc.data = numpy.vectorize(complex)(
Am_cross * numpy.cos(Ph_cross), Am_cross * numpy.sin(Ph_cross)
)

return hp, hc