def test_AffineTransformation2D_inverse(): # Test non-invertible model model1 = projections.AffineTransformation2D(matrix=[[1, 1], [1, 1]]) with pytest.raises(InputParameterError): model1.inverse model2 = projections.AffineTransformation2D(matrix=[[1.2, 3.4], [5.6, 7.8]], translation=[9.1, 10.11]) # Coordinates for vertices of a rectangle rect = [[0, 0], [1, 0], [0, 3], [1, 3]] x, y = zip(*rect) x_new, y_new = model2.inverse(*model2(x, y)) assert_allclose([x, y], [x_new, y_new], atol=1e-10) model3 = projections.AffineTransformation2D( matrix=[[1.2, 3.4], [5.6, 7.8]] * u.m, translation=[9.1, 10.11] * u.m) x_new, y_new = model3.inverse(*model3(x * u.m, y * u.m)) assert_allclose([x, y], [x_new, y_new], atol=1e-10) model4 = projections.AffineTransformation2D( matrix=[[1.2, 3.4], [5.6, 7.8]] * u.m, translation=[9.1, 10.11] * u.km) with pytest.raises(ValueError) as err: model4.inverse(*model4(x * u.m, y * u.m)) assert str(err.value) ==\ "matrix and translation must have the same units."
def test_affine_with_quantities(): x = 1 y = 2 xdeg = (x * u.pix).to(u.deg, equivalencies=u.pixel_scale(2.5 * u.deg / u.pix)) ydeg = (y * u.pix).to(u.deg, equivalencies=u.pixel_scale(2.5 * u.deg / u.pix)) xpix = x * u.pix ypix = y * u.pix # test affine with matrix only qaff = projections.AffineTransformation2D(matrix=[[1, 2], [2, 1]] * u.deg) with pytest.raises(ValueError): qx1, qy1 = qaff(xpix, ypix, equivalencies={ 'x': u.pixel_scale(2.5 * u.deg / u.pix), 'y': u.pixel_scale(2.5 * u.deg / u.pix)}) # test affine with matrix and translation qaff = projections.AffineTransformation2D(matrix=[[1, 2], [2, 1]] * u.deg, translation=[1, 2] * u.deg) qx1, qy1 = qaff(xpix, ypix, equivalencies={ 'x': u.pixel_scale(2.5 * u.deg / u.pix), 'y': u.pixel_scale(2.5 * u.deg / u.pix)}) aff = projections.AffineTransformation2D(matrix=[[1, 2], [2, 1]], translation=[1, 2]) x1, y1 = aff(xdeg.value, ydeg.value) assert_quantity_allclose(qx1, x1 * u.deg) assert_quantity_allclose(qy1, y1 * u.deg) # test the case of WCS PC and CDELT transformations pc = np.array([[0.86585778922708, 0.50029020461607], [-0.50029020461607, 0.86585778922708]]) cdelt = np.array([[1, 3.0683055555556E-05], [3.0966944444444E-05, 1]]) matrix = cdelt * pc qaff = projections.AffineTransformation2D(matrix=matrix * u.deg, translation=[0, 0] * u.deg) inv_matrix = np.linalg.inv(matrix) inv_qaff = projections.AffineTransformation2D(matrix=inv_matrix * u.pix, translation=[0, 0] * u.pix) qaff.inverse = inv_qaff qx1, qy1 = qaff(xpix, ypix, equivalencies={ 'x': u.pixel_scale(1 * u.deg / u.pix), 'y': u.pixel_scale(1 * u.deg / u.pix)}) x1, y1 = qaff.inverse(qx1, qy1, equivalencies={ 'x': u.pixel_scale(1 * u.deg / u.pix), 'y': u.pixel_scale(1 * u.deg / u.pix)}) assert_quantity_allclose(x1, xpix) assert_quantity_allclose(y1, ypix)
def test_AffineTransformation2D(): # Simple test with a scale and translation model = projections.AffineTransformation2D(matrix=[[2, 0], [0, 2]], translation=[1, 1]) # Coordinates for vertices of a rectangle rect = [[0, 0], [1, 0], [0, 3], [1, 3]] x, y = zip(*rect) new_rect = np.vstack(model(x, y)).T assert np.all(new_rect == [[1, 1], [3, 1], [1, 7], [3, 7]]) # Matrix validation error with pytest.raises(InputParameterError) as err: model.matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] assert str(err.value) ==\ "Expected transformation matrix to be a 2x2 array" # Translation validation error with pytest.raises(InputParameterError) as err: model.translation = [1, 2, 3] assert str(err.value) ==\ "Expected translation vector to be a 2 element row or column vector array" with pytest.raises(InputParameterError) as err: model.translation = [[1], [2]] assert str(err.value) ==\ "Expected translation vector to be a 2 element row or column vector array" with pytest.raises(InputParameterError) as err: model.translation = [[1, 2, 3]] assert str(err.value) ==\ "Expected translation vector to be a 2 element row or column vector array" # Incompatible shape error a = np.array([[1], [2], [3], [4]]) b = a.ravel() with mk.patch.object(np, 'vstack', autospec=True, side_effect=[a, b]) as mk_vstack: message = "Incompatible input shapes" with pytest.raises(ValueError) as err: model(x, y) assert str(err.value) == message with pytest.raises(ValueError) as err: model(x, y) assert str(err.value) == message assert mk_vstack.call_count == 2 # Input shape evaluation error x = np.array([1, 2]) y = np.array([1, 2, 3]) with pytest.raises(ValueError) as err: model.evaluate(x, y, model.matrix, model.translation) assert str(err.value) ==\ "Expected input arrays to have the same shape"
def test_AffineTransformation2D_inverse(): # Test non-invertible model model1 = projections.AffineTransformation2D( matrix=[[1, 1], [1, 1]]) with pytest.raises(InputParameterError): model1.inverse model2 = projections.AffineTransformation2D( matrix=[[1.2, 3.4], [5.6, 7.8]], translation=[9.1, 10.11]) # Coordinates for vertices of a rectangle rect = [[0, 0], [1, 0], [0, 3], [1, 3]] x, y = zip(*rect) x_new, y_new = model2.inverse(*model2(x, y)) assert_allclose([x, y], [x_new, y_new], atol=1e-10)
def test_AffineTransformation2D(): # Simple test with a scale and translation model = projections.AffineTransformation2D( matrix=[[2, 0], [0, 2]], translation=[1, 1]) # Coordinates for vertices of a rectangle rect = [[0, 0], [1, 0], [0, 3], [1, 3]] x, y = zip(*rect) new_rect = np.vstack(model(x, y)).T assert np.all(new_rect == [[1, 1], [3, 1], [1, 7], [3, 7]])
def from_tree_transform(self, node): matrix = node['matrix'] translation = node['translation'] if matrix.shape != (2, 2): raise NotImplementedError( "asdf currently only supports 2x2 (2D) rotation transformation " "matrices") if translation.shape != (2, ): raise NotImplementedError( "asdf currently only supports 2D translation transformations.") return projections.AffineTransformation2D(matrix=matrix, translation=translation)
def convert_wcs(fitswcs): ''' Accepts an astropy.wcs wcs object (based on the FITS standard). Returns the GWCS equivalent WCS object. ''' # this first version only handles non distorted ra,dec tangent projections # check that it is that case radesys_dict = { 'ICRS': coord.ICRS, 'FK5': coord.FK5, 'FK4': coord.FK4, } projection_dict = { 'TAN': projections.Pix2Sky_TAN(), 'SIN': projections.Pix2Sky_SIN() } fctypes = fitswcs.wcs.ctype fcrval = fitswcs.wcs.crval fcrpix = fitswcs.wcs.crpix if fitswcs.naxis != 2: raise ValueError("currently only handles 2d images") print(fctypes) ptypes = [ct[5:8] for ct in fctypes] for ptype in ptypes: print(ptype) if ptype not in ['TAN', 'SIN']: raise ValueError("currently only supports TAN and SIN projections") tptype = ptype # temporary since this part is only for celestial coordinates if fitswcs.cpdis1 or fitswcs.cpdis2: ### error here raise ValueError("currently doesn't support distortion") # Check for SIP correction fsip = fitswcs.sip if fsip: sipa = Polynomial2D(fsip.a_order) sipb = Polynomial2D(fsip.b_order) assign_coefficients(sipa, fsip.a) assign_coefficients(sipb, fsip.b) # now the inverse, if it exists if fsip.ap_order and fsip.bp_order: sipap = Polynomial2D(fsip.ap_order) sipbp = Polynomial2D(fsip.bp_order) assign_coefficients(sipap, fsip.ap) assign_coefficients(sipbp, fsip.bp) else: sipap = None siptrans = Identity(2) + (Mapping((0, 1, 0, 1)) | (sipa & sipb)) if sipap: siptrans.inverse = Identity(2) + (Mapping( (0, 1, 0, 1)) | (sipap & sipbp)) # construct transformation if fitswcs.wcs.has_cd(): trans1 = (Shift(-fcrpix[0]) & Shift(-fcrpix[1])) trans2 = (projections.AffineTransformation2D(fitswcs.wcs.cd) | projection_dict[tptype] | rotations.RotateNative2Celestial( fcrval[0], fcrval[1], 180.)) elif fitswcs.wcs.has_pc(): trans1 = (Shift(-fcrpix[0]) & Shift(-fcrpix[1])) pcmatrix = np.array(fitswcs.wcs.cdelt) * fitswcs.wcs.pc trans2 = (projections.AffineTransformation2D(pcmatrix) | projection_dict[tptype] | rotations.RotateNative2Celestial( fcrval[0], fcrval[1], 180.)) else: cdelt = fitswcs.wcs.cdelt crota2 = fitswcs.wcs.crota[1] * np.pi / 180 # unware of any crota1 case pscale_ratio = cdelt[1] / cdelt[0] pcmatrix = np.array( [[np.cos(crota2) * cdelt[0], -np.sin(crota2) * cdelt[1]], [np.sin(crota2) * cdelt[0], np.cos(crota2) * cdelt[1]]]) trans1 = (Shift(-fcrpix[0]) & Shift(-fcrpix[1])) trans2 = (projections.AffineTransformation2D(pcmatrix) | projection_dict[tptype] | rotations.RotateNative2Celestial( fcrval[0], fcrval[1], 180.)) if fsip: trans = trans1 | siptrans | trans2 else: trans = trans1 | trans2 detector_frame = cf.Frame2D(name="detector", axes_names=('x', 'y'), unit=(u.pix, u.pix)) # Now see if a standard frame is referenced. if fitswcs.wcs.radesys: if fitswcs.wcs.radesys in radesys_dict: reference_frame = radesys_dict[fitswcs.wcs.radesys]() sky_frame = cf.CelestialFrame(reference_frame=reference_frame, name=fitswcs.wcs.radesys.lower()) else: sky_frame = '' # or None? wcsobj = ggwcs.WCS(forward_transform=trans, input_frame=detector_frame, output_frame=sky_frame) return wcsobj