From 8fcb34581323272b4f42c9f699f361c3e605b05d Mon Sep 17 00:00:00 2001 From: md-arif-shaikh Date: Sun, 10 Nov 2024 15:47:42 +0530 Subject: [PATCH 01/17] add option for frame --- gw_eccentricity/eccDefinition.py | 82 ++++++++++++++++++++++++++++++ gw_eccentricity/gw_eccentricity.py | 3 +- 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/gw_eccentricity/eccDefinition.py b/gw_eccentricity/eccDefinition.py index 9c654c6..7b00719 100644 --- a/gw_eccentricity/eccDefinition.py +++ b/gw_eccentricity/eccDefinition.py @@ -8,6 +8,8 @@ import numpy as np import matplotlib.pyplot as plt +from copy import deepcopy +from .load_data import get_coprecessing_data_dict from .utils import peak_time_via_quadratic_fit, check_kwargs_and_set_defaults from .utils import amplitude_using_all_modes from .utils import time_deriv_4thOrder @@ -24,6 +26,7 @@ class eccDefinition: def __init__(self, dataDict, num_orbits_to_exclude_before_merger=2, precessing=False, + frame="inertial", extra_kwargs=None): """Init eccDefinition class. @@ -163,6 +166,28 @@ def __init__(self, dataDict, num_orbits_to_exclude_before_merger=2, Default is False which implies the system to be nonprecessing. + frame: str, default="inertial" + Specifies the reference frame for the modes in `dataDict`. Acceptable values are: + - "inertial": The modes in `dataDict` are in the inertial frame. + - "coprecessing": The modes in `dataDict` are in the coprecessing frame. + + If the system is precessing (`precessing=True`) and `frame="inertial"`, the modes in + `dataDict` are rotated into the coprecessing frame for further computation. If + `frame="coprecessing"` with a precessing system, the modes in `dataDict` are expected + to be already in the coprecessing frame. + + For nonprecessing systems only (2, 2) mode is sufficient for measuring eccentricity. + For precessing system, we use both (2, 2) and (2, -2) mode data in the coprecessing + frame. Therefore, if the system is nonprecessing (`precessing=False`) but + `frame="coprecessing"`, an exception is raised to avoid ambiguity because for nonprecessing systems, + inertial and coprecessing frames are equivalent and (2, -2) mode is not required. + + TODO: Should we make all m modes for l=2 mandatory for getting coprecessing modes? It seems, + any missing m modes causes oscillations in egw. + + Default value is "inertial". + + extra_kwargs: dict A dictionary of any extra kwargs to be passed. Allowed kwargs are: @@ -274,6 +299,17 @@ def __init__(self, dataDict, num_orbits_to_exclude_before_merger=2, USE THIS WITH CAUTION! """ self.precessing = precessing + self.frame = frame + # check if frame makes sense. If system is nonprecessing, frame should be inertial + self.available_frames = ["inertial", "coprecessing"] + if self.frame not in self.available_frames: + raise ValueError(f"Unknown frame `{self.frame}`. Frame should be one of " + f"{self.available_frames}") + if not self.precessing and self.frame != "inertial": + raise Exception("The system is nonprecessing since `precessing` is set to " + f"{self.precessing} but the frame is set to {self.frame}. When the " + "system is nonprecessing, frame should be 'inertial'.") + # Get data necessary for eccentricity measurement self.dataDict, self.t_merger, self.amp_gw_merger, \ min_width_for_extrema = self.process_data_dict( @@ -579,6 +615,9 @@ def process_data_dict(self, "1. 'hlm' OR \n" "2. 'amplm' and 'phaselm'\n" "But not both 1. and 2. at the same time.")) + # if the system is precessing, rotate the modes in dataDict to coprecessing frame + if self.precessing is True and self.frame == "inertial": + dataDict = self.rotate_modes(dataDict) # Create a new dictionary that will contain the data necessary for # eccentricity measurement. newDataDict = {} @@ -657,6 +696,49 @@ def process_data_dict(self, newDataDict["t"] = newDataDict["t"][ :index_num_orbits_earlier_than_merger] return newDataDict, t_merger, amp_gw_merger, min_width_for_extrema + + def rotate_modes(self, data_dict): + """"Rotate intertial modes in data_dict to coprecessing frame.""" + if "hlm" in data_dict: + data_dict = get_coprecessing_data_dict(data_dict) + if "hlm_zeroecc" in data_dict: + intertial_zeroecc_data_dict = {"t": data_dict["t_zeroecc"], + "hlm": data_dict["hlm_zeroecc"]} + coprecessing_zeroecc_data_dict = get_coprecessing_data_dict(intertial_zeroecc_data_dict) + data_dict.update({"hlm_zeroecc": coprecessing_zeroecc_data_dict["hlm"]}) + # if hlm is not in data_dict, get it from amplm and phaselm. + # We need to provide hlm to get the rotated modes. + if "hlm" not in data_dict: + amplm_dict = self.get_amplm_from_dataDict(data_dict) + phaselm_dict = self.get_phaselm_from_dataDict(data_dict) + hlm_dict = {} + # check if "hlm_zeroecc" is not in data_dict but amplm_zeroecc is in data_dict + if "amplm_zeroecc" in data_dict and "hlm_zeroecc" not in data_dict: + add_hlm_zeroecc = True + hlm_zeroecc_dict = {} + else: + add_hlm_zeroecc = False + # combine amplm and phaselm to get hlm + for k in amplm_dict["amplm"]: + hlm_dict.update({k: amplm_dict["amplm"][k] * np.exp(-1j * phaselm_dict["phaselm"][k])}) + if add_hlm_zeroecc: + hlm_zeroecc_dict.update({k: amplm_dict["amplm_zeroecc"][k] * np.exp(-1j * phaselm_dict["phaselm_zeroecc"][k])}) + inertial_ecc_data_dict = {"t": data_dict["t"], "hlm": hlm_dict} + coprecessing_ecc_data_dict = get_coprecessing_data_dict(inertial_ecc_data_dict) + data_dict.update(coprecessing_ecc_data_dict) + # remove amplm, phaselm because these are in the inertial frame + # and are given priority when using data for egw over hlm + data_dict.pop("amplm", None) + data_dict.pop("phaselm", None) + if add_hlm_zeroecc: + inertial_zeroecc_data_dict = {"t": data_dict["t_zeroecc"], "hlm": hlm_zeroecc_dict} + coprecessing_zeroecc_data_dict = get_coprecessing_data_dict(inertial_zeroecc_data_dict) + data_dict.update({"hlm_zeroecc": coprecessing_zeroecc_data_dict["hlm"]}) + # remove amplm_zeroecc, phaselm_zeroecc because these are in the inertial frame + # and are given priority when using data for egw over hlm_zeroecc + data_dict.pop("amplm_zeroecc", None) + data_dict.pop("phaselm_zeroecc", None) + return data_dict def get_amp_phase_omega_gw(self, data_dict): """Get the gw quanitities from modes dict in the coprecessing frame. diff --git a/gw_eccentricity/gw_eccentricity.py b/gw_eccentricity/gw_eccentricity.py index 6937274..6de668d 100644 --- a/gw_eccentricity/gw_eccentricity.py +++ b/gw_eccentricity/gw_eccentricity.py @@ -64,6 +64,7 @@ def measure_eccentricity(tref_in=None, dataDict=None, num_orbits_to_exclude_before_merger=2, precessing=False, + frame="inertial", extra_kwargs=None): """Measure eccentricity and mean anomaly from a gravitational waveform. @@ -469,7 +470,7 @@ def measure_eccentricity(tref_in=None, if method in available_methods: gwecc_object = available_methods[method]( dataDict, num_orbits_to_exclude_before_merger, - precessing, extra_kwargs) + precessing, frame, extra_kwargs) return_dict = gwecc_object.measure_ecc( tref_in=tref_in, fref_in=fref_in) return_dict.update({"gwecc_object": gwecc_object}) From 8f69702f7d17165506050dee4b8b4a41e1949801 Mon Sep 17 00:00:00 2001 From: md-arif-shaikh Date: Mon, 11 Nov 2024 14:42:10 +0530 Subject: [PATCH 02/17] update documentation --- gw_eccentricity/eccDefinition.py | 115 +++++++++++++++++-------------- 1 file changed, 65 insertions(+), 50 deletions(-) diff --git a/gw_eccentricity/eccDefinition.py b/gw_eccentricity/eccDefinition.py index 7b00719..428708d 100644 --- a/gw_eccentricity/eccDefinition.py +++ b/gw_eccentricity/eccDefinition.py @@ -8,7 +8,6 @@ import numpy as np import matplotlib.pyplot as plt -from copy import deepcopy from .load_data import get_coprecessing_data_dict from .utils import peak_time_via_quadratic_fit, check_kwargs_and_set_defaults from .utils import amplitude_using_all_modes @@ -159,35 +158,44 @@ def __init__(self, dataDict, num_orbits_to_exclude_before_merger=2, Default: 2. precessing: bool, default=False - Whether the system is precessing or not. For precessing systems, - the `dataDict` should contain modes in the coprecessing frame. For - nonprecessing systems, there is no distiction between the inertial - and coprecessing frame since they are the same. + Indicates whether the system is precessing. For precessing systems, + the (2, 2) and (2, -2) modes in the coprecessing frame are required + to compute `amp_gw`, `phase_gw`, and `omega_gw` (see + `get_amp_phase_omega_gw`), which are used to determine eccentricity. - Default is False which implies the system to be nonprecessing. + For precessing systems, waveform modes in the coprecessing frame + must be provided. This can be done in two ways: + - Set `frame="coprecessing"` and supply the coprecessing modes + directly via `dataDict`. + - Set `frame="inertial"` and provide the inertial frame modes + via `dataDict`. In this case, the modes in `dataDict` are + rotated internally before further computation. - frame: str, default="inertial" - Specifies the reference frame for the modes in `dataDict`. Acceptable values are: - - "inertial": The modes in `dataDict` are in the inertial frame. - - "coprecessing": The modes in `dataDict` are in the coprecessing frame. - - If the system is precessing (`precessing=True`) and `frame="inertial"`, the modes in - `dataDict` are rotated into the coprecessing frame for further computation. If - `frame="coprecessing"` with a precessing system, the modes in `dataDict` are expected - to be already in the coprecessing frame. + For nonprecessing systems, the inertial and coprecessing frames are + equivalent, so there is no distinction. - For nonprecessing systems only (2, 2) mode is sufficient for measuring eccentricity. - For precessing system, we use both (2, 2) and (2, -2) mode data in the coprecessing - frame. Therefore, if the system is nonprecessing (`precessing=False`) but - `frame="coprecessing"`, an exception is raised to avoid ambiguity because for nonprecessing systems, - inertial and coprecessing frames are equivalent and (2, -2) mode is not required. + Default is `False`, indicating the system is nonprecessing. - TODO: Should we make all m modes for l=2 mandatory for getting coprecessing modes? It seems, - any missing m modes causes oscillations in egw. + frame: str, default="inertial" + Specifies the reference frame for the modes in `dataDict`. + Acceptable values are: + - "inertial": The modes in `dataDict` are in the inertial + frame. + - "coprecessing": The modes in `dataDict` are in the + coprecessing frame. + + If the system is precessing (`precessing=True`) and + `frame="inertial"`, the modes in `dataDict` are rotated into the + coprecessing frame for further computation. If + `frame="coprecessing"` with a precessing system, the modes in + `dataDict` are expected to be already in the coprecessing frame. + + TODO: Should all m modes for l=2 be mandatory for obtaining + coprecessing modes? It seems any missing m modes cause + oscillations in egw. Default value is "inertial". - extra_kwargs: dict A dictionary of any extra kwargs to be passed. Allowed kwargs are: @@ -300,15 +308,11 @@ def __init__(self, dataDict, num_orbits_to_exclude_before_merger=2, """ self.precessing = precessing self.frame = frame - # check if frame makes sense. If system is nonprecessing, frame should be inertial + # check if frame makes sense. self.available_frames = ["inertial", "coprecessing"] if self.frame not in self.available_frames: - raise ValueError(f"Unknown frame `{self.frame}`. Frame should be one of " - f"{self.available_frames}") - if not self.precessing and self.frame != "inertial": - raise Exception("The system is nonprecessing since `precessing` is set to " - f"{self.precessing} but the frame is set to {self.frame}. When the " - "system is nonprecessing, frame should be 'inertial'.") + raise ValueError(f"Unknown frame `{self.frame}`. Frame should be " + f"one of {self.available_frames}") # Get data necessary for eccentricity measurement self.dataDict, self.t_merger, self.amp_gw_merger, \ @@ -615,7 +619,8 @@ def process_data_dict(self, "1. 'hlm' OR \n" "2. 'amplm' and 'phaselm'\n" "But not both 1. and 2. at the same time.")) - # if the system is precessing, rotate the modes in dataDict to coprecessing frame + # if the system is precessing, rotate the modes in dataDict to + # coprecessing frame if self.precessing is True and self.frame == "inertial": dataDict = self.rotate_modes(dataDict) # Create a new dictionary that will contain the data necessary for @@ -696,7 +701,7 @@ def process_data_dict(self, newDataDict["t"] = newDataDict["t"][ :index_num_orbits_earlier_than_merger] return newDataDict, t_merger, amp_gw_merger, min_width_for_extrema - + def rotate_modes(self, data_dict): """"Rotate intertial modes in data_dict to coprecessing frame.""" if "hlm" in data_dict: @@ -704,15 +709,18 @@ def rotate_modes(self, data_dict): if "hlm_zeroecc" in data_dict: intertial_zeroecc_data_dict = {"t": data_dict["t_zeroecc"], "hlm": data_dict["hlm_zeroecc"]} - coprecessing_zeroecc_data_dict = get_coprecessing_data_dict(intertial_zeroecc_data_dict) - data_dict.update({"hlm_zeroecc": coprecessing_zeroecc_data_dict["hlm"]}) + coprecessing_zeroecc_data_dict = get_coprecessing_data_dict( + intertial_zeroecc_data_dict) + data_dict.update( + {"hlm_zeroecc": coprecessing_zeroecc_data_dict["hlm"]}) # if hlm is not in data_dict, get it from amplm and phaselm. # We need to provide hlm to get the rotated modes. if "hlm" not in data_dict: amplm_dict = self.get_amplm_from_dataDict(data_dict) phaselm_dict = self.get_phaselm_from_dataDict(data_dict) hlm_dict = {} - # check if "hlm_zeroecc" is not in data_dict but amplm_zeroecc is in data_dict + # check if "hlm_zeroecc" is not in data_dict but amplm_zeroecc is + # in data_dict if "amplm_zeroecc" in data_dict and "hlm_zeroecc" not in data_dict: add_hlm_zeroecc = True hlm_zeroecc_dict = {} @@ -720,24 +728,37 @@ def rotate_modes(self, data_dict): add_hlm_zeroecc = False # combine amplm and phaselm to get hlm for k in amplm_dict["amplm"]: - hlm_dict.update({k: amplm_dict["amplm"][k] * np.exp(-1j * phaselm_dict["phaselm"][k])}) + hlm_dict.update({k: amplm_dict["amplm"][k] + * np.exp(-1j * phaselm_dict["phaselm"][k])}) if add_hlm_zeroecc: - hlm_zeroecc_dict.update({k: amplm_dict["amplm_zeroecc"][k] * np.exp(-1j * phaselm_dict["phaselm_zeroecc"][k])}) + hlm_zeroecc_dict.update( + {k: amplm_dict["amplm_zeroecc"][k] + * np.exp(-1j * phaselm_dict["phaselm_zeroecc"][k])}) inertial_ecc_data_dict = {"t": data_dict["t"], "hlm": hlm_dict} - coprecessing_ecc_data_dict = get_coprecessing_data_dict(inertial_ecc_data_dict) + coprecessing_ecc_data_dict = get_coprecessing_data_dict( + inertial_ecc_data_dict) data_dict.update(coprecessing_ecc_data_dict) # remove amplm, phaselm because these are in the inertial frame - # and are given priority when using data for egw over hlm + # and are given priority over hlm when using data for egw data_dict.pop("amplm", None) data_dict.pop("phaselm", None) if add_hlm_zeroecc: - inertial_zeroecc_data_dict = {"t": data_dict["t_zeroecc"], "hlm": hlm_zeroecc_dict} - coprecessing_zeroecc_data_dict = get_coprecessing_data_dict(inertial_zeroecc_data_dict) - data_dict.update({"hlm_zeroecc": coprecessing_zeroecc_data_dict["hlm"]}) - # remove amplm_zeroecc, phaselm_zeroecc because these are in the inertial frame - # and are given priority when using data for egw over hlm_zeroecc + inertial_zeroecc_data_dict = { + "t": data_dict["t_zeroecc"], "hlm": hlm_zeroecc_dict} + coprecessing_zeroecc_data_dict = get_coprecessing_data_dict( + inertial_zeroecc_data_dict) + data_dict.update( + {"hlm_zeroecc": coprecessing_zeroecc_data_dict["hlm"]}) + # remove amplm_zeroecc, phaselm_zeroecc because these are in + # the inertial frame and are given priority over hlm_zeroecc + # when using data for egw data_dict.pop("amplm_zeroecc", None) data_dict.pop("phaselm_zeroecc", None) + # remove inertial omegalm. The coprecessing omegalm should be computed + # from the coprecessing phase later. + for omega in ["omegalm", "omegalm_zeroecc"]: + if omega in data_dict: + data_dict.pop(omega, None) return data_dict def get_amp_phase_omega_gw(self, data_dict): @@ -768,12 +789,6 @@ def get_amp_phase_omega_gw(self, data_dict): data_dict["phaselm"][(2, 2)], data_dict["omegalm"][(2, 2)]) else: - # TODO: Currently, we assume that the input `dataDict` is already provided in the - # coprecessing frame. In the future, this assumption could be - # relaxed. If the user's `dataDict` is in the inertial frame, we can - # internally compute the corresponding modes in the coprecessing frame by - # applying the appropriate rotational transformation. - # check whether (2, -2) mode is provided. for k in ["amplm", "phaselm"]: if (2, -2) not in data_dict[k]: From ea2c1992f6756a5000caaeb6d2e8ede7afebf9cd Mon Sep 17 00:00:00 2001 From: md-arif-shaikh Date: Mon, 11 Nov 2024 21:15:58 +0530 Subject: [PATCH 03/17] raise exception if any m is missing --- gw_eccentricity/eccDefinition.py | 3 ++- gw_eccentricity/load_data.py | 14 ++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/gw_eccentricity/eccDefinition.py b/gw_eccentricity/eccDefinition.py index 428708d..93b8ba6 100644 --- a/gw_eccentricity/eccDefinition.py +++ b/gw_eccentricity/eccDefinition.py @@ -619,7 +619,8 @@ def process_data_dict(self, "1. 'hlm' OR \n" "2. 'amplm' and 'phaselm'\n" "But not both 1. and 2. at the same time.")) - # if the system is precessing, rotate the modes in dataDict to + # if the system is precessing and the modes are given in the inertial + # frame, rotate the modes and the corresponding modes in the # coprecessing frame if self.precessing is True and self.frame == "inertial": dataDict = self.rotate_modes(dataDict) diff --git a/gw_eccentricity/load_data.py b/gw_eccentricity/load_data.py index 804874c..c7dcb22 100644 --- a/gw_eccentricity/load_data.py +++ b/gw_eccentricity/load_data.py @@ -1500,13 +1500,15 @@ def package_modes_for_scri(modes_dict, ell_min, ell_max): for ell in range(ell_min, ell_max + 1): for m in range(-ell, ell + 1): if (ell, m) in keys: - # for each m > 0, the m < 0 counterpart should also exist in the `data_dict` - if m > 0: - if (ell, -m) not in keys: - raise Exception("For each m > 0, corresponding m < 0 mode should also exist " - f"in the input `data_dict`. {(ell, m)} mode exists but " - f" {(ell, -m)} mode does not exist.") result[:, i] = modes_dict[(ell, m)] + else: + # for a given ell, all (ell, m) modes should exist in the + # modes_dict + raise Exception( + f"{ell, m} mode for ell={ell} does not exist in the " + "modes dict. To get the coprecessing modes accurately, " + "all the `(ell, m)` modes for a given `ell` should exist " + "in the input modes dict.") i += 1 return result From e0f040fe08c885683e423480c384b7a7f93340a8 Mon Sep 17 00:00:00 2001 From: md-arif-shaikh Date: Mon, 11 Nov 2024 21:44:23 +0530 Subject: [PATCH 04/17] police documentation for rotate modes --- gw_eccentricity/eccDefinition.py | 35 ++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/gw_eccentricity/eccDefinition.py b/gw_eccentricity/eccDefinition.py index 93b8ba6..0124fb8 100644 --- a/gw_eccentricity/eccDefinition.py +++ b/gw_eccentricity/eccDefinition.py @@ -190,10 +190,6 @@ def __init__(self, dataDict, num_orbits_to_exclude_before_merger=2, `frame="coprecessing"` with a precessing system, the modes in `dataDict` are expected to be already in the coprecessing frame. - TODO: Should all m modes for l=2 be mandatory for obtaining - coprecessing modes? It seems any missing m modes cause - oscillations in egw. - Default value is "inertial". extra_kwargs: dict @@ -620,7 +616,7 @@ def process_data_dict(self, "2. 'amplm' and 'phaselm'\n" "But not both 1. and 2. at the same time.")) # if the system is precessing and the modes are given in the inertial - # frame, rotate the modes and the corresponding modes in the + # frame, rotate the modes and obtain the corresponding modes in the # coprecessing frame if self.precessing is True and self.frame == "inertial": dataDict = self.rotate_modes(dataDict) @@ -704,16 +700,43 @@ def process_data_dict(self, return newDataDict, t_merger, amp_gw_merger, min_width_for_extrema def rotate_modes(self, data_dict): - """"Rotate intertial modes in data_dict to coprecessing frame.""" + """"Rotate intertial frame modes to obtain coprecessing frame modes. + + Parameters + ---------- + data_dict: dict + Dictionary of modes in the inertial frame. The modes are rotated + using `get_coprecessing_data_dict` to obtain the corresponding + modes in the coprecessing frame. + + To obtain coprecessing frame modes from an inertial frame dictionary, + this dictionary should include all (ell, m) modes for a specified + ell value. For instance, the inertial modes dictionary should + contain at least all the modes for `ell=2`, i.e., (2, -2), (2, -1), + (2, 0), (2, 1), and (2, 2), to achieve accurate coprecessing frame + modes. + + Returns + ------- + data_dict with the inertial modes replaced by the corresponding + modes in the coprecessing frame. + """ if "hlm" in data_dict: data_dict = get_coprecessing_data_dict(data_dict) if "hlm_zeroecc" in data_dict: + # `get_coprecessing_data_dict` looks for modes using the key "hlm" + # and the associated time using "t". + # Make a dictionary with a key "hlm" and pass the zeroecc modes + # dict via it. Similary for the times using "t". intertial_zeroecc_data_dict = {"t": data_dict["t_zeroecc"], "hlm": data_dict["hlm_zeroecc"]} coprecessing_zeroecc_data_dict = get_coprecessing_data_dict( intertial_zeroecc_data_dict) + # update the data_dict by replacing the inertial frame zeroecc + # modes with coprecessing frame zeroecc modes. data_dict.update( {"hlm_zeroecc": coprecessing_zeroecc_data_dict["hlm"]}) + # if hlm is not in data_dict, get it from amplm and phaselm. # We need to provide hlm to get the rotated modes. if "hlm" not in data_dict: From fe90c282117b97d38afca86f46a2748800efe857 Mon Sep 17 00:00:00 2001 From: md-arif-shaikh Date: Tue, 12 Nov 2024 12:38:35 +0530 Subject: [PATCH 05/17] add documentation to gw_eccentricity --- gw_eccentricity/gw_eccentricity.py | 39 +++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/gw_eccentricity/gw_eccentricity.py b/gw_eccentricity/gw_eccentricity.py index 6de668d..7e84695 100644 --- a/gw_eccentricity/gw_eccentricity.py +++ b/gw_eccentricity/gw_eccentricity.py @@ -300,12 +300,39 @@ def measure_eccentricity(tref_in=None, Default: 2. precessing: bool, default=False - Whether the system is precessing or not. For precessing systems, the - `dataDict` should contain modes in the coprecessing frame. For - nonprecessing systems, there is no distiction between the inertial and - coprecessing frame since they are the same. - - Default is False which implies the system to be nonprecessing. + Indicates whether the system is precessing. For precessing systems, the + (2, 2) and (2, -2) modes in the coprecessing frame are required to + compute `amp_gw`, `phase_gw`, and `omega_gw` (see + `get_amp_phase_omega_gw`), which are used to determine eccentricity. + + For precessing systems, waveform modes in the coprecessing frame must + be provided. This can be done in two ways: + - Set `frame="coprecessing"` and supply the coprecessing modes + directly via `dataDict`. + - Set `frame="inertial"` and provide the inertial frame modes + via `dataDict`. In this case, the modes in `dataDict` are + rotated internally before further computation. + + For nonprecessing systems, the inertial and coprecessing frames are + equivalent, so there is no distinction. + + Default is `False`, indicating the system is nonprecessing. + + frame: str, default="inertial" + Specifies the reference frame for the modes in `dataDict`. Acceptable + values are: + - "inertial": The modes in `dataDict` are in the inertial + frame. + - "coprecessing": The modes in `dataDict` are in the + coprecessing frame. + + If the system is precessing (`precessing=True`) and `frame="inertial"`, + the modes in `dataDict` are rotated into the coprecessing frame for + further computation. If `frame="coprecessing"` with a precessing + system, the modes in `dataDict` are expected to be already in the + coprecessing frame. + + Default value is "inertial". extra_kwargs: A dict of any extra kwargs to be passed. Allowed kwargs are: spline_kwargs: From 4e40cde55b28ffdb15c03ff32dc0d0a992deb228 Mon Sep 17 00:00:00 2001 From: md-arif-shaikh Date: Tue, 12 Nov 2024 12:55:25 +0530 Subject: [PATCH 06/17] more documentation --- gw_eccentricity/eccDefinition.py | 5 ++++- gw_eccentricity/gw_eccentricity.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/gw_eccentricity/eccDefinition.py b/gw_eccentricity/eccDefinition.py index 0124fb8..acbc3c1 100644 --- a/gw_eccentricity/eccDefinition.py +++ b/gw_eccentricity/eccDefinition.py @@ -169,7 +169,10 @@ def __init__(self, dataDict, num_orbits_to_exclude_before_merger=2, directly via `dataDict`. - Set `frame="inertial"` and provide the inertial frame modes via `dataDict`. In this case, the modes in `dataDict` are - rotated internally before further computation. + rotated internally (see `rotate_modes`) before further + computation. To get the coprecessing modes from the inertial + modes accurately, `dataDict` must include all modes for + `ell=2`, i.e., (2, -2), (2, -1), (2, 0), (2, 1) and (2, 2). For nonprecessing systems, the inertial and coprecessing frames are equivalent, so there is no distinction. diff --git a/gw_eccentricity/gw_eccentricity.py b/gw_eccentricity/gw_eccentricity.py index 7e84695..e8d04bf 100644 --- a/gw_eccentricity/gw_eccentricity.py +++ b/gw_eccentricity/gw_eccentricity.py @@ -311,7 +311,10 @@ def measure_eccentricity(tref_in=None, directly via `dataDict`. - Set `frame="inertial"` and provide the inertial frame modes via `dataDict`. In this case, the modes in `dataDict` are - rotated internally before further computation. + rotated internally (see `rotate_modes`) before further + computation. To get the coprecessing modes from the inertial + modes accurately, `dataDict` must include all modes for + `ell=2`, i.e., (2, -2), (2, -1), (2, 0), (2, 1) and (2, 2). For nonprecessing systems, the inertial and coprecessing frames are equivalent, so there is no distinction. From 584aa2411cfaa580bc5315348db52235ec5e0707 Mon Sep 17 00:00:00 2001 From: md-arif-shaikh Date: Wed, 13 Nov 2024 10:48:33 +0530 Subject: [PATCH 07/17] get correct amp, phase, omega for zeroecc --- gw_eccentricity/eccDefinition.py | 60 +++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/gw_eccentricity/eccDefinition.py b/gw_eccentricity/eccDefinition.py index acbc3c1..0b2f71c 100644 --- a/gw_eccentricity/eccDefinition.py +++ b/gw_eccentricity/eccDefinition.py @@ -788,7 +788,7 @@ def rotate_modes(self, data_dict): data_dict.pop(omega, None) return data_dict - def get_amp_phase_omega_gw(self, data_dict): + def get_amp_phase_omega_gw(self, data_dict, data_name_suffix=""): """Get the gw quanitities from modes dict in the coprecessing frame. For nonprecessing systems, the amp_gw, phase_gw and omega_gw are the same @@ -810,25 +810,52 @@ def get_amp_phase_omega_gw(self, data_dict): These quantities reduce to the corresponding (2, 2) mode data when the system is nonprecessing. + + Parameters + ---------- + data_dict: dict + A dictionary with the waveform modes and times. The structure of + `data_dict` should be consistent with that of `dataDict`. + + data_name_suffix: str, default="" + A string identifier for selecting the data type when accessing + amplitude, phase, and frequency (omega) values. It is used to + specify if the waveform data corresponds to eccentric modes or + zero-eccentricity (zeroecc) modes. For instance, set + `data_name_suffix=""` for eccentric modes or + `data_name_suffix="zeroecc"` for non-eccentric modes. + + It will look for the key=`data_name` if `data_name_suffix` is empty + else key=`data_name` + "_" + "data_name_suffix" where the + `data_name` are "amplm", "phaselm" or "omegalm". """ + # get the correct keys + if data_name_suffix == "": + t_key, amp_key, phase_key, omega_key = "t", "amplm", "phaselm", "omegalm" + else: + t_key = "t" + "_" + data_name_suffix + amp_key = "amplm" + "_" + data_name_suffix + phase_key = "phaselm" + "_" + data_name_suffix + omega_key = "omegalm" + "_" + data_name_suffix if not self.precessing: - amp_gw, phase_gw, omega_gw = (data_dict["amplm"][(2, 2)], - data_dict["phaselm"][(2, 2)], - data_dict["omegalm"][(2, 2)]) + amp_gw, phase_gw, omega_gw = (data_dict[amp_key][(2, 2)], + data_dict[phase_key][(2, 2)], + data_dict[omega_key][(2, 2)]) else: # check whether (2, -2) mode is provided. - for k in ["amplm", "phaselm"]: + for k in [amp_key, phase_key]: if (2, -2) not in data_dict[k]: - raise Exception(f"(2, -2) mode not found in {k}. For precessing" - " systems, (2, -2) mode should be included in " - "`dataDict`.") - amp_gw = 0.5 * (data_dict["amplm"][(2, 2)] - + data_dict["amplm"][(2, -2)]) - phase_gw = 0.5 * (data_dict["phaselm"][(2, 2)] - - data_dict["phaselm"][(2, -2)]) + raise Exception( + f"(2, -2) mode not found in {k}. For precessing" + " systems, (2, -2) mode should be included in " + "`dataDict`.") + amp_gw = 0.5 * (data_dict[amp_key][(2, 2)] + + data_dict[amp_key][(2, -2)]) + phase_gw = 0.5 * (data_dict[phase_key][(2, 2)] + - data_dict[phase_key][(2, -2)]) omega_gw = time_deriv_4thOrder( phase_gw, - data_dict["t"][1] - data_dict["t"][0]) + data_dict[t_key][1] - data_dict[t_key][0]) return amp_gw, phase_gw, omega_gw def get_width_for_peak_finder_from_phase_gw(self, @@ -2141,9 +2168,10 @@ def compute_res_amp_gw_and_res_omega_gw(self): raise Exception( "Input time array t_zeroecc must have uniform time steps\n" f"Time steps are {self.t_zeroecc_diff}") - # get amplitude and omega of 22 mode - self.amp_gw_zeroecc = self.dataDict["amplm_zeroecc"][(2, 2)] - self.omega_gw_zeroecc = self.dataDict["omegalm_zeroecc"][(2, 2)] + # get amplitude, phase and omega omega data + self.amp_gw_zeroecc, self.phase_gw_zeroecc, self.omega_gw_zeroecc\ + = self.get_amp_phase_omega_gw(self.dataDict, + data_name_suffix="zeroecc") # to get the residual amplitude and omega, we need to shift the # zeroecc time axis such that the merger of the zeroecc is at the # same time as that of the eccentric waveform From 358c9ceb7c469aad0153c4e1d511b0341ef7cbbb Mon Sep 17 00:00:00 2001 From: md-arif-shaikh Date: Mon, 18 Nov 2024 12:42:24 +0530 Subject: [PATCH 08/17] address comments --- gw_eccentricity/eccDefinition.py | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/gw_eccentricity/eccDefinition.py b/gw_eccentricity/eccDefinition.py index 0b2f71c..e2717e0 100644 --- a/gw_eccentricity/eccDefinition.py +++ b/gw_eccentricity/eccDefinition.py @@ -175,23 +175,22 @@ def __init__(self, dataDict, num_orbits_to_exclude_before_merger=2, `ell=2`, i.e., (2, -2), (2, -1), (2, 0), (2, 1) and (2, 2). For nonprecessing systems, the inertial and coprecessing frames are - equivalent, so there is no distinction. + equivalent, so there is no distinction. For nonprecessing systems, + it is sufficient to include only the (2, 2) mode. Default is `False`, indicating the system is nonprecessing. frame: str, default="inertial" Specifies the reference frame for the modes in `dataDict`. - Acceptable values are: - - "inertial": The modes in `dataDict` are in the inertial - frame. - - "coprecessing": The modes in `dataDict` are in the - coprecessing frame. - - If the system is precessing (`precessing=True`) and - `frame="inertial"`, the modes in `dataDict` are rotated into the - coprecessing frame for further computation. If - `frame="coprecessing"` with a precessing system, the modes in - `dataDict` are expected to be already in the coprecessing frame. + + This parameter determines the frame in which the mode data is + provided. It is especially relevant for measuring eccentricity in + precessing systems, as the choice of reference frame affects the + interpretation of the modes. Use this in conjunction with the + `precessing` parameter (see its documentation for more details) to + ensure appropriate handling of the data. + + Currently `frame` can be "inertial" or "coprecessing". Default value is "inertial". @@ -308,10 +307,10 @@ def __init__(self, dataDict, num_orbits_to_exclude_before_merger=2, self.precessing = precessing self.frame = frame # check if frame makes sense. - self.available_frames = ["inertial", "coprecessing"] - if self.frame not in self.available_frames: + available_frames = ["inertial", "coprecessing"] + if self.frame not in available_frames: raise ValueError(f"Unknown frame `{self.frame}`. Frame should be " - f"one of {self.available_frames}") + f"one of {available_frames}") # Get data necessary for eccentricity measurement self.dataDict, self.t_merger, self.amp_gw_merger, \ From 6ec5da371351917a19571b32724ac5c09736b1e2 Mon Sep 17 00:00:00 2001 From: md-arif-shaikh Date: Mon, 18 Nov 2024 13:35:47 +0530 Subject: [PATCH 09/17] minor --- gw_eccentricity/eccDefinition.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gw_eccentricity/eccDefinition.py b/gw_eccentricity/eccDefinition.py index e2717e0..2e86504 100644 --- a/gw_eccentricity/eccDefinition.py +++ b/gw_eccentricity/eccDefinition.py @@ -697,8 +697,8 @@ def process_data_dict(self, for mode in newDataDict[k]: newDataDict[k][mode] = newDataDict[k][mode][ :index_num_orbits_earlier_than_merger] - newDataDict["t"] = newDataDict["t"][ - :index_num_orbits_earlier_than_merger] + newDataDict["t"] = newDataDict["t"][ + :index_num_orbits_earlier_than_merger] return newDataDict, t_merger, amp_gw_merger, min_width_for_extrema def rotate_modes(self, data_dict): From d30df44964645f7024db731e17f0ca440f99fdab Mon Sep 17 00:00:00 2001 From: md-arif-shaikh Date: Sat, 23 Nov 2024 11:00:06 +0530 Subject: [PATCH 10/17] copy over doc to gw_eccentricity --- gw_eccentricity/gw_eccentricity.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/gw_eccentricity/gw_eccentricity.py b/gw_eccentricity/gw_eccentricity.py index e8d04bf..120e584 100644 --- a/gw_eccentricity/gw_eccentricity.py +++ b/gw_eccentricity/gw_eccentricity.py @@ -322,18 +322,16 @@ def measure_eccentricity(tref_in=None, Default is `False`, indicating the system is nonprecessing. frame: str, default="inertial" - Specifies the reference frame for the modes in `dataDict`. Acceptable - values are: - - "inertial": The modes in `dataDict` are in the inertial - frame. - - "coprecessing": The modes in `dataDict` are in the - coprecessing frame. - - If the system is precessing (`precessing=True`) and `frame="inertial"`, - the modes in `dataDict` are rotated into the coprecessing frame for - further computation. If `frame="coprecessing"` with a precessing - system, the modes in `dataDict` are expected to be already in the - coprecessing frame. + Specifies the reference frame for the modes in `dataDict`. + + This parameter determines the frame in which the mode data is provided. + It is especially relevant for measuring eccentricity in precessing + systems, as the choice of reference frame affects the interpretation of + the modes. Use this in conjunction with the `precessing` parameter (see + its documentation for more details) to ensure appropriate handling of + the data. + + Currently `frame` can be "inertial" or "coprecessing". Default value is "inertial". From f5c32c138c432f89e0f18bac81d693375f38a792 Mon Sep 17 00:00:00 2001 From: md-arif-shaikh Date: Sat, 23 Nov 2024 11:02:13 +0530 Subject: [PATCH 11/17] minor --- gw_eccentricity/gw_eccentricity.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gw_eccentricity/gw_eccentricity.py b/gw_eccentricity/gw_eccentricity.py index 120e584..384b780 100644 --- a/gw_eccentricity/gw_eccentricity.py +++ b/gw_eccentricity/gw_eccentricity.py @@ -317,7 +317,8 @@ def measure_eccentricity(tref_in=None, `ell=2`, i.e., (2, -2), (2, -1), (2, 0), (2, 1) and (2, 2). For nonprecessing systems, the inertial and coprecessing frames are - equivalent, so there is no distinction. + equivalent, so there is no distinction. For nonprecessing systems, it + is sufficient to include only the (2, 2) mode. Default is `False`, indicating the system is nonprecessing. From 41dfcb80abd301bad24a3606e509554bf5d58c30 Mon Sep 17 00:00:00 2001 From: md-arif-shaikh Date: Mon, 25 Nov 2024 15:18:33 +0530 Subject: [PATCH 12/17] use suffix to simplify zeroecc handling --- gw_eccentricity/eccDefinition.py | 180 +++++++++++++++-------------- gw_eccentricity/gw_eccentricity.py | 9 +- gw_eccentricity/load_data.py | 17 ++- 3 files changed, 112 insertions(+), 94 deletions(-) diff --git a/gw_eccentricity/eccDefinition.py b/gw_eccentricity/eccDefinition.py index 2e86504..3357200 100644 --- a/gw_eccentricity/eccDefinition.py +++ b/gw_eccentricity/eccDefinition.py @@ -8,6 +8,7 @@ import numpy as np import matplotlib.pyplot as plt +import warnings from .load_data import get_coprecessing_data_dict from .utils import peak_time_via_quadratic_fit, check_kwargs_and_set_defaults from .utils import amplitude_using_all_modes @@ -169,10 +170,11 @@ def __init__(self, dataDict, num_orbits_to_exclude_before_merger=2, directly via `dataDict`. - Set `frame="inertial"` and provide the inertial frame modes via `dataDict`. In this case, the modes in `dataDict` are - rotated internally (see `rotate_modes`) before further - computation. To get the coprecessing modes from the inertial - modes accurately, `dataDict` must include all modes for - `ell=2`, i.e., (2, -2), (2, -1), (2, 0), (2, 1) and (2, 2). + rotated internally (see `transform_inertial_to_coprecessing`) + before further computation. To get the coprecessing modes + from the inertial modes accurately, `dataDict` must include + all modes for `ell=2`, i.e., (2, -2), (2, -1), (2, 0), (2, 1) + and (2, 2). For nonprecessing systems, the inertial and coprecessing frames are equivalent, so there is no distinction. For nonprecessing systems, @@ -621,7 +623,18 @@ def process_data_dict(self, # frame, rotate the modes and obtain the corresponding modes in the # coprecessing frame if self.precessing is True and self.frame == "inertial": - dataDict = self.rotate_modes(dataDict) + warnings.warn( + f"The system is precessing but the modes are provided in " + f"the {self.frame} frame. Transforming the modes from" + f" the {self.frame} frame to the coprecessing frame and " + "updating `self.frame` to `coprecessing`.") + dataDict = self.transform_inertial_to_coprecessing(dataDict) + # transform the zeroecc modes as well if provided in dataDict + if "hlm_zeroecc" in dataDict or "amplm_zeroecc" in dataDict: + dataDict = self.transform_inertial_to_coprecessing( + dataDict, suffix="_zeroecc") + # Now that the modes are in the coprecessing frame, update frame + self.frame = "coprecessing" # Create a new dictionary that will contain the data necessary for # eccentricity measurement. newDataDict = {} @@ -701,93 +714,88 @@ def process_data_dict(self, :index_num_orbits_earlier_than_merger] return newDataDict, t_merger, amp_gw_merger, min_width_for_extrema - def rotate_modes(self, data_dict): - """"Rotate intertial frame modes to obtain coprecessing frame modes. + def transform_inertial_to_coprecessing(self, data_dict, suffix=""): + """"Transfrom intertial frame modes to coprecessing frame modes. Parameters ---------- data_dict: dict - Dictionary of modes in the inertial frame. The modes are rotated - using `get_coprecessing_data_dict` to obtain the corresponding - modes in the coprecessing frame. - - To obtain coprecessing frame modes from an inertial frame dictionary, - this dictionary should include all (ell, m) modes for a specified - ell value. For instance, the inertial modes dictionary should - contain at least all the modes for `ell=2`, i.e., (2, -2), (2, -1), - (2, 0), (2, 1), and (2, 2), to achieve accurate coprecessing frame - modes. + Dictionary of modes in the inertial frame. The modes are + transformed using `get_coprecessing_data_dict` to obtain the + corresponding modes in the coprecessing frame. + + To obtain coprecessing frame modes from an inertial frame + dictionary, this dictionary should include all (ell, m) modes for a + specified ell value. For instance, the inertial modes dictionary + should contain at least all the modes for `ell=2`, i.e., (2, -2), + (2, -1), (2, 0), (2, 1), and (2, 2), to achieve accurate + coprecessing frame modes. + + suffix: str, default="" + A suffix used to specify which input modes dictionary to use for + obtaining the coprecessing modes. For example, using + `suffix="_zeroecc"` selects the input modes corresponding to the + "zeroecc" modes dictionary, which are then rotated to compute the + coprecessing modes. If left as the default value (`""`), the input + modes from the eccentric modes dictionary are used. Returns ------- data_dict with the inertial modes replaced by the corresponding modes in the coprecessing frame. """ - if "hlm" in data_dict: - data_dict = get_coprecessing_data_dict(data_dict) - if "hlm_zeroecc" in data_dict: - # `get_coprecessing_data_dict` looks for modes using the key "hlm" - # and the associated time using "t". - # Make a dictionary with a key "hlm" and pass the zeroecc modes - # dict via it. Similary for the times using "t". - intertial_zeroecc_data_dict = {"t": data_dict["t_zeroecc"], - "hlm": data_dict["hlm_zeroecc"]} - coprecessing_zeroecc_data_dict = get_coprecessing_data_dict( - intertial_zeroecc_data_dict) - # update the data_dict by replacing the inertial frame zeroecc - # modes with coprecessing frame zeroecc modes. - data_dict.update( - {"hlm_zeroecc": coprecessing_zeroecc_data_dict["hlm"]}) - + if ("hlm" + suffix) in data_dict: + data_dict = get_coprecessing_data_dict(data_dict, suffix=suffix) # if hlm is not in data_dict, get it from amplm and phaselm. # We need to provide hlm to get the rotated modes. - if "hlm" not in data_dict: + if ("hlm" + suffix) not in data_dict: amplm_dict = self.get_amplm_from_dataDict(data_dict) phaselm_dict = self.get_phaselm_from_dataDict(data_dict) - hlm_dict = {} - # check if "hlm_zeroecc" is not in data_dict but amplm_zeroecc is - # in data_dict - if "amplm_zeroecc" in data_dict and "hlm_zeroecc" not in data_dict: - add_hlm_zeroecc = True - hlm_zeroecc_dict = {} - else: - add_hlm_zeroecc = False # combine amplm and phaselm to get hlm - for k in amplm_dict["amplm"]: - hlm_dict.update({k: amplm_dict["amplm"][k] - * np.exp(-1j * phaselm_dict["phaselm"][k])}) - if add_hlm_zeroecc: - hlm_zeroecc_dict.update( - {k: amplm_dict["amplm_zeroecc"][k] - * np.exp(-1j * phaselm_dict["phaselm_zeroecc"][k])}) - inertial_ecc_data_dict = {"t": data_dict["t"], "hlm": hlm_dict} - coprecessing_ecc_data_dict = get_coprecessing_data_dict( - inertial_ecc_data_dict) - data_dict.update(coprecessing_ecc_data_dict) - # remove amplm, phaselm because these are in the inertial frame - # and are given priority over hlm when using data for egw - data_dict.pop("amplm", None) - data_dict.pop("phaselm", None) - if add_hlm_zeroecc: - inertial_zeroecc_data_dict = { - "t": data_dict["t_zeroecc"], "hlm": hlm_zeroecc_dict} - coprecessing_zeroecc_data_dict = get_coprecessing_data_dict( - inertial_zeroecc_data_dict) - data_dict.update( - {"hlm_zeroecc": coprecessing_zeroecc_data_dict["hlm"]}) - # remove amplm_zeroecc, phaselm_zeroecc because these are in - # the inertial frame and are given priority over hlm_zeroecc - # when using data for egw - data_dict.pop("amplm_zeroecc", None) - data_dict.pop("phaselm_zeroecc", None) - # remove inertial omegalm. The coprecessing omegalm should be computed - # from the coprecessing phase later. - for omega in ["omegalm", "omegalm_zeroecc"]: - if omega in data_dict: - data_dict.pop(omega, None) + hlm_dict = self.get_hlm_from_amplm_phaselm(amplm_dict, phaselm_dict) + data_dict.update(hlm_dict) + data_dict = get_coprecessing_data_dict(data_dict, suffix=suffix) + warnings.warn( + f"Removing the inertial {'amplm' + suffix}, " + f"{'phaselm' + suffix} from `dataDict`. The same is computed " + f"later from the coprecessing {'hlm' + suffix} in" + f"`get_amp_phase_omega_data.`") + data_dict.pop("amplm" + suffix, None) + data_dict.pop("phaselm" + suffix, None) + if "omegalm" + suffix in data_dict: + warnings.warn( + f"Removing the inertial {'omegalm' + suffix} from `dataDict`. " + f"The coprecessing {'omegalm' + suffix}. The same is computed " + f"later from the coprecessing {'hlm' + suffix} in " + f"`get_amp_phase_omega_data`.") + data_dict.pop("omegalm" + suffix, None) + return data_dict + + def get_hlm_from_amplm_phaselm(self, amplm_dict, phaselm_dict): + """Compute the complex hlm modes from amplitude and phase data. + + The hlm modes are calculated using the formula: hlm = amplm * exp(-1j * + phaselm), where `amplm` and `phaselm` are dictionaries containing the + amplitude and phase for each mode. + + If the `amplm` and `phaselm` dictionaries include "zeroecc" modes, + these are also processed, and the corresponding hlm_zeroecc modes are + added to the returned `data_dict`. + """ + if "amplm_zeroecc" in amplm_dict: + suffixes = ["", "_zeroecc"] + else: + suffixes = [""] + data_dict = {} + for suffix in suffixes: + data_dict["hlm" + suffix] = {} + for k in amplm_dict["amplm" + suffix]: + data_dict["hlm" + suffix].update( + {k: amplm_dict["amplm" + suffix][k] + * np.exp(-1j * phaselm_dict["phaselm" + suffix][k])}) return data_dict - def get_amp_phase_omega_gw(self, data_dict, data_name_suffix=""): + def get_amp_phase_omega_gw(self, data_dict, suffix=""): """Get the gw quanitities from modes dict in the coprecessing frame. For nonprecessing systems, the amp_gw, phase_gw and omega_gw are the same @@ -816,26 +824,26 @@ def get_amp_phase_omega_gw(self, data_dict, data_name_suffix=""): A dictionary with the waveform modes and times. The structure of `data_dict` should be consistent with that of `dataDict`. - data_name_suffix: str, default="" + suffix: str, default="" A string identifier for selecting the data type when accessing amplitude, phase, and frequency (omega) values. It is used to specify if the waveform data corresponds to eccentric modes or zero-eccentricity (zeroecc) modes. For instance, set - `data_name_suffix=""` for eccentric modes or - `data_name_suffix="zeroecc"` for non-eccentric modes. + `suffix=""` for eccentric modes or + `suffix="_zeroecc"` for non-eccentric modes. - It will look for the key=`data_name` if `data_name_suffix` is empty - else key=`data_name` + "_" + "data_name_suffix" where the + It will look for the key=`data_name` if `suffix` is empty + else key=`data_name` + `suffix` where the `data_name` are "amplm", "phaselm" or "omegalm". """ # get the correct keys - if data_name_suffix == "": + if suffix == "": t_key, amp_key, phase_key, omega_key = "t", "amplm", "phaselm", "omegalm" else: - t_key = "t" + "_" + data_name_suffix - amp_key = "amplm" + "_" + data_name_suffix - phase_key = "phaselm" + "_" + data_name_suffix - omega_key = "omegalm" + "_" + data_name_suffix + t_key = "t" + suffix + amp_key = "amplm" + suffix + phase_key = "phaselm" + suffix + omega_key = "omegalm" + suffix if not self.precessing: amp_gw, phase_gw, omega_gw = (data_dict[amp_key][(2, 2)], data_dict[phase_key][(2, 2)], @@ -2170,7 +2178,7 @@ def compute_res_amp_gw_and_res_omega_gw(self): # get amplitude, phase and omega omega data self.amp_gw_zeroecc, self.phase_gw_zeroecc, self.omega_gw_zeroecc\ = self.get_amp_phase_omega_gw(self.dataDict, - data_name_suffix="zeroecc") + suffix="_zeroecc") # to get the residual amplitude and omega, we need to shift the # zeroecc time axis such that the merger of the zeroecc is at the # same time as that of the eccentric waveform diff --git a/gw_eccentricity/gw_eccentricity.py b/gw_eccentricity/gw_eccentricity.py index 384b780..caaab31 100644 --- a/gw_eccentricity/gw_eccentricity.py +++ b/gw_eccentricity/gw_eccentricity.py @@ -311,10 +311,11 @@ def measure_eccentricity(tref_in=None, directly via `dataDict`. - Set `frame="inertial"` and provide the inertial frame modes via `dataDict`. In this case, the modes in `dataDict` are - rotated internally (see `rotate_modes`) before further - computation. To get the coprecessing modes from the inertial - modes accurately, `dataDict` must include all modes for - `ell=2`, i.e., (2, -2), (2, -1), (2, 0), (2, 1) and (2, 2). + rotated internally (see `transform_inertial_to_coprecessing`) + before further computation. To get the coprecessing modes from + the inertial modes accurately, `dataDict` must include all + modes for `ell=2`, i.e., (2, -2), (2, -1), (2, 0), (2, 1) and + (2, 2). For nonprecessing systems, the inertial and coprecessing frames are equivalent, so there is no distinction. For nonprecessing systems, it diff --git a/gw_eccentricity/load_data.py b/gw_eccentricity/load_data.py index c7dcb22..b395647 100644 --- a/gw_eccentricity/load_data.py +++ b/gw_eccentricity/load_data.py @@ -1534,7 +1534,7 @@ def unpack_scri_modes(w): return result -def get_coprecessing_data_dict(data_dict, ell_min=2, ell_max=2): +def get_coprecessing_data_dict(data_dict, ell_min=2, ell_max=2, suffix=""): """Get `data_dict` in the coprecessing frame. Given a `data_dict` containing the modes dict in the inertial frame and the @@ -1556,6 +1556,14 @@ def get_coprecessing_data_dict(data_dict, ell_min=2, ell_max=2): ell_max: int, default=2 Maximum `ell` value to use. + suffix: str, default="" + A suffix used to specify which input modes dictionary to use for + obtaining the coprecessing modes. For example, using + `suffix="_zeroecc"` selects the input modes corresponding to the + "zeroecc" modes dictionary, which are then rotated to compute the + coprecessing modes. If left as the default value (`""`), the input + modes from the eccentric modes dictionary are used. + Returns ------- Dictionary of waveform modes in the coprecessing frame and the associated @@ -1564,13 +1572,13 @@ def get_coprecessing_data_dict(data_dict, ell_min=2, ell_max=2): """ # Get list of modes from `data_dict` to use as input to `scri.WaveformModes`. ordered_mode_list = package_modes_for_scri( - data_dict["hlm"], + data_dict["hlm" + suffix], ell_min=ell_min, ell_max=ell_max) w = scri.WaveformModes( dataType=scri.h, - t=data_dict["t"], + t=data_dict["t" + suffix], data=ordered_mode_list, ell_min=ell_min, ell_max=ell_max, @@ -1583,7 +1591,8 @@ def get_coprecessing_data_dict(data_dict, ell_min=2, ell_max=2): # Create a copy of data_dict and replace the "hlm" modes in the inertial frame # with the corresponding modes in the coprecessing frame data_dict_copr = deepcopy(data_dict) - data_dict_copr.update({"hlm": unpack_scri_modes(deepcopy(w_coprecessing))}) + data_dict_copr.update( + {"hlm" + suffix: unpack_scri_modes(deepcopy(w_coprecessing))}) return data_dict_copr From 766221c10ba886371eb75b52814564e954448151 Mon Sep 17 00:00:00 2001 From: md-arif-shaikh Date: Tue, 26 Nov 2024 00:18:43 +0530 Subject: [PATCH 13/17] polish documentation --- gw_eccentricity/eccDefinition.py | 25 +++++++++++++------------ gw_eccentricity/load_data.py | 11 +++++------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/gw_eccentricity/eccDefinition.py b/gw_eccentricity/eccDefinition.py index 3357200..bc36566 100644 --- a/gw_eccentricity/eccDefinition.py +++ b/gw_eccentricity/eccDefinition.py @@ -732,12 +732,12 @@ def transform_inertial_to_coprecessing(self, data_dict, suffix=""): coprecessing frame modes. suffix: str, default="" - A suffix used to specify which input modes dictionary to use for - obtaining the coprecessing modes. For example, using - `suffix="_zeroecc"` selects the input modes corresponding to the - "zeroecc" modes dictionary, which are then rotated to compute the - coprecessing modes. If left as the default value (`""`), the input - modes from the eccentric modes dictionary are used. + A suffix specifying which inertial frame data to use when + transforming inertial frame modes to coprecessing frame modes. For + example, setting `suffix="_zeroecc"` selects the inertial frame + modes corresponding to the "zeroecc" (non-eccentric) case. If left + as the default value (`""`), the inertial frame modes for the + eccentric case are used. Returns ------- @@ -756,17 +756,18 @@ def transform_inertial_to_coprecessing(self, data_dict, suffix=""): data_dict.update(hlm_dict) data_dict = get_coprecessing_data_dict(data_dict, suffix=suffix) warnings.warn( - f"Removing the inertial {'amplm' + suffix}, " - f"{'phaselm' + suffix} from `dataDict`. The same is computed " + f"Removing the input inertial frame {'amplm' + suffix}, " + f"{'phaselm' + suffix} from `dataDict`. The corresponding " + "coprecessing frame quantities are computed " f"later from the coprecessing {'hlm' + suffix} in" - f"`get_amp_phase_omega_data.`") + f"`get_amp_phase_omega_data`.") data_dict.pop("amplm" + suffix, None) data_dict.pop("phaselm" + suffix, None) if "omegalm" + suffix in data_dict: warnings.warn( - f"Removing the inertial {'omegalm' + suffix} from `dataDict`. " - f"The coprecessing {'omegalm' + suffix}. The same is computed " - f"later from the coprecessing {'hlm' + suffix} in " + f"Removing the input inertial frame {'omegalm' + suffix} " + f"from `dataDict`. The coprecessing {'omegalm' + suffix} is " + f"computed later from the coprecessing {'hlm' + suffix} in " f"`get_amp_phase_omega_data`.") data_dict.pop("omegalm" + suffix, None) return data_dict diff --git a/gw_eccentricity/load_data.py b/gw_eccentricity/load_data.py index b395647..ccbe227 100644 --- a/gw_eccentricity/load_data.py +++ b/gw_eccentricity/load_data.py @@ -1557,12 +1557,11 @@ def get_coprecessing_data_dict(data_dict, ell_min=2, ell_max=2, suffix=""): Maximum `ell` value to use. suffix: str, default="" - A suffix used to specify which input modes dictionary to use for - obtaining the coprecessing modes. For example, using - `suffix="_zeroecc"` selects the input modes corresponding to the - "zeroecc" modes dictionary, which are then rotated to compute the - coprecessing modes. If left as the default value (`""`), the input - modes from the eccentric modes dictionary are used. + A suffix specifying which inertial frame data to use when transforming + inertial frame modes to coprecessing frame modes. For example, setting + `suffix="_zeroecc"` selects the inertial frame modes corresponding to + the "zeroecc" (non-eccentric) case. If left as the default value + (`""`), the inertial frame modes for the eccentric case are used. Returns ------- From fe7a176170ca8653be60ba9be49912689d5f89fa Mon Sep 17 00:00:00 2001 From: md-arif-shaikh Date: Tue, 26 Nov 2024 08:38:51 +0530 Subject: [PATCH 14/17] minor improvements --- gw_eccentricity/eccDefinition.py | 83 +++++++++++++++----------------- gw_eccentricity/load_data.py | 14 +++--- 2 files changed, 45 insertions(+), 52 deletions(-) diff --git a/gw_eccentricity/eccDefinition.py b/gw_eccentricity/eccDefinition.py index bc36566..69629a9 100644 --- a/gw_eccentricity/eccDefinition.py +++ b/gw_eccentricity/eccDefinition.py @@ -714,7 +714,7 @@ def process_data_dict(self, :index_num_orbits_earlier_than_merger] return newDataDict, t_merger, amp_gw_merger, min_width_for_extrema - def transform_inertial_to_coprecessing(self, data_dict, suffix=""): + def transform_inertial_to_coprecessing(self, data_dict, tag=""): """"Transfrom intertial frame modes to coprecessing frame modes. Parameters @@ -731,10 +731,10 @@ def transform_inertial_to_coprecessing(self, data_dict, suffix=""): (2, -1), (2, 0), (2, 1), and (2, 2), to achieve accurate coprecessing frame modes. - suffix: str, default="" - A suffix specifying which inertial frame data to use when + tag: str, default="" + A tag specifying which inertial frame data to use when transforming inertial frame modes to coprecessing frame modes. For - example, setting `suffix="_zeroecc"` selects the inertial frame + example, setting `tag="_zeroecc"` selects the inertial frame modes corresponding to the "zeroecc" (non-eccentric) case. If left as the default value (`""`), the inertial frame modes for the eccentric case are used. @@ -744,32 +744,32 @@ def transform_inertial_to_coprecessing(self, data_dict, suffix=""): data_dict with the inertial modes replaced by the corresponding modes in the coprecessing frame. """ - if ("hlm" + suffix) in data_dict: - data_dict = get_coprecessing_data_dict(data_dict, suffix=suffix) + if ("hlm" + tag) in data_dict: + data_dict = get_coprecessing_data_dict(data_dict, tag=tag) # if hlm is not in data_dict, get it from amplm and phaselm. # We need to provide hlm to get the rotated modes. - if ("hlm" + suffix) not in data_dict: + if ("hlm" + tag) not in data_dict: amplm_dict = self.get_amplm_from_dataDict(data_dict) phaselm_dict = self.get_phaselm_from_dataDict(data_dict) # combine amplm and phaselm to get hlm hlm_dict = self.get_hlm_from_amplm_phaselm(amplm_dict, phaselm_dict) data_dict.update(hlm_dict) - data_dict = get_coprecessing_data_dict(data_dict, suffix=suffix) + data_dict = get_coprecessing_data_dict(data_dict, tag=tag) warnings.warn( - f"Removing the input inertial frame {'amplm' + suffix}, " - f"{'phaselm' + suffix} from `dataDict`. The corresponding " + f"Removing the input inertial frame {'amplm' + tag}, " + f"{'phaselm' + tag} from `dataDict`. The corresponding " "coprecessing frame quantities are computed " - f"later from the coprecessing {'hlm' + suffix} in" + f"later from the coprecessing {'hlm' + tag} in" f"`get_amp_phase_omega_data`.") - data_dict.pop("amplm" + suffix, None) - data_dict.pop("phaselm" + suffix, None) - if "omegalm" + suffix in data_dict: + data_dict.pop("amplm" + tag, None) + data_dict.pop("phaselm" + tag, None) + if "omegalm" + tag in data_dict: warnings.warn( - f"Removing the input inertial frame {'omegalm' + suffix} " - f"from `dataDict`. The coprecessing {'omegalm' + suffix} is " - f"computed later from the coprecessing {'hlm' + suffix} in " + f"Removing the input inertial frame {'omegalm' + tag} " + f"from `dataDict`. The coprecessing {'omegalm' + tag} is " + f"computed later from the coprecessing {'hlm' + tag} in " f"`get_amp_phase_omega_data`.") - data_dict.pop("omegalm" + suffix, None) + data_dict.pop("omegalm" + tag, None) return data_dict def get_hlm_from_amplm_phaselm(self, amplm_dict, phaselm_dict): @@ -784,19 +784,19 @@ def get_hlm_from_amplm_phaselm(self, amplm_dict, phaselm_dict): added to the returned `data_dict`. """ if "amplm_zeroecc" in amplm_dict: - suffixes = ["", "_zeroecc"] + tags = ["", "_zeroecc"] else: - suffixes = [""] + tags = [""] data_dict = {} - for suffix in suffixes: - data_dict["hlm" + suffix] = {} - for k in amplm_dict["amplm" + suffix]: - data_dict["hlm" + suffix].update( - {k: amplm_dict["amplm" + suffix][k] - * np.exp(-1j * phaselm_dict["phaselm" + suffix][k])}) + for tag in tags: + data_dict["hlm" + tag] = {} + for k in amplm_dict["amplm" + tag]: + data_dict["hlm" + tag].update( + {k: amplm_dict["amplm" + tag][k] + * np.exp(-1j * phaselm_dict["phaselm" + tag][k])}) return data_dict - def get_amp_phase_omega_gw(self, data_dict, suffix=""): + def get_amp_phase_omega_gw(self, data_dict, tag=""): """Get the gw quanitities from modes dict in the coprecessing frame. For nonprecessing systems, the amp_gw, phase_gw and omega_gw are the same @@ -814,7 +814,7 @@ def get_amp_phase_omega_gw(self, data_dict, suffix=""): amp_gw = (1/2) * (amp(2, 2) + amp(2, -2)) phase_gw = (1/2) * (phase(2, 2) - phase(2, -2)) - omega_gw = d(phase_gw)/dt + omega_gw = d(phase_gw)/dt = (1/2) * (omega(2, 2) - omega(2, -2)) These quantities reduce to the corresponding (2, 2) mode data when the system is nonprecessing. @@ -825,26 +825,20 @@ def get_amp_phase_omega_gw(self, data_dict, suffix=""): A dictionary with the waveform modes and times. The structure of `data_dict` should be consistent with that of `dataDict`. - suffix: str, default="" + tag: str, default="" A string identifier for selecting the data type when accessing amplitude, phase, and frequency (omega) values. It is used to specify if the waveform data corresponds to eccentric modes or zero-eccentricity (zeroecc) modes. For instance, set - `suffix=""` for eccentric modes or - `suffix="_zeroecc"` for non-eccentric modes. + `tag=""` for eccentric modes or + `tag="_zeroecc"` for non-eccentric modes. - It will look for the key=`data_name` if `suffix` is empty - else key=`data_name` + `suffix` where the - `data_name` are "amplm", "phaselm" or "omegalm". + It will look for the key=`data_name` + `tag` where the `data_name` + are "amplm", "phaselm" or "omegalm". """ # get the correct keys - if suffix == "": - t_key, amp_key, phase_key, omega_key = "t", "amplm", "phaselm", "omegalm" - else: - t_key = "t" + suffix - amp_key = "amplm" + suffix - phase_key = "phaselm" + suffix - omega_key = "omegalm" + suffix + t_key, amp_key, phase_key, omega_key \ + = [k + tag for k in ["t", "amplm", "phaselm", "omegalm"]] if not self.precessing: amp_gw, phase_gw, omega_gw = (data_dict[amp_key][(2, 2)], data_dict[phase_key][(2, 2)], @@ -861,9 +855,8 @@ def get_amp_phase_omega_gw(self, data_dict, suffix=""): + data_dict[amp_key][(2, -2)]) phase_gw = 0.5 * (data_dict[phase_key][(2, 2)] - data_dict[phase_key][(2, -2)]) - omega_gw = time_deriv_4thOrder( - phase_gw, - data_dict[t_key][1] - data_dict[t_key][0]) + omega_gw = 0.5 * (data_dict[omega_key][(2, 2)] + - data_dict[omega_key][(2, -2)]) return amp_gw, phase_gw, omega_gw def get_width_for_peak_finder_from_phase_gw(self, @@ -2179,7 +2172,7 @@ def compute_res_amp_gw_and_res_omega_gw(self): # get amplitude, phase and omega omega data self.amp_gw_zeroecc, self.phase_gw_zeroecc, self.omega_gw_zeroecc\ = self.get_amp_phase_omega_gw(self.dataDict, - suffix="_zeroecc") + tag="_zeroecc") # to get the residual amplitude and omega, we need to shift the # zeroecc time axis such that the merger of the zeroecc is at the # same time as that of the eccentric waveform diff --git a/gw_eccentricity/load_data.py b/gw_eccentricity/load_data.py index ccbe227..5056c43 100644 --- a/gw_eccentricity/load_data.py +++ b/gw_eccentricity/load_data.py @@ -1534,7 +1534,7 @@ def unpack_scri_modes(w): return result -def get_coprecessing_data_dict(data_dict, ell_min=2, ell_max=2, suffix=""): +def get_coprecessing_data_dict(data_dict, ell_min=2, ell_max=2, tag=""): """Get `data_dict` in the coprecessing frame. Given a `data_dict` containing the modes dict in the inertial frame and the @@ -1556,10 +1556,10 @@ def get_coprecessing_data_dict(data_dict, ell_min=2, ell_max=2, suffix=""): ell_max: int, default=2 Maximum `ell` value to use. - suffix: str, default="" - A suffix specifying which inertial frame data to use when transforming + tag: str, default="" + A tag specifying which inertial frame data to use when transforming inertial frame modes to coprecessing frame modes. For example, setting - `suffix="_zeroecc"` selects the inertial frame modes corresponding to + `tag="_zeroecc"` selects the inertial frame modes corresponding to the "zeroecc" (non-eccentric) case. If left as the default value (`""`), the inertial frame modes for the eccentric case are used. @@ -1571,13 +1571,13 @@ def get_coprecessing_data_dict(data_dict, ell_min=2, ell_max=2, suffix=""): """ # Get list of modes from `data_dict` to use as input to `scri.WaveformModes`. ordered_mode_list = package_modes_for_scri( - data_dict["hlm" + suffix], + data_dict["hlm" + tag], ell_min=ell_min, ell_max=ell_max) w = scri.WaveformModes( dataType=scri.h, - t=data_dict["t" + suffix], + t=data_dict["t" + tag], data=ordered_mode_list, ell_min=ell_min, ell_max=ell_max, @@ -1591,7 +1591,7 @@ def get_coprecessing_data_dict(data_dict, ell_min=2, ell_max=2, suffix=""): # with the corresponding modes in the coprecessing frame data_dict_copr = deepcopy(data_dict) data_dict_copr.update( - {"hlm" + suffix: unpack_scri_modes(deepcopy(w_coprecessing))}) + {"hlm" + tag: unpack_scri_modes(deepcopy(w_coprecessing))}) return data_dict_copr From 0d577a8dd59d9e0ff6b107c3554b75556ce6d893 Mon Sep 17 00:00:00 2001 From: md-arif-shaikh Date: Tue, 26 Nov 2024 08:40:53 +0530 Subject: [PATCH 15/17] fix small bug --- gw_eccentricity/eccDefinition.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gw_eccentricity/eccDefinition.py b/gw_eccentricity/eccDefinition.py index 69629a9..de8884d 100644 --- a/gw_eccentricity/eccDefinition.py +++ b/gw_eccentricity/eccDefinition.py @@ -632,7 +632,7 @@ def process_data_dict(self, # transform the zeroecc modes as well if provided in dataDict if "hlm_zeroecc" in dataDict or "amplm_zeroecc" in dataDict: dataDict = self.transform_inertial_to_coprecessing( - dataDict, suffix="_zeroecc") + dataDict, tag="_zeroecc") # Now that the modes are in the coprecessing frame, update frame self.frame = "coprecessing" # Create a new dictionary that will contain the data necessary for @@ -759,7 +759,7 @@ def transform_inertial_to_coprecessing(self, data_dict, tag=""): f"Removing the input inertial frame {'amplm' + tag}, " f"{'phaselm' + tag} from `dataDict`. The corresponding " "coprecessing frame quantities are computed " - f"later from the coprecessing {'hlm' + tag} in" + f"later from the coprecessing {'hlm' + tag} in " f"`get_amp_phase_omega_data`.") data_dict.pop("amplm" + tag, None) data_dict.pop("phaselm" + tag, None) From f83d7e7703fa8d7b6e72b0bb0f499038aecfa25d Mon Sep 17 00:00:00 2001 From: md-arif-shaikh Date: Tue, 26 Nov 2024 10:07:13 +0530 Subject: [PATCH 16/17] use debug_level --- gw_eccentricity/eccDefinition.py | 33 ++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/gw_eccentricity/eccDefinition.py b/gw_eccentricity/eccDefinition.py index de8884d..a219497 100644 --- a/gw_eccentricity/eccDefinition.py +++ b/gw_eccentricity/eccDefinition.py @@ -8,7 +8,6 @@ import numpy as np import matplotlib.pyplot as plt -import warnings from .load_data import get_coprecessing_data_dict from .utils import peak_time_via_quadratic_fit, check_kwargs_and_set_defaults from .utils import amplitude_using_all_modes @@ -623,16 +622,23 @@ def process_data_dict(self, # frame, rotate the modes and obtain the corresponding modes in the # coprecessing frame if self.precessing is True and self.frame == "inertial": - warnings.warn( + # get debug level + if extra_kwargs is not None: + debug_level = extra_kwargs.get("debug_level", 0) + else: + debug_level = 0 + debug_message( f"The system is precessing but the modes are provided in " f"the {self.frame} frame. Transforming the modes from" f" the {self.frame} frame to the coprecessing frame and " - "updating `self.frame` to `coprecessing`.") - dataDict = self.transform_inertial_to_coprecessing(dataDict) + "updating `self.frame` to `coprecessing`.", + debug_level=debug_level, important=False) + dataDict = self.transform_inertial_to_coprecessing( + dataDict, debug_level=debug_level) # transform the zeroecc modes as well if provided in dataDict if "hlm_zeroecc" in dataDict or "amplm_zeroecc" in dataDict: dataDict = self.transform_inertial_to_coprecessing( - dataDict, tag="_zeroecc") + dataDict, tag="_zeroecc", debug_level=debug_level) # Now that the modes are in the coprecessing frame, update frame self.frame = "coprecessing" # Create a new dictionary that will contain the data necessary for @@ -714,7 +720,8 @@ def process_data_dict(self, :index_num_orbits_earlier_than_merger] return newDataDict, t_merger, amp_gw_merger, min_width_for_extrema - def transform_inertial_to_coprecessing(self, data_dict, tag=""): + def transform_inertial_to_coprecessing( + self, data_dict, tag="", debug_level=0): """"Transfrom intertial frame modes to coprecessing frame modes. Parameters @@ -739,6 +746,10 @@ def transform_inertial_to_coprecessing(self, data_dict, tag=""): as the default value (`""`), the inertial frame modes for the eccentric case are used. + debug_level: int, default=0 + Debug level to use. See documentation for `debug_level` under + `extra_kwargs` + Returns ------- data_dict with the inertial modes replaced by the corresponding @@ -755,20 +766,22 @@ def transform_inertial_to_coprecessing(self, data_dict, tag=""): hlm_dict = self.get_hlm_from_amplm_phaselm(amplm_dict, phaselm_dict) data_dict.update(hlm_dict) data_dict = get_coprecessing_data_dict(data_dict, tag=tag) - warnings.warn( + debug_message( f"Removing the input inertial frame {'amplm' + tag}, " f"{'phaselm' + tag} from `dataDict`. The corresponding " "coprecessing frame quantities are computed " f"later from the coprecessing {'hlm' + tag} in " - f"`get_amp_phase_omega_data`.") + f"`get_amp_phase_omega_data`.", debug_level=debug_level, + important=False) data_dict.pop("amplm" + tag, None) data_dict.pop("phaselm" + tag, None) if "omegalm" + tag in data_dict: - warnings.warn( + debug_message( f"Removing the input inertial frame {'omegalm' + tag} " f"from `dataDict`. The coprecessing {'omegalm' + tag} is " f"computed later from the coprecessing {'hlm' + tag} in " - f"`get_amp_phase_omega_data`.") + f"`get_amp_phase_omega_data`.", debug_level=debug_level, + important=False) data_dict.pop("omegalm" + tag, None) return data_dict From 02722a8d0333c06ee34386bd5f9ad1ff49704f60 Mon Sep 17 00:00:00 2001 From: md-arif-shaikh Date: Tue, 26 Nov 2024 10:45:18 +0530 Subject: [PATCH 17/17] Revert "use debug_level" This reverts commit f83d7e7703fa8d7b6e72b0bb0f499038aecfa25d. --- gw_eccentricity/eccDefinition.py | 33 ++++++++++---------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/gw_eccentricity/eccDefinition.py b/gw_eccentricity/eccDefinition.py index a219497..de8884d 100644 --- a/gw_eccentricity/eccDefinition.py +++ b/gw_eccentricity/eccDefinition.py @@ -8,6 +8,7 @@ import numpy as np import matplotlib.pyplot as plt +import warnings from .load_data import get_coprecessing_data_dict from .utils import peak_time_via_quadratic_fit, check_kwargs_and_set_defaults from .utils import amplitude_using_all_modes @@ -622,23 +623,16 @@ def process_data_dict(self, # frame, rotate the modes and obtain the corresponding modes in the # coprecessing frame if self.precessing is True and self.frame == "inertial": - # get debug level - if extra_kwargs is not None: - debug_level = extra_kwargs.get("debug_level", 0) - else: - debug_level = 0 - debug_message( + warnings.warn( f"The system is precessing but the modes are provided in " f"the {self.frame} frame. Transforming the modes from" f" the {self.frame} frame to the coprecessing frame and " - "updating `self.frame` to `coprecessing`.", - debug_level=debug_level, important=False) - dataDict = self.transform_inertial_to_coprecessing( - dataDict, debug_level=debug_level) + "updating `self.frame` to `coprecessing`.") + dataDict = self.transform_inertial_to_coprecessing(dataDict) # transform the zeroecc modes as well if provided in dataDict if "hlm_zeroecc" in dataDict or "amplm_zeroecc" in dataDict: dataDict = self.transform_inertial_to_coprecessing( - dataDict, tag="_zeroecc", debug_level=debug_level) + dataDict, tag="_zeroecc") # Now that the modes are in the coprecessing frame, update frame self.frame = "coprecessing" # Create a new dictionary that will contain the data necessary for @@ -720,8 +714,7 @@ def process_data_dict(self, :index_num_orbits_earlier_than_merger] return newDataDict, t_merger, amp_gw_merger, min_width_for_extrema - def transform_inertial_to_coprecessing( - self, data_dict, tag="", debug_level=0): + def transform_inertial_to_coprecessing(self, data_dict, tag=""): """"Transfrom intertial frame modes to coprecessing frame modes. Parameters @@ -746,10 +739,6 @@ def transform_inertial_to_coprecessing( as the default value (`""`), the inertial frame modes for the eccentric case are used. - debug_level: int, default=0 - Debug level to use. See documentation for `debug_level` under - `extra_kwargs` - Returns ------- data_dict with the inertial modes replaced by the corresponding @@ -766,22 +755,20 @@ def transform_inertial_to_coprecessing( hlm_dict = self.get_hlm_from_amplm_phaselm(amplm_dict, phaselm_dict) data_dict.update(hlm_dict) data_dict = get_coprecessing_data_dict(data_dict, tag=tag) - debug_message( + warnings.warn( f"Removing the input inertial frame {'amplm' + tag}, " f"{'phaselm' + tag} from `dataDict`. The corresponding " "coprecessing frame quantities are computed " f"later from the coprecessing {'hlm' + tag} in " - f"`get_amp_phase_omega_data`.", debug_level=debug_level, - important=False) + f"`get_amp_phase_omega_data`.") data_dict.pop("amplm" + tag, None) data_dict.pop("phaselm" + tag, None) if "omegalm" + tag in data_dict: - debug_message( + warnings.warn( f"Removing the input inertial frame {'omegalm' + tag} " f"from `dataDict`. The coprecessing {'omegalm' + tag} is " f"computed later from the coprecessing {'hlm' + tag} in " - f"`get_amp_phase_omega_data`.", debug_level=debug_level, - important=False) + f"`get_amp_phase_omega_data`.") data_dict.pop("omegalm" + tag, None) return data_dict