diff --git a/src/adler/dataclasses/AdlerPlanetoid.py b/src/adler/dataclasses/AdlerPlanetoid.py index 060b0de..deea50c 100644 --- a/src/adler/dataclasses/AdlerPlanetoid.py +++ b/src/adler/dataclasses/AdlerPlanetoid.py @@ -1,4 +1,5 @@ from lsst.rsp import get_tap_service +import pandas as pd from adler.dataclasses.Observations import Observations from adler.dataclasses.MPCORB import MPCORB @@ -306,6 +307,28 @@ def observations_in_filter(self, filter_name): return self.observations_by_filter[filter_index] + def SSObject_in_filter(self, filter_name): + """User-friendly helper function. Returns the filter-dependent values from SSObject for a given filter. + + Parameters + ----------- + filter_name : str + The desired filter. + + Returns + ----------- + ssobject_in_filter : SSObject + + + """ + + try: + filter_index = self.filter_list.index(filter_name) + except ValueError: + raise ValueError("Filter {} is not in AdlerPlanetoid.filter_list.".format(filter_name)) + + return self.SSObject.filter_dependent_values[filter_index] + def do_pretend_science(self): self.DummyScienceResult = DummyScience().science_result diff --git a/src/adler/dataclasses/SSObject.py b/src/adler/dataclasses/SSObject.py index d86414c..96664c7 100644 --- a/src/adler/dataclasses/SSObject.py +++ b/src/adler/dataclasses/SSObject.py @@ -29,8 +29,9 @@ class SSObject: numObs: int Number of LSST observations of this object - H: array_like of floats - Best fit absolute magnitudes per-filter, in same order as filter_list. + filter_dependent_values: list of FilterDependentSSO objects + A list of FilterDependentSSO objects storing the filter-dependent values H, Herr, G12, G12err and nData, + in same order as filter_list. See documentation for FilterDependentSSO object for descriptions of these variables. G12: array_like of floats Best fit G12 slope parameters per-filter, in same order as filter_list. @@ -61,11 +62,7 @@ class SSObject: firstObservationDate: float = 0.0 arc: float = 0.0 numObs: int = 0 - H: np.ndarray = field(default_factory=lambda: np.zeros(0)) - G12: np.ndarray = field(default_factory=lambda: np.zeros(0)) - Herr: np.ndarray = field(default_factory=lambda: np.zeros(0)) - G12err: np.ndarray = field(default_factory=lambda: np.zeros(0)) - nData: np.ndarray = field(default_factory=lambda: np.zeros(0)) + filter_dependent_values: list = field(default_factory=list) maxExtendedness: float = 0.0 minExtendedness: float = 0.0 medianExtendedness: float = 0.0 @@ -83,12 +80,19 @@ def construct_from_data_table(cls, ssObjectId, filter_list, data_table): G12err = np.zeros(len(filter_list)) nData = np.zeros(len(filter_list)) - for i, filter in enumerate(filter_list): - H[i] = get_from_table(data_table, filter + "_H", "float") - G12[i] = get_from_table(data_table, filter + "_G12", "float") - Herr[i] = get_from_table(data_table, filter + "_HErr", "float") - G12err[i] = get_from_table(data_table, filter + "_G12Err", "float") - nData[i] = get_from_table(data_table, filter + "_Ndata", "int") + filter_dependent_values = [] + + for i, filter_name in enumerate(filter_list): + filter_dept_object = FilterDependentSSO( + filter_name=filter_name, + H=get_from_table(data_table, filter_name + "_H", "float"), + G12=get_from_table(data_table, filter_name + "_G12", "float"), + Herr=get_from_table(data_table, filter_name + "_HErr", "float"), + G12err=get_from_table(data_table, filter_name + "_G12Err", "float"), + nData=get_from_table(data_table, filter_name + "_Ndata", "int"), + ) + + filter_dependent_values.append(filter_dept_object) maxExtendedness = get_from_table(data_table, "maxExtendedness", "float") minExtendedness = get_from_table(data_table, "minExtendedness", "float") @@ -101,12 +105,41 @@ def construct_from_data_table(cls, ssObjectId, filter_list, data_table): firstObservationDate, arc, numObs, - H, - G12, - Herr, - G12err, - nData, + filter_dependent_values, maxExtendedness, minExtendedness, medianExtendedness, ) + + +@dataclass +class FilterDependentSSO: + """Filter-dependent object information from SSObject. All attributes carry the same names as the column names from the SSObject table. + + Attributes: + ----------- + filter_name : str + Single-letter name of the filter for which these values are relevant. + + H : float + Best fit absolute magnitude in filter. + + G12: float + Best fit G12 slope parameters in filter. + + Herr : float + Uncertainty of H. + + G12Err : float + Uncertainty of G12. + + nData: array_like of ints + The number of data points used to fit the phase curve in this filter. + """ + + filter_name: str + H: float + G12: float + Herr: float + G12err: float + nData: int = 0 diff --git a/tests/adler/dataclasses/test_AdlerPlanetoid.py b/tests/adler/dataclasses/test_AdlerPlanetoid.py index a92b777..aafdba2 100644 --- a/tests/adler/dataclasses/test_AdlerPlanetoid.py +++ b/tests/adler/dataclasses/test_AdlerPlanetoid.py @@ -32,7 +32,7 @@ def test_construct_from_SQL(): # did we pick up all the filters? assert len(test_planetoid.observations_by_filter) == 6 - assert len(test_planetoid.SSObject.H) == 6 + assert len(test_planetoid.SSObject.filter_dependent_values) == 6 assert test_planetoid.filter_list == ["u", "g", "r", "i", "z", "y"] # checking the date range to ensure it's the default @@ -44,7 +44,7 @@ def test_construct_with_single_filter(): # should only be one filter in here now assert len(test_planetoid.observations_by_filter) == 1 - assert len(test_planetoid.SSObject.H) == 1 + assert len(test_planetoid.SSObject.filter_dependent_values) == 1 assert test_planetoid.filter_list == ["g"] assert_almost_equal( @@ -91,17 +91,21 @@ def test_construct_with_date_range(): def test_observations_in_filter(): test_planetoid = AdlerPlanetoid.construct_from_SQL(ssoid, test_db_path) - assert_almost_equal( - test_planetoid.observations_in_filter("g").mag, - [ - 21.33099937, - 22.67099953, - 23.5359993, - 22.85000038, - 22.97599983, - 22.94499969, - 23.13599968, - 23.19400024, - 23.1609993, - ], - ) + # Python dataclasses create an __eq__ for you so object-to-object comparison just works, isn't that nice? + assert test_planetoid.observations_in_filter("u") == test_planetoid.observations_by_filter[0] + assert test_planetoid.observations_in_filter("g") == test_planetoid.observations_by_filter[1] + assert test_planetoid.observations_in_filter("r") == test_planetoid.observations_by_filter[2] + assert test_planetoid.observations_in_filter("i") == test_planetoid.observations_by_filter[3] + assert test_planetoid.observations_in_filter("z") == test_planetoid.observations_by_filter[4] + assert test_planetoid.observations_in_filter("y") == test_planetoid.observations_by_filter[5] + + +def test_SSObject_in_filter(): + test_planetoid = AdlerPlanetoid.construct_from_SQL(ssoid, test_db_path) + + assert test_planetoid.SSObject_in_filter("u") == test_planetoid.SSObject.filter_dependent_values[0] + assert test_planetoid.SSObject_in_filter("g") == test_planetoid.SSObject.filter_dependent_values[1] + assert test_planetoid.SSObject_in_filter("r") == test_planetoid.SSObject.filter_dependent_values[2] + assert test_planetoid.SSObject_in_filter("i") == test_planetoid.SSObject.filter_dependent_values[3] + assert test_planetoid.SSObject_in_filter("z") == test_planetoid.SSObject.filter_dependent_values[4] + assert test_planetoid.SSObject_in_filter("y") == test_planetoid.SSObject.filter_dependent_values[5] diff --git a/tests/adler/dataclasses/test_SSObject.py b/tests/adler/dataclasses/test_SSObject.py index f4121e4..b6cb05b 100644 --- a/tests/adler/dataclasses/test_SSObject.py +++ b/tests/adler/dataclasses/test_SSObject.py @@ -36,17 +36,35 @@ def test_construct_SSObject_from_data_table(): data_table = get_data_table(test_query, sql_filename=test_db_path) test_SSObject = SSObject.construct_from_data_table(ssoid, filter_list, data_table) + test_values_r = [ + test_SSObject.filter_dependent_values[0].H, + test_SSObject.filter_dependent_values[0].G12, + test_SSObject.filter_dependent_values[0].Herr, + test_SSObject.filter_dependent_values[0].G12err, + test_SSObject.filter_dependent_values[0].nData, + ] + + test_values_g = [ + test_SSObject.filter_dependent_values[1].H, + test_SSObject.filter_dependent_values[1].G12, + test_SSObject.filter_dependent_values[1].Herr, + test_SSObject.filter_dependent_values[1].G12err, + test_SSObject.filter_dependent_values[1].nData, + ] + + expected_values_g = [20.292325973510742, 1.7233933210372925, 0.030210301280021667, 0.0404973067343235, 9] + + expected_values_r = [19.805892944335938, 1.52932608127594, 0.01974303089082241, 0.05071713775396347, 38] + assert test_SSObject.ssObjectId == 8268570668335894776 assert test_SSObject.filter_list == filter_list assert_almost_equal(test_SSObject.discoverySubmissionDate, 60218.0, decimal=6) assert_almost_equal(test_SSObject.firstObservationDate, 60220.01958, decimal=6) assert_almost_equal(test_SSObject.arc, 3342.05859375, decimal=6) assert test_SSObject.numObs == 94 - assert_almost_equal(test_SSObject.H, [19.80589294, 20.29232597], decimal=6) - assert_almost_equal(test_SSObject.G12, [1.52932608, 1.72339332], decimal=6) - assert_almost_equal(test_SSObject.Herr, [0.01974303, 0.0302103], decimal=6) - assert_almost_equal(test_SSObject.G12err, [0.05071714, 0.04049731], decimal=6) - assert_equal(test_SSObject.nData, [38.0, 9.0]) assert_equal(test_SSObject.maxExtendedness, 0.0) assert_equal(test_SSObject.minExtendedness, 0.0) assert_equal(test_SSObject.medianExtendedness, 0.0) + + assert_almost_equal(test_values_r, expected_values_r) + assert_almost_equal(test_values_g, expected_values_g)