From 13b4f720488e31aa7f8a4aaefdb4f16983758c0e Mon Sep 17 00:00:00 2001 From: Steph Merritt Date: Tue, 12 Mar 2024 13:19:36 +0000 Subject: [PATCH 1/7] Fixes/methods on AdlerData. --- src/adler/dataclasses/AdlerData.py | 93 ++++++++++++++++++++--- tests/adler/dataclasses/test_AdlerData.py | 71 +++++++++++++---- 2 files changed, 142 insertions(+), 22 deletions(-) diff --git a/src/adler/dataclasses/AdlerData.py b/src/adler/dataclasses/AdlerData.py index d42aa82..052d56f 100644 --- a/src/adler/dataclasses/AdlerData.py +++ b/src/adler/dataclasses/AdlerData.py @@ -46,10 +46,10 @@ class AdlerData: filter_list: list model_lists: list = field(default_factory=list) - phaseAngle_min_adler: np.ndarray = field(default_factory=lambda: np.zeros(0, dtype=float)) - phaseAngle_range_adler: np.ndarray = field(default_factory=lambda: np.zeros(0, dtype=float)) - nobs_adler: np.ndarray = field(default_factory=lambda: np.zeros(0, dtype=int)) - arc_adler: np.ndarray = field(default_factory=lambda: np.zeros(0, dtype=float)) + phaseAngle_min_adler: np.ndarray = field(default_factory=lambda: np.empty(0, dtype=float)) + phaseAngle_range_adler: np.ndarray = field(default_factory=lambda: np.empty(0, dtype=float)) + nobs_adler: np.ndarray = field(default_factory=lambda: np.empty(0, dtype=int)) + arc_adler: np.ndarray = field(default_factory=lambda: np.empty(0, dtype=float)) # Note that these are lists and not arrays because appending to Numpy arrays (i.e. to add parameters for a different model) is not recommended. # They can be cast to Numpy arrays later if needed. @@ -66,10 +66,10 @@ def __post_init__(self): self.model_lists = [[] for a in range(0, filter_length)] - self.phaseAngle_min_adler = np.zeros(filter_length, dtype=float) - self.phaseAngle_range_adler = np.zeros(filter_length, dtype=float) - self.nobs_adler = np.zeros(filter_length, dtype=int) - self.arc_adler = np.zeros(filter_length, dtype=float) + self.phaseAngle_min_adler = np.empty(filter_length, dtype=float) + self.phaseAngle_range_adler = np.empty(filter_length, dtype=float) + self.nobs_adler = np.empty(filter_length, dtype=int) + self.arc_adler = np.empty(filter_length, dtype=float) self.H_adler = [[] for a in range(0, filter_length)] self.H_err_adler = [[] for a in range(0, filter_length)] @@ -130,7 +130,7 @@ def populate_phase_parameters( try: filter_index = self.filter_list.index(filter_name) except ValueError: - raise Exception("Filter {} is not in supplied filter list.".format(filter_name)) + raise ValueError("Filter {} does not exist in AdlerData.filter_list.".format(filter_name)) # If parameters and/or parameters_err are not lists, error out. if not isinstance(parameters, list) or not isinstance(parameters_err, list): @@ -156,3 +156,78 @@ def populate_phase_parameters( self.H_err_adler[filter_index][model_index] = H_err self.phase_parameters[filter_index][model_index] = parameters self.phase_parameters_err[filter_index][model_index] = parameters_err + + def print_data(self): + """Convenience method to clearly print the stored values.""" + + print("Phase parameters (per filter):\n") + for f, filter_name in enumerate(self.filter_list): + print("Filter: {}".format(filter_name)) + print("Phase angle minimum: {}".format(self.phaseAngle_min_adler[f])) + print("Phase angle range: {}".format(self.phaseAngle_range_adler[f])) + print("Number of observations: {}".format(self.nobs_adler[f])) + print("Arc: {}".format(self.arc_adler[f])) + + for m, model_name in enumerate(self.model_lists[f]): + print("Model: {}.".format(model_name)) + print("\tH: {}".format(self.H_adler[f][m])) + print("\tH error: {}".format(self.H_err_adler[f][m])) + print("\tPhase parameter(s): {}".format(self.phase_parameters[f][m])) + print("\tPhase parameter(s) error: {}".format(self.phase_parameters_err[f][m])) + + print("\n") + + def get_phase_parameters_in_filter(self, filter_name, model_name=None): + """Convenience method to return the phase parameters in a specific filter and model. + + Parameters + ----------- + filter_name : str + The filter of interest. + + model_name : str, optional + The model name of the model of interest. If this is not supplied, the code automatically returns the + parameters for the first model in the list. + + + Returns + ----------- + parameters_dict : dict + Dictionary of the phase curve parameters for the specified filter and model. + + """ + + try: + filter_index = self.filter_list.index(filter_name) + except ValueError: + raise ValueError("Filter {} does not exist in AdlerData.filter_list.".format(filter_name)) + + if model_name: + try: + model_index = self.model_lists[filter_index].index(model_name) + except ValueError: + raise ValueError( + "Model {} does not exist for filter {} in AdlerData.model_lists.".format( + model_name, filter_name + ) + ) + else: + model_index = 0 + print( + "No model name specified. Returning phase parameters for first model in list: {}.".format( + self.model_lists[filter_index][model_index] + ) + ) + + parameters_dict = { + "phaseAngle_min": self.phaseAngle_min_adler[filter_index], + "phaseAngle_range": self.phaseAngle_range_adler[filter_index], + "nobs": self.nobs_adler[filter_index], + "arc": self.arc_adler[filter_index], + "H": self.H_adler[filter_index][model_index], + "H_err": self.H_err_adler[filter_index][model_index], + "phase_parameters": self.phase_parameters[filter_index][model_index], + "phase_parameters_err": self.phase_parameters_err[filter_index][model_index], + } + + return parameters_dict diff --git a/tests/adler/dataclasses/test_AdlerData.py b/tests/adler/dataclasses/test_AdlerData.py index 397143d..79ea4f9 100644 --- a/tests/adler/dataclasses/test_AdlerData.py +++ b/tests/adler/dataclasses/test_AdlerData.py @@ -1,21 +1,25 @@ from numpy.testing import assert_array_equal import pytest +from adler.dataclasses.AdlerData import AdlerData -def test_populate_phase_parameters(): - from adler.dataclasses.AdlerData import AdlerData - test_object = AdlerData(["u", "g", "r"]) +# setting up the AdlerData object to be used for testing + +test_object = AdlerData(["u", "g", "r"]) - test_object.populate_phase_parameters("u", "model_1", 11.0, 12.0, 13, 14.0, 15.0, 16.0, [17.0], [18.0]) - test_object.populate_phase_parameters( - "u", "model_2", 21.0, 22.0, 23, 24.0, 25.0, 26.0, [27.0, 27.5], [28.0, 28.5] - ) - test_object.populate_phase_parameters("g", "model_1", 31.0, 32.0, 33, 34.0, 35.0, 36.0, [37.0], [38.0]) - test_object.populate_phase_parameters( - "r", "model_2", 41.0, 42.0, 43, 44.0, 45.0, 46.0, [47.0, 47.5], [48.0, 48.5] - ) +test_object.populate_phase_parameters("u", "model_1", 11.0, 12.0, 13, 14.0, 15.0, 16.0, [17.0], [18.0]) +test_object.populate_phase_parameters( + "u", "model_2", 21.0, 22.0, 23, 24.0, 25.0, 26.0, [27.0, 27.5], [28.0, 28.5] +) +test_object.populate_phase_parameters("g", "model_1", 31.0, 32.0, 33, 34.0, 35.0, 36.0, [37.0], [38.0]) +test_object.populate_phase_parameters( + "r", "model_2", 41.0, 42.0, 43, 44.0, 45.0, 46.0, [47.0, 47.5], [48.0, 48.5] +) + +def test_populate_phase_parameters(): + # test to make sure the object is correctly populated assert test_object.filter_list == ["u", "g", "r"] assert test_object.model_lists == [["model_1", "model_2"], ["model_1"], ["model_2"]] @@ -24,7 +28,6 @@ def test_populate_phase_parameters(): assert_array_equal(test_object.nobs_adler, [23, 33, 43]) assert_array_equal(test_object.arc_adler, [24.0, 34.0, 44.0]) - # test to make sure the object is correctly populated assert test_object.H_adler == [[15.0, 25.0], [35.0], [45.0]] assert test_object.H_err_adler == [[16.0, 26.0], [36.0], [46.0]] assert test_object.phase_parameters == [[[17.0], [27.0, 27.5]], [[37.0]], [[47.0, 47.5]]] @@ -39,4 +42,46 @@ def test_populate_phase_parameters(): with pytest.raises(Exception) as error_info_2: test_object.populate_phase_parameters("y", "model_1", 11.0, 12.0, 13, 14.0, 15.0, 16.0, 17.0, 18.0) - assert error_info_2.value.args[0] == "Filter y is not in supplied filter list." + assert error_info_2.value.args[0] == "Filter y does not exist in AdlerData.filter_list." + + +def test_get_phase_parameters_in_filter(): + u_model2 = { + "phaseAngle_min": 21.0, + "phaseAngle_range": 22.0, + "nobs": 23, + "arc": 24.0, + "H": 25.0, + "H_err": 26.0, + "phase_parameters": [27.0, 27.5], + "phase_parameters_err": [28.0, 28.5], + } + + u_model1 = { + "phaseAngle_min": 21.0, + "phaseAngle_range": 22.0, + "nobs": 23, + "arc": 24.0, + "H": 15.0, + "H_err": 16.0, + "phase_parameters": [17.0], + "phase_parameters_err": [18.0], + } + + # making sure the correct parameters are retreived + assert test_object.get_phase_parameters_in_filter("u", model_name="model_2") == u_model2 + assert test_object.get_phase_parameters_in_filter("u") == u_model1 + assert test_object.get_phase_parameters_in_filter( + "r", "model_2" + ) == test_object.get_phase_parameters_in_filter("r") + + # checking the error messages + with pytest.raises(ValueError) as error_info_1: + error_dict = test_object.get_phase_parameters_in_filter("f", model_name="model_2") + + assert error_info_1.value.args[0] == "Filter f does not exist in AdlerData.filter_list." + + with pytest.raises(ValueError) as error_info_2: + error_dict_2 = test_object.get_phase_parameters_in_filter("r", model_name="model_1") + + assert error_info_2.value.args[0] == "Model model_1 does not exist for filter r in AdlerData.model_lists." From 85f4284d943bb14b00949ad2e135e5356258ec39 Mon Sep 17 00:00:00 2001 From: Steph Merritt Date: Tue, 12 Mar 2024 13:29:23 +0000 Subject: [PATCH 2/7] Adding test for print_data() method. --- tests/adler/dataclasses/test_AdlerData.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/adler/dataclasses/test_AdlerData.py b/tests/adler/dataclasses/test_AdlerData.py index 79ea4f9..2d7babe 100644 --- a/tests/adler/dataclasses/test_AdlerData.py +++ b/tests/adler/dataclasses/test_AdlerData.py @@ -85,3 +85,15 @@ def test_get_phase_parameters_in_filter(): error_dict_2 = test_object.get_phase_parameters_in_filter("r", model_name="model_1") assert error_info_2.value.args[0] == "Model model_1 does not exist for filter r in AdlerData.model_lists." + + +# here the capsys fixture captures any output to the terminal +def test_print_data(capsys): + test_object.print_data() + + # get what was printed to the terminal + captured = capsys.readouterr() + + expected = "Phase parameters (per filter):\n\nFilter: u\nPhase angle minimum: 21.0\nPhase angle range: 22.0\nNumber of observations: 23\nArc: 24.0\nModel: model_1.\n\tH: 15.0\n\tH error: 16.0\n\tPhase parameter(s): [17.0]\n\tPhase parameter(s) error: [18.0]\nModel: model_2.\n\tH: 25.0\n\tH error: 26.0\n\tPhase parameter(s): [27.0, 27.5]\n\tPhase parameter(s) error: [28.0, 28.5]\n\n\nFilter: g\nPhase angle minimum: 31.0\nPhase angle range: 32.0\nNumber of observations: 33\nArc: 34.0\nModel: model_1.\n\tH: 35.0\n\tH error: 36.0\n\tPhase parameter(s): [37.0]\n\tPhase parameter(s) error: [38.0]\n\n\nFilter: r\nPhase angle minimum: 41.0\nPhase angle range: 42.0\nNumber of observations: 43\nArc: 44.0\nModel: model_2.\n\tH: 45.0\n\tH error: 46.0\n\tPhase parameter(s): [47.0, 47.5]\n\tPhase parameter(s) error: [48.0, 48.5]\n\n\n" + + assert captured.out == expected From 15d4de8779976931de46e19efa33164a2ce3d7b7 Mon Sep 17 00:00:00 2001 From: Steph Merritt Date: Tue, 12 Mar 2024 16:12:06 +0000 Subject: [PATCH 3/7] Fixing populate_phase_parameters(). --- src/adler/dataclasses/AdlerData.py | 102 ++++++++++++++++------ tests/adler/dataclasses/test_AdlerData.py | 45 ++++++---- 2 files changed, 103 insertions(+), 44 deletions(-) diff --git a/src/adler/dataclasses/AdlerData.py b/src/adler/dataclasses/AdlerData.py index 052d56f..b68d195 100644 --- a/src/adler/dataclasses/AdlerData.py +++ b/src/adler/dataclasses/AdlerData.py @@ -79,17 +79,18 @@ def __post_init__(self): def populate_phase_parameters( self, filter_name, - model_name, - phaseAngle_min, - phaseAngle_range, - nobs, - arc, - H, - H_err, - parameters, - parameters_err, + model_name=None, + phaseAngle_min=None, + phaseAngle_range=None, + nobs=None, + arc=None, + H=None, + H_err=None, + parameters=[], + parameters_err=[], ): - """Convenience method to correctly populate phase curve arrays/lists. + """Convenience method to correctly populate phase curve arrays/lists. Only the supplied arguments to the method will + be updated, allowing for only some values to be populated if desired. Parameters ----------- @@ -97,31 +98,31 @@ def populate_phase_parameters( filter_name : str The one-letter name of the filter in which the phase curve was calculated. - model_name : str - The name of the model used to calculate the phase curve. + model_name : str, optional + The name of the model used to calculate the phase curve. If not supplied, no model-dependent parameters will be updated. - phaseAngle_min : float + phaseAngle_min : float, optional Minimum phase angle of observations used in fitting model (degrees) - phaseAngle_range : float + phaseAngle_range : float, optional Max minus min phase angle range of observations used in fitting model (degrees). - nobs : int + nobs : int, optional Number of observations used in fitting model. - arc : float + arc : float, optional Observational arc used to fit model (days). - H : float + H : float, optional Absolute magnitude in model. - H_err : float + H_err : float, optional Error on the absolute magnitude. - parameters : list + parameters : list, optional Phase parameters of the model. - parameters_err : list + parameters_err : list, optional Phase parameter errors. """ @@ -136,12 +137,24 @@ def populate_phase_parameters( if not isinstance(parameters, list) or not isinstance(parameters_err, list): raise TypeError("Both parameters and parameters_err arguments must be lists.") - self.phaseAngle_min_adler[filter_index] = phaseAngle_min - self.phaseAngle_range_adler[filter_index] = phaseAngle_range - self.nobs_adler[filter_index] = nobs - self.arc_adler[filter_index] = arc + self.phaseAngle_min_adler[filter_index] = self.update_value( + self.phaseAngle_min_adler[filter_index], phaseAngle_min + ) + self.phaseAngle_range_adler[filter_index] = self.update_value( + self.phaseAngle_range_adler[filter_index], phaseAngle_range + ) + self.nobs_adler[filter_index] = self.update_value(self.nobs_adler[filter_index], nobs) + self.arc_adler[filter_index] = self.update_value(self.arc_adler[filter_index], arc) + + if model_name is None and ( + any(v is not None for v in [H, H_err]) or len(parameters) != 0 or len(parameters_err) != 0 + ): + raise Exception("No model name given. Cannot update model-specific parameters.") + + elif model_name is None: + pass - if model_name not in self.model_lists[filter_index]: + elif model_name not in self.model_lists[filter_index]: self.model_lists[filter_index].append(model_name) self.H_adler[filter_index].append(H) @@ -152,10 +165,41 @@ def populate_phase_parameters( else: model_index = self.model_lists[filter_index].index(model_name) - self.H_adler[filter_index][model_index] = H - self.H_err_adler[filter_index][model_index] = H_err - self.phase_parameters[filter_index][model_index] = parameters - self.phase_parameters_err[filter_index][model_index] = parameters_err + self.H_adler[filter_index][model_index] = self.update_value( + self.H_adler[filter_index][model_index], H + ) + self.H_err_adler[filter_index][model_index] = self.update_value( + self.H_err_adler[filter_index][model_index], H_err + ) + self.phase_parameters[filter_index][model_index] = self.update_value( + self.phase_parameters[filter_index][model_index], parameters + ) + self.phase_parameters_err[filter_index][model_index] = self.update_value( + self.phase_parameters_err[filter_index][model_index], parameters_err + ) + + def update_value(self, original_value, new_value): + """Returns one of two values depending on whether one of them is None. Used to update class attributes. + + Parameters + ----------- + original_value : any + Original value of the attribute. + + new_value : any or None + The value to replace it with, if this is not None. + + + Returns + ----------- + any + Either original_value (if new_value is None) or new_value. + + """ + if not new_value: + return original_value + else: + return new_value def print_data(self): """Convenience method to clearly print the stored values.""" diff --git a/tests/adler/dataclasses/test_AdlerData.py b/tests/adler/dataclasses/test_AdlerData.py index 2d7babe..db9e179 100644 --- a/tests/adler/dataclasses/test_AdlerData.py +++ b/tests/adler/dataclasses/test_AdlerData.py @@ -10,7 +10,7 @@ test_object.populate_phase_parameters("u", "model_1", 11.0, 12.0, 13, 14.0, 15.0, 16.0, [17.0], [18.0]) test_object.populate_phase_parameters( - "u", "model_2", 21.0, 22.0, 23, 24.0, 25.0, 26.0, [27.0, 27.5], [28.0, 28.5] + "u", model_name="model_2", H=25.0, H_err=26.0, parameters=[27.0, 27.5], parameters_err=[28.0, 28.5] ) test_object.populate_phase_parameters("g", "model_1", 31.0, 32.0, 33, 34.0, 35.0, 36.0, [37.0], [38.0]) test_object.populate_phase_parameters( @@ -23,34 +23,49 @@ def test_populate_phase_parameters(): assert test_object.filter_list == ["u", "g", "r"] assert test_object.model_lists == [["model_1", "model_2"], ["model_1"], ["model_2"]] - assert_array_equal(test_object.phaseAngle_min_adler, [21.0, 31.0, 41.0]) - assert_array_equal(test_object.phaseAngle_range_adler, [22.0, 32.0, 42.0]) - assert_array_equal(test_object.nobs_adler, [23, 33, 43]) - assert_array_equal(test_object.arc_adler, [24.0, 34.0, 44.0]) + assert_array_equal(test_object.phaseAngle_min_adler, [11.0, 31.0, 41.0]) + assert_array_equal(test_object.phaseAngle_range_adler, [12.0, 32.0, 42.0]) + assert_array_equal(test_object.nobs_adler, [13, 33, 43]) + assert_array_equal(test_object.arc_adler, [14.0, 34.0, 44.0]) assert test_object.H_adler == [[15.0, 25.0], [35.0], [45.0]] assert test_object.H_err_adler == [[16.0, 26.0], [36.0], [46.0]] assert test_object.phase_parameters == [[[17.0], [27.0, 27.5]], [[37.0]], [[47.0, 47.5]]] assert test_object.phase_parameters_err == [[[18.0], [28.0, 28.5]], [[38.0]], [[48.0, 48.5]]] + # check to make sure model-dependent parameter is correctly updated (then return it to previous) + test_object.populate_phase_parameters("u", "model_1", H=99.0) + assert test_object.H_adler[0][0] == 99.0 + test_object.populate_phase_parameters("u", "model_1", H=15.0) + + # check to make sure filter-dependent parameter is correctly updated (then return it to previous) + test_object.populate_phase_parameters("u", nobs=99) + assert test_object.nobs_adler[0] == 99 + test_object.populate_phase_parameters("u", nobs=13) + # testing to make sure the correct error messages trigger with pytest.raises(TypeError) as error_info_1: test_object.populate_phase_parameters("u", "model_1", 11.0, 12.0, 13, 14.0, 15.0, 16.0, 17.0, 18.0) assert error_info_1.value.args[0] == "Both parameters and parameters_err arguments must be lists." - with pytest.raises(Exception) as error_info_2: + with pytest.raises(ValueError) as error_info_2: test_object.populate_phase_parameters("y", "model_1", 11.0, 12.0, 13, 14.0, 15.0, 16.0, 17.0, 18.0) assert error_info_2.value.args[0] == "Filter y does not exist in AdlerData.filter_list." + with pytest.raises(Exception) as error_info_3: + test_object.populate_phase_parameters("u", H=4.0) + + assert error_info_3.value.args[0] == "No model name given. Cannot update model-specific parameters." + def test_get_phase_parameters_in_filter(): u_model2 = { - "phaseAngle_min": 21.0, - "phaseAngle_range": 22.0, - "nobs": 23, - "arc": 24.0, + "phaseAngle_min": 11.0, + "phaseAngle_range": 12.0, + "nobs": 13, + "arc": 14.0, "H": 25.0, "H_err": 26.0, "phase_parameters": [27.0, 27.5], @@ -58,10 +73,10 @@ def test_get_phase_parameters_in_filter(): } u_model1 = { - "phaseAngle_min": 21.0, - "phaseAngle_range": 22.0, - "nobs": 23, - "arc": 24.0, + "phaseAngle_min": 11.0, + "phaseAngle_range": 12.0, + "nobs": 13, + "arc": 14.0, "H": 15.0, "H_err": 16.0, "phase_parameters": [17.0], @@ -94,6 +109,6 @@ def test_print_data(capsys): # get what was printed to the terminal captured = capsys.readouterr() - expected = "Phase parameters (per filter):\n\nFilter: u\nPhase angle minimum: 21.0\nPhase angle range: 22.0\nNumber of observations: 23\nArc: 24.0\nModel: model_1.\n\tH: 15.0\n\tH error: 16.0\n\tPhase parameter(s): [17.0]\n\tPhase parameter(s) error: [18.0]\nModel: model_2.\n\tH: 25.0\n\tH error: 26.0\n\tPhase parameter(s): [27.0, 27.5]\n\tPhase parameter(s) error: [28.0, 28.5]\n\n\nFilter: g\nPhase angle minimum: 31.0\nPhase angle range: 32.0\nNumber of observations: 33\nArc: 34.0\nModel: model_1.\n\tH: 35.0\n\tH error: 36.0\n\tPhase parameter(s): [37.0]\n\tPhase parameter(s) error: [38.0]\n\n\nFilter: r\nPhase angle minimum: 41.0\nPhase angle range: 42.0\nNumber of observations: 43\nArc: 44.0\nModel: model_2.\n\tH: 45.0\n\tH error: 46.0\n\tPhase parameter(s): [47.0, 47.5]\n\tPhase parameter(s) error: [48.0, 48.5]\n\n\n" + expected = "Phase parameters (per filter):\n\nFilter: u\nPhase angle minimum: 11.0\nPhase angle range: 12.0\nNumber of observations: 13\nArc: 14.0\nModel: model_1.\n\tH: 15.0\n\tH error: 16.0\n\tPhase parameter(s): [17.0]\n\tPhase parameter(s) error: [18.0]\nModel: model_2.\n\tH: 25.0\n\tH error: 26.0\n\tPhase parameter(s): [27.0, 27.5]\n\tPhase parameter(s) error: [28.0, 28.5]\n\n\nFilter: g\nPhase angle minimum: 31.0\nPhase angle range: 32.0\nNumber of observations: 33\nArc: 34.0\nModel: model_1.\n\tH: 35.0\n\tH error: 36.0\n\tPhase parameter(s): [37.0]\n\tPhase parameter(s) error: [38.0]\n\n\nFilter: r\nPhase angle minimum: 41.0\nPhase angle range: 42.0\nNumber of observations: 43\nArc: 44.0\nModel: model_2.\n\tH: 45.0\n\tH error: 46.0\n\tPhase parameter(s): [47.0, 47.5]\n\tPhase parameter(s) error: [48.0, 48.5]\n\n\n" assert captured.out == expected From 0c6964b6ec7a0c5cafb040db5b91abe3ecd09d27 Mon Sep 17 00:00:00 2001 From: jrob93 Date: Wed, 13 Mar 2024 16:10:13 +0000 Subject: [PATCH 4/7] update arguments of populate_phase_parameters to match get_phase_parameters_in_filter --- src/adler/dataclasses/AdlerData.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/adler/dataclasses/AdlerData.py b/src/adler/dataclasses/AdlerData.py index b68d195..c477695 100644 --- a/src/adler/dataclasses/AdlerData.py +++ b/src/adler/dataclasses/AdlerData.py @@ -86,8 +86,8 @@ def populate_phase_parameters( arc=None, H=None, H_err=None, - parameters=[], - parameters_err=[], + phase_parameters=[], + phase_parameters_err=[], ): """Convenience method to correctly populate phase curve arrays/lists. Only the supplied arguments to the method will be updated, allowing for only some values to be populated if desired. @@ -119,10 +119,10 @@ def populate_phase_parameters( H_err : float, optional Error on the absolute magnitude. - parameters : list, optional + phase_parameters : list, optional Phase parameters of the model. - parameters_err : list, optional + phase_parameters_err : list, optional Phase parameter errors. """ @@ -134,8 +134,8 @@ def populate_phase_parameters( raise ValueError("Filter {} does not exist in AdlerData.filter_list.".format(filter_name)) # If parameters and/or parameters_err are not lists, error out. - if not isinstance(parameters, list) or not isinstance(parameters_err, list): - raise TypeError("Both parameters and parameters_err arguments must be lists.") + if not isinstance(phase_parameters, list) or not isinstance(phase_parameters_err, list): + raise TypeError("Both phase_parameters and phase_parameters_err arguments must be lists.") self.phaseAngle_min_adler[filter_index] = self.update_value( self.phaseAngle_min_adler[filter_index], phaseAngle_min @@ -147,9 +147,11 @@ def populate_phase_parameters( self.arc_adler[filter_index] = self.update_value(self.arc_adler[filter_index], arc) if model_name is None and ( - any(v is not None for v in [H, H_err]) or len(parameters) != 0 or len(parameters_err) != 0 + any(v is not None for v in [H, H_err]) + or len(phase_parameters) != 0 + or len(phase_parameters_err) != 0 ): - raise Exception("No model name given. Cannot update model-specific parameters.") + raise Exception("No model name given. Cannot update model-specific phase_parameters.") elif model_name is None: pass @@ -159,8 +161,8 @@ def populate_phase_parameters( self.H_adler[filter_index].append(H) self.H_err_adler[filter_index].append(H_err) - self.phase_parameters[filter_index].append(parameters) - self.phase_parameters_err[filter_index].append(parameters_err) + self.phase_parameters[filter_index].append(phase_parameters) + self.phase_parameters_err[filter_index].append(phase_parameters_err) else: model_index = self.model_lists[filter_index].index(model_name) @@ -172,10 +174,10 @@ def populate_phase_parameters( self.H_err_adler[filter_index][model_index], H_err ) self.phase_parameters[filter_index][model_index] = self.update_value( - self.phase_parameters[filter_index][model_index], parameters + self.phase_parameters[filter_index][model_index], phase_parameters ) self.phase_parameters_err[filter_index][model_index] = self.update_value( - self.phase_parameters_err[filter_index][model_index], parameters_err + self.phase_parameters_err[filter_index][model_index], phase_parameters_err ) def update_value(self, original_value, new_value): From b05434bb3437e29e8223aaecfe4c0c087a16a1e7 Mon Sep 17 00:00:00 2001 From: jrob93 Date: Wed, 13 Mar 2024 16:20:11 +0000 Subject: [PATCH 5/7] fix the unit tests --- tests/adler/dataclasses/test_AdlerData.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/adler/dataclasses/test_AdlerData.py b/tests/adler/dataclasses/test_AdlerData.py index db9e179..b300318 100644 --- a/tests/adler/dataclasses/test_AdlerData.py +++ b/tests/adler/dataclasses/test_AdlerData.py @@ -10,7 +10,12 @@ test_object.populate_phase_parameters("u", "model_1", 11.0, 12.0, 13, 14.0, 15.0, 16.0, [17.0], [18.0]) test_object.populate_phase_parameters( - "u", model_name="model_2", H=25.0, H_err=26.0, parameters=[27.0, 27.5], parameters_err=[28.0, 28.5] + "u", + model_name="model_2", + H=25.0, + H_err=26.0, + phase_parameters=[27.0, 27.5], + phase_parameters_err=[28.0, 28.5], ) test_object.populate_phase_parameters("g", "model_1", 31.0, 32.0, 33, 34.0, 35.0, 36.0, [37.0], [38.0]) test_object.populate_phase_parameters( @@ -47,7 +52,10 @@ def test_populate_phase_parameters(): with pytest.raises(TypeError) as error_info_1: test_object.populate_phase_parameters("u", "model_1", 11.0, 12.0, 13, 14.0, 15.0, 16.0, 17.0, 18.0) - assert error_info_1.value.args[0] == "Both parameters and parameters_err arguments must be lists." + assert ( + error_info_1.value.args[0] + == "Both phase_parameters and phase_parameters_err arguments must be lists." + ) with pytest.raises(ValueError) as error_info_2: test_object.populate_phase_parameters("y", "model_1", 11.0, 12.0, 13, 14.0, 15.0, 16.0, 17.0, 18.0) @@ -57,7 +65,7 @@ def test_populate_phase_parameters(): with pytest.raises(Exception) as error_info_3: test_object.populate_phase_parameters("u", H=4.0) - assert error_info_3.value.args[0] == "No model name given. Cannot update model-specific parameters." + assert error_info_3.value.args[0] == "No model name given. Cannot update model-specific phase_parameters." def test_get_phase_parameters_in_filter(): From f4bed7fa450dfeeb796ae18bb4efdca202fe9a80 Mon Sep 17 00:00:00 2001 From: Steph Merritt Date: Thu, 14 Mar 2024 15:15:06 +0000 Subject: [PATCH 6/7] Applying suggested fixes to AdlerData. --- src/adler/dataclasses/AdlerData.py | 48 +++++++++++------------ tests/adler/dataclasses/test_AdlerData.py | 8 ++-- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/src/adler/dataclasses/AdlerData.py b/src/adler/dataclasses/AdlerData.py index c477695..38d6265 100644 --- a/src/adler/dataclasses/AdlerData.py +++ b/src/adler/dataclasses/AdlerData.py @@ -46,10 +46,10 @@ class AdlerData: filter_list: list model_lists: list = field(default_factory=list) - phaseAngle_min_adler: np.ndarray = field(default_factory=lambda: np.empty(0, dtype=float)) - phaseAngle_range_adler: np.ndarray = field(default_factory=lambda: np.empty(0, dtype=float)) - nobs_adler: np.ndarray = field(default_factory=lambda: np.empty(0, dtype=int)) - arc_adler: np.ndarray = field(default_factory=lambda: np.empty(0, dtype=float)) + phaseAngle_min_adler: np.ndarray = field(default_factory=lambda: np.full(0, np.nan, dtype=float)) + phaseAngle_range_adler: np.ndarray = field(default_factory=lambda: np.full(0, np.nan, dtype=float)) + nobs_adler: np.ndarray = field(default_factory=lambda: np.zeros(0, dtype=int)) + arc_adler: np.ndarray = field(default_factory=lambda: np.full(0, np.nan, dtype=float)) # Note that these are lists and not arrays because appending to Numpy arrays (i.e. to add parameters for a different model) is not recommended. # They can be cast to Numpy arrays later if needed. @@ -66,10 +66,10 @@ def __post_init__(self): self.model_lists = [[] for a in range(0, filter_length)] - self.phaseAngle_min_adler = np.empty(filter_length, dtype=float) - self.phaseAngle_range_adler = np.empty(filter_length, dtype=float) - self.nobs_adler = np.empty(filter_length, dtype=int) - self.arc_adler = np.empty(filter_length, dtype=float) + self.phaseAngle_min_adler = np.full(filter_length, np.nan, dtype=float) + self.phaseAngle_range_adler = np.full(filter_length, np.nan, dtype=float) + self.nobs_adler = np.zeros(filter_length, dtype=int) + self.arc_adler = np.full(filter_length, np.nan, dtype=float) self.H_adler = [[] for a in range(0, filter_length)] self.H_err_adler = [[] for a in range(0, filter_length)] @@ -248,7 +248,16 @@ def get_phase_parameters_in_filter(self, filter_name, model_name=None): except ValueError: raise ValueError("Filter {} does not exist in AdlerData.filter_list.".format(filter_name)) - if model_name: + parameters_dict = { + "phaseAngle_min": self.phaseAngle_min_adler[filter_index], + "phaseAngle_range": self.phaseAngle_range_adler[filter_index], + "nobs": self.nobs_adler[filter_index], + "arc": self.arc_adler[filter_index], + } + + if not model_name: + print("No model name specified. Returning non-model-dependent phase parameters.") + else: try: model_index = self.model_lists[filter_index].index(model_name) except ValueError: @@ -257,23 +266,10 @@ def get_phase_parameters_in_filter(self, filter_name, model_name=None): model_name, filter_name ) ) - else: - model_index = 0 - print( - "No model name specified. Returning phase parameters for first model in list: {}.".format( - self.model_lists[filter_index][model_index] - ) - ) - parameters_dict = { - "phaseAngle_min": self.phaseAngle_min_adler[filter_index], - "phaseAngle_range": self.phaseAngle_range_adler[filter_index], - "nobs": self.nobs_adler[filter_index], - "arc": self.arc_adler[filter_index], - "H": self.H_adler[filter_index][model_index], - "H_err": self.H_err_adler[filter_index][model_index], - "phase_parameters": self.phase_parameters[filter_index][model_index], - "phase_parameters_err": self.phase_parameters_err[filter_index][model_index], - } + parameters_dict["H"] = self.H_adler[filter_index][model_index] + parameters_dict["H_err"] = self.H_err_adler[filter_index][model_index] + parameters_dict["phase_parameters"] = self.phase_parameters[filter_index][model_index] + parameters_dict["phase_parameters_err"] = self.phase_parameters_err[filter_index][model_index] return parameters_dict diff --git a/tests/adler/dataclasses/test_AdlerData.py b/tests/adler/dataclasses/test_AdlerData.py index b300318..066a889 100644 --- a/tests/adler/dataclasses/test_AdlerData.py +++ b/tests/adler/dataclasses/test_AdlerData.py @@ -91,12 +91,12 @@ def test_get_phase_parameters_in_filter(): "phase_parameters_err": [18.0], } + u_independent = {"phaseAngle_min": 11.0, "phaseAngle_range": 12.0, "nobs": 13, "arc": 14.0} + # making sure the correct parameters are retreived assert test_object.get_phase_parameters_in_filter("u", model_name="model_2") == u_model2 - assert test_object.get_phase_parameters_in_filter("u") == u_model1 - assert test_object.get_phase_parameters_in_filter( - "r", "model_2" - ) == test_object.get_phase_parameters_in_filter("r") + assert test_object.get_phase_parameters_in_filter("u", model_name="model_1") == u_model1 + assert test_object.get_phase_parameters_in_filter("u") == u_independent # checking the error messages with pytest.raises(ValueError) as error_info_1: From a675c40979c3e8f44d42f7de5987d11fbd34dcca Mon Sep 17 00:00:00 2001 From: Steph Merritt Date: Thu, 14 Mar 2024 15:17:14 +0000 Subject: [PATCH 7/7] Adding _readthedocs/ to .gitignore. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ea13164..a7b6b17 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ **/.DS_Store +_readthedocs/ # Byte-compiled / optimized / DLL files __pycache__/