def ifu_slicer2asdf(ifuslicer, outname, ref_kw): """ Create an asdf reference file with the MSA description. ifu_slicer2asdf("IFU_slicer.sgd", "ifu_slicer.asdf") Parameters ---------- ifuslicer : str A fits file with the IFU slicer description outname : str Name of output ASDF file. """ f = fits.open(ifuslicer) tree = ref_kw.copy() data = f[1].data header = f[1].header shiftx = models.Shift(header['XREF'], name='ifu_slicer_xref') shifty = models.Shift(header['YREF'], name='ifu_slicer_yref') rot = models.Rotation2D(header['ROT'], name='ifu_slicer_rot') model = rot | shiftx & shifty tree['model'] = model tree['data'] = f[1].data f.close() fasdf = AsdfFile() fasdf.tree = tree fasdf.add_history_entry("Build 6") fasdf.write_to(outname) return fasdf
def ifupost2asdf(ifupost_files, outname, ref_kw): """ Create a reference file of type ``ifupost`` . Combines all IDT ``IFU-POST`` reference files in one ASDF file. forward direction : MSA to Collimator backward_direction: Collimator to MSA Parameters ---------- ifupost_files : list Names of all ``IFU-POST`` IDT reference files outname : str Name of output ``ASDF`` file """ fa = AsdfFile() fa.tree = ref_kw for fifu in ifupost_files: n = int((fifu.split('IFU-POST_')[1]).split('.pcf')[0]) fa.tree[n] = {} with open(fifu) as f: lines = [l.strip() for l in f.readlines()] factors = lines[lines.index('*Factor 2') + 1].split() rotation_angle = float(lines[lines.index('*Rotation') + 1]) input_rot_center = lines[lines.index('*InputRotationCentre 2') + 1].split() output_rot_center = lines[lines.index('*OutputRotationCentre 2') + 1].split() linear_sky2det = homothetic_sky2det(input_rot_center, rotation_angle, factors, output_rot_center) degree = int(lines[lines.index('*FitOrder') + 1]) xcoeff_index = lines.index('*xForwardCoefficients 21 2') xlines = lines[xcoeff_index + 1: xcoeff_index + 22] xcoeff_forward = coeffs_from_pcf(degree, xlines) x_poly_forward = models.Polynomial2D(degree, name='x_poly_forward', **xcoeff_forward) ycoeff_index = lines.index('*yForwardCoefficients 21 2') ycoeff_forward = coeffs_from_pcf(degree, lines[ycoeff_index + 1: ycoeff_index + 22]) y_poly_forward = models.Polynomial2D(degree, name='y_poly_forward', **ycoeff_forward) xcoeff_index = lines.index('*xBackwardCoefficients 21 2') xcoeff_backward = coeffs_from_pcf(degree, lines[xcoeff_index + 1: xcoeff_index + 22]) x_poly_backward = models.Polynomial2D(degree, name='x_poly_backward', **xcoeff_backward) ycoeff_index = lines.index('*yBackwardCoefficients 21 2') ycoeff_backward = coeffs_from_pcf(degree, lines[ycoeff_index + 1: ycoeff_index + 22]) y_poly_backward = models.Polynomial2D(degree, name='y_poly_backward', **ycoeff_backward) output2poly_mapping = Identity(2, name='output_mapping') output2poly_mapping.inverse = Mapping([0, 1, 0, 1]) input2poly_mapping = Mapping([0, 1, 0, 1], name='input_mapping') input2poly_mapping.inverse = Identity(2) model_poly = input2poly_mapping | (x_poly_forward & y_poly_forward) | output2poly_mapping model = linear_sky2det | model_poly fa.tree[n]['model'] = model fa.add_history_entry("Build 6") asdffile = fa.write_to(outname) return asdffile
def ote2asdf(otepcf, outname, ref_kw): """ ref_kw = common_reference_file_keywords('OTE', 'NIRSPEC OTE transform - CDP4') ote2asdf('Model/Ref_Files/CoordTransform/OTE.pcf', 'jwst_nirspec_ote_0001.asdf', ref_kw) """ with open(otepcf) as f: lines = [l.strip() for l in f.readlines()] factors = lines[lines.index('*Factor 2 1') + 1].split() # this corresponds to modeling Rotation direction as is rotation_angle = float(lines[lines.index('*Rotation') + 1]) input_rot_center = lines[lines.index('*InputRotationCentre 2 1') + 1].split() output_rot_center = lines[lines.index('*OutputRotationCentre 2 1') + 1].split() mlinear = homothetic_det2sky(input_rot_center, rotation_angle, factors, output_rot_center) degree = int(lines[lines.index('*FitOrder') + 1]) xcoeff_index = lines.index('*xBackwardCoefficients 21 2') xlines = lines[xcoeff_index + 1].split('\t') xcoeff_backward = coeffs_from_pcf(degree, xlines) x_poly_forward = models.Polynomial2D(degree, name='x_poly_forward', **xcoeff_backward) xcoeff_index = lines.index('*xForwardCoefficients 21 2') xlines = lines[xcoeff_index + 1].split('\t') xcoeff_forward = coeffs_from_pcf(degree, xlines) x_poly_backward = models.Polynomial2D(degree, name='x_poly_backward', **xcoeff_forward) ycoeff_index = lines.index('*yBackwardCoefficients 21 2') ylines = lines[ycoeff_index + 1].split('\t') ycoeff_backward = coeffs_from_pcf(degree, ylines) y_poly_forward = models.Polynomial2D(degree, name='y_poly_forward', **ycoeff_backward) ycoeff_index = lines.index('*yForwardCoefficients 21 2') ylines = lines[ycoeff_index + 1].split('\t') ycoeff_forward = coeffs_from_pcf(degree, ylines) y_poly_backward = models.Polynomial2D(degree, name='y_poly_backward', **ycoeff_forward) x_poly_forward.inverse = x_poly_backward y_poly_forward.inverse = y_poly_backward output2poly_mapping = Identity(2, name='output_mapping') output2poly_mapping.inverse = Mapping([0, 1, 0, 1]) input2poly_mapping = Mapping([0, 1, 0, 1], name='input_mapping') input2poly_mapping.inverse = Identity(2) model_poly = input2poly_mapping | (x_poly_forward & y_poly_forward) | output2poly_mapping model = model_poly | mlinear f = AsdfFile() f.tree = ref_kw.copy() f.tree['model'] = model f.add_history_entry("Build 6") f.write_to(outname) return model_poly, mlinear
def create_regions_file(slices, detector, band, channel, name, author, useafter, description): tree = create_reffile_header("REGIONS", detector, band, channel, author, useafter, description) tree['filename'] = name f = AsdfFile() tree['regions'] = slices f.tree = tree f.add_history_entry( "DOCUMENT: MIRI-TN-00001-ETH; SOFTWARE: polyd2c_CDP5.pro; DATA USED: Data set of: - FM Test Campaign relevant to MRS-OPT-01, MRS-OPT-02, MRS-OPT-04, MRS-OPT-08; - CV1 Test Campaign relevant to MRS-OPT-02; - CV2 Test Campaign relevant to MRS-OPT-02; - Laboratory measurement of SPO; ============ DIFFERENCES: - New file structure: Change of Extention names and Table Column Headers.; - Replaced V2/V3 with XAN/YAN;" ) f.write_to(name)
def wavelength_range(spectral_conf, outname, ref_kw): """ Parameters ---------- spectral_conf : str reference file: spectralconfigurations.txt outname : str output file name """ with open(spectral_conf) as f: lines = f.readlines() lines = [l.strip() for l in lines][13:] lines = [l.split() for l in lines] tree = ref_kw.copy() filter_grating = {} for l in lines: f_g = l[0] + '_' + l[1] filter_grating[f_g] = { 'order': int(l[2]), 'range': [float(l[3]), float(l[4])] } tree['filter_grating'] = filter_grating # values in lamp_grating come from private communication with the INS team #lamp_grating = {} filter_grating['FLAT1_G140M'] = {'order': -1, 'range': [1e-6, 1.8e-6]} filter_grating['LINE1_G140M'] = {'order': -1, 'range': [1e-6, 1.8e-6]} filter_grating['FLAT1_G140H'] = {'order': -1, 'range': [1e-6, 1.8e-6]} filter_grating['LINE1_G140H'] = {'order': -1, 'range': [1e-6, 1.8e-6]} filter_grating['FLAT2_G235M'] = {'order': -1, 'range': [1.7e-6, 3.1e-6]} filter_grating['LINE2_G235M'] = {'order': -1, 'range': [1.7e-6, 3.1e-6]} filter_grating['FLAT2_G235H'] = {'order': -1, 'range': [1.7e-6, 3.1e-6]} filter_grating['LINE2_G235H'] = {'order': -1, 'range': [1.7e-6, 3.1e-6]} filter_grating['FLAT3_G395M'] = {'order': -1, 'range': [2.9e-6, 5.3e-6]} filter_grating['LINE3_G395M'] = {'order': -1, 'range': [2.9e-6, 5.3e-6]} filter_grating['FLAT3_G395H'] = {'order': -1, 'range': [2.9e-6, 5.3e-6]} filter_grating['LINE3_G395H'] = {'order': -1, 'range': [2.9e-6, 5.3e-6]} filter_grating['REF_G140M'] = {'order': -1, 'range': [1.3e-6, 1.7e-6]} filter_grating['REF_G140H'] = {'order': -1, 'range': [1.3e-6, 1.7e-6]} filter_grating['TEST_MIRROR'] = {'order': -1, 'range': [0.6e-6, 5.3e-6]} #for grating in ["G140H", "G140M", "G235H", "G235M", "G395H", "G395M", "MIRROR"]: #lamp_grating['FLAT4_{0}'.format(grating)] = {'order': -1, 'range': [0.7e-6, 1.2e-6]} #for grating in ["G140H", "G140M", "G235H", "G235M", "G395H", "G395M", "MIRROR"]: #lamp_grating['LINE4_{0}'.format(grating)] = {'order': -1, 'range': [0.6e-6, 5.3e-6]} #tree['lamp_grating'] = lamp_grating fasdf = AsdfFile() fasdf.tree = tree fasdf.add_history_entry("Build 6") fasdf.write_to(outname) return fasdf
def wavelength_range(spectral_conf, outname, ref_kw): """ Parameters ---------- spectral_conf : str reference file: spectralconfigurations.txt outname : str output file name """ with open(spectral_conf) as f: lines = f.readlines() lines = [l.strip() for l in lines][13 :] lines = [l.split() for l in lines] tree = ref_kw.copy() filter_grating = {} for l in lines: f_g = l[0] + '_' + l[1] filter_grating[f_g] = {'order': int(l[2]), 'range': [float(l[3]), float(l[4])]} tree['filter_grating'] = filter_grating # values in lamp_grating come from private communication with the INS team #lamp_grating = {} filter_grating['FLAT1_G140M'] = {'order': -1, 'range': [1e-6, 1.8e-6]} filter_grating['LINE1_G140M'] = {'order': -1, 'range': [1e-6, 1.8e-6]} filter_grating['FLAT1_G140H'] = {'order': -1, 'range': [1e-6, 1.8e-6]} filter_grating['LINE1_G140H'] = {'order': -1, 'range': [1e-6, 1.8e-6]} filter_grating['FLAT2_G235M'] = {'order': -1, 'range': [1.7e-6, 3.1e-6]} filter_grating['LINE2_G235M'] = {'order': -1, 'range': [1.7e-6, 3.1e-6]} filter_grating['FLAT2_G235H'] = {'order': -1, 'range': [1.7e-6, 3.1e-6]} filter_grating['LINE2_G235H'] = {'order': -1, 'range': [1.7e-6, 3.1e-6]} filter_grating['FLAT3_G395M'] = {'order': -1, 'range': [2.9e-6, 5.3e-6]} filter_grating['LINE3_G395M'] = {'order': -1, 'range': [2.9e-6, 5.3e-6]} filter_grating['FLAT3_G395H'] = {'order': -1, 'range': [2.9e-6, 5.3e-6]} filter_grating['LINE3_G395H'] = {'order': -1, 'range': [2.9e-6, 5.3e-6]} filter_grating['REF_G140M'] = {'order': -1, 'range': [1.3e-6, 1.7e-6]} filter_grating['REF_G140H'] = {'order': -1, 'range': [1.3e-6, 1.7e-6]} filter_grating['TEST_MIRROR'] = {'order': -1, 'range': [0.6e-6, 5.3e-6]} #for grating in ["G140H", "G140M", "G235H", "G235M", "G395H", "G395M", "MIRROR"]: #lamp_grating['FLAT4_{0}'.format(grating)] = {'order': -1, 'range': [0.7e-6, 1.2e-6]} #for grating in ["G140H", "G140M", "G235H", "G235M", "G395H", "G395M", "MIRROR"]: #lamp_grating['LINE4_{0}'.format(grating)] = {'order': -1, 'range': [0.6e-6, 5.3e-6]} #tree['lamp_grating'] = lamp_grating fasdf = AsdfFile() fasdf.tree = tree fasdf.add_history_entry("Build 6") fasdf.write_to(outname) return fasdf
def create_wavelengthrange_file(name, detector, author, useafter, description): f = AsdfFile() # Relaxing the range to match the distortion. The table above # comes from the report and is "as designed". wavelengthrange = { '1SHORT': (4.68, 5.97), '1MEDIUM': (5.24, 6.87), '1LONG': (6.2, 7.90), '2SHORT': (7.27, 9.03), '2MEDIUM': (8.43, 10.39), '2LONG': (9.76, 11.97), '3SHORT': (11.29, 13.75), '3MEDIUM': (13.08, 15.86), '3LONG': (15.14, 18.29), '4SHORT': (17.40, 21.20), '4MEDIUM': (20.31, 24.68), '4LONG': (23.72, 28.75) } channels = [ '1SHORT', '1MEDIUM', '1LONG', '2SHORT', '2MEDIUM', '2LONG', '3SHORT', '3MEDIUM', '3LONG', '4SHORT', '4MEDIUM', '4LONG' ] tree = create_reffile_header("WAVELENGTHRANGE", detector, band="N/A", channel="N/A", author=author, useafter=useafter, description=description) tree['filename'] = name tree['author'] = 'Nadia Dencheva' tree['detector'] = "N/A" tree['channels'] = channels f.tree = tree vr = np.empty((12, 2), dtype=np.float) for i, ch in enumerate(channels): vr[i] = wavelengthrange[ch] f.tree['wavelengthrange'] = vr f.add_history_entry( "DOCUMENT: MIRI-TN-00001-ETH; SOFTWARE: polyd2c_CDP5.pro; DATA USED: Data set of: - FM Test Campaign relevant to MRS-OPT-01, MRS-OPT-02, MRS-OPT-04, MRS-OPT-08; - CV1 Test Campaign relevant to MRS-OPT-02; - CV2 Test Campaign relevant to MRS-OPT-02; - Laboratory measurement of SPO; ============ DIFFERENCES: - New file structure: Change of Extention names and Table Column Headers.; - Replaced V2/V3 with XAN/YAN;" ) f.write_to(name)
def create_distortion_file(reftype, detector, band, channel, data, name, author, useafter, description): description = 'MIRI MRS Distortion Maps' tree = create_reffile_header(reftype, detector, band, channel, author, useafter, description) tree['filename'] = name adata, bdata, xdata, ydata, bzero, bdel = data tree['alpha_model'] = adata tree['beta_model'] = bdata tree['x_model'] = xdata tree['y_model'] = ydata tree['bzero'] = bzero tree['bdel'] = bdel f = AsdfFile() f.tree = tree f.add_history_entry( "DOCUMENT: MIRI-TN-00001-ETH; SOFTWARE: polyd2c_CDP5.pro; DATA USED: Data set of: - FM Test Campaign relevant to MRS-OPT-01, MRS-OPT-02, MRS-OPT-04, MRS-OPT-08; - CV1 Test Campaign relevant to MRS-OPT-02; - CV2 Test Campaign relevant to MRS-OPT-02; - Laboratory measurement of SPO; ============ DIFFERENCES: - New file structure: Change of Extention names and Table Column Headers.; - Replaced V2/V3 with XAN/YAN;" ) f.write_to(name)
def msa2asdf(msafile, outname, ref_kw): """ Create an asdf reference file with the MSA description. mas2asfdf("MSA.msa", "msa.asdf") Parameters ---------- msafile : str A fits file with MSA description (MSA.msa) outname : str Name of output ASDF file. """ f = fits.open(msafile) tree = ref_kw.copy() data = f[5].data # SLITS and IFU header = f[5].header shiftx = models.Shift(header['SLITXREF'], name='slit_xref') shifty = models.Shift(header['SLITYREF'], name='slit_yref') slitrot = models.Rotation2D(header['SLITROT'], name='slit_rot') tree[5] = {} tree[5]['model'] = slitrot | shiftx & shifty tree[5]['data'] = f[5].data for i in range(1, 5): header = f[i].header shiftx = models.Shift(header['QUADXREF'], name='msa_xref') shifty = models.Shift(header['QUADYREF'], name='msa_yref') slitrot = models.Rotation2D(header['QUADROT'], name='msa_rot') tree[i] = {} tree[i]['model'] = slitrot | shiftx & shifty tree[i]['data'] = f[i].data f.close() fasdf = AsdfFile() fasdf.tree = tree fasdf.add_history_entry("Build 6") fasdf.write_to(outname) return fasdf
def create_v23(reftype, detector, band, channels, data, name, author, useafter, description): """ Create the transform from MIRI Local to telescope V2/V3 system for all channels. """ channel = "".join([ch[0] for ch in channels]) tree = create_reffile_header(reftype, detector, band, channel, author, useafter, description) """ tree = {"detector": detector, "instrument" : "MIRI", "band": band, "channel": channel, "exp_type": "MIR_MRS", "pedigree": "GROUND", "title": "MIRI IFU model - based on CDP-4", "reftype": reftype, "author": author, "useafter": useafter, "description": description } """ tree['filename'] = name ab_v23 = data[0] v23_ab = data[1] m = {} c0_0, c0_1, c1_0, c1_1 = ab_v23[0][1:] ch1_v2 = models.Polynomial2D(2, c0_0=c0_0, c1_0=c1_0, c0_1=c0_1, c1_1=c1_1, name="ab_v23") c0_0, c0_1, c1_0, c1_1 = v23_ab[0][1:] ch1_a = models.Polynomial2D(2, c0_0=c0_0, c1_0=c1_0, c0_1=c0_1, c1_1=c1_1, name="v23_ab") c0_0, c0_1, c1_0, c1_1 = ab_v23[1][1:] ch1_v3 = models.Polynomial2D(2, c0_0=c0_0, c1_0=c1_0, c0_1=c0_1, c1_1=c1_1, name="ab_v23") c0_0, c0_1, c1_0, c1_1 = v23_ab[1][1:] ch1_b = models.Polynomial2D(2, c0_0=c0_0, c1_0=c1_0, c0_1=c0_1, c1_1=c1_1, name="v23_ab") c0_0, c0_1, c1_0, c1_1 = ab_v23[2][1:] ch2_v2 = models.Polynomial2D(2, c0_0=c0_0, c1_0=c1_0, c0_1=c0_1, c1_1=c1_1, name="ab_v23") c0_0, c0_1, c1_0, c1_1 = v23_ab[2][1:] ch2_a = models.Polynomial2D(2, c0_0=c0_0, c1_0=c1_0, c0_1=c0_1, c1_1=c1_1, name="v23_ab") c0_0, c0_1, c1_0, c1_1 = ab_v23[3][1:] ch2_v3 = models.Polynomial2D(2, c0_0=c0_0, c1_0=c1_0, c0_1=c0_1, c1_1=c1_1, name="ab_v23") c0_0, c0_1, c1_0, c1_1 = v23_ab[3][1:] ch2_b = models.Polynomial2D(2, c0_0=c0_0, c1_0=c1_0, c0_1=c0_1, c1_1=c1_1, name="v23_ab") ch1_for = ch1_v2 & ch1_v3 ch2_for = ch2_v2 & ch2_v3 ch1_for.inverse = ch1_a & ch1_b ch2_for.inverse = ch2_a & ch2_b m[channels[0]] = ch1_for m[channels[1]] = ch2_for tree['model'] = m f = AsdfFile() f.tree = tree f.add_history_entry( "DOCUMENT: MIRI-TN-00001-ETH; SOFTWARE: polyd2c_CDP5.pro; DATA USED: Data set of: - FM Test Campaign relevant to MRS-OPT-01, MRS-OPT-02, MRS-OPT-04, MRS-OPT-08; - CV1 Test Campaign relevant to MRS-OPT-02; - CV2 Test Campaign relevant to MRS-OPT-02; - Laboratory measurement of SPO; ============ DIFFERENCES: - New file structure: Change of Extention names and Table Column Headers.; - Replaced V2/V3 with XAN/YAN;" ) f.write_to(name)
def fpa2asdf(fpafile, outname, ref_kw): """ Create an asdf reference file with the FPA description. The CDP2 delivery includes a fits file - "FPA.fpa" which is the input to this function. This file is converted to asdf and is a reference file of type "FPA". nirspec_fs_ref_tools.fpa2asdf('Ref_Files/CoordTransform/Description/FPA.fpa', 'fpa.asdf') Parameters ---------- fpafile : str A fits file with FPA description (FPA.fpa) outname : str Name of output ASDF file. """ with open(fpafile) as f: lines = [l.strip() for l in f.readlines()] # NRS1 ind = lines.index("*SCA491_PitchX") nrs1_pitchx = float(lines[ind + 1]) ind = lines.index("*SCA491_PitchY") nrs1_pitchy = float(lines[ind + 1]) ind = lines.index("*SCA491_RotAngle") nrs1_angle = float(lines[ind + 1]) ind = lines.index("*SCA491_PosX") nrs1_posx = float(lines[ind + 1]) ind = lines.index("*SCA491_PosY") nrs1_posy = float(lines[ind + 1]) # NRS2 ind = lines.index("*SCA492_PitchX") nrs2_pitchx = float(lines[ind + 1]) ind = lines.index("*SCA492_PitchY") nrs2_pitchy = float(lines[ind + 1]) ind = lines.index("*SCA492_RotAngle") nrs2_angle = float(lines[ind + 1]) ind = lines.index("*SCA492_PosX") nrs2_posx = float(lines[ind + 1]) ind = lines.index("*SCA492_PosY") nrs2_posy = float(lines[ind + 1]) tree = ref_kw.copy() # NRS1 Sky to Detector scaling = np.array([[1 / nrs1_pitchx, 0], [0, 1 / nrs1_pitchy]]) rotmat = models.Rotation2D._compute_matrix(-nrs1_angle) matrix = np.dot(rotmat, scaling) aff = models.AffineTransformation2D(matrix, name='fpa_affine_sky2detector') nrs1_sky2det = models.Shift(-nrs1_posx, name='fpa_shift_x') & \ models.Shift(-nrs1_posy, name='fpa_shift_y') | aff # NRS1 Detector to Sky rotmat = models.Rotation2D._compute_matrix(-nrs1_angle) scaling = np.array([[nrs1_pitchx, 0], [0, nrs1_pitchy]]) matrix = np.dot(rotmat, scaling) aff = models.AffineTransformation2D(matrix, name='fpa_affine_detector2sky') nrs1_det2sky = aff | models.Shift(nrs1_posx, name='fpa_shift_x_det2sky') & \ models.Shift(nrs1_posy, name='fpa_shift_y_det2sky') nrs1_det2sky.inverse = nrs1_sky2det # NRS2 Sky to Detector scaling = np.array([[-1 / nrs2_pitchx, 0], [0, -1 / nrs2_pitchy]]) rotmat = models.Rotation2D._compute_matrix(-nrs2_angle) matrix = np.dot(rotmat, scaling) aff = models.AffineTransformation2D(matrix, name='fpa_affine_sky2detector') nrs2_sky2det = models.Shift(-nrs2_posx, name='fpa_shixft_x') & \ models.Shift(-nrs2_posy, name='fpa_shift_y') | aff # NRS2 Detector to Sky rotmat = models.Rotation2D._compute_matrix(nrs2_angle) scaling = np.array([[-nrs2_pitchx, 0], [0, -nrs2_pitchy]]) matrix = np.dot(rotmat, scaling) aff = models.AffineTransformation2D(matrix, name='fpa_affine_detector2sky') nrs2_det2sky = aff | models.Shift(nrs2_posx, name='fpa_shift_x_det2sky') & \ models.Shift(nrs2_posy, name='fpa_shift_y_det2sky') nrs2_det2sky.inverse = nrs2_sky2det tree['NRS1'] = nrs1_det2sky tree['NRS2'] = nrs2_det2sky fasdf = AsdfFile() fasdf.tree = tree fasdf.add_history_entry("Build 6") fasdf.write_to(outname) return fasdf
def fore2asdf(pcffore, outname, ref_kw): """ forward direction : msa 2 ote backward_direction: msa 2 fpa """ with open(pcffore) as f: lines = [l.strip() for l in f.readlines()] fore_det2sky = linear_from_pcf_det2sky(pcffore) fore_linear = fore_det2sky fore_linear.inverse = fore_det2sky.inverse & Identity(1) # compute the polynomial degree = int(lines[lines.index('*FitOrder') + 1]) xcoeff_index = lines.index('*xForwardCoefficients 21 2') xlines = lines[xcoeff_index + 1: xcoeff_index + 22] xcoeff_forward = coeffs_from_pcf(degree, xlines) # Polynomial Correction in x x_poly_backward = models.Polynomial2D(degree, name="x_poly_backward", **xcoeff_forward) xlines_distortion = lines[xcoeff_index + 22: xcoeff_index + 43] xcoeff_forward_distortion = coeffs_from_pcf(degree, xlines_distortion) x_poly_backward_distortion = models.Polynomial2D(degree, name="x_backward_distortion", **xcoeff_forward_distortion) # do chromatic correction # the input is Xote, Yote, lam model_x_backward = (Mapping((0, 1), n_inputs=3) | x_poly_backward) + \ ((Mapping((0,1), n_inputs=3) | x_poly_backward_distortion) * \ (Mapping((2,)) | Identity(1))) ycoeff_index = lines.index('*yForwardCoefficients 21 2') ycoeff_forward = coeffs_from_pcf(degree, lines[ycoeff_index + 1: ycoeff_index + 22]) y_poly_backward = models.Polynomial2D(degree, name="y_poly_backward", **ycoeff_forward) ylines_distortion = lines[ycoeff_index + 22: ycoeff_index + 43] ycoeff_forward_distortion = coeffs_from_pcf(degree, ylines_distortion) y_poly_backward_distortion = models.Polynomial2D(degree, name="y_backward_distortion", **ycoeff_forward_distortion) # do chromatic correction # the input is Xote, Yote, lam model_y_backward = (Mapping((0,1), n_inputs=3) | y_poly_backward) + \ ((Mapping((0, 1), n_inputs=3) | y_poly_backward_distortion) * \ (Mapping((2,)) | Identity(1) )) xcoeff_index = lines.index('*xBackwardCoefficients 21 2') xcoeff_backward = coeffs_from_pcf(degree, lines[xcoeff_index + 1: xcoeff_index + 22]) x_poly_forward = models.Polynomial2D(degree,name="x_poly_forward", **xcoeff_backward) xcoeff_backward_distortion = coeffs_from_pcf(degree, lines[xcoeff_index + 22: xcoeff_index + 43]) x_poly_forward_distortion = models.Polynomial2D(degree, name="x_forward_distortion", **xcoeff_backward_distortion) # the chromatic correction is done here # the input is Xmsa, Ymsa, lam model_x_forward = (Mapping((0,1), n_inputs=3) | x_poly_forward) + \ ((Mapping((0,1), n_inputs=3) | x_poly_forward_distortion) * \ (Mapping((2,)) | Identity(1))) ycoeff_index = lines.index('*yBackwardCoefficients 21 2') ycoeff_backward = coeffs_from_pcf(degree, lines[ycoeff_index + 1: ycoeff_index + 22]) y_poly_forward = models.Polynomial2D(degree, name="y_poly_forward",**ycoeff_backward) ycoeff_backward_distortion = coeffs_from_pcf(degree, lines[ycoeff_index + 22: ycoeff_index + 43]) y_poly_forward_distortion = models.Polynomial2D(degree, name="y_forward_distortion", **ycoeff_backward_distortion) # do chromatic correction # the input is Xmsa, Ymsa, lam model_y_forward = (Mapping((0,1), n_inputs=3) | y_poly_forward) + \ ((Mapping((0,1), n_inputs=3) | y_poly_forward_distortion) * \ (Mapping((2,)) | Identity(1))) #assign inverse transforms model_x = model_x_forward.copy() model_y = model_y_forward.copy() model_x.inverse = model_x_backward model_y.inverse = model_y_backward output2poly_mapping = Identity(2, name="output_mapping") output2poly_mapping.inverse = Mapping([0, 1, 2, 0, 1, 2]) input2poly_mapping = Mapping([0, 1, 2, 0, 1, 2], name="input_mapping") input2poly_mapping.inverse = Identity(2) model_poly = input2poly_mapping | (model_x & model_y) | output2poly_mapping model = model_poly | fore_linear f = AsdfFile() f.tree = ref_kw.copy() f.tree['model'] = model f.add_history_entry("Build 6") asdffile = f.write_to(outname) return asdffile
def disperser2asdf(disfile, tiltyfile, tiltxfile, outname, ref_kw): """ Create a NIRSPEC disperser reference file in ASDF format. Combine information stored in disperser_G?.dis and disperser_G?_TiltY.gtp files delievred by the IDT. disperser2asdf("disperser_G140H.dis", "disperser_G140H_TiltY.gtp", "disperserG140H.asdf") Parameters ---------- disfile : list or str A list of .dis files or a wild card string (*.dis). tiltyfile : str File with tilt_Y data, e.g. disperser_G395H_TiltY.gtp. outname : str Name of output ASDF file. Returns ------- fasdf : asdf.AsdfFile """ disperser = disfile.split('.dis')[0].split('_')[1] with open(disfile) as f: lines = [l.strip() for l in f.readlines()] try: ind = lines.index('*TYPE') disperser_type = (lines[ind + 1]).lower() except ValueError: raise ValueError("Unknown disperser type in {0}".format(disfile)) if disperser_type == 'gratingdata': d = dict.fromkeys( ['groove_density', 'theta_z', 'theta_y', 'theta_x', 'tilt_y']) elif disperser_type == 'prismdata': d = dict.fromkeys([ 'tref', 'pref', 'angle', 'coefformula', 'thermalcoef', 'wbound' 'theta_z', 'theta_y', 'theta_x', 'tilt_y' ]) d.update(ref_kw) try: ind = lines.index('*GRATINGNAME') grating_name = lines[ind + 1] except ValueError: grating_name = 'PRISM' #for line in lines: ind = lines.index('*THETAZ') d['theta_z'] = float(lines[ind + 1]) / 3600. # in degrees ind = lines.index('*THETAX') d['theta_x'] = float(lines[ind + 1]) / 3600. # in degrees ind = lines.index('*THETAY') d['theta_y'] = float(lines[ind + 1]) / 3600. # in degrees ind = lines.index('*TILTY') d['tilt_y'] = float(lines[ind + 1]) # in degrees try: ind = lines.index('*TILTX') d['tilt_x'] = float(lines[ind + 1]) # in degrees except ValueError: d['tilt_x'] = 0.0 if disperser_type == 'gratingdata': ind = lines.index('*GROOVEDENSITY') d['groove_density'] = float(lines[ind + 1]) elif disperser_type == 'prismdata': ind = lines.index('*ANGLE') d['angle'] = float(lines[ind + 1]) # in degrees ind = lines.index('*TREF') d['tref'] = float(lines[ind + 1]) # Temperature in K ind = lines.index('*PREF') d['pref'] = float(lines[ind + 1]) # Pressure in ATM ind = lines.index('*COEFFORMULA') coefs = np.array(lines[ind:ind + int(l[-1])], dtype=np.float) kcoef = coefs[::2] lcoef = coefs[1::2] d['lcoef'] = lcoef d['kcoef'] = kcoef # 6 coeffs - D0, D1, D2, E0, E1, lambdak ind = lines.index('*THERMALCOEF') coefs = lines[ind:ind + int(l[-1])] d['tcoef'] = [float(c) for c in coefs] ind = lines.index('*WBOUND') coefs = lines[ind:ind + 2] d['wbound'] = [float(c) for c in coefs] assert grating_name in tiltyfile assert grating_name in tiltxfile tiltyd = disperser_tilt(tiltyfile) tiltxd = disperser_tilt(tiltxfile) d['gwa_tiltx'] = tiltyd d['gwa_tilty'] = tiltxd fasdf = AsdfFile() fasdf.tree = d fasdf.add_history_entry("Build 6") fasdf.write_to(outname) return fasdf
def fore2asdf(pcffore, outname, ref_kw): """ forward direction : msa 2 ote backward_direction: msa 2 fpa """ with open(pcffore) as f: lines = [l.strip() for l in f.readlines()] fore_det2sky = linear_from_pcf_det2sky(pcffore) fore_linear = fore_det2sky fore_linear.inverse = fore_det2sky.inverse & Identity(1) # compute the polynomial degree = int(lines[lines.index('*FitOrder') + 1]) xcoeff_index = lines.index('*xForwardCoefficients 21 2') xlines = lines[xcoeff_index + 1:xcoeff_index + 22] xcoeff_forward = coeffs_from_pcf(degree, xlines) # Polynomial Correction in x x_poly_backward = models.Polynomial2D(degree, name="x_poly_backward", **xcoeff_forward) xlines_distortion = lines[xcoeff_index + 22:xcoeff_index + 43] xcoeff_forward_distortion = coeffs_from_pcf(degree, xlines_distortion) x_poly_backward_distortion = models.Polynomial2D( degree, name="x_backward_distortion", **xcoeff_forward_distortion) # do chromatic correction # the input is Xote, Yote, lam model_x_backward = (Mapping((0, 1), n_inputs=3) | x_poly_backward) + \ ((Mapping((0,1), n_inputs=3) | x_poly_backward_distortion) * \ (Mapping((2,)) | Identity(1))) ycoeff_index = lines.index('*yForwardCoefficients 21 2') ycoeff_forward = coeffs_from_pcf(degree, lines[ycoeff_index + 1:ycoeff_index + 22]) y_poly_backward = models.Polynomial2D(degree, name="y_poly_backward", **ycoeff_forward) ylines_distortion = lines[ycoeff_index + 22:ycoeff_index + 43] ycoeff_forward_distortion = coeffs_from_pcf(degree, ylines_distortion) y_poly_backward_distortion = models.Polynomial2D( degree, name="y_backward_distortion", **ycoeff_forward_distortion) # do chromatic correction # the input is Xote, Yote, lam model_y_backward = (Mapping((0,1), n_inputs=3) | y_poly_backward) + \ ((Mapping((0, 1), n_inputs=3) | y_poly_backward_distortion) * \ (Mapping((2,)) | Identity(1) )) xcoeff_index = lines.index('*xBackwardCoefficients 21 2') xcoeff_backward = coeffs_from_pcf( degree, lines[xcoeff_index + 1:xcoeff_index + 22]) x_poly_forward = models.Polynomial2D(degree, name="x_poly_forward", **xcoeff_backward) xcoeff_backward_distortion = coeffs_from_pcf( degree, lines[xcoeff_index + 22:xcoeff_index + 43]) x_poly_forward_distortion = models.Polynomial2D( degree, name="x_forward_distortion", **xcoeff_backward_distortion) # the chromatic correction is done here # the input is Xmsa, Ymsa, lam model_x_forward = (Mapping((0,1), n_inputs=3) | x_poly_forward) + \ ((Mapping((0,1), n_inputs=3) | x_poly_forward_distortion) * \ (Mapping((2,)) | Identity(1))) ycoeff_index = lines.index('*yBackwardCoefficients 21 2') ycoeff_backward = coeffs_from_pcf( degree, lines[ycoeff_index + 1:ycoeff_index + 22]) y_poly_forward = models.Polynomial2D(degree, name="y_poly_forward", **ycoeff_backward) ycoeff_backward_distortion = coeffs_from_pcf( degree, lines[ycoeff_index + 22:ycoeff_index + 43]) y_poly_forward_distortion = models.Polynomial2D( degree, name="y_forward_distortion", **ycoeff_backward_distortion) # do chromatic correction # the input is Xmsa, Ymsa, lam model_y_forward = (Mapping((0,1), n_inputs=3) | y_poly_forward) + \ ((Mapping((0,1), n_inputs=3) | y_poly_forward_distortion) * \ (Mapping((2,)) | Identity(1))) #assign inverse transforms model_x = model_x_forward.copy() model_y = model_y_forward.copy() model_x.inverse = model_x_backward model_y.inverse = model_y_backward output2poly_mapping = Identity(2, name="output_mapping") output2poly_mapping.inverse = Mapping([0, 1, 2, 0, 1, 2]) input2poly_mapping = Mapping([0, 1, 2, 0, 1, 2], name="input_mapping") input2poly_mapping.inverse = Identity(2) model_poly = input2poly_mapping | (model_x & model_y) | output2poly_mapping model = model_poly | fore_linear f = AsdfFile() f.tree = ref_kw.copy() f.tree['model'] = model f.add_history_entry("Build 6") asdffile = f.write_to(outname) return asdffile
def pcf2asdf(pcffile, outname, ref_file_kw): """ Create an asdf reference file with the transformation coded in a NIRSPEC Camera.pcf or Collimator*.pcf file. - forward (team): sky to detector - Shift inputs to input_rotation_center - Rotate inputs - Scale inputs - Shift inputs to output_rot_center - Apply polynomial distortion - backward_team (team definition) detector to sky - Apply polynomial distortion - Shift inputs to output_rot_center - Scale inputs - Rotate inputs - Shift inputs to input_rotation_center WCS implementation - forward: detector to sky - equivalent to backward_team - backward: sky to detector - equivalent to forward_team Parameters ---------- pcffile : str one of the NIRSPEC ".pcf" reference files provided by the IDT team. "pcf" stands for "polynomial coefficients fit" outname : str Name of reference file to be wriiten to disk. Returns ------- fasdf : AsdfFile AsdfFile object Examples -------- >>> pcf2asdf("Camera.pcf", "camera.asdf") """ linear_det2sky = linear_from_pcf_det2sky(pcffile) with open(pcffile) as f: lines = [l.strip() for l in f.readlines()] degree = int(lines[lines.index('*FitOrder') + 1]) xcoeff_index = lines.index('*xForwardCoefficients 21 2') xlines = lines[xcoeff_index + 1:xcoeff_index + 22] xcoeff_forward = coeffs_from_pcf(degree, xlines) x_poly_backward = models.Polynomial2D(degree, name='x_poly_backward', **xcoeff_forward) ycoeff_index = lines.index('*yForwardCoefficients 21 2') ycoeff_forward = coeffs_from_pcf(degree, lines[ycoeff_index + 1:ycoeff_index + 22]) y_poly_backward = models.Polynomial2D(degree, name='y_poly_backward', **ycoeff_forward) xcoeff_index = lines.index('*xBackwardCoefficients 21 2') xcoeff_backward = coeffs_from_pcf( degree, lines[xcoeff_index + 1:xcoeff_index + 22]) x_poly_forward = models.Polynomial2D(degree, name='x_poly_forward', **xcoeff_backward) ycoeff_index = lines.index('*yBackwardCoefficients 21 2') ycoeff_backward = coeffs_from_pcf( degree, lines[ycoeff_index + 1:ycoeff_index + 22]) y_poly_forward = models.Polynomial2D(degree, name='y_poly_forward', **ycoeff_backward) x_poly_forward.inverse = x_poly_backward y_poly_forward.inverse = y_poly_backward output2poly_mapping = Identity(2, name='output_mapping') output2poly_mapping.inverse = Mapping([0, 1, 0, 1]) input2poly_mapping = Mapping([0, 1, 0, 1], name='input_mapping') input2poly_mapping.inverse = Identity(2) model_poly = input2poly_mapping | (x_poly_forward & y_poly_forward) | output2poly_mapping model = model_poly | linear_det2sky f = AsdfFile() f.tree = ref_file_kw.copy() f.add_history_entry("Build 6") f.tree['model'] = model f.write_to(outname)
def disperser2asdf(disfile, tiltyfile, tiltxfile, outname, ref_kw): """ Create a NIRSPEC disperser reference file in ASDF format. Combine information stored in disperser_G?.dis and disperser_G?_TiltY.gtp files delievred by the IDT. disperser2asdf("disperser_G140H.dis", "disperser_G140H_TiltY.gtp", "disperserG140H.asdf") Parameters ---------- disfile : list or str A list of .dis files or a wild card string (*.dis). tiltyfile : str File with tilt_Y data, e.g. disperser_G395H_TiltY.gtp. outname : str Name of output ASDF file. Returns ------- fasdf : asdf.AsdfFile """ disperser = disfile.split('.dis')[0].split('_')[1] with open(disfile) as f: lines=[l.strip() for l in f.readlines()] try: ind = lines.index('*TYPE') disperser_type = (lines[ind + 1]).lower() except ValueError: raise ValueError("Unknown disperser type in {0}".format(disfile)) if disperser_type == 'gratingdata': d = dict.fromkeys(['groove_density', 'theta_z', 'theta_y', 'theta_x', 'tilt_y']) elif disperser_type == 'prismdata': d = dict.fromkeys(['tref', 'pref', 'angle', 'coefformula', 'thermalcoef', 'wbound' 'theta_z', 'theta_y', 'theta_x', 'tilt_y']) d.update(ref_kw) try: ind = lines.index('*GRATINGNAME') grating_name = lines[ind + 1] except ValueError: grating_name = 'PRISM' #for line in lines: ind = lines.index('*THETAZ') d['theta_z'] = float(lines[ind + 1]) / 3600. # in degrees ind = lines.index('*THETAX') d['theta_x'] = float(lines[ind + 1]) / 3600. # in degrees ind = lines.index('*THETAY') d['theta_y'] = float(lines[ind + 1]) / 3600. # in degrees ind = lines.index('*TILTY') d['tilt_y'] = float(lines[ind + 1]) # in degrees try: ind = lines.index('*TILTX') d['tilt_x'] = float(lines[ind + 1]) # in degrees except ValueError: d['tilt_x'] = 0.0 if disperser_type == 'gratingdata': ind = lines.index('*GROOVEDENSITY') d['groove_density'] = float(lines[ind + 1]) elif disperser_type == 'prismdata': ind = lines.index('*ANGLE') d['angle'] = float(lines[ind + 1]) # in degrees ind = lines.index('*TREF') d['tref'] = float(lines[ind + 1]) # Temperature in K ind = lines.index('*PREF') d['pref'] = float(lines[ind + 1]) # Pressure in ATM ind = lines.index('*COEFFORMULA') coefs = np.array(lines[ind : ind+int(l[-1])], dtype=np.float) kcoef = coefs[::2] lcoef = coefs[1::2] d['lcoef'] = lcoef d['kcoef'] = kcoef # 6 coeffs - D0, D1, D2, E0, E1, lambdak ind = lines.index('*THERMALCOEF') coefs = lines[ind : ind+int(l[-1])] d['tcoef'] = [float(c) for c in coefs] ind = lines.index('*WBOUND') coefs = lines[ind : ind + 2] d['wbound'] = [float(c) for c in coefs] assert grating_name in tiltyfile assert grating_name in tiltxfile tiltyd = disperser_tilt(tiltyfile) tiltxd = disperser_tilt(tiltxfile) d['gwa_tiltx'] = tiltyd d['gwa_tilty'] = tiltxd fasdf = AsdfFile() fasdf.tree = d fasdf.add_history_entry("Build 6") fasdf.write_to(outname) return fasdf
def pcf2asdf(pcffile, outname, ref_file_kw): """ Create an asdf reference file with the transformation coded in a NIRSPEC Camera.pcf or Collimator*.pcf file. - forward (team): sky to detector - Shift inputs to input_rotation_center - Rotate inputs - Scale inputs - Shift inputs to output_rot_center - Apply polynomial distortion - backward_team (team definition) detector to sky - Apply polynomial distortion - Shift inputs to output_rot_center - Scale inputs - Rotate inputs - Shift inputs to input_rotation_center WCS implementation - forward: detector to sky - equivalent to backward_team - backward: sky to detector - equivalent to forward_team Parameters ---------- pcffile : str one of the NIRSPEC ".pcf" reference files provided by the IDT team. "pcf" stands for "polynomial coefficients fit" outname : str Name of reference file to be wriiten to disk. Returns ------- fasdf : AsdfFile AsdfFile object Examples -------- >>> pcf2asdf("Camera.pcf", "camera.asdf") """ linear_det2sky = linear_from_pcf_det2sky(pcffile) with open(pcffile) as f: lines = [l.strip() for l in f.readlines()] degree = int(lines[lines.index('*FitOrder') + 1]) xcoeff_index = lines.index('*xForwardCoefficients 21 2') xlines = lines[xcoeff_index + 1: xcoeff_index + 22] xcoeff_forward = coeffs_from_pcf(degree, xlines) x_poly_backward = models.Polynomial2D(degree, name='x_poly_backward', **xcoeff_forward) ycoeff_index = lines.index('*yForwardCoefficients 21 2') ycoeff_forward = coeffs_from_pcf(degree, lines[ycoeff_index + 1: ycoeff_index + 22]) y_poly_backward = models.Polynomial2D(degree, name='y_poly_backward', **ycoeff_forward) xcoeff_index = lines.index('*xBackwardCoefficients 21 2') xcoeff_backward = coeffs_from_pcf(degree, lines[xcoeff_index + 1: xcoeff_index + 22]) x_poly_forward = models.Polynomial2D(degree, name='x_poly_forward', **xcoeff_backward) ycoeff_index = lines.index('*yBackwardCoefficients 21 2') ycoeff_backward = coeffs_from_pcf(degree, lines[ycoeff_index + 1: ycoeff_index + 22]) y_poly_forward = models.Polynomial2D(degree, name='y_poly_forward', **ycoeff_backward) x_poly_forward.inverse = x_poly_backward y_poly_forward.inverse = y_poly_backward output2poly_mapping = Identity(2, name='output_mapping') output2poly_mapping.inverse = Mapping([0, 1, 0, 1]) input2poly_mapping = Mapping([0, 1, 0, 1], name='input_mapping') input2poly_mapping.inverse = Identity(2) model_poly = input2poly_mapping | (x_poly_forward & y_poly_forward) | output2poly_mapping model = model_poly | linear_det2sky f = AsdfFile() f.tree = ref_file_kw.copy() f.add_history_entry("Build 6") f.tree['model'] = model f.write_to(outname)
def ifupost2asdf(ifupost_files, outname, ref_kw): """ Create a reference file of type ``ifupost`` . Combines all IDT ``IFU-POST`` reference files in one ASDF file. forward direction : MSA to Collimator backward_direction: Collimator to MSA Parameters ---------- ifupost_files : list Names of all ``IFU-POST`` IDT reference files outname : str Name of output ``ASDF`` file """ fa = AsdfFile() fa.tree = ref_kw for fifu in ifupost_files: n = int((fifu.split('IFU-POST_')[1]).split('.pcf')[0]) fa.tree[n] = {} with open(fifu) as f: lines = [l.strip() for l in f.readlines()] factors = lines[lines.index('*Factor 2') + 1].split() rotation_angle = float(lines[lines.index('*Rotation') + 1]) input_rot_center = lines[lines.index('*InputRotationCentre 2') + 1].split() output_rot_center = lines[lines.index('*OutputRotationCentre 2') + 1].split() linear_sky2det = homothetic_sky2det(input_rot_center, rotation_angle, factors, output_rot_center) degree = int(lines[lines.index('*FitOrder') + 1]) xcoeff_index = lines.index('*xForwardCoefficients 21 2') xlines = lines[xcoeff_index + 1:xcoeff_index + 22] xcoeff_forward = coeffs_from_pcf(degree, xlines) x_poly_forward = models.Polynomial2D(degree, name='x_poly_forward', **xcoeff_forward) ycoeff_index = lines.index('*yForwardCoefficients 21 2') ycoeff_forward = coeffs_from_pcf( degree, lines[ycoeff_index + 1:ycoeff_index + 22]) y_poly_forward = models.Polynomial2D(degree, name='y_poly_forward', **ycoeff_forward) xcoeff_index = lines.index('*xBackwardCoefficients 21 2') xcoeff_backward = coeffs_from_pcf( degree, lines[xcoeff_index + 1:xcoeff_index + 22]) x_poly_backward = models.Polynomial2D(degree, name='x_poly_backward', **xcoeff_backward) ycoeff_index = lines.index('*yBackwardCoefficients 21 2') ycoeff_backward = coeffs_from_pcf( degree, lines[ycoeff_index + 1:ycoeff_index + 22]) y_poly_backward = models.Polynomial2D(degree, name='y_poly_backward', **ycoeff_backward) output2poly_mapping = Identity(2, name='output_mapping') output2poly_mapping.inverse = Mapping([0, 1, 0, 1]) input2poly_mapping = Mapping([0, 1, 0, 1], name='input_mapping') input2poly_mapping.inverse = Identity(2) model_poly = input2poly_mapping | ( x_poly_forward & y_poly_forward) | output2poly_mapping model = linear_sky2det | model_poly fa.tree[n]['model'] = model fa.add_history_entry("Build 6") asdffile = fa.write_to(outname) return asdffile
def fpa2asdf(fpafile, outname, ref_kw): """ Create an asdf reference file with the FPA description. The CDP2 delivery includes a fits file - "FPA.fpa" which is the input to this function. This file is converted to asdf and is a reference file of type "FPA". nirspec_fs_ref_tools.fpa2asdf('Ref_Files/CoordTransform/Description/FPA.fpa', 'fpa.asdf') Parameters ---------- fpafile : str A fits file with FPA description (FPA.fpa) outname : str Name of output ASDF file. """ with open(fpafile) as f: lines = [l.strip() for l in f.readlines()] # NRS1 ind = lines.index("*SCA491_PitchX") nrs1_pitchx = float(lines[ind+1]) ind = lines.index("*SCA491_PitchY") nrs1_pitchy = float(lines[ind+1]) ind = lines.index("*SCA491_RotAngle") nrs1_angle = float(lines[ind+1]) ind = lines.index("*SCA491_PosX") nrs1_posx = float(lines[ind+1]) ind = lines.index("*SCA491_PosY") nrs1_posy = float(lines[ind+1]) # NRS2 ind = lines.index("*SCA492_PitchX") nrs2_pitchx = float(lines[ind+1]) ind = lines.index("*SCA492_PitchY") nrs2_pitchy = float(lines[ind+1]) ind = lines.index("*SCA492_RotAngle") nrs2_angle = float(lines[ind+1]) ind = lines.index("*SCA492_PosX") nrs2_posx = float(lines[ind+1]) ind = lines.index("*SCA492_PosY") nrs2_posy = float(lines[ind+1]) tree = ref_kw.copy() # NRS1 Sky to Detector scaling = np.array([[1/nrs1_pitchx, 0], [0, 1/nrs1_pitchy]]) rotmat = models.Rotation2D._compute_matrix(-nrs1_angle) matrix = np.dot(rotmat, scaling) aff = models.AffineTransformation2D(matrix, name='fpa_affine_sky2detector') nrs1_sky2det = models.Shift(-nrs1_posx, name='fpa_shift_x') & \ models.Shift(-nrs1_posy, name='fpa_shift_y') | aff # NRS1 Detector to Sky rotmat = models.Rotation2D._compute_matrix(-nrs1_angle) scaling = np.array([[nrs1_pitchx, 0], [0, nrs1_pitchy]]) matrix = np.dot(rotmat, scaling) aff = models.AffineTransformation2D(matrix, name='fpa_affine_detector2sky') nrs1_det2sky = aff | models.Shift(nrs1_posx, name='fpa_shift_x_det2sky') & \ models.Shift(nrs1_posy, name='fpa_shift_y_det2sky') nrs1_det2sky.inverse = nrs1_sky2det # NRS2 Sky to Detector scaling = np.array([[-1/nrs2_pitchx, 0], [0, -1/nrs2_pitchy]]) rotmat = models.Rotation2D._compute_matrix(-nrs2_angle) matrix = np.dot(rotmat, scaling) aff = models.AffineTransformation2D(matrix, name='fpa_affine_sky2detector') nrs2_sky2det = models.Shift(-nrs2_posx, name='fpa_shixft_x') & \ models.Shift(-nrs2_posy, name='fpa_shift_y') | aff # NRS2 Detector to Sky rotmat = models.Rotation2D._compute_matrix(nrs2_angle) scaling = np.array([[-nrs2_pitchx, 0], [0, -nrs2_pitchy]]) matrix = np.dot(rotmat, scaling) aff = models.AffineTransformation2D(matrix, name='fpa_affine_detector2sky') nrs2_det2sky = aff | models.Shift(nrs2_posx, name='fpa_shift_x_det2sky') & \ models.Shift(nrs2_posy, name='fpa_shift_y_det2sky') nrs2_det2sky.inverse = nrs2_sky2det tree['NRS1'] = nrs1_det2sky tree['NRS2'] = nrs2_det2sky fasdf = AsdfFile() fasdf.tree = tree fasdf.add_history_entry("Build 6") fasdf.write_to(outname) return fasdf
def create_nircam_distortion(coefffile, detector, aperture, opgsname, outname): """ Create an asdf reference file with all distortion components for the NIRCam imager. NOTE: The IDT has not provided any distortion information. The files are constructed using ISIM transformations provided/(computed?) by the TEL team which they use to create the SIAF file. These reference files should be replaced when/if the IDT provides us with distortion. Parameters ---------- detector : str NRCB1, NRCB2, NRCB3, NRCB4, NRCB5, NRCA1, NRCA2, NRCA3, NRCA4, NRCA5 aperture : str Name of the aperture/subarray. (e.g. FULL, SUB160, SUB320, SUB640, GRISM_F322W2) outname : str Name of output file. Examples -------- """ numdet = detector[-1] module = detector[-2] channel = 'SHORT' if numdet == '5': channel = 'LONG' full_aperture = detector + '_' + aperture #"Forward' transformations. science --> ideal --> V2V3 sci2idlx, sci2idly, sciunit, idlunit = read_siaf_table.get_siaf_transform(coefffile,full_aperture,'science','ideal', 5) idl2v2v3x, idl2v2v3y = read_siaf_table.get_siaf_v2v3_transform(coefffile,full_aperture,from_system='ideal') #'Reverse' transformations. V2V3 --> ideal --> science v2v32idlx, v2v32idly = read_siaf_table.get_siaf_v2v3_transform(coefffile,full_aperture,to_system='ideal') idl2scix, idl2sciy, idlunit, sciunit = read_siaf_table.get_siaf_transform(coefffile,full_aperture,'ideal','science', 5) #Map the models together to make a single transformation model = Mapping([0, 1, 0, 1]) | sci2idlx & sci2idly | Mapping([0, 1, 0, 1]) | idl2v2v3x & idl2v2v3y model_inv = Mapping([0, 1, 0, 1]) | v2v32idlx & v2v32idly | Mapping([0, 1, 0, 1]) | idl2scix & idl2sciy model.inverse = model_inv #In the reference file headers, we need to switch NRCA5 to NRCALONG, and same #for module B. if detector[-1] == '5': detector = detector[0:4] + 'LONG' tree = {"TITLE": "NIRCAM Distortion", "TELESCOP": "JWST", "INSTRUMENT": "NIRCAM", "PEDIGREE": "GROUND", "REFTYPE" : "DISTORTION", "AUTHOR": "B. Hilbert", "DETECTOR": detector, "MODULE": module, "CHANNEL": channel, "SUBARRAY": opgsname, "DESCRIP": "Distortion model function created from SIAF coefficients", "EXP_TYPE": "NRC_IMAGE", "USEAFTER": "2014-01-01T00:00:00", "model": model } fasdf = AsdfFile() fasdf.tree = tree sdict = {'name':'nircam_reftools.py','author':'B.Hilbert','homepage':'https://github.com/spacetelescope/jwreftools','version':'0.7'} fasdf.add_history_entry("File created from a file of distortion coefficients, NIRCam_SIAF_2016-09-29.csv, provided by Colin Cox in October 2016. Software used: https://github.com/spacetelescope/jwreftools",software=sdict) fasdf.write_to(outname)
def create_nircam_distortion(coefffile, detector, aperture, opgsname, outname): """ Create an asdf reference file with all distortion components for the NIRCam imager. NOTE: The IDT has not provided any distortion information. The files are constructed using ISIM transformations provided/(computed?) by the TEL team which they use to create the SIAF file. These reference files should be replaced when/if the IDT provides us with distortion. Parameters ---------- detector : str NRCB1, NRCB2, NRCB3, NRCB4, NRCB5, NRCA1, NRCA2, NRCA3, NRCA4, NRCA5 aperture : str Name of the aperture/subarray. (e.g. FULL, SUB160, SUB320, SUB640, GRISM_F322W2) outname : str Name of output file. Examples -------- """ numdet = detector[-1] module = detector[-2] channel = 'SHORT' if numdet == '5': channel = 'LONG' full_aperture = detector + '_' + aperture #"Forward' transformations. science --> ideal --> V2V3 sci2idlx, sci2idly, sciunit, idlunit = read_siaf_table.get_siaf_transform( coefffile, full_aperture, 'science', 'ideal', 5) idl2v2v3x, idl2v2v3y = read_siaf_table.get_siaf_v2v3_transform( coefffile, full_aperture, from_system='ideal') #'Reverse' transformations. V2V3 --> ideal --> science v2v32idlx, v2v32idly = read_siaf_table.get_siaf_v2v3_transform( coefffile, full_aperture, to_system='ideal') idl2scix, idl2sciy, idlunit, sciunit = read_siaf_table.get_siaf_transform( coefffile, full_aperture, 'ideal', 'science', 5) #Map the models together to make a single transformation model = Mapping([0, 1, 0, 1]) | sci2idlx & sci2idly | Mapping( [0, 1, 0, 1]) | idl2v2v3x & idl2v2v3y model_inv = Mapping([0, 1, 0, 1]) | v2v32idlx & v2v32idly | Mapping( [0, 1, 0, 1]) | idl2scix & idl2sciy model.inverse = model_inv #In the reference file headers, we need to switch NRCA5 to NRCALONG, and same #for module B. if detector[-1] == '5': detector = detector[0:4] + 'LONG' tree = { "TITLE": "NIRCAM Distortion", "TELESCOP": "JWST", "INSTRUMENT": "NIRCAM", "PEDIGREE": "GROUND", "REFTYPE": "DISTORTION", "AUTHOR": "B. Hilbert", "DETECTOR": detector, "MODULE": module, "CHANNEL": channel, "SUBARRAY": opgsname, "DESCRIP": "Distortion model function created from SIAF coefficients", "EXP_TYPE": "NRC_IMAGE", "USEAFTER": "2014-01-01T00:00:00", "model": model } fasdf = AsdfFile() fasdf.tree = tree sdict = { 'name': 'nircam_reftools.py', 'author': 'B.Hilbert', 'homepage': 'https://github.com/spacetelescope/jwreftools', 'version': '0.7' } fasdf.add_history_entry( "File created from a file of distortion coefficients, NIRCam_SIAF_2016-09-29.csv, provided by Colin Cox in October 2016. Software used: https://github.com/spacetelescope/jwreftools", software=sdict) fasdf.write_to(outname)