Skip to content

Commit

Permalink
Add source Metrics and plots
Browse files Browse the repository at this point in the history
Adding metrics on associated and unassociated sources, as well as pipeline to create a bar graph comparing associated and unassociated sources. 
Rename demoMetric


Lint fix


Typo Fix


Formatting Fix


Add __all__ and updated docstrings


Formatting fixes


Small fix


Removed repeated Unique Action


Updated docstring
  • Loading branch information
bsmartradio committed Dec 8, 2022
1 parent 1a58e5a commit a17f3de
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 47 deletions.
13 changes: 13 additions & 0 deletions pipelines/diaObjectAssociatedSources.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
description: |
Pipeline to create metrics for associated and unassociated sources from diaObject tables
tasks:
analyzeDiaObjectTableSources:
class: lsst.analysis.tools.tasks.DiaObjectTableAssociatedSourcesTask
config:
connections.outputName: sourcesOutput
bands: ['g']
metrics.sourceMetrics: CountSources
plots.analysisPlots: SourcesPlot
python: |
from lsst.analysis.tools.analysisMetrics import *
from lsst.analysis.tools.analysisPlots import *
44 changes: 0 additions & 44 deletions python/lsst/analysis/tools/actions/scalar/scalarActions.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,47 +171,3 @@ def getInputSchema(self) -> KeyedDataSchema:
def __call__(self, data: KeyedData, **kwargs) -> Scalar:
mask = self.getMask(**kwargs)
return cast(Scalar, float(np.min(cast(Vector, data[self.vectorKey.format(**kwargs)])[mask])))


class UniqueAction(ScalarAction):
vectorKey = Field[str]("Key of Vector from which to investigate the number of unique entries")

def getInputSchema(self) -> KeyedDataSchema:
return ((self.vectorKey, Vector),)

def __call__(self, data: KeyedData, **kwargs) -> Scalar:
mask = self.getMask(**kwargs)
return cast(Scalar, int(len(np.unique(cast(Vector, data[self.vectorKey.format(**kwargs)])[mask]))))


class MaxAction(ScalarAction):
vectorKey = Field[str]("Key of Vector to find maximum")

def getInputSchema(self) -> KeyedDataSchema:
return ((self.vectorKey, Vector),)

def __call__(self, data: KeyedData, **kwargs) -> Scalar:
mask = self.getMask(**kwargs)
return cast(Scalar, float(np.max(cast(Vector, data[self.vectorKey.format(**kwargs)])[mask])))


class MinAction(ScalarAction):
vectorKey = Field[str]("Key for the vector to perform action on")

def getInputSchema(self) -> KeyedDataSchema:
return ((self.vectorKey, Vector),)

def __call__(self, data: KeyedData, **kwargs) -> Scalar:
mask = self.getMask(**kwargs)
return cast(Scalar, float(np.min(cast(Vector, data[self.vectorKey.format(**kwargs)])[mask])))


class UniqueAction(ScalarAction):
vectorKey = Field[str]("Key of Vector from which to investigate the number of unique entries")

def getInputSchema(self) -> KeyedDataSchema:
return ((self.vectorKey, Vector),)

def __call__(self, data: KeyedData, **kwargs) -> Scalar:
mask = self.getMask(**kwargs)
return cast(Scalar, int(len(np.unique(cast(Vector, data[self.vectorKey.format(**kwargs)])[mask]))))
1 change: 1 addition & 0 deletions python/lsst/analysis/tools/analysisMetrics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@
from .photometricRepeatabilityMetrics import *
from .psfResidualMetrics import *
from .skyFluxStatisticMetrics import *
from .sourceMetrics import *
4 changes: 3 additions & 1 deletion python/lsst/analysis/tools/analysisMetrics/seeingMetric.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

from ..interfaces import AnalysisMetric

__all__ = ("SeeingStatistics",)


class SeeingStatistics(AnalysisMetric):
"""Calculate seeing statistics from the ccdVisit table.
Expand All @@ -38,6 +40,6 @@ def setDefaults(self):

self.produce.units = {
"medianSeeing": "arcsec",
"minSeeing": "arcsev",
"minSeeing": "arcsec",
"maxSeeing": "arcsec",
}
53 changes: 53 additions & 0 deletions python/lsst/analysis/tools/analysisMetrics/sourceMetrics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# 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 lsst.analysis.tools.actions.scalar import CountAction, FracThreshold

from ..analysisParts.baseSources import BaseSources
from ..interfaces import AnalysisMetric

__all__ = ("CountSources",)


class CountSources(AnalysisMetric, BaseSources):
"""Counts associated and unassociated sources as
well as their percentage of the total sources."""

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

self.process.calculateActions.associatedPercent = FracThreshold(
op="gt", threshold=1.0, vectorKey="nDiaSources"
)
self.process.calculateActions.unassociatedPercent = FracThreshold(
op="le", threshold=1.0, vectorKey="nDiaSources"
)

self.process.calculateActions.associatedCount = CountAction(vectorKey="associatedVector")
self.process.calculateActions.unassociatedCount = CountAction(vectorKey="unassociatedVector")

self.produce.units = {
"associatedPercent": "count",
"unassociatedPercent": "count",
"associatedCount": "count",
"unassociatedCount": "count",
"uniqueSources": "count",
}
6 changes: 4 additions & 2 deletions python/lsst/analysis/tools/analysisParts/baseSources.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from lsst.analysis.tools.actions.scalar import UniqueAction
from lsst.analysis.tools.actions.scalar import CountUniqueAction
from lsst.analysis.tools.actions.vector import DownselectVector, LoadVector, ThresholdSelector, VectorSelector
from lsst.analysis.tools.interfaces import AnalysisTool

__all__ = ("BaseSources",)


class BaseSources(AnalysisTool):
"""Base class for counting associated and unassociated sources."""
Expand Down Expand Up @@ -30,4 +32,4 @@ def setDefaults(self):
vectorKey="nDiaSources", selector=self.process.buildActions.unassociatedVectorSelector
)

self.process.buildActions.uniqueSources = UniqueAction(vectorKey="nDiaSources")
self.process.buildActions.uniqueSources = CountUniqueAction(vectorKey="nDiaSources")
22 changes: 22 additions & 0 deletions python/lsst/analysis/tools/analysisPlots/analysisPlots.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,17 @@
"YPerpCModelPlot",
"TargetRefCatDeltaRAScatterPlot",
"TargetRefCatDeltaRAScatterPlot",
"SourcesPlot",
)

from lsst.pex.config import Field

from ..actions.plot.barPlots import BarPanel, BarPlot
from ..actions.plot.colorColorFitPlot import ColorColorFitPlot
from ..actions.plot.histPlot import HistPanel, HistPlot
from ..actions.plot.scatterplotWithTwoHists import ScatterPlotStatsAction, ScatterPlotWithTwoHists
from ..actions.plot.skyPlot import SkyPlot
from ..actions.scalar import CountAction
from ..actions.vector import (
AstromDiff,
CoaddPlotFlagSelector,
Expand All @@ -53,6 +56,7 @@
VectorSelector,
)
from ..analysisParts.baseFluxRatio import BasePsfApRatio
from ..analysisParts.baseSources import BaseSources
from ..analysisParts.genericPrep import CoaddPrep, VisitPrep
from ..analysisParts.shapeSizeFractional import BasePsfResidualMixin
from ..analysisParts.stellarLocus import WPerpCModel, WPerpPSF, XPerpCModel, XPerpPSF, YPerpCModel, YPerpPSF
Expand Down Expand Up @@ -329,3 +333,21 @@ def setDefaults(self):
self.produce.panels["panel_flux"] = HistPanel()
self.produce.panels["panel_flux"].label = "Psf/Ap Ratio"
self.produce.panels["panel_flux"].hists = dict(fluxRatioMetric="Ratio")


class SourcesPlot(AnalysisPlot, BaseSources):
"""Plot a histogram of the associated and unassociated Sources"""

def setDefaults(self, **kwargs):
super().setDefaults()

self.process.calculateActions.associatedCount = CountAction(vectorKey="associatedVector")
self.process.calculateActions.unassociatedCount = CountAction(vectorKey="unassociatedVector")

self.produce = BarPlot()
self.produce.panels["panel_source"] = BarPanel()
self.produce.panels["panel_source"].label = "N Assoc and Unassoc Sources"
self.produce.panels["panel_source"].bars = dict(
associatedVector="Associated Sources",
unassociatedVector="Unassociated Sources",
)
1 change: 1 addition & 0 deletions python/lsst/analysis/tools/tasks/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .associatedSourcesTractAnalysis import *
from .catalogMatch import *
from .diaObjectTableAssocAnalysis import *
from .diaSourceTableVisitAnalysis import *
from .diffMatchedAnalysis import *
from .objectTableTractAnalysis import *
Expand Down
35 changes: 35 additions & 0 deletions python/lsst/analysis/tools/tasks/diaObjectTableAssocAnalysis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from __future__ import annotations

from lsst.pipe.base import connectionTypes as ct

from .base import AnalysisBaseConfig, AnalysisBaseConnections, AnalysisPipelineTask

__all__ = [
"DiaObjectTableAnalysisConnections",
"DiaObjectTableAnalysisConfig",
"DiaObjectTableAssociatedSourcesTask",
]


class DiaObjectTableAnalysisConnections(
AnalysisBaseConnections,
dimensions=("visit", "band"),
defaultTemplates={"coaddName": "deep", "fakesType": ""},
):

data = ct.Input(
doc="CcdVisit-based DiaObject table to load from the butler",
name="{fakesType}{coaddName}Diff_diaObject",
storageClass="DataFrame",
dimensions=("visit", "band", "detector"),
deferLoad=True,
)


class DiaObjectTableAnalysisConfig(AnalysisBaseConfig, pipelineConnections=DiaObjectTableAnalysisConnections):
pass


class DiaObjectTableAssociatedSourcesTask(AnalysisPipelineTask):
ConfigClass = DiaObjectTableAnalysisConfig
_DefaultName = "DiaObjectTableAssociatedSources"

0 comments on commit a17f3de

Please sign in to comment.