diff --git a/python/lsst/pipe/tasks/functors.py b/python/lsst/pipe/tasks/functors.py index 619c80f43..bf01175fe 100644 --- a/python/lsst/pipe/tasks/functors.py +++ b/python/lsst/pipe/tasks/functors.py @@ -28,6 +28,7 @@ "ComputePixelScale", "ConvertPixelToArcseconds", "ConvertPixelSqToArcsecondsSq", "ConvertDetectorAngleToPositionAngle", + "ConvertDetectorAngleErrToPositionAngleErr", "ReferenceBand", "Photometry", "NanoJansky", "NanoJanskyErr", "LocalPhotometry", "LocalNanojansky", "LocalNanojanskyErr", "LocalDipoleMeanFlux", @@ -1554,6 +1555,28 @@ def _func(self, df): ) +class ConvertDetectorAngleErrToPositionAngleErr(Functor): + """Convert a detector angle error to a position angle error. + + Returns + ------- + position angle error : degrees + """ + + name = "PositionAngleErr" + + def __init__(self, theta_err_col, **kwargs): + self.theta_err_col = theta_err_col + super().__init__(**kwargs) + + @property + def columns(self): + return [self.theta_err_col] + + def _func(self, df): + return np.rad2deg(df[self.theta_err_col]) + + class ReferenceBand(Functor): """Return the band used to seed multiband forced photometry. @@ -1992,14 +2015,7 @@ def _func(self, df): class MomentsBase(Functor): - """Base class for functors that use shape moments and localWCS - - Attributes - ---------- - is_covariance : bool - Whether the shape columns are terms of a covariance matrix. If False, - they will be assumed to be terms of a correlation matrix instead. - """ + """Base class for functors that use shape moments and localWCS""" is_covariance: bool = True diff --git a/tests/test_functors.py b/tests/test_functors.py index 2abd6d906..52900a333 100644 --- a/tests/test_functors.py +++ b/tests/test_functors.py @@ -53,8 +53,8 @@ MomentsG1Sky, MomentsG2Sky, MomentsTraceSky, CorrelationIuuSky, CorrelationIvvSky, CorrelationIuvSky, SemimajorAxisFromCorrelation, SemiminorAxisFromCorrelation, - PositionAngleFromCorrelation - ) + PositionAngleFromCorrelation, + ConvertDetectorAngleErrToPositionAngleErr) ROOT = os.path.abspath(os.path.dirname(__file__)) @@ -763,6 +763,19 @@ def testConvertDetectorAngleToPositionAngle(self): np.testing.assert_allclose(coord_diff, 0, rtol=0, atol=5e-6) + # Test position angle error + def testConvertDetectorAngleErrToPositionAngleErr(self): + """Test conversion of detector angle error in radians to position angle error in degrees.""" + theta_err_values = np.random.uniform(0, np.pi / 4, size=self.nRecords) + self.dataDict["theta_err"] = theta_err_values + df = self.getSimpleDataFrame(self.dataDict) + + func = ConvertDetectorAngleErrToPositionAngleErr("theta_err") + val = self._funcVal(func, df) + + expected = np.rad2deg(theta_err_values) + np.testing.assert_allclose(val.values, expected, rtol=0, atol=1e-13) + def testConvertPixelToArcseconds(self): """Test calculations of the pixel scale, conversions of pixel to arcseconds.