diff --git a/python/pfs/utils/datamodel/__init__.py b/python/pfs/utils/datamodel/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/python/pfs/utils/datamodel/ag.py b/python/pfs/utils/datamodel/ag.py index ab8dfe8..8b6db1d 100644 --- a/python/pfs/utils/datamodel/ag.py +++ b/python/pfs/utils/datamodel/ag.py @@ -1,11 +1,21 @@ +import warnings from enum import IntFlag -class AutoGuiderStarMask(IntFlag): +class SourceCatalogFlags(IntFlag): """ - Represents a bitmask for guide star properties. + Represents a bitmask for catalog guide star properties. + + This was formerly named AutoGuiderStarMask. + + See: + + https://irsa.ipac.caltech.edu/data/Gaia/dr3/gaia_dr3_source_colDescriptions.html + https://gea.esac.esa.int/archive/documentation/GDR3/Gaia_archive/chap_datamodel/sec_dm_main_source_catalogue/ssec_dm_gaia_source.html Attributes: + NONE: No properties. There shouldn't be any of these as everything is + either GAIA or HSC. GAIA: Gaia DR3 catalog. HSC: HSC PDR3 catalog. PMRA: Proper motion RA is measured. @@ -20,6 +30,8 @@ class AutoGuiderStarMask(IntFlag): PHOTO_SIG: Photometric measurement is significant (SNR>5). GALAXY: Is a galaxy candidate. """ + + NONE = 0x00000 GAIA = 0x00001 HSC = 0x00002 PMRA = 0x00004 @@ -34,22 +46,109 @@ class AutoGuiderStarMask(IntFlag): PHOTO_SIG = 0x00800 GALAXY = 0x01000 + GOOD_PROPER_MOTION = PMRA | PMRA_SIG | PMDEC | PMDEC_SIG + GOOD_PARALLAX = PARA | PARA_SIG + GOOD_ASTROMETRY = ASTROMETRIC | NON_BINARY + GOOD_PHOTOMETRY = PHOTO_SIG + + GOOD_ACQUISITION_STARS = GAIA | GOOD_PROPER_MOTION | GOOD_PARALLAX | GOOD_ASTROMETRY | GOOD_PHOTOMETRY + GOOD_GUIDING_STARS = GAIA | HSC + + BAD_ACQUISITION_STARS = GALAXY | ASTROMETRIC_SIG | HSC + BAD_GUIDING_STARS = GALAXY + + def __str__(self): + if self == SourceCatalogFlags.NONE: + return "NONE" + flags = [flag.name for flag in SourceCatalogFlags if flag in self and flag != SourceCatalogFlags.NONE] + return "|".join(flags) -class SourceDetectionFlag(IntFlag): + +class SourceDetectionFlags(IntFlag): """ Represents a bitmask for detection properties. + This was formerly named SourceDetectionFlag (singular). + Attributes: - RIGHT: Source is detected on the right side of the image. + NONE: No issues detected. + RIGHT: Source is detected on the right side of the image, which has + a piece of glass in front of the sensor. EDGE: Source is detected at the edge of the image. SATURATED: Source is saturated. BAD_SHAPE: Source has a bad shape. BAD_ELLIP: Source has a bad ellipticity. FLAT_TOP: Source has a flat top profile. + BAD_SIZE: Source has a bad size. """ + + NONE = 0x0000 RIGHT = 0x0001 EDGE = 0x0002 SATURATED = 0x0004 BAD_SHAPE = 0x0008 BAD_ELLIP = 0x0010 FLAT_TOP = 0x0020 + BAD_SIZE = 0x0040 + + GOOD_DETECTION = NONE | RIGHT + BAD_DETECTION = EDGE | SATURATED | BAD_SHAPE | BAD_ELLIP | FLAT_TOP | BAD_SIZE + + def __str__(self): + if self == SourceDetectionFlags.NONE: + return "NONE" + flags = [flag.name for flag in SourceDetectionFlags if flag in self and flag != SourceDetectionFlags.NONE] + return "|".join(flags) + + +class SourceMatchingFlags(IntFlag): + """ + Represents a bitmask for matching properties between detected and catalog sources. + + Attributes: + GOOD_MATCH: Source successfully matched with exactly one catalog entry + within tolerance. + NO_MATCH: Source has no matching catalog entry within tolerance. + BAD_RESIDUAL: Source matched but has residual position difference + larger than allowed threshold. + UNUSED_MULTI_MATCH: Source was matched to a catalog entry, but wasn't the + closest source so is unused. + """ + + GOOD_MATCH = 0x0000 + NO_MATCH = 0x0001 + BAD_RESIDUAL = 0x0002 + UNUSED_MULTI_MATCH = 0x0004 + + def __str__(self): + if self == SourceMatchingFlags.GOOD_MATCH: + return "GOOD_MATCH" + flags = [flag.name for flag in SourceMatchingFlags if flag in self and flag != SourceMatchingFlags.GOOD_MATCH] + return "|".join(flags) + + +def __getattr__(name): + if name == "AutoGuiderStarMask": + warnings.warn( + "AutoGuiderStarMask is deprecated and will be removed in a future version. " + "Please use SourceCatalogFlags instead.", + DeprecationWarning, + stacklevel=2, + ) + return SourceCatalogFlags + + if name == "SourceDetectionFlag": + warnings.warn( + "SourceDetectionFlag is deprecated and will be removed in a future version. " + "Please use SourceDetectionFlags (plural) instead.", + DeprecationWarning, + stacklevel=2, + ) + return SourceDetectionFlags + + msg = f"module {__name__!r} has no attribute {name!r}" + raise AttributeError(msg) + + +def __dir__(): + return sorted([*list(globals().keys()), "AutoGuiderStarMask", "SourceDetectionFlag"])