def test_ShiftCoeffs(verbose=False): """ Test accuracy of shift_coefficients method""" # First invent a plausible polynomial order = 5 a = makeup_polynomial() if verbose: print('A') polynomial.print_triangle(a) # Shift by a random step np.random.seed(seed=1) [xshift, yshift] = 1024.0 * np.random.rand(2) - 512.0 ashift = polynomial.shift_coefficients(a, xshift, yshift, verbose) if verbose: print('AS') polynomial.print_triangle(ashift) # Choose a random point [x, y] = 2048 * np.random.rand(2) - 1024.0 u1 = polynomial.poly(a, x, y, order) u2 = polynomial.poly(ashift, x - xshift, y - yshift, order) if verbose: print('XY', x, y) print('Shift', xshift, yshift) print('U values', u1, u2, u1 - u2) assert abs(u1 - u2) < 1.0e-12, 'Inaccurate shift transformation' return None
def test_RotateCoeffs(verbose=False): """Test accuracy of inversion method""" # First invent a random but plausible polynomial array a = makeup_polynomial() order = 5 if verbose: print('A') polynomial.print_triangle(a) # Random point within 2048 square with origin at the center np.random.seed(seed=1) [x, y] = 2048.0 * np.random.rand(2) - 1024.0 u = polynomial.poly(a, x, y, order) # Random angle theta = 360 * np.random.rand(1) if verbose: print('Angle', theta) thetar = np.radians(theta) xp = x * np.cos(thetar) - y * np.sin(thetar) yp = x * np.sin(thetar) + y * np.cos(thetar) ap = polynomial.prepend_rotation_to_polynomial(a, theta, order) u = polynomial.poly(a, x, y, order) up = polynomial.poly(ap, xp, yp, order) # using transformed point and polynomial if verbose: print('X Y', x, y) print('U', u) print('XP YP', xp, yp) print('UP', up) print('UP-U', up - u) assert abs(up - u) < 1.0e-12, 'Inaccurate transformation conversion'
def test_invert(verbose=True): """Test accuracy of inversion method""" # First invent a plausible pair of polynomial arrays order = 5 a = makeup_polynomial() b = makeup_polynomial() # Modify linear terms in b array so sclae term is b[2] btemp = b[1] b[1] = b[2] b[2] = btemp if verbose: print('A') polynomial.print_triangle(a) print('B') polynomial.print_triangle(b) # Random point within 2048 square with origin at the center np.random.seed(seed=1) (x, y) = 2048.0 * np.random.rand(2) - 1024.0 u = polynomial.poly(a, x, y, order) v = polynomial.poly(b, x, y, order) if verbose: print('X Y', x, y) print('U V', u, v) (x2, y2, error, iterations) = polynomial.invert(a, b, u, v, verbose=verbose) if verbose: print('Error', error, ' after', iterations, ' iterations') print('X2 Y2', x2, y2) print('Dx Dy', x2 - x, y2 - y) assert abs(x2 - x) < 1.0e-12 and abs(y2 - y) < 1.0e-12, 'Error too large' return
def test_two_step(verbose=False): # make up random polynomials of order 5 with terms which decrease strongly with power. A = makeup_polynomial() B = makeup_polynomial() a = np.array([1.0, 0.5, 0.1]) b = np.array([2.0, 0.2, 0.6]) (A2, B2) = polynomial.two_step(A, B, a, b) if verbose: print('\nA') polynomial.print_triangle(A) # print('B') print('B') polynomial.print_triangle(B) print('\nLinear terms') print('a', a) print('b', b) print('\nA2') polynomial.print_triangle(A2) print('B2') polynomial.print_triangle(B2) # Now do a test calculation (x, y) = (10, 5) xp = a[0] + a[1] * x + a[2] * y yp = b[0] + b[1] * x + b[2] * y u = polynomial.poly(A, xp, yp, 5) v = polynomial.poly(B, xp, yp, 5) up = polynomial.poly(A2, x, y, 5) vp = polynomial.poly(B2, x, y, 5) if verbose: print('x,y', x, y) print('xp,yp', xp, yp) print('Two step', u, v) print('One step', up, vp) assert abs(u - up) < 1.0e-12 and abs( v - vp) < 1.0e-12, 'Inaccurate transformation'
def test_poly(verbose=False): """ Tests polynomial evaluation by calculating a 9 by 9 array across a 2048 pixel grid Then polyfit is used to fit the calculated points to generate a new pair of polynomials Finally the original x,y points are used in the new polynomials and the outputs compared This incidentally provides a robust test of polyfit parameters verbose: logical value. If True, print statements and graph will be output if False or unassigned there will be no output unless the assert statement issues a Polynomial inaccuracy message. return: None """ [x, y] = np.mgrid[0:9, 0:9] xp = 256.0 * x - 1024.0 yp = 256.0 * y - 1024.0 #u = np.zeros((9, 9)) #v = np.zeros((9, 9)) # Random polynomials a = makeup_polynomial() b = makeup_polynomial() # Switch linear terms for b coefficients so that b[2] is approximate scale btemp = b[1] b[1] = b[2] b[2] = btemp if verbose: print('A coefficients') polynomial.print_triangle(a) print('B coefficients') polynomial.print_triangle(b) # Evaluate polynomials acting on x,y arrays u = polynomial.poly(a, x, y, 5) v = polynomial.poly(b, x, y, 5) # Fit new polynomials to calculated positions s1 = polynomial.polyfit(u, x, y, 5) s2 = polynomial.polyfit(v, x, y, 5) # Evaluate new polynomials uc = polynomial.poly(s1, x, y, 5) vc = polynomial.poly(s2, x, y, 5) # Compare outputs du = uc - u dv = vc - v u_std = np.std(du) v_std = np.std(dv) if verbose: print('Fitted polynomials') print('S1') polynomial.print_triangle(s1) print('S2') polynomial.print_triangle(s2) print('Fit comparison STDs {:10.2e} {:10.2e}'.format(u_std, v_std)) pl.figure(1) pl.clf() pl.grid(True) pl.plot(u, v, 'gx') pl.plot(uc, vc, 'r+') assert u_std < 1.0e-12 and v_std < 1.0e-12, 'Polynomial inaccuracy' return None
def get_mirim_coefficients(distortion_file, verbose=False): """Read delivered FITS file for MIRI imager and return data to be ingested in SIAF. Parameters ---------- distortion_file : str Name of distortion file. verbose : bool verbosity Returns ------- csv_data : dict Dictionary containing the data """ miri = fits.open(os.path.join(source_data_dir, distortion_file)) T = miri['T matrix'].data TI = miri['TI matrix'].data # CDP7 T matrices transform from/to v2,v3 in arcsec # set VtoAN and ANtoV to unit matrix VtoAN = np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]) ANtoV = np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]) TV = np.dot(T, VtoAN) VT = np.dot(ANtoV, TI) prod = np.dot(VT, TV) TT = np.dot(T, TI) if verbose: print('T\n', T) print('TI\n', TI) print('VtoAN\n', VtoAN) print('\n TV V2V3 to XY Entrance') print(TV) print(1.0 / TV[1, 1], 'arcsec/mm') print('\nANtoV\n', ANtoV) print('\n VTXY entrance to V2V3') print('VT\n', VT) print() print('VT comparison\n', prod) print('T comparison\n', TT) # Get linear coefficient layout A = miri['AI matrix'].data B = miri['BI matrix'].data C = miri['A matrix'].data D = miri['B matrix'].data AL = untangle(A) BL = untangle(B) CL = untangle(C) DL = untangle(D) if verbose: print('Initial AL\n', AL) print('Initial BL\n', BL) print('CL\n', CL) print('DL\n', DL) # scale factor corresponding to 25 mum pixel size, i.e. 40 pixels/mm order = 4 k = 0 for i in range(order + 1): factor = 0.025**i for j in range(i + 1): AL[k] = AL[k] * factor BL[k] = BL[k] * factor k += 1 AF = VT[0, 0] * AL + VT[0, 1] * BL AF[0] = AF[0] + VT[0, 2] BF = VT[1, 0] * AL + VT[1, 1] * BL BF[0] = BF[0] + VT[1, 2] if verbose: polynomial.print_triangle(AF) polynomial.print_triangle(BF) print('AL scaled\n', AL) print('\n A FINAL') print('\n B FINAL') ## print('INVERSE TRANSFORMATIONS') # Combine TV with polynomial using polynomial.two_step # combination of several polynomial coefficients a = np.array([TV[0, 2], TV[0, 0], TV[0, 1]]) b = np.array([TV[1, 2], TV[1, 0], TV[1, 1]]) (C2, D2) = polynomial.two_step(CL, DL, a, b) CF = 40 * C2 DF = 40 * D2 if verbose: polynomial.print_triangle(CF) polynomial.print_triangle(DF) print('a', a) print('b', b) print('\nC Final') print('\nD Final') # if verbose: # Test two_step v2 = -280 v3 = -430 xin = TV[0, 0] * v2 + TV[0, 1] * v3 + TV[0, 2] yin = TV[1, 0] * v2 + TV[1, 1] * v3 + TV[1, 2] xmm = polynomial.poly(CL, xin, yin, 4) ymm = polynomial.poly(DL, xin, yin, 4) xmm2 = polynomial.poly(C2, v2, v3, 4) ymm2 = polynomial.poly(D2, v2, v3, 4) # Backwards check xp = 0 yp = 0 v2 = polynomial.poly(AF, xp, yp, 4) v3 = polynomial.poly(BF, xp, yp, 4) xpix = polynomial.poly(CF, v2, v3, 4) ypix = polynomial.poly(DF, v2, v3, 4) print('IN', xin, yin) print('MM', xmm, ymm) print('MM2', xmm2, ymm2) print('V', v2, v3) print('Original ', xp, yp) print('Recovered', xpix, ypix) print('Change ', xpix - xp, ypix - yp) invcheck(AF, BF, CF, DF, 4, -512.0, 512.0) CS = polynomial.shift_coefficients(CF, AF[0], BF[0]) DS = polynomial.shift_coefficients(DF, AF[0], BF[0]) CS[0] = 0.0 DS[0] = 0.0 # extract V2,V3 reference position V2cen = AF[0] V3cen = BF[0] # reset zero order coefficients to zero AF[0] = 0.0 BF[0] = 0.0 if verbose: polynomial.print_triangle(CS) polynomial.print_triangle(DS) invcheck(AF, BF, CS, DS, 4, -512.0, 512.0) print('\nCS') print('\nDS') print('\nDetector Center') # if verbose: xscalec = np.hypot(AF[1], BF[1]) yscalec = np.hypot(AF[2], BF[2]) # compute angles xanglec = np.rad2deg(np.arctan2(AF[1], BF[1])) yanglec = np.rad2deg(np.arctan2(AF[2], BF[2])) if verbose: print('Position', V2cen, V3cen) print('Scales %10.6f %10.6f' % (xscalec, yscalec)) print('Angles %10.6f %10.6f' % (xanglec, yanglec)) # if verbose: xcen = 1033 / 2 ycen = 1025 / 2 xref = 693.5 - xcen yref = 512.5 - ycen V2Ref = polynomial.poly(AF, xref, yref, 4) + V2cen V3Ref = polynomial.poly(BF, xref, yref, 4) + V3cen dV2dx = polynomial.dpdx(AF, xref, yref) dV3dx = polynomial.dpdx(BF, xref, yref) dV2dy = polynomial.dpdy(AF, xref, yref) dV3dy = polynomial.dpdy(BF, xref, yref) xangler = np.arctan2(dV2dx, dV3dx) yangler = np.arctan2(dV2dy, dV3dy) # if verbose: print('Axis angles', np.rad2deg(xangler), np.rad2deg(yangler)) # if verbose: # Illum reference position xscaler = np.hypot(dV2dx, dV3dx) yscaler = np.hypot(dV2dy, dV3dy) xangler = np.rad2deg(np.arctan2(dV2dx, dV3dx)) yangler = np.rad2deg(np.arctan2(dV2dy, dV3dy)) # if verbose: print('\nIllum reference position') print('xref=', xref) print('Position', V2Ref, V3Ref) print('Scales %10.6f %10.6f' % (xscaler, yscaler)) print('Angles %10.6f %10.6f %10.6f' % (xangler, yangler, yangler - xangler)) # if verbose: # Slit position xslit = (326.13) yslit = (300.70) dxslit = xslit - xcen dyslit = yslit - ycen V2slit = polynomial.poly(AF, dxslit, dyslit, 4) + V2cen V3slit = polynomial.poly(BF, dxslit, dyslit, 4) + V3cen dV2dx = polynomial.dpdx(AF, dxslit, yslit) dV3dx = polynomial.dpdx(BF, dxslit, dyslit) dV2dy = polynomial.dpdy(AF, dxslit, dyslit) dV3dy = polynomial.dpdy(BF, dxslit, dyslit) xangles = np.arctan2(dV2dx, dV3dx) yangles = np.arctan2(dV2dy, dV3dy) # if verbose: print('\nSlit') print('Position', dxslit, dyslit) print('V2,V3', V2slit, V3slit) print('Slit angles', np.rad2deg(xangles), np.rad2deg(yangles)) # if verbose: # Corners xc = np.array([-516.0, 516.0, 516.0, -516.0, -516.0]) yc = np.array([-512.0, -512.0, 512.0, 512.0, -512.0]) V2c = polynomial.poly(AF, xc, yc, 4) V3c = polynomial.poly(BF, xc, yc, 4) V2c = V2c + V2cen V3c = V3c + V3cen # if verbose: print('\nCorners') print('V2 %10.4f %10.4f %10.4f %10.4f' % (V2c[0], V2c[1], V2c[2], V2c[3])) print('V3 %10.4f %10.4f %10.4f %10.4f' % (V3c[0], V3c[1], V3c[2], V3c[3])) # make figure pl.figure(1) pl.clf() pl.title('MIRI Detector') pl.plot(V2cen, V3cen, 'r+') pl.plot(V2c, V3c, ':') pl.grid(True) pl.axis('equal') pl.plot(V2Ref, V3Ref, 'b+') pl.plot(V2slit, V3slit, 'c+') pl.gca().invert_xaxis() pl.show() ## Rotated versions print('Angle', yanglec) print('Rotated') # incorporate rotation in coefficients a = np.deg2rad(yanglec) AR = AF * np.cos(a) - BF * np.sin(a) BR = AF * np.sin(a) + BF * np.cos(a) CR = polynomial.prepend_rotation_to_polynomial(CS, yanglec) DR = polynomial.prepend_rotation_to_polynomial(DS, yanglec) if verbose: print('AR') polynomial.print_triangle(AR) print('BR') polynomial.print_triangle(BF) print('\n', AR[2], ' near zero') # if verbose: invcheck(AR, BR, CR, DR, 4, -512.0, 512.0) # Check positions using rotated (Ideal) coefficients # if verbose: xi = polynomial.poly(AR, xc, yc, 4) yi = polynomial.poly(BR, xc, yc, 4) v2r = xi * np.cos(a) + yi * np.sin(a) + V2cen v3r = -xi * np.sin(a) + yi * np.cos(a) + V3cen # if verbose: print('V2', v2r) print('V3', v3r) pl.plot(v2r, v3r, '--') CRFl = polynomial.flip_x(CR) DRFl = polynomial.flip_x(DR) # see TR: "polynomial origin being at the detector center with # pixel position (516.5, 512.5). " detector_center_pixel_x = 516.5 detector_center_pixel_y = 512.5 # dictionary holding data written to csv csv_data = {} csv_data['DET_OSS'] = {} csv_data['DET_OSS']['A'] = AR csv_data['DET_OSS']['B'] = BR csv_data['DET_OSS']['C'] = CR csv_data['DET_OSS']['D'] = DR csv_data['DET_OSS']['Xref'] = detector_center_pixel_x csv_data['DET_OSS']['Yref'] = detector_center_pixel_y csv_data['DET_OSS']['Xref_inv'] = V2cen csv_data['DET_OSS']['Yref_inv'] = V3cen csv_data['DET_OSS']['xAngle'] = xanglec csv_data['DET_OSS']['yAngle'] = yanglec csv_data['DET_DMF'] = {} csv_data['DET_DMF']['A'] = -AR csv_data['DET_DMF']['B'] = BR csv_data['DET_DMF']['C'] = CRFl csv_data['DET_DMF']['D'] = DRFl csv_data['DET_DMF']['Xref'] = detector_center_pixel_x csv_data['DET_DMF']['Yref'] = detector_center_pixel_y csv_data['DET_DMF']['Xref_inv'] = V2cen csv_data['DET_DMF']['Yref_inv'] = V3cen csv_data['DET_DMF']['xAngle'] = xanglec csv_data['DET_DMF']['yAngle'] = yanglec return csv_data
def reorder(pcfName, verbose=False): '''Use pcf files ''' # order = 5 print('\n =============================================%\n') print(pcfName) xForward = [] yForward = [] xBackward = [] yBackward = [] pcf = open(pcfName) # One of the pcf files text = pcf.readline() while text != '': text = pcf.readline() if '*DATE' in text: print(pcf.readline()) if '*FitOrder' in text: order = int(pcf.readline()) terms = (order + 1) * (order + 2) // 2 print('Order', order, terms, ' terms') if '*xForward' in text: text = pcf.readline() f = text.split() # Array of terms text strings for k in range(terms): xForward.append(float(f[k])) xForward = np.array(xForward) if '*xBackward' in text: text = pcf.readline() f = text.split() # Array of terms text strings for k in range(terms): xBackward.append(float(f[k])) xBackward = np.array(xBackward) if '*yForward' in text: text = pcf.readline() f = text.split() # Array of terms text strings for k in range(terms): yForward.append(float(f[k])) yForward = np.array(yForward) if '*yBackward' in text: text = pcf.readline() f = text.split() # Array of terms text strings for k in range(terms): yBackward.append(float(f[k])) yBackward = np.array(yBackward) pcf.close() # Now reorder coefficients Aarray = np.zeros((order + 1, order + 1)) Barray = np.zeros((order + 1, order + 1)) Carray = np.zeros((order + 1, order + 1)) Darray = np.zeros((order + 1, order + 1)) terms = (order + 1) * (order + 2) // 2 A2 = np.zeros(terms) B2 = np.zeros(terms) C2 = np.zeros(terms) D2 = np.zeros(terms) k1 = 0 for i in range(order + 1): for j in range(order + 1 - i): Aarray[j, i] = xForward[k1] Barray[j, i] = yForward[k1] Carray[j, i] = xBackward[k1] Darray[j, i] = yBackward[k1] k1 += 1 k2 = 0 for i in range(order + 1): for j in range(i + 1): A2[k2] = Aarray[j, i - j] B2[k2] = Barray[j, i - j] C2[k2] = Carray[j, i - j] D2[k2] = Darray[j, i - j] k2 += 1 if verbose: print('\n', pcfName) print('A') polynomial.print_triangle(A2, order=5) print('\nB') polynomial.print_triangle(B2, order=5) print('\nC') polynomial.print_triangle(C2, order=5) print('\nD') polynomial.print_triangle(D2, order=5) # Convert V2V3 output polynomials to XAN,YAN type # print (year, pcfName) # print (pcfName) year = '2017' if year == '2016' and 'GWA2OTE' in pcfName: B2 = -B2 B2[0] = B2[0] - 0.13 (C2, D2) = polynomial.TwoStep(C2, D2, [0.0, 1.0, 0.0], [-0.13, 0.0, -1.0], 5) print('\nAdjusted Polynomials') print('A') polynomial.print_triangle(A2, order=5) print('\nB') polynomial.print_triangle(B2, order=5) print('\nC') polynomial.print_triangle(C2, order=5) print('\nD') polynomial.print_triangle(D2, order=5) return (A2, B2, C2, D2)