Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DM-37193: Reorganize vectorActions #108

Merged
merged 8 commits into from
May 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
from ...statistics import nansigmaMad, sigmaMad
from ..keyedData.summaryStatistics import SummaryStatisticAction
from ..scalar import MedianAction
from ..vector import MagColumnNanoJansky, SnSelector
from ..vector import ConvertFluxToMag, SnSelector
from .plotUtils import addPlotInfo, addSummaryPlot, generateSummaryStats, mkColormap

# ignore because coolwarm is actually part of module
Expand Down Expand Up @@ -105,7 +105,7 @@ def __call__(self, data: KeyedData, **kwargs) -> KeyedData:
statAction.setDefaults()

medianAction = MedianAction(vectorKey="mag")
magAction = MagColumnNanoJansky(vectorKey="flux")
magAction = ConvertFluxToMag(vectorKey="flux")

for maskKey, binName in ((lowMaskKey, "low"), (highMaskKey, "high")):
name = f"{prefix}{binName}SN{self.identity.capitalize() if self.identity else ''}"
Expand Down
3 changes: 3 additions & 0 deletions python/lsst/analysis/tools/actions/vector/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# TODO: Any way to avoid this causing a circular import?
# from .calcBinnedStats import CalcBinnedStatsAction
from .calcRhoStatistics import *
from .calcShapeSize import CalcShapeSize
from .ellipticity import *
from .mathActions import *
from .selectors import *
from .vectorActions import *
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from ...interfaces import KeyedData, KeyedDataAction, Vector
from .calcShapeSize import CalcShapeSize
from .ellipticity import CalcE, CalcEDiff
from .vectorActions import FractionalDifference
from .mathActions import FractionalDifference

if TYPE_CHECKING:
from treecorr import GGCorrelation, KKCorrelation
Expand Down
132 changes: 132 additions & 0 deletions python/lsst/analysis/tools/actions/vector/mathActions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# This file is part of analysis_tools.
#
# Developed for the LSST Data Management System.
# This product includes software developed by the LSST Project
# (https://www.lsst.org).
# See the COPYRIGHT file at the top-level directory of this distribution
# for details of code ownership.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from __future__ import annotations

__all__ = (
"ConstantValue",
"AddVector",
"SubtractVector",
"DivideVector",
"MultiplyVector",
"FractionalDifference",
)

import logging

import numpy as np
from lsst.pex.config import Field
from lsst.pex.config.configurableActions import ConfigurableActionField

from ...interfaces import KeyedData, KeyedDataSchema, Vector, VectorAction

_LOG = logging.getLogger(__name__)


class ConstantValue(VectorAction):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most vector actions in the mathActions file end with the suffix Vector (all except here and FractionalDifference). Is it worth considering making that consistent here too? E.g., ConstantVector? ConstantValueVector?

Copy link
Contributor Author

@taranu taranu May 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was actually considering renaming it to Scalarsomething rather than Constantsomething, but decided against it.

But to the extent that there is a naming scheme, the Vector-suffixed actions all begin with verbs (see also LoadVector and DownselectVector in vectorActions.py), whereas the unsuffixed actions are nouns (ConstantValue, MagDiff as short for MagnitudeDifference, etc). In principle you could verbify the various Diff(erence) actions since difference is a verb too, but I don't think the names would be any clearer. For ConstantValue, I can't think of a good way to verbify it at all. ReturnScalar? Actually, LoadScalar would be consistent with LoadVector, even though it's not really loading anything.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. In which case, I suggest leaving this (and the other non-conformant action here) as-is for the time being. Further changes can be punted to a future ticket, if desired.

"""Return a constant scalar value."""

value = Field[float](doc="A single constant value", optional=False)

def getInputSchema(self) -> KeyedDataSchema:
return ()

def __call__(self, data: KeyedData, **kwargs) -> Vector:
return np.array([self.value])


class AddVector(VectorAction):
"""Calculate (A+B)."""

actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")

def getInputSchema(self) -> KeyedDataSchema:
yield from self.actionA.getInputSchema() # type: ignore
yield from self.actionB.getInputSchema() # type: ignore

def __call__(self, data: KeyedData, **kwargs) -> Vector:
vecA = self.actionA(data, **kwargs) # type: ignore
vecB = self.actionB(data, **kwargs) # type: ignore
return vecA + vecB


class SubtractVector(VectorAction):
"""Calculate (A-B)."""

actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")

def getInputSchema(self) -> KeyedDataSchema:
yield from self.actionA.getInputSchema() # type: ignore
yield from self.actionB.getInputSchema() # type: ignore

def __call__(self, data: KeyedData, **kwargs) -> Vector:
vecA = self.actionA(data, **kwargs) # type: ignore
vecB = self.actionB(data, **kwargs) # type: ignore
return vecA - vecB


class MultiplyVector(VectorAction):
"""Calculate (A*B)"""

actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")

def getInputSchema(self) -> KeyedDataSchema:
yield from self.actionA.getInputSchema() # type: ignore
yield from self.actionB.getInputSchema() # type: ignore

def __call__(self, data: KeyedData, **kwargs) -> Vector:
vecA = self.actionA(data, **kwargs) # type: ignore
vecB = self.actionB(data, **kwargs) # type: ignore
return vecA * vecB


class DivideVector(VectorAction):
"""Calculate (A/B)"""

actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")

def getInputSchema(self) -> KeyedDataSchema:
yield from self.actionA.getInputSchema() # type: ignore
yield from self.actionB.getInputSchema() # type: ignore

def __call__(self, data: KeyedData, **kwargs) -> Vector:
vecA = self.actionA(data, **kwargs) # type: ignore
vecB = self.actionB(data, **kwargs) # type: ignore
return vecA / vecB


class FractionalDifference(VectorAction):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most vector actions in the mathActions file end with the suffix Vector (all except here and ConstantValue). Is it worth considering making that consistent here too?

"""Calculate (A-B)/B."""

actionA = ConfigurableActionField[VectorAction](doc="Action which supplies vector A")
actionB = ConfigurableActionField[VectorAction](doc="Action which supplies vector B")

def getInputSchema(self) -> KeyedDataSchema:
yield from self.actionA.getInputSchema() # type: ignore
yield from self.actionB.getInputSchema() # type: ignore

def __call__(self, data: KeyedData, **kwargs) -> Vector:
vecA = self.actionA(data, **kwargs) # type: ignore
vecB = self.actionB(data, **kwargs) # type: ignore
return (vecA - vecB) / vecB