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-37727: Refactor and develop further the ref cat matching code #133

Merged
merged 13 commits into from
Nov 30, 2023
Merged
26 changes: 25 additions & 1 deletion pipelines/coaddQualityCore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,33 @@ tasks:
from lsst.analysis.tools.contexts import *
from lsst.analysis.tools.actions.plot import *
catalogMatchTract:
class: lsst.analysis.tools.tasks.catalogMatch.CatalogMatchTask
class: lsst.analysis.tools.tasks.astrometricCatalogMatch.AstrometricCatalogMatchTask
config:
connections.refCatalog: gaia_dr2_20200414
refCatObjectTract:
class: lsst.analysis.tools.tasks.refCatObjectAnalysis.RefCatObjectAnalysisTask
config:
atools.astromDiffRAScatterPlot: TargetRefCatDeltaRAScatterPlot
atools.astromDiffDecScatterPlot: TargetRefCatDeltaDecScatterPlot
atools.astromDiffRASkyPlot: TargetRefCatDeltaRASkyPlot
atools.astromDiffDecSkyPlot: TargetRefCatDeltaDecSkyPlot
python: |
from lsst.analysis.tools.atools import *

## Perform photometric comparison to the reference catalog
photometricCatalogMatch:
class: lsst.analysis.tools.tasks.photometricCatalogMatch.PhotometricCatalogMatchTask
config:
connections.refCatalog: ps1_pv3_3pi_20170110
photometricRefCatObjectTract:
class: lsst.analysis.tools.tasks.refCatObjectPhotometricAnalysis.RefCatObjectPhotometricAnalysisTask
config:
atools.targetRefCatDeltaPsfScatterPlot: TargetRefCatDeltaPsfScatterPlot
atools.targetRefCatDeltaCModelScatterPlot: TargetRefCatDeltaCModelScatterPlot
atools.targetRefCatDeltaPsfSkyPlot: TargetRefCatDeltaPsfSkyPlot
atools.targetRefCatDeltaCModelSkyPlot: TargetRefCatDeltaCModelSkyPlot
python: |
from lsst.analysis.tools.atools import *
plotPropertyMapTract:
class: lsst.analysis.tools.tasks.PropertyMapTractAnalysisTask
config:
Expand Down
25 changes: 25 additions & 0 deletions pipelines/visitQualityCore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,28 @@ tasks:
python: |
from lsst.analysis.tools.atools import *
from lsst.analysis.tools.contexts import *
catalogMatchVisit:
class: lsst.analysis.tools.tasks.astrometricCatalogMatch.AstrometricCatalogMatchVisitTask
config:
connections.refCatalog: gaia_dr2_20200414
astrometricRefCatSourceVisit:
class: lsst.analysis.tools.tasks.refCatSourceAnalysis.RefCatSourceAnalysisTask
config:
atools.astromDiffRASkyVisitPlot: TargetRefCatDeltaRASkyVisitPlot
atools.astromDiffDecSkyVisitPlot: TargetRefCatDeltaDecSkyVisitPlot
atools.astromDiffRAScatterVisitPlot: TargetRefCatDeltaRAScatterVisitPlot
atools.astromDiffDecScatterVisitPlot: TargetRefCatDeltaDecScatterVisitPlot
python: |
from lsst.analysis.tools.atools import *
photometricMatchVisit:
class: lsst.analysis.tools.tasks.photometricCatalogMatch.PhotometricCatalogMatchVisitTask
config:
extraColumns: ["x", "y", "ap09Flux", "ap09FluxErr"]
photometricRefCatSourceVisit:
class: lsst.analysis.tools.tasks.refCatSourcePhotometricAnalysis.RefCatSourcePhotometricAnalysisTask
config:
atools.photomDiffPsfSkyVisitPlot: TargetRefCatDeltaPsfSkyVisitPlot
atools.photomDiffAp09SkyVisitPlot: TargetRefCatDeltaAp09SkyVisitPlot
atools.photoDiffPsfScatterVisitPlot: TargetRefCatDeltaPsfScatterVisitPlot
atools.photoDiffCModelScatterVisitPlot: TargetRefCatDeltaAp09ScatterVisitPlot
python: from lsst.analysis.tools.atools import *
2 changes: 1 addition & 1 deletion pipelines/visitQualityExtended.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ description: |
Tier2 plots and metrics to assess visit quality
tasks:
catalogMatchVisit:
class: lsst.analysis.tools.tasks.catalogMatch.CatalogMatchVisitTask
class: lsst.analysis.tools.tasks.astrometricCatalogMatch.AstrometricCatalogMatchVisitTask
refCatSourceVisit:
class: lsst.analysis.tools.tasks.refCatSourceAnalysis.RefCatSourceAnalysisTask
2 changes: 1 addition & 1 deletion python/lsst/analysis/tools/actions/plot/histPlot.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ def _getPanelRange(self, data, panel, mads=None, meds=None):
minMed = np.nanmin(meds)
panel_range = [minMed - lowerRange * maxMad, maxMed + upperRange * maxMad]
if panel_range[1] - panel_range[0] == 0:
self.log.info(
log.info(
"NOTE: panel_range for {} based on med/sigMad was 0. Computing using "
"percentile range instead.".format(panel)
)
Expand Down
5 changes: 4 additions & 1 deletion python/lsst/analysis/tools/actions/plot/plotUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,10 @@ def generateSummaryStats(data, skymap, plotInfo):
# Once the objectTable_tract catalogues are using gen 3 patches
# this will go away
onPatch = data["patch"] == patch
stat = np.nanmedian(data[yCol][onPatch])
if sum(onPatch) == 0:
stat = np.nan
else:
stat = np.nanmedian(data[yCol][onPatch])
try:
patchTuple = (int(patch.split(",")[0]), int(patch.split(",")[-1]))
patchInfo = tractInfo.getPatchInfo(patchTuple)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ class ScatterPlotWithTwoHists(PlotAction):

addSummaryPlot = Field[bool](
doc="Add a summary plot to the figure?",
default=False,
default=True,
)

_stats = ("median", "sigmaMad", "count", "approxMag")
Expand Down Expand Up @@ -673,9 +673,9 @@ def _makeTopHistogram(
# Top histogram
topHist = figure.add_subplot(gs[0, :-1], sharex=ax)

if "all" in self.plotTypes:
x_all = f"x{self._datatypes['all'].suffix_xy}"
keys_notall = [x for x in self.plotTypes if x != "all"]
if "any" in self.plotTypes:
x_all = data[f"x{self._datatypes['any'].suffix_xy}"]
keys_notall = [x for x in self.plotTypes if x != "any"]
else:
x_all = np.concatenate([data[f"x{self._datatypes[key].suffix_xy}"] for key in self.plotTypes])
keys_notall = self.plotTypes
Expand Down Expand Up @@ -712,16 +712,16 @@ def _makeSideHistogram(
# Side histogram
sideHist = figure.add_subplot(gs[1:, -1], sharey=ax)

if "all" in self.plotTypes:
y_all = f"y{self._datatypes['all'].suffix_xy}"
keys_notall = [x for x in self.plotTypes if x != "all"]
if "any" in self.plotTypes:
y_all = data[f"y{self._datatypes['any'].suffix_xy}"]
keys_notall = [x for x in self.plotTypes if x != "any"]
else:
y_all = np.concatenate([data[f"y{self._datatypes[key].suffix_xy}"] for key in self.plotTypes])
keys_notall = self.plotTypes

y_min, y_max = ax.get_ylim()
bins = np.linspace(y_min, y_max, 100)
sideHist.hist(y_all, bins=bins, color="grey", alpha=0.3, orientation="horizontal", log=True)
sideHist.hist(np.array(y_all), bins=bins, color="grey", alpha=0.3, orientation="horizontal", log=True)
Copy link
Contributor

Choose a reason for hiding this comment

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

I realize this is outside your PR, but this line made me look at where y_all is set above, and I can't see how line 716 works. In line 719, y_all is a numpy array, but in line 716, it's a string. Also, "all" is not one of the options in the documentation for self.plotTypes or self._datatypes. Maybe @taranu remembers? In any case, I think y_all should already be a numpy array if line 716 is wrong, so you shouldn't have to add this.

Copy link
Collaborator Author

@sr525 sr525 Aug 15, 2023

Choose a reason for hiding this comment

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

I think it is supposed to be any rather than all and also data[], I will test it properly.

kwargs_hist = dict(
bins=bins,
histtype="step",
Expand Down
14 changes: 12 additions & 2 deletions python/lsst/analysis/tools/actions/scalar/scalarActions.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ def getInputSchema(self) -> KeyedDataSchema:

def __call__(self, data: KeyedData, **kwargs) -> Scalar:
mask = self.getMask(**kwargs)
return cast(Scalar, float(np.nanmedian(cast(Vector, data[self.vectorKey.format(**kwargs)])[mask])))
if len(data[self.vectorKey.format(**kwargs)][mask]) != 0:
med = cast(Scalar, float(np.nanmedian(cast(Vector, data[self.vectorKey.format(**kwargs)])[mask])))
else:
med = np.NaN

return med


class MeanAction(ScalarAction):
Expand All @@ -49,7 +54,12 @@ def getInputSchema(self) -> KeyedDataSchema:

def __call__(self, data: KeyedData, **kwargs) -> Scalar:
mask = self.getMask(**kwargs)
return cast(Scalar, float(np.nanmean(cast(Vector, data[self.vectorKey.format(**kwargs)])[mask])))
if len(data[self.vectorKey.format(**kwargs)][mask]) != 0:
mean = cast(Scalar, float(np.nanmean(cast(Vector, data[self.vectorKey.format(**kwargs)])[mask])))
else:
mean = np.NaN

return mean


class StdevAction(ScalarAction):
Expand Down
33 changes: 29 additions & 4 deletions python/lsst/analysis/tools/actions/vector/selectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,15 @@ class CoaddPlotFlagSelector(FlagSelector):
def getInputSchema(self) -> KeyedDataSchema:
yield from super().getInputSchema()

def refMatchContext(self):
self.selectWhenFalse = [
"{band}_psfFlux_flag_target",
"{band}_pixelFlags_saturatedCenter_target",
"{band}_extendedness_flag_target",
"xy_flag_target",
]
self.selectWhenTrue = ["detect_isPatchInner_target", "detect_isDeblendedSource_target"]

def __call__(self, data: KeyedData, **kwargs) -> Vector:
result: Optional[Vector] = None
bands: tuple[str, ...]
Expand Down Expand Up @@ -162,9 +171,19 @@ class VisitPlotFlagSelector(FlagSelector):
(i.e., using sourceTable_visit catalogs).
"""

catalogSuffix = Field[str](doc="The suffix to apply to all the keys.", default="")

def getInputSchema(self) -> KeyedDataSchema:
yield from super().getInputSchema()

def refMatchContext(self):
self.selectWhenFalse = [
"psfFlux_flag_target",
"pixelFlags_saturatedCenter_target",
"extendedness_flag_target",
"centroid_flag_target",
]

def __call__(self, data: KeyedData, **kwargs) -> Vector:
result: Optional[Vector] = None
temp = super().__call__(data, **kwargs)
Expand Down Expand Up @@ -227,8 +246,11 @@ class SnSelector(SelectorBase):
)

def getInputSchema(self) -> KeyedDataSchema:
yield (fluxCol := self.fluxType), Vector
yield f"{fluxCol}{self.uncertaintySuffix}", Vector
fluxCol = self.fluxType
fluxInd = fluxCol.find("lux") + len("lux")
errCol = f"{fluxCol}"[:fluxInd] + f"{self.uncertaintySuffix}" + f"{fluxCol}"[fluxInd:]
yield fluxCol, Vector
yield errCol, Vector

def __call__(self, data: KeyedData, **kwargs) -> Vector:
"""Makes a mask of objects that have S/N greater than
Expand Down Expand Up @@ -260,8 +282,11 @@ def __call__(self, data: KeyedData, **kwargs) -> Vector:
bands = ("",)
for band in bands:
fluxCol = self.fluxType.format(**(kwargs | dict(band=band)))
errCol = f"{fluxCol}{self.uncertaintySuffix.format(**kwargs)}"
vec = cast(Vector, data[fluxCol]) / cast(Vector, data[errCol])
fluxInd = fluxCol.find("lux") + len("lux")
errCol = (
f"{fluxCol}"[:fluxInd] + f"{self.uncertaintySuffix.format(**kwargs)}" + f"{fluxCol}"[fluxInd:]
)
vec = cast(Vector, data[fluxCol]) / data[errCol]
Copy link
Contributor

Choose a reason for hiding this comment

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

Was getting rid of the cast() around data[errCol] on purpose? It's fine if so, I just don't immediately understand why.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't remember. I think the cast around the result should be sufficent though?

temp = (vec > self.threshold) & (vec < self.maxSN)
if mask is not None:
mask &= temp # type: ignore
Expand Down
6 changes: 3 additions & 3 deletions python/lsst/analysis/tools/actions/vector/vectorActions.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,9 @@ def getInputSchema(self) -> KeyedDataSchema:
return ((self.decKey, Vector), (self.raKey, Vector))

def __call__(self, data: KeyedData, **kwargs) -> Vector:
ra = data[self.raKey]
dec = data[self.decKey]
return ra.to_numpy() * np.cos((dec.to_numpy() * u.degree).to(u.radian).value)
ra = np.array(data[self.raKey])
dec = np.array(data[self.decKey])
return ra * np.cos((dec * u.degree).to(u.radian).value)


# Statistical vectorActions
Expand Down
2 changes: 1 addition & 1 deletion python/lsst/analysis/tools/atools/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from .astrometricRepeatability import *
from .astrometryWithReference import *
from .coveragePlots import *
from .diaSolarSystemObjectMetrics import *
from .diaSourceMetrics import *
Expand All @@ -15,6 +14,7 @@
from .photometricRepeatability import *
from .photometry import *
from .propertyMap import *
from .refCatMatchPlots import *
from .seeingMetric import *
from .shapes import *
from .simpleDiaPlot import *
Expand Down