Skip to content

Commit

Permalink
Make magCut a class variable.
Browse files Browse the repository at this point in the history
Change valid test to use self.task.

Add comment.

Simplify string names in test and code.

Add error handling to runQuantum.

Add/modify docs.

Add connections init for metric config.

Remove automated renaming.
  • Loading branch information
morriscb committed Dec 10, 2020
1 parent 5e296b1 commit 0c94d9b
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 31 deletions.
43 changes: 22 additions & 21 deletions python/lsst/ap/pipe/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,37 +55,31 @@ class ApFakesCompletenessMetricConnections(
)


# Inherits from InsertFakesConfig to preserve column names in the fakes
# catalog.
class ApFakesCompletenessMetricConfig(
MetricTask.ConfigClass,
InsertFakesConfig,
pipelineConnections=ApFakesCompletenessMetricConnections):
"""ApFakesCompleteness config.
"""
magMin = pexConfig.RangeField(
doc="Minimum magnitude the mag distribution. All magnitudes requested "
"are set to the same value.",
dtype=int,
doc="Minimum of cut on magnitude range used to compute completeness "
"in.",
dtype=float,
default=20,
min=1,
max=40,
)
magMax = pexConfig.RangeField(
doc="Maximum magnitude the mag distribution. All magnitudes requested "
"are set to the same value.",
doc="Maximum of cut on magnitude range used to compute completeness "
"in.",
dtype=int,
default=30,
min=1,
max=40,
)

@property
def metricName(self):
"""The metric calculated by a `MetricTask` with this config
(`lsst.verify.Name`, read-only).
"""
return Name(package=self.connections.package,
metric=f"{self.connections.metric}Mag{self.magMin}t{self.magMax}")


class ApFakesCompletenessMetricTask(MetricTask):
"""Metric task for summarizing the completeness of fakes inserted into the
Expand All @@ -95,11 +89,20 @@ class ApFakesCompletenessMetricTask(MetricTask):
ConfigClass = ApFakesCompletenessMetricConfig

def runQuantum(self, butlerQC, inputRefs, outputRefs):
inputs = butlerQC.get(inputRefs)
inputs["band"] = butlerQC.quantum.dataId["band"]

outputs = self.run(**inputs)
butlerQC.put(outputs, outputRefs)
try:
inputs = butlerQC.get(inputRefs)
inputs["band"] = butlerQC.quantum.dataId["band"]
outputs = self.run(**inputs)
if outputs.measurement is not None:
butlerQC.put(outputs, outputRefs)
else:
self.log.debugf("Skipping measurement of {!r} on {} "
"as not applicable.", self, inputRefs)
except MetricComputationError:
# Apparently lsst.log doesn't have built-in exception support?
self.log.errorf(
"Measurement of {!r} failed on {}->{}\n{}",
self, inputRefs, outputRefs, traceback.format_exc())

def run(self, matchedFakes, band):
"""Compute the completeness of recovered fakes within a magnitude
Expand All @@ -119,8 +122,6 @@ def run(self, matchedFakes, band):
the ratio (`lsst.verify.Measurement` or `None`)
"""
if matchedFakes is not None:
metricName = \
f"{self.config.metricName}"
magnitudes = matchedFakes[f"{self.config.magVar}" % band]
magCutFakes = matchedFakes[np.logical_and(magnitudes > self.config.magMin,
magnitudes < self.config.magMax)]
Expand All @@ -130,7 +131,7 @@ def run(self, matchedFakes, band):
"ill defined.")
else:
meas = Measurement(
metricName,
self.config.metricName,
(magCutFakes["diaSourceId"] > 0).sum() / len(magCutFakes) * u.dimensionless_unscaled)
else:
self.log.info("Nothing to do: no matched catalog found.")
Expand Down
22 changes: 12 additions & 10 deletions tests/test_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import numpy as np
import unittest

from lsst.pipe.base import testUtils
import lsst.skymap as skyMap
import lsst.utils.tests
from lsst.verify import Name
Expand Down Expand Up @@ -74,23 +75,24 @@ def setUp(self):
fakeCat = fakesTask.run(self.tractId, self.simpleMap).fakeCat

self.band = 'g'
magCut = 25
magMask = (fakeCat[f"{fakesConfig.magVar}" % self.band] < magCut)
self.magCut = 25
magMask = (fakeCat[fakesConfig.magVar % self.band] < self.magCut)
self.expectedAllMatched = magMask.sum()
ids = np.where(magMask, np.arange(1, len(fakeCat) + 1, dtype=int), 0)
# Add columns to mimic the matched fakes result without running the
# full pipeline.
self.fakeCat = fakeCat.assign(diaObjectId=ids,
filterName=["g"] * len(fakeCat),
diaSourceId=ids)

def testValid(self):
"""Test the run method.
"""
metricComplete = self.makeTask(20, 30)
result = metricComplete.run(self.fakeCat, self.band)
lsst.pipe.base.testUtils.assertValidOutput(metricComplete, result)
result = self.task.run(self.fakeCat, self.band)
testUtils.assertValidOutput(self.task, result)

meas = result.measurement
self.assertEqual(meas.metric_name, Name(metric="ap_pipe.apFakesCompletenessMag20t30"))
self.assertEqual(meas.metric_name, Name(metric="ap_pipe.apFakesCompleteness"))
self.assertEqual(
meas.quantity,
self.expectedAllMatched / self.targetSources * u.dimensionless_unscaled)
Expand All @@ -99,19 +101,19 @@ def testMissingData(self):
"""Test the run method with no data.
"""
result = self.task.run(None, None)
lsst.pipe.base.testUtils.assertValidOutput(self.task, result)
testUtils.assertValidOutput(self.task, result)
meas = result.measurement
self.assertIsNone(meas)

def testValidEmpty(self):
"""Test the run method with a valid but zero result.
"""
metricComplete = self.makeTask(25, 30)
metricComplete = self.makeTask(self.magCut, self.magCut + 5)
result = metricComplete.run(self.fakeCat, self.band)
lsst.pipe.base.testUtils.assertValidOutput(metricComplete, result)
testUtils.assertValidOutput(metricComplete, result)

meas = result.measurement
self.assertEqual(meas.metric_name, Name(metric="ap_pipe.apFakesCompletenessMag25t30"))
self.assertEqual(meas.metric_name, Name(metric="ap_pipe.apFakesCompleteness"))
self.assertEqual(meas.quantity, 0 * u.dimensionless_unscaled)


Expand Down

0 comments on commit 0c94d9b

Please sign in to comment.