From 5b49c08db137ce751ef8b2518fbd79ce44a8e37a Mon Sep 17 00:00:00 2001 From: Melanie Clarke Date: Tue, 17 Sep 2024 09:54:23 -0400 Subject: [PATCH] JP-3551: Exclude overlapping background candidates (#8744) Co-authored-by: Tyler Pauly --- CHANGES.rst | 4 + jwst/associations/lib/rules_level2_base.py | 261 +++++++++++------- .../tests/data/pool_024b_nirspec_fss_nods.csv | 20 ++ .../tests/data/pool_024c_nirspec_fss_nods.csv | 50 ++++ .../tests/test_level2_background.py | 41 +++ jwst/regtest/test_associations_sdp_pools.py | 5 + 6 files changed, 286 insertions(+), 95 deletions(-) create mode 100755 jwst/associations/tests/data/pool_024b_nirspec_fss_nods.csv create mode 100755 jwst/associations/tests/data/pool_024c_nirspec_fss_nods.csv diff --git a/CHANGES.rst b/CHANGES.rst index 51fdfe145b..d40d6fa86b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -36,6 +36,10 @@ associations - Remove ``MultilineLogger`` and no longer set it as the default logger. [#8781] +- Excluded nearby background candidates from NIRSpec fixed slit associations + for S1600A1 with 5 point dithers, to reduce overlap between background nods + and science exposure. [#8744] + badpix_selfcal -------------- diff --git a/jwst/associations/lib/rules_level2_base.py b/jwst/associations/lib/rules_level2_base.py index def32a8f2a..a152e1048b 100644 --- a/jwst/associations/lib/rules_level2_base.py +++ b/jwst/associations/lib/rules_level2_base.py @@ -26,7 +26,7 @@ IMAGE2_NONSCIENCE_EXP_TYPES, IMAGE2_SCIENCE_EXP_TYPES, PRODUCT_NAME_DEFAULT, - SPEC2_SCIENCE_EXP_TYPES, + SPEC2_SCIENCE_EXP_TYPES ) from jwst.associations.lib.member import Member from jwst.associations.lib.process_list import ListCategory @@ -391,98 +391,6 @@ def validate_candidates(self, member): # fail. return False - def make_nod_asns(self): - """Make background nod Associations - - For observing modes, such as NIRSpec MSA, exposures can be - nodded, such that the object is in a different position in the - slitlet. The association creation simply groups these all - together as a single association, all exposures marked as - `science`. When complete, this method will create separate - associations each exposure becoming the single science - exposure, and the other exposures then become `background`. - - Returns - ------- - associations : [association[, ...]] - List of new associations to be used in place of - the current one. - - """ - - for product in self['products']: - members = product['members'] - - # Split out the science vs. non-science - # The non-science exposures will get attached - # to every resulting association. - science_exps = [ - member - for member in members - if member['exptype'] == 'science' - ] - nonscience_exps = [ - member - for member in members - if member['exptype'] != 'science' - ] - - # Create new associations for each science, using - # the other science as background. - results = [] - for science_exp in science_exps: - asn = copy.deepcopy(self) - asn.data['products'] = None - - product_name = remove_suffix( - splitext(split(science_exp['expname'])[1])[0] - )[0] - asn.new_product(product_name) - new_members = asn.current_product['members'] - new_members.append(science_exp) - - for other_science in science_exps: - if other_science['expname'] != science_exp['expname']: - if science_exp.item['exp_type'] in ['nrs_fixedslit', 'nrs_msaspec']: - try: - sci_prim_dithpt = (int(science_exp.item['patt_num']) - 1) // \ - int(science_exp.item['subpxpts']) - other_prim_dithpt = (int(other_science.item['patt_num']) - 1) // \ - int(other_science.item['subpxpts']) - if sci_prim_dithpt != other_prim_dithpt: - now_background = Member(other_science) - now_background['exptype'] = 'background' - new_members.append(now_background) - # Catch missing values with KeyError, NULL values with ValueError - except (ValueError, KeyError): - try: - sci_prim_dithpt = (int(science_exp.item['patt_num']) - 1) // \ - int(science_exp.item['subpxpns']) - other_prim_dithpt = (int(other_science.item['patt_num']) - 1) // \ - int(other_science.item['subpxpns']) - if sci_prim_dithpt != other_prim_dithpt: - now_background = Member(other_science) - now_background['exptype'] = 'background' - new_members.append(now_background) - except (ValueError, KeyError, ZeroDivisionError): - if science_exp.item['exp_type'] == 'nrs_msaspec': - now_background = Member(other_science) - now_background['exptype'] = 'background' - new_members.append(now_background) - else: - pass - else: - now_background = Member(other_science) - now_background['exptype'] = 'background' - new_members.append(now_background) - - new_members += nonscience_exps - - if asn.is_valid: - results.append(asn) - - return results - def __repr__(self): try: file_name, json_repr = self.ioregistry['json'].dump(self) @@ -1060,7 +968,7 @@ def _init_hook(self, item): class AsnMixin_Lv2Nod: """Associations that need to create nodding associations - For some spectragraphic modes, background spectra are taken by + For some spectrographic modes, background spectra are taken by nodding between different slits, or internal slit positions. The main associations rules will collect all the exposures of all the nods into a single association. Then, on finalization, this one association @@ -1068,10 +976,173 @@ class AsnMixin_Lv2Nod: as science, and the other nods are treated as background. """ + @staticmethod + def nod_background_overlap(science_item, background_item): + """ + Check that a candidate background nod will not overlap with science. + + For NIRSpec fixed slit or MOS data, this returns True if the + background candidate shares a primary dither point with the + science. + + In addition, for NIRSpec fixed slit exposures taken with slit + S1600A1 in a 5-point nod pattern, this returns True when the + background candidate is in the next closest primary position + to the science. + + For any other data, this function returns False (no overlap). + """ + # Get exp_type, needed for any data: + # if not present, return False + try: + exptype = str(science_item['exp_type']).lower() + except KeyError: + return False + + # Return False for any non-FS or MOS data + if exptype not in ['nrs_fixedslit', 'nrs_msaspec']: + return False + + # Get pattern number values, needed for FS or MOS + try: + numdthpt = int(science_item['numdthpt']) + patt_num = int(science_item['patt_num']) + bkg_num = int(background_item['patt_num']) + except (KeyError, ValueError): + numdthpt = 0 + patt_num = None + bkg_num = None + + # Get subpxpts (or old alternate 'subpxpns') + try: + subpx = int(science_item['subpxpts']) + except (KeyError, ValueError): + try: + subpx = int(science_item['subpxpns']) + except (KeyError, ValueError): + subpx = None + try: + bkg_subpx = int(background_item['subpxpts']) + except (KeyError, ValueError): + try: + bkg_subpx = int(background_item['subpxpns']) + except (KeyError, ValueError): + bkg_subpx = None + + # If values not found, return False for MOS, True for FS + if (None in [patt_num, bkg_num, subpx, bkg_subpx] + or subpx == 0 or bkg_subpx == 0): + if exptype == 'nrs_fixedslit': + # These values are required for background + # candidates for FS: report an overlap. + return True + else: + # For MOS, it's okay to go ahead and use them. + # Report no overlap. + return False + + # Check for primary point overlap + sci_prim_dithpt = (patt_num - 1) // subpx + bkg_prim_dithpt = (bkg_num - 1) // bkg_subpx + if sci_prim_dithpt == bkg_prim_dithpt: + # Primary points are the same - overlap is present + return True + + # Primary points are not the same - + # no further check needed for MOS + if exptype == 'nrs_msaspec': + return False + + # Get slit name, needed only for FS S1600A1 check + try: + slit = str(science_item['fxd_slit']).lower() + except KeyError: + slit = None + + # Background is currently only expected to overlap severely for + # 5 point dithers with fixed slit S1600A1. Only the nearest + # dithers to the science observation need to be excluded. + if (exptype == 'nrs_fixedslit' + and slit == 's1600a1' + and numdthpt // subpx == 5 + and abs(sci_prim_dithpt - bkg_prim_dithpt) <= 1): + return True + + # For anything else, return False + return False + + def make_nod_asns(self): + """Make background nod Associations + + For observing modes, such as NIRSpec MSA, exposures can be + nodded, such that the object is in a different position in the + slitlet. The association creation simply groups these all + together as a single association, all exposures marked as + `science`. When complete, this method will create separate + associations each exposure becoming the single science + exposure, and the other exposures then become `background`. + + Returns + ------- + associations : [association[, ...]] + List of new associations to be used in place of + the current one. + + """ + + for product in self['products']: + members = product['members'] + + # Split out the science vs. non-science + # The non-science exposures will get attached + # to every resulting association. + science_exps = [ + member + for member in members + if member['exptype'] == 'science' + ] + nonscience_exps = [ + member + for member in members + if member['exptype'] != 'science' + ] + + # Create new associations for each science, using + # the other science as background. + results = [] + for science_exp in science_exps: + asn = copy.deepcopy(self) + asn.data['products'] = None + + product_name = remove_suffix( + splitext(split(science_exp['expname'])[1])[0] + )[0] + asn.new_product(product_name) + new_members = asn.current_product['members'] + new_members.append(science_exp) + + for other_science in science_exps: + if other_science['expname'] != science_exp['expname']: + # check for likely overlap between science + # and background candidate + overlap = self.nod_background_overlap( + science_exp.item, other_science.item) + if not overlap: + now_background = Member(other_science) + now_background['exptype'] = 'background' + new_members.append(now_background) + + new_members += nonscience_exps + + if asn.is_valid: + results.append(asn) + + return results + def finalize(self): """Finalize association - For some spectragraphic modes, background spectra and taken by + For some spectrographic modes, background spectra are taken by nodding between different slits, or internal slit positions. The main associations rules will collect all the exposures of all the nods into a single association. Then, on finalization, this one association diff --git a/jwst/associations/tests/data/pool_024b_nirspec_fss_nods.csv b/jwst/associations/tests/data/pool_024b_nirspec_fss_nods.csv new file mode 100755 index 0000000000..805a66a98a --- /dev/null +++ b/jwst/associations/tests/data/pool_024b_nirspec_fss_nods.csv @@ -0,0 +1,20 @@ +# NIRSpec Fixed-slit with various nods and dithers +# +# This example contains a 5 point dither for S1600A1, no subpixel dither +# +FILENAME|OBS_ID|PROGRAM|OBS_NUM|VISIT|VISIT_ID|VISITGRP|VISITYPE|SEQ_ID|ACT_ID|EXPOSURE|EXP_TYPE|NEXPOSUR|EXPCOUNT|INSTRUME|DETECTOR|CHANNEL|TARGETID|TARGPROP|TARGNAME|TARGTYPE|TEMPLATE|PNTGTYPE|PNTG_SEQ|TARGORDN|EXPSPCIN|DITHPTIN|MOSTILNO|MODULE|FILTER|PUPIL|DITHERID|PATTTYPE|PATTSTRT|NUMDTHPT|PATTSIZE|SUBPXPNS|PATT_NUM|SUBPXNUM|SUBPIXEL|APERNAME|SDP_VER|SUBARRAY|GRATING|FXD_SLIT|BAND|GWA_XTIL|GWA_YTIL|ASN_CANDIDATE|EXPOSERR|IS_PSF|IS_IMPRT|BKGDTARG|TSOVISIT|MSAMETFL|SPAT_NUM|SPEC_NUM +# +# Initialize ACID. This is done with a dummy exposure that will not match any association +set acid|OBS_ID|PROGRAM|OBS_NUM|VISIT|VISIT_ID|VISITGRP|VISITYPE|SEQ_ID|ACT_ID|EXPOSURE|EXP_TYPE|NEXPOSUR|EXPCOUNT|INSTRUME|DETECTOR|CHANNEL|TARGETID|TARGPROP|TARGNAME|TARGTYPE|TEMPLATE|PNTGTYPE|PNTG_SEQ|TARGORDN|EXPSPCIN|DITHPTIN|MOSTILNO|MODULE|FILTER|PUPIL|DITHERID|PATTTYPE|PATTSTRT|NUMDTHPT|PATTSIZE|SUBPXPNS|PATT_NUM|SUBPXNUM|SUBPIXEL|APERNAME|SDP_VER|SUBARRAY|GRATING|FXD_SLIT|BAND|GWA_XTIL|GWA_YTIL|@!next(acid)|EXPOSERR|IS_PSF|IS_IMPRT|BKGDTARG|TSOVISIT|MSAMETFL|SPAT_NUM|SPEC_NUM +# +# Primary Dither=5, Sub-pixel Pattern=None, F290LP/G395H/S1600A1 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!next(obsnum)|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|5|NULL|1|1|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|1|NULL +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|5|NULL|1|1|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|1|NULL +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|5|NULL|1|2|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|NULL +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|5|NULL|1|2|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|NULL +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|5|NULL|1|3|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|NULL +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|5|NULL|1|3|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|NULL +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|5|NULL|1|4|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|NULL +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|5|NULL|1|4|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|NULL +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|5|NULL|1|5|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|NULL +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|5|NULL|1|5|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|NULL diff --git a/jwst/associations/tests/data/pool_024c_nirspec_fss_nods.csv b/jwst/associations/tests/data/pool_024c_nirspec_fss_nods.csv new file mode 100755 index 0000000000..67dfcb8cd5 --- /dev/null +++ b/jwst/associations/tests/data/pool_024c_nirspec_fss_nods.csv @@ -0,0 +1,50 @@ +# NIRSpec Fixed-slit with various nods and dithers +# +# This example contains a 5 point dither for S1600A1, subpixel pattern both +# +FILENAME|OBS_ID|PROGRAM|OBS_NUM|VISIT|VISIT_ID|VISITGRP|VISITYPE|SEQ_ID|ACT_ID|EXPOSURE|EXP_TYPE|NEXPOSUR|EXPCOUNT|INSTRUME|DETECTOR|CHANNEL|TARGETID|TARGPROP|TARGNAME|TARGTYPE|TEMPLATE|PNTGTYPE|PNTG_SEQ|TARGORDN|EXPSPCIN|DITHPTIN|MOSTILNO|MODULE|FILTER|PUPIL|DITHERID|PATTTYPE|PATTSTRT|NUMDTHPT|PATTSIZE|SUBPXPNS|PATT_NUM|SUBPXNUM|SUBPIXEL|APERNAME|SDP_VER|SUBARRAY|GRATING|FXD_SLIT|BAND|GWA_XTIL|GWA_YTIL|ASN_CANDIDATE|EXPOSERR|IS_PSF|IS_IMPRT|BKGDTARG|TSOVISIT|MSAMETFL|SPAT_NUM|SPEC_NUM +# +# Initialize ACID. This is done with a dummy exposure that will not match any association +set acid|OBS_ID|PROGRAM|OBS_NUM|VISIT|VISIT_ID|VISITGRP|VISITYPE|SEQ_ID|ACT_ID|EXPOSURE|EXP_TYPE|NEXPOSUR|EXPCOUNT|INSTRUME|DETECTOR|CHANNEL|TARGETID|TARGPROP|TARGNAME|TARGTYPE|TEMPLATE|PNTGTYPE|PNTG_SEQ|TARGORDN|EXPSPCIN|DITHPTIN|MOSTILNO|MODULE|FILTER|PUPIL|DITHERID|PATTTYPE|PATTSTRT|NUMDTHPT|PATTSIZE|SUBPXPNS|PATT_NUM|SUBPXNUM|SUBPIXEL|APERNAME|SDP_VER|SUBARRAY|GRATING|FXD_SLIT|BAND|GWA_XTIL|GWA_YTIL|@!next(acid)|EXPOSERR|IS_PSF|IS_IMPRT|BKGDTARG|TSOVISIT|MSAMETFL|SPAT_NUM|SPEC_NUM +# +# Primary Dither=5, Sub-pixel Pattern=Both, F290LP/G395H/S1600A1 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!next(obsnum)|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|1|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|1|1 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|1|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|1|1 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|2|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|1|2 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|2|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|1|2 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|3|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|1|3 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|3|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|1|3 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|4|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|1|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|4|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|1|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|5|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|1 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|5|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|1 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|6|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|2 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|6|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|2 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|7|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|3 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|7|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|3 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|8|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|8|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|9|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|9|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|10|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|10|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|11|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|11|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|12|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|12|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|13|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|13|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|14|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|14|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|15|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|15|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|16|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|16|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|17|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|17|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|18|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|18|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|19|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|19|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS1|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|20|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 +@!fmt_fname(next(expnum))|V93125002001P0000000002106|93125|@!obsnum.value|1|93125002001|2|PRIME_TARGETED_FIXED|1|06|1|NRS_FIXEDSLIT|6|6|NIRSPEC|NRS2|NULL|1|TARGET-OBSERVATION-2|NULL|FIXED|NIRSpec Fixed-slit Spectroscopy|SCIENCE|6|1|1|1|1|NULL|F290LP|NULL|NULL|NULL|NULL|20|NULL|4|20|NULL|NULL|S200A1|2017_1|SUB200A1|G395H|S1600A1|NULL|0.2866025270000001|0.17855911|@!fmt_cand([(obsnum.value, 'OBSERVATION')])|NULL|NULL|F|F|F|F|2|4 diff --git a/jwst/associations/tests/test_level2_background.py b/jwst/associations/tests/test_level2_background.py index 4af3eb8685..8fb7ed2e1c 100644 --- a/jwst/associations/tests/test_level2_background.py +++ b/jwst/associations/tests/test_level2_background.py @@ -1,4 +1,6 @@ """Test Level2 background nods""" +import pytest + from jwst.associations.tests.helpers import ( combine_pools, registry_level2_only, @@ -15,6 +17,7 @@ '4': 4, # Both, 4-to-1 exposure count } + def test_nrs_msa_nod(): pool = combine_pools(t_path('data/pool_023_nirspec_msa_3nod.csv')) all_candidates = constrain_on_candidates(None) @@ -81,3 +84,41 @@ def test_nrs_fixedslit_nod_chop(): if asn['asn_id'].startswith('c'): nods += 1 assert len(asn['products'][0]['members']) == nods + + +@pytest.mark.parametrize('pool_name,n_asn', + [('pool_024b_nirspec_fss_nods', 10), + ('pool_024c_nirspec_fss_nods', 40)]) +def test_nrs_fixedslit_5point(pool_name, n_asn): + """Test NIRSpec Fixed-slit background nod S1600A1 5 point + subpixel""" + pool = combine_pools(t_path(f'data/{pool_name}.csv')) + constraint_all_candidates = constrain_on_candidates(None) + asns = generate(pool, registry_level2_only( + global_constraints=constraint_all_candidates) + ) + assert len(asns) == n_asn + for asn in asns: + n_dithers = int(asn.constraints['nods'].value) + n_spectral_dithers = int(asn.constraints['subpxpts'].value) + + sci_expnames = [] + for member in asn['products'][0]['members']: + if member['exptype'] == 'science': + sci_expnames.append(member['expname']) + assert len(sci_expnames) == 1 + + # Expect self + all exposures not at the same primary dither. + # Also expect nearest 2 dithers to be excluded, + # or 1 if it's the first or last primary dither. + first_last_files = list(range(1, n_spectral_dithers * 2 + 1)) + first_last_files += list(range(n_asn, + n_asn - n_spectral_dithers * 2, -1)) + first_last = [f'jw_000{i:02d}_rate.fits' for i in first_last_files] + + if sci_expnames[0] in first_last: + n_extra = 1 + else: + n_extra = 2 + n_members = n_dithers - (1 + n_extra) * n_spectral_dithers + 1 + + assert len(asn['products'][0]['members']) == n_members diff --git a/jwst/regtest/test_associations_sdp_pools.py b/jwst/regtest/test_associations_sdp_pools.py index 4444e40a3b..3c63554fda 100644 --- a/jwst/regtest/test_associations_sdp_pools.py +++ b/jwst/regtest/test_associations_sdp_pools.py @@ -132,6 +132,11 @@ 'xfail': None, 'slow': False, }, + 'jw01678_20240721t195707_pool': { + 'args': [], + 'xfail': None, + 'slow': False, + }, 'jw02064_20230302t112350_pool': { 'args': [], 'xfail': None,