|
1 | 1 | import os |
2 | 2 | import shutil |
3 | | -import pytest |
| 3 | +import numpy as np |
| 4 | +from astropy.io import fits |
4 | 5 |
|
5 | 6 | from stsci.tools import teal |
6 | 7 | from stwcs import updatewcs |
7 | | -from drizzlepac import astrodrizzle, tweakreg |
| 8 | +from stwcs.wcsutil import HSTWCS, altwcs |
| 9 | +from drizzlepac import astrodrizzle, tweakback, tweakreg |
8 | 10 | from drizzlepac import pixtopix, pixtosky, skytopix |
9 | 11 |
|
10 | 12 | from ..resources import BaseACS |
11 | 13 |
|
12 | 14 |
|
13 | 15 | class TestAcsTweak(BaseACS): |
14 | 16 |
|
15 | | - #@pytest.mark.xfail |
16 | 17 | def test_tweak(self): |
17 | 18 | """ This test confirms that image alignment performed by tweakreg |
18 | 19 | works to find the correct alignment solution and that the solution |
@@ -78,8 +79,79 @@ def test_tweak(self): |
78 | 79 | for i in range(1,5): |
79 | 80 | self.ignore_keywords += ['D00{}DATA'.format(i), 'D00{}MASK'.format(i)] |
80 | 81 | self.compare_outputs(outputs) |
| 82 | + |
| 83 | + |
| 84 | + def test_tweakback(self): |
| 85 | + """Verify tweakback propagates WCS shifts back to the FLT inputs.""" |
| 86 | + |
| 87 | + # Prepare input files and track their original WCS coordinates. |
| 88 | + input_files = [ |
| 89 | + self.get_input_file('input', 'j94f05bgq_flt.fits'), |
| 90 | + self.get_input_file('input', 'j9irw1rqq_flt.fits') |
| 91 | + ] |
| 92 | + tracked_pixels = {} |
| 93 | + original_world = {} |
| 94 | + original_primary_names = {} |
| 95 | + for fname in input_files: |
| 96 | + tracked_pixels[fname] = {} |
| 97 | + original_world[fname] = {} |
| 98 | + original_primary_names[fname] = {} |
| 99 | + for chip in (1, 2): |
| 100 | + wcs_obj = HSTWCS(fname, ext=('SCI', chip)) |
| 101 | + pixel = np.array([[wcs_obj.naxis1 / 2.0, wcs_obj.naxis2 / 2.0]]) |
| 102 | + tracked_pixels[fname][chip] = pixel |
| 103 | + original_world[fname][chip] = wcs_obj.all_pix2world(pixel, 1)[0] |
| 104 | + original_primary_names[fname][chip] = wcs_obj.wcs.name.strip().upper() |
| 105 | + |
| 106 | + # Set up a drizzled image containing both the original and tweaked WCS. |
| 107 | + drz_source = self.get_data('truth', 'reference_tweak.fits') |
| 108 | + drz_file = 'tweakback_input_drz.fits' |
| 109 | + shutil.copyfile(drz_source, drz_file) |
| 110 | + altwcs.archive_wcs(drz_file, ('SCI', 1), wcskey='A', wcsname='ORIG_WCS') |
| 111 | + with fits.open(drz_file, mode='update') as hdul: |
| 112 | + hdr = hdul[('SCI', 1)].header |
| 113 | + hdr['CRVAL1'] += 2.5e-5 |
| 114 | + hdr['CRVAL2'] -= 1.7e-5 |
| 115 | + hdr['WCSNAME'] = 'TWBK_TWEAK' |
| 116 | + hdul.flush() |
| 117 | + |
| 118 | + # Measure the sky shift encoded between the archived and tweaked WCS. |
| 119 | + drz_original_wcs = HSTWCS(drz_file, ext=('SCI', 1), wcskey='A') |
| 120 | + drz_updated_wcs = HSTWCS(drz_file, ext=('SCI', 1)) |
| 121 | + drz_pixel = np.array([[drz_updated_wcs.naxis1 / 2.0, drz_updated_wcs.naxis2 / 2.0]]) |
| 122 | + original_world_coord = drz_original_wcs.all_pix2world(drz_pixel, 1)[0] |
| 123 | + updated_world_coord = drz_updated_wcs.all_pix2world(drz_pixel, 1)[0] |
| 124 | + expected_shift = np.asarray(updated_world_coord) - np.asarray(original_world_coord) |
| 125 | + assert np.linalg.norm(expected_shift) > 0.0 # shift is not nothing |
| 126 | + |
| 127 | + # Apply tweakback to transfer the computed shift back onto the FLT files. |
| 128 | + tweakback.apply_tweak( |
| 129 | + f"{drz_file}[sci,1]", |
| 130 | + orig_wcs_name='ORIG_WCS', |
| 131 | + input_files=','.join(input_files), |
| 132 | + output_wcs_name='TWBK_APPLIED' |
| 133 | + ) |
| 134 | + |
| 135 | + # Confirm the propagated solution updates each chip consistently. |
| 136 | + for fname in input_files: |
| 137 | + with fits.open(fname) as hdul: |
| 138 | + for chip in (1, 2): |
| 139 | + wcs_new = HSTWCS(hdul, ext=('SCI', chip)) |
| 140 | + world_new = wcs_new.all_pix2world(tracked_pixels[fname][chip], 1)[0] |
| 141 | + world_old = original_world[fname][chip] |
| 142 | + applied_shift = np.asarray(world_new) - np.asarray(world_old) |
| 143 | + assert np.allclose(applied_shift, expected_shift, atol=5e-6) |
| 144 | + assert wcs_new.wcs.name.strip().upper() == 'TWBK_APPLIED' |
| 145 | + alt_names = [ |
| 146 | + name.strip().upper() |
| 147 | + for name in altwcs.wcsnames(hdul, ext=('SCI', chip), include_primary=False).values() |
| 148 | + ] |
| 149 | + assert any( |
| 150 | + stored.startswith(original_primary_names[fname][chip]) |
| 151 | + for stored in alt_names |
| 152 | + ) |
| 153 | + |
81 | 154 |
|
82 | | - #@pytest.mark.xfail |
83 | 155 | def test_pixsky1(self): |
84 | 156 | """This test verifies that the coordinate transformation tasks |
85 | 157 | 'pixtopix', 'pixtosky', and 'skytopix' still work as expected. |
|
0 commit comments