def ifu_slicer2asdf(ifuslicer, outname): """ 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. """ ref_kw = common_reference_file_keywords("IFUSLICER", "NIRSPEC IFU SLICER description - CDP4") 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.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 fasdf = AsdfFile() fasdf.tree = tree fasdf.write_to(outname) return fasdf
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 prism2asdf(prifile, tiltyfile, tiltxfile, outname): """Create a NIRSPEC prism disperser reference file in ASDF format. Combine information stored in disperser_G?.dis and disperser_G?_TiltY.gtp files delievred by the IDT. Parameters ---------- prifile : list or str File with primary information for the PRSIM tiltyfile : str File with tilt_Y data, e.g. disperser_PRISM_TiltY.gtp. tiltxfile: str File with tilt_x data, e.g. disperser_PRISM_TiltX.gtp. outname : str Name of output ASDF file. Returns ------- fasdf : asdf.AsdfFile """ params = common_reference_file_keywords("PRISM", "NIRSPEC PRISM Model") flist = [prifile, tiltyfile, tiltxfile] # translate the files for fname in flist: try: refparams = dict_from_file(fname) except: print("Disperser file was not converted.") raise pdict = {} coeffs = {} parts = fname.lower().split(".")[0] ref = str("_".join(parts.split("_")[1:])) if "pri" not in fname: try: for i, c in enumerate(refparams['CoeffsTemperature00']): coeffs['c' + str(i)] = c pdict['tilt_model'] = models.Polynomial1D(len(coeffs)-1, **coeffs) del refparams['CoeffsTemperature00'] except KeyError: print("Missing CoeffsTemperature in {0}".format(fname)) raise # store the rest of the keys for k, v in refparams.items(): pdict[k] = v print(pdict) params[ref] = pdict fasdf = AsdfFile() fasdf.tree = params fasdf.write_to(outname) return fasdf
def ifupost2asdf(ifupost_files, outname): """ 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 """ ref_kw = common_reference_file_keywords("IFUPOST", "NIRSPEC IFU-POST transforms - CDP4") 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 asdffile = fa.write_to(outname) return asdffile
def pcf_forward(pcffile, outname): """ Create the **IDT** forward transform from collimator to gwa. """ with open(pcffile) as f: lines = [l.strip() for l in f.readlines()] factors = lines[lines.index('*Factor 2') + 1].split() # factor==1/factor in backward msa2ote direction and factor==factor in sky2detector direction scale = models.Scale(float(factors[0]), name="x_scale") & \ models.Scale(float(factors[1]), name="y_scale") rotation_angle = lines[lines.index('*Rotation') + 1] # The minius sign here is because astropy.modeling has the opposite direction of rotation than the idl implementation rotation = models.Rotation2D(-float(rotation_angle), name='rotation') # Here the model is called "output_shift" but in the team version it is the "input_shift". input_rot_center = lines[lines.index('*InputRotationCentre 2') + 1].split() input_rot_shift = models.Shift(-float(input_rot_center[0]), name='input_x_shift') & \ models.Shift(-float(input_rot_center[1]), name='input_y_shift') # Here the model is called "input_shift" but in the team version it is the "output_shift". output_rot_center = lines[lines.index('*OutputRotationCentre 2') + 1].split() output_rot_shift = models.Shift(float(output_rot_center[0]), name='output_x_shift') & \ models.Shift(float(output_rot_center[1]), name='output_y_shift') 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) x_poly_forward.inverse = x_poly_backward y_poly_forward.inverse = y_poly_backward poly_mapping1 = Mapping((0, 1, 0, 1)) poly_mapping1.inverse = Identity(2) poly_mapping2 = Identity(2) poly_mapping2.inverse = Mapping((0, 1, 0, 1)) model = input_rot_shift | rotation | scale | output_rot_shift | \ poly_mapping1 | x_poly_forward & y_poly_forward | poly_mapping2 f = AsdfFile() f.tree = {'model': model} f.write_to(outname)
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, outformat): 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) #,all_array_storage=outformat)
def create_v23(reftype, detector, band, channels, data, name): """ Create the transform from MIRI Local to telescope V2/V3 system for all channels. """ channel = "".join([ch[0] for ch in channels]) 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": "N. Dencheva" } 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.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") scalex_nrs1 = models.Scale(1 / float(lines[ind + 1]), name='fpa_scale_x') ind = lines.index("*SCA491_PitchY") scaley_nrs1 = models.Scale(1 / float(lines[ind + 1]), name='fpa_scale_y') ind = lines.index("*SCA491_RotAngle") rot_nrs1 = models.Rotation2D(np.rad2deg(-float(lines[ind + 1])), name='fpa_rotation') ind = lines.index("*SCA491_PosX") shiftx_nrs1 = models.Shift(-float(lines[ind + 1]), name='fpa_shift_x') ind = lines.index("*SCA491_PosY") shifty_nrs1 = models.Shift(-float(lines[ind + 1]), name='fpa_shift_y') # NRS2 ind = lines.index("*SCA492_PitchX") scalex_nrs2 = models.Scale(1 / float(lines[ind + 1]), name='fpa_scale_x') ind = lines.index("*SCA492_PitchY") scaley_nrs2 = models.Scale(1 / float(lines[ind + 1]), name='fpa_scale_y') ind = lines.index("*SCA492_RotAngle") rot_nrs2 = models.Rotation2D(np.rad2deg(float(lines[ind + 1])), name='fpa_rotation') ind = lines.index("*SCA492_PosX") shiftx_nrs2 = models.Shift(-float(lines[ind + 1]), name='fpa_shift_x') ind = lines.index("*SCA492_PosY") shifty_nrs2 = models.Shift(-float(lines[ind + 1]), name='fpa_shift_y') tree = ref_kw.copy() tree['NRS1'] = (shiftx_nrs1 & shifty_nrs1) | rot_nrs1 | (scalex_nrs1 & scaley_nrs1) tree['NRS2'] = (shiftx_nrs2 & shifty_nrs2) | rot_nrs2 | (scalex_nrs2 & scaley_nrs2) fasdf = AsdfFile() fasdf.tree = tree fasdf.write_to(outname) return fasdf
def create_specwcs_file(reftype, detector, band, channel, lmodel, name, author, useafter, description): tree = create_reffile_header(reftype, detector, band, channel, author, useafter, description) tree['subarray'] = "N/A" tree['filename'] = name tree['model'] = lmodel 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 create_distortion_file(reftype, detector, band, channel, data, name): tree = create_reffile_header(reftype, detector, band, channel) adata, bdata, xdata, ydata, sdata1, sdata2 = data tree['alpha_model'] = adata tree['beta_model'] = bdata tree['x_model'] = xdata tree['y_model'] = ydata tree['slice_model'] = {str(channel[0])+band: sdata1, str(channel[1])+band: sdata2} f = AsdfFile() f.tree = tree f.write_to(name)
def create_wavelengthrange_file(name): f = AsdfFile() #wavelengthrange = {'1SHORT': (4.88, 5.77), #'1MEDIUM': (5.64, 6.67), #'1LONG': (6.50, 7.70), #'2SHORT': (7.47, 8.83), #'2MEDIUM': (8.63, 10.19), #'2LONG': (9.96, 11.77), #'3SHORT': (11.49, 13.55), #'3MEDIUM': (13.28, 15.66), #'3LONG': (15.34, 18.09), #'4SHORT': (17.60, 21.00), #'4MEDIUM': (20.51, 24.48), #'4LONG': (23.92, 28.55) #} # 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 = { "instrument": "MIRI", "exp_type": "MIR_MRS", "pedigree": "GROUND", "title": "MIRI IFU model - based on CDP-4", "reftype": "WAVELENGTHRANGE", "author": "N. Dencheva" } 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.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") scalex_nrs1 = models.Scale(1/float(lines[ind+1]), name='fpa_scale_x') ind = lines.index("*SCA491_PitchY") scaley_nrs1 = models.Scale(1/float(lines[ind+1]), name='fpa_scale_y') ind = lines.index("*SCA491_RotAngle") rot_nrs1 = models.Rotation2D(np.rad2deg(-float(lines[ind+1])), name='fpa_rotation') ind = lines.index("*SCA491_PosX") shiftx_nrs1 = models.Shift(-float(lines[ind+1]), name='fpa_shift_x') ind = lines.index("*SCA491_PosY") shifty_nrs1 = models.Shift(-float(lines[ind+1]), name='fpa_shift_y') # NRS2 ind = lines.index("*SCA492_PitchX") scalex_nrs2 = models.Scale(1/float(lines[ind+1]), name='fpa_scale_x') ind = lines.index("*SCA492_PitchY") scaley_nrs2 = models.Scale(1/float(lines[ind+1]), name='fpa_scale_y') ind = lines.index("*SCA492_RotAngle") rot_nrs2 = models.Rotation2D(np.rad2deg(float(lines[ind+1])), name='fpa_rotation') ind = lines.index("*SCA492_PosX") shiftx_nrs2 = models.Shift(-float(lines[ind+1]), name='fpa_shift_x') ind = lines.index("*SCA492_PosY") shifty_nrs2 = models.Shift(-float(lines[ind+1]), name='fpa_shift_y') tree = ref_kw.copy() tree['NRS1'] = (shiftx_nrs1 & shifty_nrs1) | rot_nrs1 | (scalex_nrs1 & scaley_nrs1) tree['NRS2'] = (shiftx_nrs2 & shifty_nrs2) | rot_nrs2 | (scalex_nrs2 & scaley_nrs2) fasdf = AsdfFile() fasdf.tree = tree 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_distortion_file(reftype, detector, band, channel, data, name): tree = create_reffile_header(reftype, detector, band, channel) adata, bdata, xdata, ydata, sdata1, sdata2 = data tree['alpha_model'] = adata tree['beta_model'] = bdata tree['x_model'] = xdata tree['y_model'] = ydata tree['slice_model'] = { str(channel[0]) + band: sdata1, str(channel[1]) + band: sdata2 } f = AsdfFile() f.tree = tree 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 create_wavelengthrange_file(name): f = AsdfFile() #wavelengthrange = {'1SHORT': (4.88, 5.77), #'1MEDIUM': (5.64, 6.67), #'1LONG': (6.50, 7.70), #'2SHORT': (7.47, 8.83), #'2MEDIUM': (8.63, 10.19), #'2LONG': (9.96, 11.77), #'3SHORT': (11.49, 13.55), #'3MEDIUM': (13.28, 15.66), #'3LONG': (15.34, 18.09), #'4SHORT': (17.60, 21.00), #'4MEDIUM': (20.51, 24.48), #'4LONG': (23.92, 28.55) #} # 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 = { "instrument": "MIRI", "exp_type": "MIR_MRS", "pedigree": "GROUND", "title": "MIRI IFU model - based on CDP-4", "reftype": "WAVELENGTHRANGE", "author": "N. Dencheva" } 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.write_to(name)
def create_miri_imager_filter_offset(distfile, outname): """ Create an asdf reference file with the filter offsets for the MIRI imager. Note: The IDT supplied distortion file lists sky to pixel as the forward transform. Since "forward" in the JWST pipeline is from pixel to sky, the offsets are taken with the opposite sign. Parameters ---------- distfile : str MIRI imager DISTORTION file provided by the IDT team. outname : str Name of reference file to be wriiten to disk. Returns ------- fasdf : AsdfFile AsdfFile object Examples ------- >>> create_miri_imager_filer_offset('MIRI_FM_MIRIMAGE_DISTORTION_03.02.00.fits', 'jwst_miri_filter_offset_0001.asdf') """ with fits.open(distfile) as f: data = f[9].data d = dict.fromkeys(data.field('FILTER')) for i in data: d[i[0]] = {'column_offset': -i[1], 'row_offset': -i[2]} tree = { "title": "MIRI imager filter offset - CDP4", "reftype": "FILTEROFFSET", "instrument": "MIRI", "detector": "MIRIMAGE", "pedigree": "GROUND", "author": "N. Dencheva", "exp_type": "MIR_IMAGE" } tree.update(d) f = AsdfFile() f.tree = tree f.write_to(outname)
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_miri_imager_filter_offset(distfile, outname): """ Create an asdf reference file with the filter offsets for the MIRI imager. Note: The IDT supplied distortion file lists sky to pixel as the forward transform. Since "forward" in the JWST pipeline is from pixel to sky, the offsets are taken with the opposite sign. Parameters ---------- distfile : str MIRI imager DISTORTION file provided by the IDT team. outname : str Name of reference file to be wriiten to disk. Returns ------- fasdf : AsdfFile AsdfFile object Examples ------- >>> create_miri_imager_filer_offset('MIRI_FM_MIRIMAGE_DISTORTION_03.02.00.fits', 'jwst_miri_filter_offset_0001.asdf') """ with fits.open(distfile) as f: data = f[9].data d = dict.fromkeys(data.field('FILTER')) for i in data: d[i[0]] = {'column_offset': -i[1], 'row_offset': -i[2]} tree = {"title": "MIRI imager filter offset - CDP4", "reftype": "FILTEROFFSET", "instrument": "MIRI", "detector": "MIRIMAGE", "pedigree": "GROUND", "author": "N. Dencheva", "exp_type": "MIR_IMAGE" } tree.update(d) f = AsdfFile() f.tree = tree f.write_to(outname)
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. The CDP2 delivery includes a fits file - "MSA.msa". This file is converted to asdf and serves as a reference file of type "REGIONS". mas2asfdf("MSA.msa", "msa.asdf") --> creates an 85MB file 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') for j, slit in enumerate( ['S200A1', 'S200A2', 'S400A1', 'S1600A1', 'S200B1', 'IFU']): slitdata = data[j] t = {} for i, s in enumerate(['xcenter', 'ycenter', 'xsize', 'ysize']): t[s] = slitdata[i + 1] model = models.Scale(t['xsize']) & models.Scale(t['ysize']) | \ models.Shift(t['xcenter']) & models.Shift(t['ycenter']) | \ slitrot | shiftx & shifty t['model'] = model tree[slit] = t f.close() fasdf = AsdfFile() fasdf.tree = tree fasdf.write_to(outname) return fasdf
def msa2asdf(msafile, outname, ref_kw): """ Create an asdf reference file with the MSA description. The CDP2 delivery includes a fits file - "MSA.msa". This file is converted to asdf and serves as a reference file of type "REGIONS". mas2asfdf("MSA.msa", "msa.asdf") --> creates an 85MB file 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') for j, slit in enumerate(['S200A1', 'S200A2', 'S400A1', 'S1600A1', 'S200B1', 'IFU']): slitdata = data[j] t = {} for i, s in enumerate(['xcenter', 'ycenter', 'xsize', 'ysize']): t[s] = slitdata[i+1] model = models.Scale(t['xsize']) & models.Scale(t['ysize']) | \ models.Shift(t['xcenter']) & models.Shift(t['ycenter']) | \ slitrot | shiftx & shifty t['model'] = model tree[slit] = t f.close() fasdf = AsdfFile() fasdf.tree = tree fasdf.write_to(outname) return fasdf
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 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 fasdf = AsdfFile() fasdf.tree = tree fasdf.write_to(outname) return fasdf
def create_distortion_file(reftype, detector, band, channel, channels, data, name, author, useafter, description, outformat): description = 'MIRI MRS Distortion Maps' 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-6", "reftype": reftype, "author": author, "useafter": useafter, "description": description } """ tree['filename'] = name # Split the provided data vector into its pieces adata, bdata, xdata, ydata, bzero, bdel, ab_v23, v23_ab = data """ Construct the xy -> alpha,beta model """ tree['alpha_model'] = adata tree['beta_model'] = bdata tree['x_model'] = xdata tree['y_model'] = ydata tree['bzero'] = bzero tree['bdel'] = bdel """ Create the transform from MIRI Local to telescope V2/V3 system for all channels. """ channel = "".join([ch[0] for ch in channels]) m = {} # Read in coefficients from the tables. Note that we'll flip the coefficient # ordering since they were set up for column-major indexing (IDL) but we're working in # python (row-major) # ab -> v2 transform for first channel c0_0, c1_0, c0_1, 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") # v2,v3 -> a transform for first channel c0_0, c1_0, c0_1, 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") # ab -> v3 transform for first channel c0_0, c1_0, c0_1, 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") # v2,v3 -> b transform for first channel c0_0, c1_0, c0_1, 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") # ab -> v2 transform for second channel c0_0, c1_0, c0_1, 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") # v2,v3 -> a transform for second channel c0_0, c1_0, c0_1, 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") # ab -> v3 transform for second channel c0_0, c1_0, c0_1, 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") # v2,v3 -> b transform for second channel c0_0, c1_0, c0_1, 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") # Transforms from the CDP only went to XAN,YAN, now need a transform to V2,V3 # Mapping to transform from XAN,YAN in arcmin to V2,V3 in arcsec xanyan_to_v2v3 = models.Identity(1) & (models.Scale(-1) | models.Shift( -7.8)) | models.Scale(60.) & models.Scale(60.) # Since the matrix transforms need a 4-element input we need a mapping # to go from (0,1) to (0,1,0,1) map = models.Mapping((0, 1, 0, 1), n_inputs=2) # Put the mappings all together ch1 = map | ch1_v2 & ch1_v3 | xanyan_to_v2v3 ch2 = map | ch2_v2 & ch2_v3 | xanyan_to_v2v3 # And make the inverse mapping ch1.inverse = xanyan_to_v2v3.inverse | map | ch1_a & ch1_b ch2.inverse = xanyan_to_v2v3.inverse | map | ch2_a & ch2_b #pdb.set_trace() m[channels[0]] = ch1 m[channels[1]] = ch2 tree['abv2v3_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) #,all_array_storage=outformat)
def create_nircam_distortion(channel, module, detector, outname): """ Create an asdf reference file with all distortion components for the MIRI 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 ---------- channel : str header['channel'] or ImageModel.meta.imstrument.channel ("SHORT" or "LONG") module : str header['module'] or ImageModel.meta.imstrument.module ("A" or "B") detector : str NRCB1, NRCB2, NRCB3, NRCB4, NRCB5, NRCA1, NRCA2, NRCA3, NRCA4, NRCA5 (NRCA5 and NRCB5 are the LW detectors? or simply NRCA and NRCB) outname : str Name of output file. Examples -------- """ if channel == "SHORT": ch = "SW" elif channel == "LONG": ch = "LW" else: raise ValueError("Channel {0} not found".format(ch)) numdet = detector[-1] det = detector[-2] if numdet == '5': numdet = "1" from_system = "NIRCAM" + det + ch + "_" + numdet to_system = "NIRCAM" + det + ch amodel, bmodel, startunit, endunit = read_siaf_table.get_siaf_transform( from_system, to_system, 1, 1) to_otesky_x, to_otesky_y, startunit, endunit = read_siaf_table.get_siaf_transform( to_system, "OTESKY", 5, 5) ote2nrcx, ote2nrcy, startunit, endunit = read_siaf_table.get_siaf_transform( "OTESKY", to_system, 5, 5) nrc2detx, nrc2dety, startunit, endunit = read_siaf_table.get_siaf_transform( to_system, from_system, 1, 1) model = Mapping([0, 1, 0, 1]) | amodel & bmodel | Mapping([0, 1, 0, 1]) | \ to_otesky_x & to_otesky_y model_inv = Mapping([0, 1, 0, 1]) | ote2nrcx & ote2nrcy | Mapping((0, 1, 0, 1)) | \ nrc2detx & nrc2dety model.inverse = model_inv tree = {"title": "NIRCAM Distortion", "instrument": "NIRCAM", "pedigree": "GROUND", "reftype" : "DISTORTION", "author": "N. Dencheva", "detector": detector, "module": module, "channel": channel, "exp_type": "NRC_IMAGE", "model": model } fasdf = AsdfFile() fasdf.tree = tree fasdf.write_to(outname)
def create_specwcs_file(reftype, detector, band, channel, lmodel, name): tree = create_reffile_header(reftype, detector, band, channel) tree['model'] = lmodel f = AsdfFile() f.tree = tree f.write_to(name)
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.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 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()] d = dict.fromkeys(['groove_density', 'theta_z', 'theta_y', 'theta_x', 'tilt_y']) d.update(ref_kw) for line in lines: ind = lines.index('*GRATINGNAME') grating_name = lines[ind + 1] ind = lines.index('*GROOVEDENSITY') d['groove_density'] = float(lines[ind + 1]) 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 assert grating_name in tiltyfile assert grating_name in tiltxfile with open(tiltyfile) as f: s = f.read() tiltyd = {} vals = s.split('*') for line in vals[::-1]: if line.startswith("CoeffsTemperature00"): l = line.split('\n') n = int(l[0].split()[1]) coeffs = {} for i , c in enumerate([float(c) for c in l[1:1+n]]): coeffs['c' + str(i)] = c tiltyd['tilt_model'] = models.Polynomial1D(n-1, **coeffs) elif line.startswith("Temperatures"): l = line.split('\n') n = int(l[0].split()[1]) coeffs = l[1:1+n] tiltyd['temperatures'] = [float(c) for c in coeffs] elif line.startswith("Zeroreadings"): l = line.split('\n') n = int(l[0].split()[1]) coeffs = l[1:1+n] tiltyd['zeroreadings'] = [float(c) for c in coeffs] elif line.startswith("Unit"): tiltyd['unit'] = line.split('\n')[1] with open(tiltxfile) as f: s = f.read() tiltxd = {} vals = s.split('*') for line in vals[::-1]: if line.startswith("CoeffsTemperature00"): l = line.split('\n') n = int(l[0].split()[1]) coeffs = {} for i , c in enumerate([float(c) for c in l[1:1+n]]): coeffs['c' + str(i)] = c tiltxd['tilt_model'] = models.Polynomial1D(n-1, **coeffs) elif line.startswith("Temperatures"): l = line.split('\n') n = int(l[0].split()[1]) coeffs = l[1:1+n] tiltxd['temperatures'] = [float(c) for c in coeffs] elif line.startswith("Zeroreadings"): l = line.split('\n') n = int(l[0].split()[1]) coeffs = l[1:1+n] tiltxd['zeroreadings'] = [float(c) for c in coeffs] elif line.startswith("Unit"): tiltxd['unit'] = line.split('\n')[1] d['gwa_tiltx'] = tiltyd d['gwa_tilty'] = tiltxd fasdf = AsdfFile() fasdf.tree = d fasdf.write_to(outname) return fasdf
def create_miri_imager_distortion(distfile, outname): """ Create an asdf reference file with all distortion components for the MIRI imager. The filter offsets are stored in a sepaate file. Note: The IDT supplied distortion file lists sky to pixel as the forward transform. Since "forward" in the JWST pipeline is from pixel to sky, the meaning of forward and inverse matrices and the order in which they are applied is switched. The order of operation from pixel to sky is: - Apply MI matrix - Apply Ai and BI matrices - Apply the TI matrix (this gives V2/V3 coordinates) Parameters ---------- distfile : str MIRI imager DISTORTION file provided by the IDT team. outname : str Name of reference file to be wriiten to disk. Returns ------- fasdf : AsdfFile AsdfFile object Examples -------- >>> create_miri_imager_distortion("MIRI_FM_MIRIMAGE_DISTORTION_03.02.00.fits", 'test.asdf') """ fdist = fits.open(distfile) mi_matrix = fdist[8].data mi_col = models.Polynomial1D(1, c0=mi_matrix[0, 2], c1=mi_matrix[0, 0], name="M_column_correction") mi_row = models.Polynomial1D(1, c0=mi_matrix[1, 2], c1=mi_matrix[1, 1], name="M_row_correction") m_matrix = fdist[4].data m_col = models.Polynomial1D(1, c0=m_matrix[0, 2], c1=m_matrix[0, 0]) m_row = models.Polynomial1D(1, c0=m_matrix[1, 2], c1=m_matrix[1, 1]) mi_col.inverse = m_col mi_row.inverse = m_row m_transform = mi_col & mi_row #mi_row & mi_col ai_matrix = fdist[6].data a_matrix = fdist[2].data col_poly = polynomial_from_coeffs_matrix(ai_matrix, name="A_correction") col_poly.inverse = polynomial_from_coeffs_matrix(a_matrix) bi_matrix = fdist[5].data b_matrix = fdist[1].data row_poly = polynomial_from_coeffs_matrix(bi_matrix, name="B_correction") row_poly.inverse = polynomial_from_coeffs_matrix(b_matrix) poly = col_poly & row_poly ti_matrix = fdist[7].data t_matrix = fdist[3].data ti_col = models.Polynomial2D(1, name='TI_column_correction') ti_col.parameters = ti_matrix[0][::-1] ti_row = models.Polynomial2D(1, name='TI_row_correction') ti_row.parameters = ti_matrix[1][::-1] t_col = models.Polynomial2D(1, name='T_column_correction') t_col.parameters = t_matrix[0][::-1] t_row = models.Polynomial2D(1, name='T_row_correction') t_row.parameters = t_matrix[1][::-1] ti_col.inverse = t_col ti_row.inverse = t_row t_transform = ti_row & ti_col mapping = models.Mapping([0, 1, 0, 1]) mapping.inverse = models.Identity(2) # ident is created here so that mapping can be assigned as inverse ident = models.Identity(2) ident.inverse = models.Mapping([0, 1, 0, 1]) poly2t_mapping = models.Mapping([0, 1, 0, 1]) poly2t_mapping.inverse = models.Mapping([0, 1, 0, 1]) distortion_transform = m_transform | mapping | poly | poly2t_mapping | t_transform | ident | models.Mapping( [1, 0]) fdist.close() f = AsdfFile() tree = { "title": "MIRI imager distortion - CDP4", "reftype": "DISTORTION", "instrument": "MIRI", "detector": "MIRIMAGE", "exp_type": "MIR_IMAGE", "pedigree": "GROUND", "author": "N. Dencheva", "model": distortion_transform } f.tree = tree fasdf = 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 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()] factors = lines[lines.index('*Factor 2') + 1].split() # factor==1/factor in backward msa2ote direction and == factor in ote2msa direction scale = models.Scale(1. / float(factors[0]), name='scale_x') & \ models.Scale(1 / float(factors[1]), name='scale_y') rotation_angle = lines[lines.index('*Rotation') + 1] rotation = models.Rotation2D(float(rotation_angle), name='rotation') input_rot_center = lines[lines.index('*InputRotationCentre 2') + 1].split() output_offset = models.Shift(float(input_rot_center[0]), name="output_x_shift") & \ models.Shift(float(input_rot_center[1]), name="output_y_shift") output_rot_center = lines[lines.index('*OutputRotationCentre 2') + 1].split() input_offset = models.Shift(-float(output_rot_center[0]), name="input_x_shift") & \ models.Shift(-float(output_rot_center[1]), name="input_y_shift") 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,))) 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,))) 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,))) 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,))) #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 fore_linear = (input_offset | rotation | scale | output_offset) fore_linear_inverse = fore_linear.inverse fore_linear.inverse = fore_linear_inverse & Identity(1) model = model_poly | fore_linear f = AsdfFile() f.tree = ref_kw.copy() f.tree['model'] = model 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 """ #t = {} disperser = disfile.split('.dis')[0].split('_')[1] with open(disfile) as f: lines = [l.strip() for l in f.readlines()] d = dict.fromkeys( ['groove_density', 'theta_z', 'theta_y', 'theta_x', 'tilt_y']) d.update(ref_kw) for line in lines: ind = lines.index('*GRATINGNAME') grating_name = lines[ind + 1] ind = lines.index('*GROOVEDENSITY') d['groove_density'] = float(lines[ind + 1]) 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 assert grating_name in tiltyfile assert grating_name in tiltxfile with open(tiltyfile) as f: s = f.read() tiltyd = {} vals = s.split('*') for line in vals[::-1]: if line.startswith("CoeffsTemperature00"): l = line.split('\n') n = int(l[0].split()[1]) coeffs = {} for i, c in enumerate([float(c) for c in l[1:1 + n]]): coeffs['c' + str(i)] = c tiltyd['tilt_model'] = models.Polynomial1D(n - 1, **coeffs) elif line.startswith("Temperatures"): l = line.split('\n') n = int(l[0].split()[1]) coeffs = l[1:1 + n] tiltyd['temperatures'] = [float(c) for c in coeffs] elif line.startswith("Zeroreadings"): l = line.split('\n') n = int(l[0].split()[1]) coeffs = l[1:1 + n] tiltyd['zeroreadings'] = [float(c) for c in coeffs] elif line.startswith("Unit"): tiltyd['unit'] = line.split('\n')[1] with open(tiltxfile) as f: s = f.read() tiltxd = {} vals = s.split('*') for line in vals[::-1]: if line.startswith("CoeffsTemperature00"): l = line.split('\n') n = int(l[0].split()[1]) coeffs = {} for i, c in enumerate([float(c) for c in l[1:1 + n]]): coeffs['c' + str(i)] = c tiltxd['tilt_model'] = models.Polynomial1D(n - 1, **coeffs) elif line.startswith("Temperatures"): l = line.split('\n') n = int(l[0].split()[1]) coeffs = l[1:1 + n] tiltxd['temperatures'] = [float(c) for c in coeffs] elif line.startswith("Zeroreadings"): l = line.split('\n') n = int(l[0].split()[1]) coeffs = l[1:1 + n] tiltxd['zeroreadings'] = [float(c) for c in coeffs] elif line.startswith("Unit"): tiltxd['unit'] = line.split('\n')[1] """ TODO: add prism specific coefficients, get_disperser_info.pro """ d['gwa_tiltx'] = tiltyd d['gwa_tilty'] = tiltxd fasdf = AsdfFile() fasdf.tree = d 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") """ with open(pcffile) as f: lines = [l.strip() for l in f.readlines()] factors = lines[lines.index('*Factor 2') + 1].split() scale = models.Scale(1 / float(factors[0]), name="x_scale") & \ models.Scale(1 / float(factors[1]), name="y_scale") rotation_angle = lines[lines.index('*Rotation') + 1] # Backward rotation is in the counter-clockwise direction as in modeling # Forward is clockwise backward_rotation = models.Rotation2D(float(rotation_angle), name='rotation') rotation = backward_rotation.copy() # Here the model is called "output_shift" but in the team version it is the "input_shift". input_rot_center = lines[lines.index('*InputRotationCentre 2') + 1].split() output_offset = models.Shift(float(input_rot_center[0]), name='output_x_shift') & \ models.Shift(float(input_rot_center[1]), name='output_y_shift') # Here the model is called "input_shift" but in the team version it is the "output_shift". output_rot_center = lines[lines.index('*OutputRotationCentre 2') + 1].split() input_offset = models.Shift(-float(output_rot_center[0]), name='input_x_shift') & \ models.Shift(-float(output_rot_center[1]), name='input_y_shift') 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 | input_offset | scale | rotation | output_offset f = AsdfFile() f.tree = ref_file_kw.copy() f.tree['model'] = model f.write_to(outname)
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() scale = models.Scale(1 / float(factors[0]), name="x_scale") & \ models.Scale(1 / float(factors[1]), name="y_scale") # this corresponds to modeling Rotation direction as is rotation_angle = lines[lines.index('*Rotation') + 1] rotation = models.Rotation2D(float(rotation_angle), name='rotation') input_rot_center = lines[lines.index('*InputRotationCentre 2 1') + 1].split() output_offset = models.Shift(float(input_rot_center[0]), name='output_x_shift') & \ models.Shift(float(input_rot_center[1]), name='output_y_shift') # Here the model is called "input_shift" but in the team version it is the "output_shift". output_rot_center = lines[lines.index('*OutputRotationCentre 2 1') + 1].split() input_offset = models.Shift(-float(output_rot_center[0]), name='input_x_shift') & \ models.Shift(-float(output_rot_center[1]), name='input_y_shift') degree = int(lines[lines.index('*FitOrder') + 1]) 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('*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) 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) 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) x_poly_forward.inverse = x_poly_backward y_poly_forward.inverse = y_poly_backward mlinear = input_offset | rotation | scale | output_offset 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.write_to(outname)
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 create_miri_imager_distortion(distfile, outname): """ Create an asdf reference file with all distortion components for the MIRI imager. The filter offsets are stored in a sepaate file. Note: The IDT supplied distortion file lists sky to pixel as the forward transform. Since "forward" in the JWST pipeline is from pixel to sky, the meaning of forward and inverse matrices and the order in which they are applied is switched. The order of operation from pixel to sky is: - Apply MI matrix - Apply Ai and BI matrices - Apply the TI matrix (this gives V2/V3 coordinates) Parameters ---------- distfile : str MIRI imager DISTORTION file provided by the IDT team. outname : str Name of reference file to be wriiten to disk. Returns ------- fasdf : AsdfFile AsdfFile object Examples -------- >>> create_miri_imager_distortion("MIRI_FM_MIRIMAGE_DISTORTION_03.02.00.fits", 'test.asdf') """ fdist = fits.open(distfile) mi_matrix = fdist[8].data mi_col = models.Polynomial1D(1, c0=mi_matrix[0, 2], c1=mi_matrix[0,0], name="M_column_correction") mi_row = models.Polynomial1D(1, c0=mi_matrix[1, 2], c1=mi_matrix[1,1], name="M_row_correction") m_matrix = fdist[4].data m_col = models.Polynomial1D(1, c0=m_matrix[0, 2], c1=m_matrix[0,0]) m_row = models.Polynomial1D(1, c0=m_matrix[1, 2], c1=m_matrix[1,1]) mi_col.inverse = m_col mi_row.inverse = m_row m_transform = mi_col & mi_row #mi_row & mi_col ai_matrix = fdist[6].data a_matrix = fdist[2].data col_poly = polynomial_from_coeffs_matrix(ai_matrix, name="A_correction") col_poly.inverse = polynomial_from_coeffs_matrix(a_matrix) bi_matrix = fdist[5].data b_matrix = fdist[1].data row_poly = polynomial_from_coeffs_matrix(bi_matrix, name="B_correction") row_poly.inverse = polynomial_from_coeffs_matrix(b_matrix) poly = col_poly & row_poly ti_matrix = fdist[7].data t_matrix = fdist[3].data ti_col = models.Polynomial2D(1, name='TI_column_correction') ti_col.parameters = ti_matrix[0][::-1] ti_row = models.Polynomial2D(1, name='TI_row_correction') ti_row.parameters = ti_matrix[1][::-1] t_col = models.Polynomial2D(1, name='T_column_correction') t_col.parameters = t_matrix[0][::-1] t_row = models.Polynomial2D(1, name='T_row_correction') t_row.parameters = t_matrix[1][::-1] ti_col.inverse = t_col ti_row.inverse = t_row t_transform = ti_row & ti_col mapping = models.Mapping([0, 1, 0, 1]) mapping.inverse = models.Identity(2) # ident is created here so that mapping can be assigned as inverse ident = models.Identity(2) ident.inverse = models.Mapping([0,1,0,1]) poly2t_mapping = models.Mapping([0, 1, 0, 1]) poly2t_mapping.inverse = models.Mapping([0, 1, 0, 1]) distortion_transform = m_transform | mapping | poly | poly2t_mapping | t_transform | ident fdist.close() f = AsdfFile() tree = {"title": "MIRI imager distortion - CDP4", "reftype": "DISTORTION", "instrument": "MIRI", "detector": "MIRIMAGE", "exp_type": "MIR_IMAGE", "pedigree": "GROUND", "author": "N. Dencheva", "model": distortion_transform } f.tree = tree fasdf = f.write_to(outname)
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 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 asdffile = f.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_regions_file(slices, detector, band, channel, name): tree = create_reffile_header("REGIONS", detector, band, channel) f = AsdfFile() tree['regions'] = slices f.tree = tree 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 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") """ with open(pcffile) as f: lines = [l.strip() for l in f.readlines()] factors = lines[lines.index('*Factor 2') + 1].split() scale = models.Scale(1 / float(factors[0]), name="x_scale") & \ models.Scale(1 / float(factors[1]), name="y_scale") rotation_angle = lines[lines.index('*Rotation') + 1] # Backward rotation is in the counter-clockwise direction as in modeling # Forward is clockwise backward_rotation = models.Rotation2D(float(rotation_angle), name='rotation') rotation = backward_rotation.copy() # Here the model is called "output_shift" but in the team version it is the "input_shift". input_rot_center = lines[lines.index('*InputRotationCentre 2') + 1].split() output_offset = models.Shift(float(input_rot_center[0]), name='output_x_shift') & \ models.Shift(float(input_rot_center[1]), name='output_y_shift') # Here the model is called "input_shift" but in the team version it is the "output_shift". output_rot_center = lines[lines.index('*OutputRotationCentre 2') + 1].split() input_offset = models.Shift(-float(output_rot_center[0]), name='input_x_shift') & \ models.Shift(-float(output_rot_center[1]), name='input_y_shift') 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 | input_offset |scale |rotation |output_offset f = AsdfFile() f.tree = ref_file_kw.copy() f.tree['model'] = model f.write_to(outname)
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 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()] factors = lines[lines.index('*Factor 2') + 1].split() # factor==1/factor in backward msa2ote direction and == factor in ote2msa direction scale = models.Scale(1. / float(factors[0]), name='scale_x') & \ models.Scale(1 / float(factors[1]), name='scale_y') rotation_angle = lines[lines.index('*Rotation') + 1] rotation = models.Rotation2D(float(rotation_angle), name='rotation') input_rot_center = lines[lines.index('*InputRotationCentre 2') + 1].split() output_offset = models.Shift(float(input_rot_center[0]), name="output_x_shift") & \ models.Shift(float(input_rot_center[1]), name="output_y_shift") output_rot_center = lines[lines.index('*OutputRotationCentre 2') + 1].split() input_offset = models.Shift(-float(output_rot_center[0]), name="input_x_shift") & \ models.Shift(-float(output_rot_center[1]), name="input_y_shift") 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,))) 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,))) 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,))) 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,))) #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 fore_linear = (input_offset | rotation | scale | output_offset) fore_linear_inverse = fore_linear.inverse fore_linear.inverse = fore_linear_inverse & Identity(1) model = model_poly | fore_linear f = AsdfFile() f.tree = ref_kw.copy() f.tree['model'] = model asdffile = f.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 = np.rad2deg(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 = np.rad2deg(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_sky2det = models.Shift(-nrs1_posx) & models.Shift(-nrs1_posy) | \ models.Rotation2D(-nrs1_angle) | \ models.Scale(1/nrs1_pitchx) & models.Scale(1/nrs1_pitchy) nrs1_det2sky = models.Rotation2D(nrs1_angle) | \ models.Scale(nrs1_pitchx) & models.Scale(nrs1_pitchy) | \ models.Shift(nrs1_posx) & models.Shift(nrs1_posy) nrs1_det2sky.inverse = nrs1_sky2det nrs2_sky2det = models.Shift(-nrs2_posx) & models.Shift(-nrs2_posy) | \ models.Rotation2D(-nrs2_angle) | \ models.Scale(1/nrs2_pitchx) & models.Scale(1/nrs2_pitchy) nrs2_det2sky = models.Rotation2D(nrs2_angle) | \ models.Scale(nrs2_pitchx) & models.Scale(nrs2_pitchy) | \ models.Shift(nrs2_posx) & models.Shift(nrs2_posy) nrs2_det2sky.inverse = nrs1_sky2det tree['NRS1'] = nrs1_det2sky tree['NRS2'] = nrs2_sky2det fasdf = AsdfFile() fasdf.tree = tree 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_v23(reftype, detector, band, channels, data, name): """ Create the transform from MIRI Local to telescope V2/V3 system for all channels. """ channel = "".join([ch[0] for ch in channels]) 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": "N. Dencheva" } 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.write_to(name)