Skip to content

Commit 9c9bde8

Browse files
committed
Modify Stamp for N-archive elements (bckwd compat)
1 parent 1098895 commit 9c9bde8

File tree

2 files changed

+255
-173
lines changed

2 files changed

+255
-173
lines changed

python/lsst/meas/algorithms/brightStarStamps.py

+48-64
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
__all__ = ["BrightStarStamp", "BrightStarStamps"]
2525

2626
import logging
27-
from collections.abc import Collection
27+
from collections.abc import Collection, Mapping
2828
from dataclasses import dataclass
2929
from functools import reduce
3030
from operator import ior
@@ -34,15 +34,16 @@
3434
from lsst.afw.image import MaskedImageF
3535
from lsst.afw.math import Property, StatisticsControl, makeStatistics, stringToStatisticsProperty
3636
from lsst.afw.table.io import Persistable
37+
from lsst.daf.base import PropertyList
3738
from lsst.geom import Point2I
3839

39-
from .stamps import AbstractStamp, Stamps, readFitsWithOptions
40+
from .stamps import StampBase, Stamps, readFitsWithOptions
4041

4142
logger = logging.getLogger(__name__)
4243

4344

4445
@dataclass
45-
class BrightStarStamp(AbstractStamp):
46+
class BrightStarStamp(StampBase):
4647
"""Single stamp centered on a bright star, normalized by its annularFlux.
4748
4849
Parameters
@@ -55,8 +56,9 @@ class BrightStarStamp(AbstractStamp):
5556
Gaia object identifier
5657
position : `~lsst.geom.Point2I`
5758
Origin of the stamps in its origin exposure (pixels)
58-
archive_element : `~lsst.afw.table.io.Persistable` or None, optional
59-
Archive element (e.g. Transform or WCS) associated with this stamp.
59+
archive_elements : `~collections.abc.Mapping`[ `str` , \
60+
`~lsst.afw.table.io.Persistable`], optional
61+
Archive elements (e.g. Transform / WCS) associated with this stamp.
6062
annularFlux : `float` or None, optional
6163
Flux in an annulus around the object
6264
"""
@@ -65,15 +67,15 @@ class BrightStarStamp(AbstractStamp):
6567
gaiaGMag: float
6668
gaiaId: int
6769
position: Point2I
68-
archive_element: Persistable | None = None
70+
archive_elements: Mapping[str, Persistable] | None = None
6971
annularFlux: float | None = None
7072
minValidAnnulusFraction: float = 0.0
7173
validAnnulusFraction: float | None = None
7274
optimalInnerRadius: int | None = None
7375
optimalOuterRadius: int | None = None
7476

7577
@classmethod
76-
def factory(cls, stamp_im, metadata, idx, archive_element=None, minValidAnnulusFraction=0.0):
78+
def factory(cls, stamp_im, metadata, idx, archive_elements=None, minValidAnnulusFraction=0.0):
7779
"""This method is needed to service the FITS reader. We need a standard
7880
interface to construct objects like this. Parameters needed to
7981
construct this object are passed in via a metadata dictionary and then
@@ -90,8 +92,9 @@ def factory(cls, stamp_im, metadata, idx, archive_element=None, minValidAnnulusF
9092
needed by the constructor.
9193
idx : `int`
9294
Index into the lists in ``metadata``
93-
archive_element : `~lsst.afw.table.io.Persistable` or None, optional
94-
Archive element (e.g. Transform or WCS) associated with this stamp.
95+
archive_elements : `~collections.abc.Mapping`[ `str` , \
96+
`~lsst.afw.table.io.Persistable`], optional
97+
Archive elements (e.g. Transform / WCS) associated with this stamp.
9598
minValidAnnulusFraction : `float`, optional
9699
The fraction of valid pixels within the normalization annulus of a
97100
star.
@@ -101,23 +104,39 @@ def factory(cls, stamp_im, metadata, idx, archive_element=None, minValidAnnulusF
101104
brightstarstamp : `BrightStarStamp`
102105
An instance of this class
103106
"""
104-
if "X0S" in metadata and "Y0S" in metadata:
105-
x0 = metadata.getArray("X0S")[idx]
106-
y0 = metadata.getArray("Y0S")[idx]
107+
if "X0" in metadata and "Y0" in metadata:
108+
x0 = metadata["X0"]
109+
y0 = metadata["X0"]
107110
position = Point2I(x0, y0)
108111
else:
109112
position = None
110113
return cls(
111114
stamp_im=stamp_im,
112-
gaiaGMag=metadata.getArray("G_MAGS")[idx],
113-
gaiaId=metadata.getArray("GAIA_IDS")[idx],
115+
gaiaGMag=metadata["G_MAGS"],
116+
gaiaId=metadata["GAIA_IDS"],
114117
position=position,
115-
archive_element=archive_element,
116-
annularFlux=metadata.getArray("ANNULAR_FLUXES")[idx],
118+
archive_elements=archive_elements,
119+
annularFlux=metadata["ANNULAR_FLUXES"],
117120
minValidAnnulusFraction=minValidAnnulusFraction,
118-
validAnnulusFraction=metadata.getArray("VALID_PIXELS_FRACTION")[idx],
121+
validAnnulusFraction=metadata["VALID_PIXELS_FRACTION"],
119122
)
120123

124+
def _getMaskedImage(self):
125+
return self.stamp_im
126+
127+
def _getArchiveElements(self):
128+
return self.archive_elements
129+
130+
def _getMetadata(self) -> PropertyList | None:
131+
md = PropertyList()
132+
md["G_MAG"] = self.gaiaGMag
133+
md["GAIA_ID"] = self.gaiaId
134+
md["X0"] = self.position.x
135+
md["Y0"] = self.position.y
136+
md["ANNULAR_FLUX"] = self.annularFlux
137+
md["VALID_PIXELS_FRACTION"] = self.validAnnulusFraction
138+
return md
139+
121140
def measureAndNormalize(
122141
self,
123142
annulus: SpanSet,
@@ -248,13 +267,8 @@ def __init__(
248267
use_archive=False,
249268
):
250269
super().__init__(starStamps, metadata, use_mask, use_variance, use_archive)
251-
# Ensure stamps contain a flux measure if expected to be normalized.
252-
self._checkNormalization(False, innerRadius, outerRadius)
253-
self._innerRadius, self._outerRadius = innerRadius, outerRadius
254-
if innerRadius is not None and outerRadius is not None:
255-
self.normalized = True
256-
else:
257-
self.normalized = False
270+
# From v2 onwards, stamps are now always assumed to be unnormalized
271+
self.normalized = False
258272
self.nb90Rots = nb90Rots
259273

260274
@classmethod
@@ -449,26 +463,6 @@ def initAndNormalize(
449463
return bss, badStamps
450464
return bss
451465

452-
def _refresh_metadata(self):
453-
"""Refresh metadata. Should be called before writing the object out.
454-
455-
This method adds full lists of positions, Gaia magnitudes, IDs and
456-
annular fluxes to the shared metadata.
457-
"""
458-
self._metadata["G_MAGS"] = self.getMagnitudes()
459-
self._metadata["GAIA_IDS"] = self.getGaiaIds()
460-
positions = self.getPositions()
461-
self._metadata["X0S"] = [xy0[0] for xy0 in positions]
462-
self._metadata["Y0S"] = [xy0[1] for xy0 in positions]
463-
self._metadata["ANNULAR_FLUXES"] = self.getAnnularFluxes()
464-
self._metadata["VALID_PIXELS_FRACTION"] = self.getValidPixelsFraction()
465-
self._metadata["NORMALIZED"] = self.normalized
466-
self._metadata["INNER_RADIUS"] = self._innerRadius
467-
self._metadata["OUTER_RADIUS"] = self._outerRadius
468-
if self.nb90Rots is not None:
469-
self._metadata["NB_90_ROTS"] = self.nb90Rots
470-
return None
471-
472466
@classmethod
473467
def readFits(cls, filename):
474468
"""Build an instance of this class from a file.
@@ -493,26 +487,16 @@ def readFitsWithOptions(cls, filename, options):
493487
"""
494488
stamps, metadata = readFitsWithOptions(filename, BrightStarStamp.factory, options)
495489
nb90Rots = metadata["NB_90_ROTS"] if "NB_90_ROTS" in metadata else None
496-
if metadata["NORMALIZED"]:
497-
return cls(
498-
stamps,
499-
innerRadius=metadata["INNER_RADIUS"],
500-
outerRadius=metadata["OUTER_RADIUS"],
501-
nb90Rots=nb90Rots,
502-
metadata=metadata,
503-
use_mask=metadata["HAS_MASK"],
504-
use_variance=metadata["HAS_VARIANCE"],
505-
use_archive=metadata["HAS_ARCHIVE"],
506-
)
507-
else:
508-
return cls(
509-
stamps,
510-
nb90Rots=nb90Rots,
511-
metadata=metadata,
512-
use_mask=metadata["HAS_MASK"],
513-
use_variance=metadata["HAS_VARIANCE"],
514-
use_archive=metadata["HAS_ARCHIVE"],
515-
)
490+
# For backwards compatibility, always assume stamps are unnormalized.
491+
# This allows older stamps to be read in successfully.
492+
return cls(
493+
stamps,
494+
nb90Rots=nb90Rots,
495+
metadata=metadata,
496+
use_mask=metadata["HAS_MASK"],
497+
use_variance=metadata["HAS_VARIANCE"],
498+
use_archive=metadata["HAS_ARCHIVE"],
499+
)
516500

517501
def append(self, item, innerRadius=None, outerRadius=None):
518502
"""Add an additional bright star stamp.

0 commit comments

Comments
 (0)