diff --git a/proseco/catalog.py b/proseco/catalog.py index 007cd0ba..d7fc8cab 100644 --- a/proseco/catalog.py +++ b/proseco/catalog.py @@ -90,14 +90,22 @@ def _get_aca_catalog(**kwargs): aca.call_args = kwargs.copy() aca.set_attrs_from_kwargs(**kwargs) + # Get stars (typically from AGASC) and do not filter for stars near + # the ACA FOV. This leaves the full radial selection available for + # later roll optimization. Use aca.stars or aca.acqs.stars from here. + aca.set_stars(filter_near_fov=False) + kwargs.pop('stars', None) + # Share a common dark map for memory / processing kwargs['dark'] = aca.dark aca.log('Starting get_acq_catalog') - aca.acqs = get_acq_catalog(**kwargs) - aca.log('Starting get_fid_catalog') - aca.fids = get_fid_catalog(acqs=aca.acqs, **kwargs) + aca.acqs = get_acq_catalog(stars=aca.stars, **kwargs) + # Note that aca.acqs.stars is a filtered version of aca.stars and includes + # only stars that are in or near ACA FOV. Use this for fids and guides stars. + aca.log('Starting get_fid_catalog') + aca.fids = get_fid_catalog(stars=aca.acqs.stars, acqs=aca.acqs, **kwargs) aca.acqs.fids = aca.fids if aca.optimize: @@ -106,9 +114,8 @@ def _get_aca_catalog(**kwargs): aca.acqs.fid_set = aca.fids['id'] - stars = kwargs.pop('stars', aca.acqs.stars) aca.log('Starting get_guide_catalog') - aca.guides = get_guide_catalog(stars=stars, fids=aca.fids, **kwargs) + aca.guides = get_guide_catalog(stars=aca.acqs.stars, fids=aca.fids, **kwargs) # Make a merged starcheck-like catalog. Catch any errors at this point to avoid # impacting operational work (call from Matlab). diff --git a/proseco/characteristics.py b/proseco/characteristics.py index c8b39ea9..82c86752 100644 --- a/proseco/characteristics.py +++ b/proseco/characteristics.py @@ -2,6 +2,7 @@ 'row_max': 512.0, 'col_min': -512.0, 'col_max': 512.0, + 'fov_pad': 40.0, # Padding *outside* CCD (filtering AGASC stars in/near FOV in set_stars) 'window_pad': 7, 'row_pad': 8, 'col_pad': 1, @@ -10,8 +11,9 @@ PIX_2_ARC = 4.96289 ARC_2_PIX = 1.0 / PIX_2_ARC -max_ccd_row = 512 - 8 # Max allowed row for stars (SOURCE?) -max_ccd_col = 512 - 1 # Max allow col for stars (SOURCE?) +# Convenience characteristics +max_ccd_row = CCD['row_max'] - CCD['row_pad'] # Max allowed row for stars (SOURCE?) +max_ccd_col = CCD['col_max'] - CCD['col_pad'] # Max allow col for stars (SOURCE?) # Column spoiler rules col_spoiler_mag_diff = 4.5 diff --git a/proseco/core.py b/proseco/core.py index 44d10b5e..46f6cac7 100644 --- a/proseco/core.py +++ b/proseco/core.py @@ -532,21 +532,30 @@ def set_bad_pixels_in_dark(self): for r0, r1, c0, c1 in ACA.bad_pixels: self.dark.aca[r0:r1 + 1, c0:c1 + 1] = ACA.bad_pixel_dark_current - def set_stars(self, acqs=None): + def set_stars(self, acqs=None, filter_near_fov=True): """Set the object ``stars`` attribute to an appropriate StarsTable object. If ``acqs`` is defined that will be a previously computed AcqTable with ``stars`` already available, so use that. :param acqs: AcqTable for same observation + :param filter_near_fov: include only stars in or near ACA FOV """ if acqs is None: if self.stars is None: - self.stars = StarsTable.from_agasc(self.att, date=self.date, logger=self.log) + stars = StarsTable.from_agasc(self.att, date=self.date, logger=self.log) else: - self.stars = StarsTable.from_stars(self.att, self.stars, logger=self.log) + stars = StarsTable.from_stars(self.att, self.stars, logger=self.log) else: - self.stars = acqs.stars + stars = acqs.stars + + if filter_near_fov: + ok = ((np.abs(stars['row']) < ACA.CCD['row_max'] + ACA.CCD['fov_pad']) & + (np.abs(stars['col']) < ACA.CCD['col_max'] + ACA.CCD['fov_pad'])) + if not np.all(ok): + stars = stars[ok] + + self.stars = stars def plot(self, ax=None): """ @@ -886,9 +895,6 @@ def from_agasc(cls, att, date=None, radius=1.2, logger=None): """ Get AGASC stars in the ACA FOV. This uses the mini-AGASC, so only stars within 3-sigma of 11.5 mag. - TO DO: maybe use the full AGASC, for faint candidate acq stars with - large uncertainty. - TO DO: AGASC version selector? :param att: any Quat-compatible attitude :param date: DateTime compatible date for star proper motion (default=NOW) @@ -1006,11 +1012,6 @@ def from_stars(cls, att, stars, logger=None, copy=True): mag_err = np.sqrt(mag_aca_err ** 2 + mag_std_dev ** 2) stars.add_column(Column(mag_err, name='mag_err'), index=8) - # Filter stars in or near ACA FOV - rcmax = 512.0 + 200 / 5 # 200 arcsec padding around CCD edge - ok = (row > -rcmax) & (row < rcmax) & (col > -rcmax) & (col < rcmax) - stars = stars[ok] - logger('Finished star processing', level=1) return stars diff --git a/proseco/tests/test_catalog.py b/proseco/tests/test_catalog.py index d1461a43..42a12f07 100644 --- a/proseco/tests/test_catalog.py +++ b/proseco/tests/test_catalog.py @@ -24,6 +24,7 @@ def test_get_aca_catalog_49531(): Test of getting an ER using the mica.starcheck archive for getting the obs parameters. This tests a regression introduced in the acq-fid functionality. + """ aca = get_aca_catalog(49531, raise_exc=True) assert len(aca.acqs) == 8 @@ -64,6 +65,9 @@ def test_get_aca_catalog_20259(): """ Test obsid 20259 which has two spoiled fids: HRC-2 is yellow and HRC-4 is red. Expectation is to choose fids 1, 2, 3 (not 4). + + Also do a test that set_stars() processing is behaving as expected. + """ aca = get_aca_catalog(20259, raise_exc=True) exp = ['slot idx id type sz yang zang dim res halfw', @@ -83,6 +87,12 @@ def test_get_aca_catalog_20259(): repr(aca) # Apply default formats assert aca[TEST_COLS].pformat(max_width=-1) == exp + # Check that acqs, guides, and fids are sharing the same stars table + # but that it is different from the larger aca stars table. + assert aca.stars is not aca.acqs.stars + assert aca.fids.stars is aca.acqs.stars + assert aca.guides.stars is aca.acqs.stars + def test_exception_handling(): """