def test_build_fit_matrix_identity(): i = np.identity(2) r = linearfit.build_fit_matrix(0) # also test that default scale value = 1 assert np.allclose(i, r, rtol=0, atol=_ATOL) r = linearfit.build_fit_matrix((0, 0), (1, 1)) assert np.allclose(i, r, rtol=0, atol=_ATOL)
def test_align_wcs_refcat_from_imcat(mock_fits_wcs, enforce): shift = (12, -34) rot = (15, 17) scale = (1.0123, 0.9876) crpix = mock_fits_wcs.wcs.crpix - 1 xy = 1024 * np.random.random((100, 2)) m = build_fit_matrix(rot, scale) xyr = np.dot(xy - crpix, m) + crpix + shift imcat = Table(xy, names=('x', 'y')) refcat = Table(xyr, names=('x', 'y')) tpwcs1 = FITSWCS(mock_fits_wcs, meta={'catalog': imcat}) tpwcs2 = copy.deepcopy(tpwcs1) reftpwcs = FITSWCS(mock_fits_wcs, meta={'catalog': refcat}) input_catalogs = [reftpwcs, tpwcs1, tpwcs2] status = align_wcs( input_catalogs, refcat=None, fitgeom='general', match=None, enforce_user_order=enforce, expand_refcat=True ) assert status for cat in input_catalogs: if cat.meta['fit_info']['status'] == 'REFERENCE': if enforce: assert cat is reftpwcs continue assert cat.meta['fit_info']['status'] == 'SUCCESS'
def test_align_wcs_simple_ref_image_general(shift, rot, scale, fitgeom, weighted, mock_fits_wcs): xy = 1024 * np.random.random((100, 2)) if weighted: w = np.ones((100, 1)) xy = np.hstack((xy, w)) names = ('x', 'y', 'weight') else: names = ('x', 'y') m = build_fit_matrix(rot, scale) xyr = np.dot(xy[:, :2], m.T) + shift imcat = Table(xy, names=names) radec = mock_fits_wcs.wcs_pix2world(xyr, 0) if weighted: radec = np.hstack((radec, w)) names = ('RA', 'DEC', 'weight') else: names = ('RA', 'DEC') refcat = Table(radec, names=names) tpwcs = FITSWCS(mock_fits_wcs, meta={'catalog': imcat}) status = align_wcs(tpwcs, refcat, fitgeom=fitgeom, match=None) assert status assert tpwcs.meta['fit_info']['status'] == 'SUCCESS' assert tpwcs.meta['fit_info']['fitgeom'] == fitgeom assert np.allclose(tpwcs.meta['fit_info']['shift'], shift) assert np.allclose(tpwcs.meta['fit_info']['matrix'], m) assert np.allclose(tpwcs.meta['fit_info']['rot'], rot) assert tpwcs.meta['fit_info']['proper'] assert np.allclose(tpwcs.meta['fit_info']['scale'], scale) assert tpwcs.meta['fit_info']['rmse'] < 1.0e-8
def test_align_wcs_simple_twpwcs_ref(mock_fits_wcs): shift = (12, -34) rot = (15, 17) scale = (1.0123, 0.9876) xy = 1024 * np.random.random((100, 2)) m = build_fit_matrix(rot, scale) xyr = np.dot(xy, m.T) + shift imcat = Table(xy, names=('x', 'y')) refcat = Table(xyr, names=('x', 'y')) tpwcs = FITSWCS(mock_fits_wcs, meta={'catalog': imcat}) reftpwcs = FITSWCS(mock_fits_wcs, meta={'catalog': refcat}) status = align_wcs(tpwcs, reftpwcs, ref_tpwcs=tpwcs, fitgeom='general', match=None) assert status assert tpwcs.meta['fit_info']['status'] == 'SUCCESS' assert tpwcs.meta['fit_info']['fitgeom'] == 'general' assert np.allclose(tpwcs.meta['fit_info']['shift'], shift) assert np.allclose(tpwcs.meta['fit_info']['matrix'], m) assert np.allclose(tpwcs.meta['fit_info']['rot'], rot) assert tpwcs.meta['fit_info']['proper'] assert np.allclose(tpwcs.meta['fit_info']['scale'], scale) assert tpwcs.meta['fit_info']['rmse'] < 1.0e-8
def mock_jwst_wcs(): cd = build_fit_matrix((36, 47), 1e-5) w = make_mock_jwst_wcs(v2ref=123.0, v3ref=500.0, roll=115.0, crpix=[512.0, 512.0], cd=cd, crval=[82.0, 12.0]) return w
def ideal_large_data(request): # rscale data with proper rotations and no noise uv = np.random.random((_LARGE_SAMPLE_SIZE, 2)) # assume an image size of 4096x2048: uv[:, 0] *= 2047.0 uv[:, 1] *= 4095.0 # rotation angle(s): angle = 360.0 * np.random.random() # 0 ... 360 if request.param == 'shifts': angle = (0, 0) scale = (1, 1) proper = True transform = 'shift' elif request.param == 'rscale': angle = (angle, angle) scale = 2 * (0.8 + 0.4 * np.random.random(), ) # 0.8 ... 1.2 proper = True transform = 'rscale' elif request.param == 'rscale-flip-x': angle = ((angle + 180.0) % 360.0, angle) scale = 2 * (0.8 + 0.4 * np.random.random(), ) # 0.8 ... 1.2 proper = False transform = 'rscale' elif request.param == 'rscale-flip-y': angle = (angle, (angle + 180.0) % 360.0) scale = 2 * (0.8 + 0.4 * np.random.random(), ) # 0.8 ... 1.2 proper = False transform = 'rscale' elif request.param == 'affine': # rotation angles: offset = 150.0 * (np.random.random() - 0.5) # -75 ... 75 offset += 180.0 * np.random.choice([0.0, 1.0]) # add random axis flip angle = (angle, (angle + offset) % 360.0) # scales: scale = 0.8 + 0.4 * np.random.random(2) # 0.8 ... 1.2 # proper: rad = np.deg2rad(angle) proper = (np.prod(np.cos(rad)) + np.prod(np.sin(rad))) > 0 transform = 'general' shift = 200.0 * (np.random.random(2) - 0.5) # -100 ... +100 rmat = linearfit.build_fit_matrix(angle, scale) skew = angle[1] - angle[0] # apply rscale xy = np.dot(uv, rmat.T) + shift return uv, xy, angle, scale, shift, rmat, proper, skew, transform
def mock_fits_wcs(): cd = build_fit_matrix((36, 47), 1e-5) w = fitswcs.WCS(naxis=2) w.wcs.cd = cd w.wcs.crval = [82.0, 12.0] w.wcs.crpix = [512.0, 512.0] w.wcs.ctype = ['RA---TAN', 'DEC--TAN'] w.pixel_shape = [1024, 2048] w.pixel_bounds = ((-0.5, 1024 - 0.5), (-0.5, 2048 - 0.5)) w.wcs.set() return w
def test_build_fit_matrix_generalized(rot, scale): i = np.identity(2) m = linearfit.build_fit_matrix(rot, scale) # check scale: assert np.allclose(np.sqrt(np.sum(m**2, axis=0)), scale, rtol=0, atol=_ATOL) ms = np.diag(scale) # check rotations: mr = linearfit.build_fit_matrix(rot, 1) mrinv = linearfit.build_fit_matrix(rot[::-1], 1).T assert np.allclose(np.linalg.det(mr) * i, np.dot(mr, mrinv), rtol=0, atol=_ATOL) assert np.allclose(m, np.dot(mr, ms), rtol=0, atol=_ATOL)
def test_fitswcs_coord_transforms(mock_fits_wcs): w = fitswcs.WCS(naxis=2) w.wcs.cd = build_fit_matrix(0, 1e-5) w.wcs.crval = [12, 24] w.wcs.crpix = [500, 512] w.wcs.ctype = ['RA---TAN', 'DEC--TAN'] w.pixel_shape = [1024, 2048] w.wcs.set() wc = tpwcs.FITSWCS(w) wc.set_correction() assert np.allclose(wc.det_to_world(499, 511), (12, 24), atol=_ATOL) assert np.allclose(wc.world_to_det(12, 24), (499, 511), atol=_ATOL) assert np.allclose(wc.det_to_tanp(499, 511), (0, 0), atol=_ATOL) assert np.allclose(wc.tanp_to_det(0, 0), (499, 511), atol=_ATOL) assert np.allclose(wc.world_to_tanp(12, 24), (0, 0), atol=1e-8) assert np.allclose(wc.tanp_to_world(0, 0), (12, 24), atol=_ATOL)
def test_inv_order2(): feps = 1000 * np.finfo(np.float64).eps # Generate a 2D rotation/scale/skew matrix + some random noise. # The reason for this complicated approach is to avoid creating # singular matrices. angle1 = 360 * np.random.random() angle2 = angle1 + 50 * (np.random.random() - 0.5) scale1 = 0.7 + 0.6 * np.random.random() scale2 = 0.7 + 0.6 * np.random.random() a = linearfit.build_fit_matrix((angle1, angle2), (scale1, scale2)) # invert using numpy.linalg: use_numpy = linalg._USE_NUMPY_LINALG_INV linalg._USE_NUMPY_LINALG_INV = True try: x = linalg.inv(a) r = np.identity(2) - np.dot(a, x) # Use Morris Newman's formula to asses the quality of the inversion # (see https://nvlpubs.nist.gov/nistpubs/jres/78B/jresv78Bn2p65_A1b.pdf # January 3, 1974). err = 2.0 * np.abs(np.dot(x, r)).max() / (1.0 - np.abs(r).max()) assert err < feps finally: linalg._USE_NUMPY_LINALG_INV = use_numpy # invert using tweakwcs.linalg: linalg._USE_NUMPY_LINALG_INV = False try: x = linalg.inv(a) r = np.identity(2) - np.dot(a, x) # Use Morris Newman's formula to asses the quality of the inversion # (see https://nvlpubs.nist.gov/nistpubs/jres/78B/jresv78Bn2p65_A1b.pdf # January 3, 1974). err = 2.0 * np.abs(np.dot(x, r)).max() / (1.0 - np.abs(r).max()) assert err < feps finally: linalg._USE_NUMPY_LINALG_INV = use_numpy
def test_align_wcs_minobj(mock_fits_wcs): shift = (12, -34) rot = (15, 17) scale = (1.0123, 0.9876) crpix = mock_fits_wcs.wcs.crpix - 1 xy = 1024 * np.random.random((100, 2)) m = build_fit_matrix(rot, scale) xyr = np.dot(xy - crpix, m) + crpix + shift imcat = Table(xy, names=('x', 'y')) refcat = Table(xyr, names=('x', 'y')) tpwcs1 = FITSWCS(mock_fits_wcs, meta={'catalog': imcat}) reftpwcs = FITSWCS(mock_fits_wcs, meta={'catalog': refcat}) status = align_wcs([reftpwcs, tpwcs1], refcat=None, fitgeom='general', minobj=200, match=None, enforce_user_order=True, expand_refcat=False) assert status assert reftpwcs.meta['fit_info']['status'] == 'REFERENCE' assert tpwcs1.meta['fit_info']['status'] == 'FAILED: not enough matches'
def test_build_fit_matrix_rot(rot): i = np.identity(2) m = linearfit.build_fit_matrix(rot) minv = linearfit.build_fit_matrix(360 - rot) assert np.allclose(i, np.dot(m, minv), rtol=0, atol=_ATOL)