Skip to content

Commit

Permalink
Remove AB and consolidate AA1 tool
Browse files Browse the repository at this point in the history
  • Loading branch information
cmsaunders committed Dec 22, 2023
1 parent 92619f6 commit 1e9c3a6
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 60 deletions.
3 changes: 3 additions & 0 deletions pipelines/coaddQualityCore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ tasks:
atools.astromDiffDecScatterPlot: TargetRefCatDeltaDecScatterPlot
atools.astromDiffRASkyPlot: TargetRefCatDeltaRASkyPlot
atools.astromDiffDecSkyPlot: TargetRefCatDeltaDecSkyPlot
atools.astromDiffMetrics: TargetRefCatDeltaMetrics
atools.astromDiffMetrics.applyContext: CoaddContext
python: |
from lsst.analysis.tools.atools import *
from lsst.analysis.tools.contexts import *
## Perform photometric comparison to the reference catalog
photometricCatalogMatch:
Expand Down
7 changes: 3 additions & 4 deletions pipelines/visitQualityCore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@ tasks:
atools.astromDiffDecSkyVisitPlot: TargetRefCatDeltaDecSkyVisitPlot
atools.astromDiffRAScatterVisitPlot: TargetRefCatDeltaRAScatterVisitPlot
atools.astromDiffDecScatterVisitPlot: TargetRefCatDeltaDecScatterVisitPlot
atools.astromDiffRAMetrics: TargetRefCatDeltaVisitMetrics
atools.astromDiffRAMetrics.coordinate: "RA"
atools.astromDiffDecMetrics: TargetRefCatDeltaVisitMetrics
atools.astromDiffDecMetrics.coordinate: "Dec"
atools.astromDiffMetrics: TargetRefCatDeltaMetrics
atools.astromDiffMetrics.applyContext: VisitContext
python: |
from lsst.analysis.tools.atools import *
from lsst.analysis.tools.contexts import *
photometricMatchVisit:
class: lsst.analysis.tools.tasks.photometricCatalogMatch.PhotometricCatalogMatchVisitTask
config:
Expand Down
10 changes: 4 additions & 6 deletions python/lsst/analysis/tools/actions/scalar/scalarActions.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ class FracThreshold(ScalarFromVectorAction):
threshold = Field[float](doc="Threshold to apply.")
percent = Field[bool](doc="Express result as percentage", default=False)
relative_to_median = Field[bool](doc="Calculate threshold relative to " "the median?", default=False)
absolute_value = Field[bool](doc="Take absolute value of distribution")

def __call__(self, data: KeyedData, **kwargs) -> Scalar:
mask = self.getMask(**kwargs)
Expand All @@ -163,16 +162,15 @@ def __call__(self, data: KeyedData, **kwargs) -> Scalar:
n_values = len(values)
if n_values == 0:
return np.nan
# If relative_to_median is set, shift the values to be values - median
threshold = self.threshold
# If relative_to_median is set, shift the threshold to be median+thresh
if self.relative_to_median and len(values) > 0:
offset = nanMedian(values)
if np.isfinite(offset):
values -= offset
if self.absolute_value:
values = abs(values)
threshold += offset
result = cast(
Scalar,
float(np.sum(getattr(operator, self.op)(values, self.threshold)) / n_values), # type: ignore
float(np.sum(getattr(operator, self.op)(values, threshold)) / n_values), # type: ignore
)
if self.percent:
return 100.0 * result
Expand Down
29 changes: 29 additions & 0 deletions python/lsst/analysis/tools/actions/vector/vectorActions.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"PerGroupStatistic",
"ResidualWithPerGroupStatistic",
"RAcosDec",
"AngularSeparation",
)

import logging
Expand All @@ -40,6 +41,7 @@
import numpy as np
import pandas as pd
from astropy import units as u
from astropy.coordinates import SkyCoord
from lsst.pex.config import DictField, Field
from lsst.pex.config.configurableActions import ConfigurableActionField, ConfigurableActionStructField

Expand Down Expand Up @@ -283,6 +285,33 @@ def __call__(self, data: KeyedData, **kwargs) -> Vector:
return ra * np.cos((dec * u.degree).to(u.radian).value)


class AngularSeparation(VectorAction):
"""Calculate the angular separation between two coordinate positions."""

raKey_A = Field[str](doc="RA coordinate for position A", default="coord_ra")
decKey_A = Field[str](doc="Dec coordinate for position A", default="coord_dec")
raKey_B = Field[str](doc="RA coordinate for position B", default="coord_ra")
decKey_B = Field[str](doc="Dec coordinate for position B", default="coord_dec")
outputUnit = Field[str](doc="Output astropy unit", default="milliarcsecond")

def getInputSchema(self) -> KeyedDataSchema:
return (
(self.decKey_A, Vector),
(self.raKey_A, Vector),
(self.decKey_B, Vector),
(self.raKey_B, Vector),
)

def __call__(self, data: KeyedData, **kwargs) -> Vector:
ra_A = np.array(data[self.raKey_A])
dec_A = np.array(data[self.decKey_A])
ra_B = np.array(data[self.raKey_B])
dec_B = np.array(data[self.decKey_B])
coord_A = SkyCoord(ra_A * u.degree, dec_A * u.degree)
coord_B = SkyCoord(ra_B * u.degree, dec_B * u.degree)
return coord_A.separation(coord_B).to(u.Unit(self.outputUnit)).value


# Statistical vectorActions


Expand Down
139 changes: 89 additions & 50 deletions python/lsst/analysis/tools/atools/refCatMatchPlots.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,16 @@
"TargetRefCatDeltaDecSkyVisitPlot",
"TargetRefCatDeltaRAScatterVisitPlot",
"TargetRefCatDeltaDecScatterVisitPlot",
"TargetRefCatDeltaVisitMetrics",
"TargetRefCatDeltaMetrics",
)

from lsst.pex.config import ChoiceField, Field
from lsst.pex.config import Field

from ..actions.plot.scatterplotWithTwoHists import ScatterPlotStatsAction, ScatterPlotWithTwoHists
from ..actions.plot.skyPlot import SkyPlot
from ..actions.scalar.scalarActions import FracThreshold, MedianAction, SigmaMadAction
from ..actions.scalar.scalarActions import MedianAction, SigmaMadAction
from ..actions.vector import (
AngularSeparation,
CoaddPlotFlagSelector,
ConvertFluxToMag,
ConvertUnits,
Expand Down Expand Up @@ -535,71 +536,109 @@ def setDefaults(self):
self.produce.zAxisLabel = "Dec$_{{target}}$ - Dec$_{{ref}}$ (marcsec)"


class TargetRefCatDeltaVisitMetrics(TargetRefCatDelta):
class TargetRefCatDeltaMetrics(AnalysisTool):
"""Calculate the AA1, AB1, and ABF1 metrics from the difference between the
target and reference catalog coordinates.
"""

AB2 = Field[float](
doc="Distance (in mas) from the mean at which to calculate percentage of outliers", default=20
)
coordinate = ChoiceField[str](
doc="The coordinate direction",
optional=False,
allowed={"RA": "Right ascension", "Dec": "Declination"},
parameterizedBand = Field[bool](
doc="Does this AnalysisTool support band as a name parameter", default=True
)

def coaddContext(self) -> None:
"""Apply coadd options for the metrics. Applies the coadd plot flag
selector and sets flux types.
"""
self.prep.selectors.flagSelector = CoaddPlotFlagSelector()
self.prep.selectors.starSelector.vectorKey = "{band}_extendedness_target"

self.applyContext(RefMatchContext)

self.process.buildActions.mags.vectorKey = "{band}_psfFlux_target"

self.produce.metric.newNames = {
"AA1_RA": "{band}_AA1_RA_coadd",
"AA1_sigmaMad_RA": "{band}_AA1_sigmaMad_RA_coadd",
"AA1_Dec": "{band}_AA1_Dec_coadd",
"AA1_sigmaMad_Dec": "{band}_AA1_sigmaMad_Dec_coadd",
"AA1_tot": "{band}_AA1_tot_coadd",
"AA1_sigmaMad_tot": "{band}_AA1_sigmaMad_tot_coadd",
}

def visitContext(self) -> None:
"""Apply visit options for the metrics. Applies the coadd plot flag
selector and sets flux types.
"""
self.parameterizedBand = False
self.prep.selectors.flagSelector = VisitPlotFlagSelector()
self.prep.selectors.starSelector.vectorKey = "extendedness_target"

self.applyContext(RefMatchContext)

self.process.buildActions.mags.vectorKey = "psfFlux_target"

def setDefaults(self):
super().setDefaults()

self.applyContext(VisitContext)
self.applyContext(RefMatchContext)
self.prep.selectors.starSelector = StarSelector()

self.process.buildActions.astromDiff = ConvertUnits(
# Calculate difference in RA
self.process.buildActions.astromDiffRA = ConvertUnits(
buildAction=SubtractVector, inUnit="degree", outUnit="milliarcsecond"
)
self.process.buildActions.astromDiffRA.buildAction.actionA = RAcosDec(
raKey="coord_ra_target", decKey="dec_ref"
)
self.process.buildActions.astromDiffRA.buildAction.actionB = RAcosDec(
raKey="ra_ref", decKey="dec_ref"
)
# Calculate difference in Dec
self.process.buildActions.astromDiffDec = ConvertUnits(
buildAction=SubtractVector, inUnit="degree", outUnit="milliarcsecond"
)
self.process.buildActions.astromDiffDec.buildAction.actionA = LoadVector(vectorKey="coord_dec_target")
self.process.buildActions.astromDiffDec.buildAction.actionB = LoadVector(vectorKey="dec_ref")
# Calculate total difference (using astropy)
self.process.buildActions.astromDiffTot = AngularSeparation(
raKey_A="coord_ra_target",
decKey_A="coord_dec_target",
raKey_B="ra_ref",
decKey_B="dec_ref",
)

self.process.buildActions.mags = ConvertFluxToMag()
self.process.buildActions.mags.vectorKey = "psfFlux_target"

self.process.filterActions.brightStars = DownselectVector(vectorKey="astromDiff")
self.process.filterActions.brightStars.selector = RangeSelector(
# Filter down to only objects with mag 17-21.5
self.process.filterActions.brightStarsRA = DownselectVector(vectorKey="astromDiffRA")
self.process.filterActions.brightStarsRA.selector = RangeSelector(
vectorKey="mags", minimum=17, maximum=21.5
)

self.process.calculateActions.AA1 = MedianAction(vectorKey="brightStars")
self.process.calculateActions.AB1 = SigmaMadAction(vectorKey="brightStars")

self.produce.metric.units = {"AA1": "mas", "AB1": "mas", "ABF1": "percent"}

def finalize(self):
super().finalize()

if self.coordinate == "RA":
self.process.buildActions.astromDiff.buildAction.actionA = RAcosDec(
raKey="coord_ra_target", decKey="dec_ref"
)
self.process.buildActions.astromDiff.buildAction.actionB = RAcosDec(
raKey="ra_ref", decKey="dec_ref"
)

else:
self.process.buildActions.astromDiff.buildAction.actionA = LoadVector(
vectorKey="coord_dec_target"
)
self.process.buildActions.astromDiff.buildAction.actionB = LoadVector(vectorKey="dec_ref")

self.process.calculateActions.ABF1 = FracThreshold(
vectorKey="brightStars",
threshold=self.AB2,
percent=True,
op="gt",
relative_to_median=True,
absolute_value=True,
self.process.filterActions.brightStarsDec = DownselectVector(vectorKey="astromDiffDec")
self.process.filterActions.brightStarsDec.selector = RangeSelector(
vectorKey="mags", minimum=17, maximum=21.5
)

self.produce.metric.newNames = {
"AA1": f"AA1_{self.coordinate}",
"AB1": f"AB1_{self.coordinate}",
"ABF1": f"ABF1_{self.coordinate}",
self.process.filterActions.brightStarsTot = DownselectVector(vectorKey="astromDiffTot")
self.process.filterActions.brightStarsTot.selector = RangeSelector(
vectorKey="mags", minimum=17, maximum=21.5
)

# Calculate median and sigmaMad
self.process.calculateActions.AA1_RA = MedianAction(vectorKey="brightStarsRA")
self.process.calculateActions.AA1_sigmaMad_RA = SigmaMadAction(vectorKey="brightStarsRA")

self.process.calculateActions.AA1_Dec = MedianAction(vectorKey="brightStarsDec")
self.process.calculateActions.AA1_sigmaMad_Dec = SigmaMadAction(vectorKey="brightStarsDec")

self.process.calculateActions.AA1_tot = MedianAction(vectorKey="brightStarsTot")
self.process.calculateActions.AA1_sigmaMad_tot = SigmaMadAction(vectorKey="brightStarsTot")

self.produce.metric.units = {
"AA1_RA": "mas",
"AA1_sigmaMad_RA": "mas",
"AA1_Dec": "mas",
"AA1_sigmaMad_Dec": "mas",
"AA1_tot": "mas",
"AA1_sigmaMad_tot": "mas",
}

0 comments on commit 1e9c3a6

Please sign in to comment.