Coverage for python/pfs/datamodel/masks.py : 22%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
"""Helper for dealing with symbolic names for mask values
For science, we care about the symbolic name (i.e., what the mask represents; e.g., ``NO_DATA``), but this needs to be translated to the implementation (i.e., an integer) so pixels can be selected.
Parameters ---------- **kwargs : `dict` mapping `str` to `int` The mask planes. The integers should all be positive in the range 0..63. """
self.flags = kwargs assert all(ii >= 0 and ii < self._maxSize and isinstance(ii, int) for ii in kwargs.values())
"""Representation""" return "%s(%s)" % (self.__class__.__name__, self.flags)
"""Iterator""" return iter(self.flags)
"""Retrieve value for a single mask name""" return 2**self.flags[name]
"""Number of bits used""" return len(self.flags)
"""Is mask name used?""" return name in self.flags
"""Retrieve value for multiple masks""" return sum(self[name] for name in args)
"""Return a copy""" return type(self)(**self.flags)
"""Add mask name""" if name in self.flags: return self[name] if len(self) >= self._maxSize: raise RuntimeError("No bits remaining") # Find the lowest available bit existing = set(self.flags.values()) for ii in range(self._maxSize): if ii not in existing: value = ii break else: raise AssertionError("Something's broken") self.flags[name] = value return self[name]
def fromFitsHeader(cls, header): """Read from a FITS header
Parameters ---------- header : `dict` FITS header keyword-value pairs.
Returns ------- self : `MaskHelper` Constructed mask helper. """ maskPlanes = {} for key, value in header.items(): if key.startswith(cls.maskPlanePrefix) or key.startswith("HIERARCH " + cls.maskPlanePrefix): name = key[key.rfind(cls.maskPlanePrefix) + len(cls.maskPlanePrefix):] maskPlanes[name] = value continue return cls(**maskPlanes)
"""Write to a FITS header
Returns ------- header : `dict` FITS header keyword-value pairs. """ return {self.maskPlanePrefix + key: value for key, value in self.flags.items()}
def fromMerge(cls, helpers): """Construct from multiple `MaskHelper`s
There must be no discrepancies between the inputs.
Parameters ---------- helpers : iterable of `MaskHelper` `MaskHelper`s to merge.
Returns ------- self : `MaskHelper` Merged `MaskHelper`. """ maskPlanes = {} for hh in helpers: for name, value in hh.flags.items(): if name in maskPlanes: if maskPlanes[name] != value: raise RuntimeError("Cannot merge MaskHelpers due to mismatch: %s" % (name,)) else: maskPlanes[name] = value return cls(**maskPlanes)
"""Interpret a value from the mask
Breaks down the provided value into the corresponding mask plane names.
Parameters ---------- value : `int` Value to interpret.
names : `list` of `str` List of mask planes that are set in the provided value. """ return [nn for nn, vv in self.flags.items() if (value & 2**vv) != 0]
"""Return counts of each mask plane
Parameters ---------- mask : `numpy.ndarray` Mask array.
Returns ------- counts : `dict` (`str`: `int`) Counts for each mask plane. An additional result indexed by an empty string corresponds to the number of pixels with no mask plane set. """ return {",".join(self.interpret(value)): num for value, num in Counter(mask.flatten()).items()} |