From b20209a04c1f571105b9386c556f7e1eb7774d94 Mon Sep 17 00:00:00 2001 From: Ian Sullivan Date: Tue, 22 Sep 2026 18:18:46 -0700 Subject: [PATCH] Support lsst.images format for AP metric inputs --- pipelines/apDetectorVisitQualityCore.yaml | 6 +++- .../tools/tasks/calexpSummaryAnalysis.py | 31 +++++++++++++++++-- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/pipelines/apDetectorVisitQualityCore.yaml b/pipelines/apDetectorVisitQualityCore.yaml index 057776191..2f99e6f8a 100644 --- a/pipelines/apDetectorVisitQualityCore.yaml +++ b/pipelines/apDetectorVisitQualityCore.yaml @@ -5,6 +5,9 @@ parameters: # Note that these parameter names are shared with ApPipe, and are overwritten # by changes in the values there. coaddName: goodSeeing + # Whether the images this pipeline reads from are legacy afw Exposures or + # lsst.images types. + image_type: legacy tasks: analyzeAssociatedDiaSourceTable: @@ -272,8 +275,9 @@ tasks: analyzePreliminarySummaryStats: class: lsst.analysis.tools.tasks.CalexpSummaryAnalysisTask config: - connections.data: preliminary_visit_image.summaryStats + connections.data: preliminary_visit_image connections.outputName: initialPviSummary + input_image_type: parameters.image_type atools.initialPviSummaryMetrics: CalexpSummaryMetrics python: from lsst.analysis.tools.atools import * analyzeVisitSampledImageSubtractionMetrics: diff --git a/python/lsst/analysis/tools/tasks/calexpSummaryAnalysis.py b/python/lsst/analysis/tools/tasks/calexpSummaryAnalysis.py index 014ad853c..79448c8f7 100644 --- a/python/lsst/analysis/tools/tasks/calexpSummaryAnalysis.py +++ b/python/lsst/analysis/tools/tasks/calexpSummaryAnalysis.py @@ -25,6 +25,9 @@ "CalexpSummaryAnalysisTask", ) +import dataclasses + +import lsst.pex.config as pexConfig from lsst.pipe.base import ( InputQuantizedConnection, OutputQuantizedConnection, @@ -42,16 +45,38 @@ class CalexpSummaryAnalysisConnections( defaultTemplates={"inputName": "calexp.summaryStats", "outputName": "calexpSummary"}, ): data = cT.Input( - doc="Calibrated exposure summary statistics to load from the butler", + doc="Summary statistics of a visit image, which is a legacy Exposure or an " + "lsst.images.VisitImage depending on input_image_type. Only the parent dataset type is " + "taken from connections.data; input_image_type sets the component that is read from it.", name="calexp.summaryStats", storageClass="ExposureSummaryStats", dimensions=("visit", "band", "detector"), deferLoad=False, ) + def __init__(self, *, config=None): + super().__init__(config=config) + + parent = self.data.name.split(".")[0] + if config.input_image_type == "future": + name = f"{parent}.summary_stats" + storage_class = "ObservationSummaryStats" + else: + name = f"{parent}.summaryStats" + storage_class = "ExposureSummaryStats" + self.data = dataclasses.replace(self.data, name=name, storageClass=storage_class) + class CalexpSummaryAnalysisConfig(AnalysisBaseConfig, pipelineConnections=CalexpSummaryAnalysisConnections): - pass + input_image_type = pexConfig.ChoiceField[str]( + "Which image type to read the summary statistics from.", + allowed={ + "legacy": "Read ``summaryStats`` from an `lsst.afw.image.Exposure`.", + "future": "Read ``summary_stats`` from an `lsst.images.VisitImage`.", + }, + optional=False, + default="legacy", + ) class CalexpSummaryAnalysisTask(AnalysisPipelineTask): @@ -70,6 +95,6 @@ def runQuantum( summary = inputs["data"] if summary is None: - raise UpstreamFailureNoWorkFound("No summary stats attached to calexp.") + raise UpstreamFailureNoWorkFound("No summary stats attached to the input image.") outputs = self.run(data=summary.__dict__) butlerQC.put(outputs, outputRefs)