From deb4b67c7c5146dab2b207c70bb2f98d479beac8 Mon Sep 17 00:00:00 2001 From: Brett Graham Date: Mon, 24 Feb 2025 12:56:08 -0500 Subject: [PATCH] remove unused dqflag functions (#409) --- changes/409.removal.rst | 1 + src/stdatamodels/basic_utils.py | 43 -------- src/stdatamodels/dqflags.py | 104 -------------------- src/stdatamodels/jwst/datamodels/dqflags.py | 9 -- tests/test_dq.py | 43 -------- 5 files changed, 1 insertion(+), 199 deletions(-) create mode 100644 changes/409.removal.rst delete mode 100644 src/stdatamodels/basic_utils.py delete mode 100644 src/stdatamodels/dqflags.py delete mode 100644 tests/test_dq.py diff --git a/changes/409.removal.rst b/changes/409.removal.rst new file mode 100644 index 00000000..7f0b770b --- /dev/null +++ b/changes/409.removal.rst @@ -0,0 +1 @@ +Remove unused dqflags and basic_utils submodules. diff --git a/src/stdatamodels/basic_utils.py b/src/stdatamodels/basic_utils.py deleted file mode 100644 index 6106ea54..00000000 --- a/src/stdatamodels/basic_utils.py +++ /dev/null @@ -1,43 +0,0 @@ -import re - - -__all__ = ["multiple_replace"] - - -def multiple_replace(string, rep_dict): - """Single-pass replacement of multiple substrings - - Similar to `str.replace`, except that a dictionary of replacements - can be specified. - - The replacements are done in a single-pass. This means that a previous - replacement will not be replaced by a subsequent match. - - Parameters - ---------- - string: str - The source string to have replacements done on it. - - rep_dict: dict - The replacements were key is the input substring and - value is the replacement - - Returns - ------- - replaced: str - New string with the replacements done - - Examples - -------- - Basic example that also demonstrates the single-pass nature. - If the replacements where chained, the result would have been - 'lamb lamb' - - >>> multiple_replace("button mutton", {"but": "mut", "mutton": "lamb"}) - 'mutton lamb' - - """ - pattern = re.compile( - "|".join([re.escape(k) for k in sorted(rep_dict, key=len, reverse=True)]), flags=re.DOTALL - ) - return pattern.sub(lambda x: rep_dict[x.group(0)], string) diff --git a/src/stdatamodels/dqflags.py b/src/stdatamodels/dqflags.py deleted file mode 100644 index 7377560a..00000000 --- a/src/stdatamodels/dqflags.py +++ /dev/null @@ -1,104 +0,0 @@ -""" -Implementation --------------- - -The flags are implemented as "bit flags": Each flag is assigned a bit position -in a byte, or multi-byte word, of memory. If that bit is set, the flag assigned -to that bit is interpreted as being set or active. - -The data structure that stores bit flags is just the standard Python `int`, -which provides 32 bits. Bits of an integer are most easily referred to using -the formula `2**bit_number` where `bit_number` is the 0-index bit of interest. -""" - -from astropy.nddata.bitmask import interpret_bit_flags as ap_interpret_bit_flags -from stdatamodels.basic_utils import multiple_replace - - -def interpret_bit_flags(bit_flags, flip_bits=None, mnemonic_map=None): - """Converts input bit flags to a single integer value (bit mask) or `None`. - - Wraps `astropy.nddate.bitmask.interpret_bit_flags`, allowing the - bit mnemonics to be used in place of integers. - - Parameters - ---------- - bit_flags : int, str, list, None - See `astropy.nddate.bitmask.interpret_bit_flags`. - Also allows strings using Roman mnemonics - - flip_bits : bool, None - See `astropy.nddata.bitmask.interpret_bit_flags`. - - mnemonic_map : {str: int[,...]} - Dictionary associating the mnemonic string to an integer value - representing the set bit for that mnemonic. - - Returns - ------- - bitmask : int or None - Returns an integer bit mask formed from the input bit value or `None` - if input ``bit_flags`` parameter is `None` or an empty string. - If input string value was prepended with '~' (or ``flip_bits`` was set - to `True`), then returned value will have its bits flipped - (inverse mask). - """ - if mnemonic_map is None: - raise TypeError("`mnemonic_map` is a required argument") - bit_flags_dm = bit_flags - if isinstance(bit_flags, str): - dm_flags = {key: str(val) for key, val in mnemonic_map.items()} - bit_flags_dm = multiple_replace(bit_flags, dm_flags) - - return ap_interpret_bit_flags(bit_flags_dm, flip_bits=flip_bits) - - -def dqflags_to_mnemonics(dqflags, mnemonic_map): - """Interpret value as bit flags and return the mnemonics - - Parameters - ---------- - dqflags : int-like - The value to interpret as DQ flags - - mnemonic_map: {str: int[,...]} - Dictionary associating the mnemonic string to an integer value - representing the set bit for that mnemonic. - - Returns - ------- - mnemonics : {str[,...]} - Set of mnemonics represented by the set bit flags - - Examples - -------- - >>> pixel = { - ... "GOOD": 0, # No bits set, all is good - ... "DO_NOT_USE": 2**0, # Bad pixel. Do not use - ... "SATURATED": 2**1, # Pixel saturated during exposure - ... "JUMP_DET": 2**2, # Jump detected during exposure - ... } - - >>> group = { - ... "GOOD": pixel["GOOD"], - ... "DO_NOT_USE": pixel["DO_NOT_USE"], - ... "SATURATED": pixel["SATURATED"], - ... } - - >>> dqflags_to_mnemonics(1, pixel) - {'DO_NOT_USE'} - - >>> dqflags_to_mnemonics(7, pixel) # doctest: +SKIP - {'JUMP_DET', 'DO_NOT_USE', 'SATURATED'} - - >>> dqflags_to_mnemonics(7, pixel) == {"JUMP_DET", "DO_NOT_USE", "SATURATED"} - True - - >>> dqflags_to_mnemonics(1, mnemonic_map=pixel) - {'DO_NOT_USE'} - - >>> dqflags_to_mnemonics(1, mnemonic_map=group) - {'DO_NOT_USE'} - """ - mnemonics = {mnemonic for mnemonic, value in mnemonic_map.items() if (dqflags & value)} - return mnemonics diff --git a/src/stdatamodels/jwst/datamodels/dqflags.py b/src/stdatamodels/jwst/datamodels/dqflags.py index a0559101..5ff74abe 100644 --- a/src/stdatamodels/jwst/datamodels/dqflags.py +++ b/src/stdatamodels/jwst/datamodels/dqflags.py @@ -17,11 +17,6 @@ the formula `2**bit_number` where `bit_number` is the 0-index bit of interest. """ -# These imports are here for backwards compatibility -from astropy.nddata.bitmask import interpret_bit_flags as ap_interpret_bit_flags -from stdatamodels.dqflags import interpret_bit_flags, dqflags_to_mnemonics -from stdatamodels.basic_utils import multiple_replace - # Pixel-specific flags pixel = { "GOOD": 0, # No bits set, all is good @@ -73,10 +68,6 @@ } __all__ = [ - "ap_interpret_bit_flags", - "interpret_bit_flags", - "dqflags_to_mnemonics", - "multiple_replace", "pixel", "group", ] diff --git a/tests/test_dq.py b/tests/test_dq.py deleted file mode 100644 index 1793034f..00000000 --- a/tests/test_dq.py +++ /dev/null @@ -1,43 +0,0 @@ -from stdatamodels import dqflags - -PIXEL = { - "GOOD": 0, # No bits set, all is good - "DO_NOT_USE": 2**0, # Bad pixel. Do not use. - "SATURATED": 2**1, # Pixel saturated during exposure - "JUMP_DET": 2**2, # Jump detected during exposure - "DROPOUT": 2**3, # Data lost in transmission - "OUTLIER": 2**4, # Flagged by outlier detection (was RESERVED_1) - "PERSISTENCE": 2**5, # High persistence (was RESERVED_2) - "AD_FLOOR": 2**6, # Below A/D floor (0 DN, was RESERVED_3) - "RESERVED_4": 2**7, # - "UNRELIABLE_ERROR": 2**8, # Uncertainty exceeds quoted error - "NON_SCIENCE": 2**9, # Pixel not on science portion of detector - "DEAD": 2**10, # Dead pixel - "HOT": 2**11, # Hot pixel - "WARM": 2**12, # Warm pixel - "LOW_QE": 2**13, # Low quantum efficiency - "RC": 2**14, # RC pixel - "TELEGRAPH": 2**15, # Telegraph pixel - "NONLINEAR": 2**16, # Pixel highly nonlinear - "BAD_REF_PIXEL": 2**17, # Reference pixel cannot be used - "NO_FLAT_FIELD": 2**18, # Flat field cannot be measured - "NO_GAIN_VALUE": 2**19, # Gain cannot be measured - "NO_LIN_CORR": 2**20, # Linearity correction not available - "NO_SAT_CHECK": 2**21, # Saturation check not available - "UNRELIABLE_BIAS": 2**22, # Bias variance large - "UNRELIABLE_DARK": 2**23, # Dark variance large - "UNRELIABLE_SLOPE": 2**24, # Slope variance large (i.e., noisy pixel) - "UNRELIABLE_FLAT": 2**25, # Flat variance large - "OPEN": 2**26, # Open pixel (counts move to adjacent pixels) - "ADJ_OPEN": 2**27, # Adjacent to open pixel - "UNRELIABLE_RESET": 2**28, # Sensitive to reset anomaly - "MSA_FAILED_OPEN": 2**29, # Pixel sees light from failed-open shutter - "OTHER_BAD_PIXEL": 2**30, # A catch-all flag - "REFERENCE_PIXEL": 2**31, # Pixel is a reference pixel -} - - -def test_dqflags(): - assert dqflags.dqflags_to_mnemonics(1, PIXEL) == {"DO_NOT_USE"} - assert dqflags.dqflags_to_mnemonics(7, PIXEL) == {"JUMP_DET", "DO_NOT_USE", "SATURATED"} - assert dqflags.interpret_bit_flags("DO_NOT_USE + WARM", mnemonic_map=PIXEL) == 4097