Beispiel #1
0
def test_shutter_size_on_sky():
    """
    Test the size of a MOS shutter on sky is ~ .2 x .4 arcsec.
    """
    image = create_nirspec_mos_file()
    model = datamodels.ImageModel(image)
    msaconfl = get_file_path('msa_configuration.fits')

    model.meta.instrument.msa_metadata_file = msaconfl
    model.meta.instrument.msa_metadata_id = 12

    refs = create_reference_files(model)

    pipe = nirspec.create_pipeline(model, refs, slit_y_range=(-.5, .5))
    w = wcs.WCS(pipe)
    model.meta.wcs = w
    slit = w.get_transform('slit_frame', 'msa_frame').slits[0]
    wslit = nirspec.nrs_wcs_set_input(model, slit.name)
    virtual_corners_x = [-.5, -.5, .5, .5, -.5]
    virtual_corners_y = [-.5, .5, .5, -.5, -.5]
    input_lam = [2e-6] * 5

    slit2world = wslit.get_transform('slit_frame', 'world')
    ra, dec, lam = slit2world(virtual_corners_x, virtual_corners_y, input_lam)
    sky = coords.SkyCoord(ra * u.deg, dec * u.deg)
    sep_x = sky[0].separation(sky[3]).to(u.arcsec)
    sep_y = sky[0].separation(sky[1]).to(u.arcsec)

    assert sep_x.value > 0.193
    assert sep_x.value < 0.194
    assert sep_y.value > 0.45
    assert sep_y.value < 0.46
Beispiel #2
0
def test_nirspec_ifu_against_esa():
    """
    Test Nirspec IFU mode using CV3 reference files.
    """
    ref = fits.open(get_file_path('Trace_IFU_Slice_00_SMOS-MOD-G1M-17-5344175105_30192_JLAB88.fits'))

    # Test NRS1
    pyw = astwcs.WCS(ref['SLITY1'].header)
    hdul = create_nirspec_ifu_file("OPAQUE", "G140M")
    im = datamodels.ImageModel(hdul)
    im.meta.filename = "test_ifu.fits"
    refs = create_reference_files(im)

    pipe = nirspec.create_pipeline(im, refs, slit_y_range=[-.5, .5])
    w = wcs.WCS(pipe)
    im.meta.wcs = w
    # Test evaluating the WCS (slice 0)
    w0 = nirspec.nrs_wcs_set_input(im, 0)

    # get positions within the slit and the coresponding lambda
    slit1 = ref['SLITY1'].data # y offset on the slit
    lam = ref['LAMBDA1'].data
    # filter out locations outside the slit
    cond = np.logical_and(slit1 < .5, slit1 > -.5)
    y, x = cond.nonzero() # 0-based

    x, y = pyw.wcs_pix2world(x, y, 0)
    # The pipeline accepts 0-based cooridnates
    x -= 1
    y -= 1
    sca2world = w0.get_transform('sca', 'msa_frame')
    _, slit_y, lp = sca2world(x, y)

    lp *= 10**-6
    assert_allclose(lp, lam[cond], atol=1e-13)
Beispiel #3
0
 def _create_image_model(grating='G395H', filter='F290LP', **kwargs):
     hdul = create_nirspec_ifu_file(grating=grating,
                                    filter=filter,
                                    **kwargs)
     im = datamodels.ImageModel(hdul)
     refs = create_reference_files(im)
     pipeline = nirspec.create_pipeline(im, refs, slit_y_range=[-0.5, 0.5])
     w = wcs.WCS(pipeline)
     im.meta.wcs = w
     return im, refs
Beispiel #4
0
def test_nirspec_imaging():
    """
    Test Nirspec Imaging mode using build 6 reference files.
    """
    #Test creating the WCS
    f = create_nirspec_imaging_file()
    im = datamodels.ImageModel(f)

    refs = create_reference_files(im)

    pipe = nirspec.create_pipeline(im, refs, slit_y_range=[-.5, .5])
    w = wcs.WCS(pipe)
    im.meta.wcs = w
    # Test evaluating the WCS
    im.meta.wcs(1, 2)
Beispiel #5
0
def test_nirspec_fs_esa():
    """
    Test Nirspec FS mode using build 6 reference files.
    """
    # Test creating the WCS
    filename = create_nirspec_fs_file(grating="G140M", filter="F100LP")
    im = datamodels.ImageModel(filename)
    im.meta.filename = "test_fs.fits"
    refs = create_reference_files(im)

    pipe = nirspec.create_pipeline(im, refs, slit_y_range=[-.5, .5])
    w = wcs.WCS(pipe)
    im.meta.wcs = w
    # Test evaluating the WCS
    w1 = nirspec.nrs_wcs_set_input(im, "S200A1")

    ref = fits.open(
        get_file_path(
            'Trace_SLIT_A_200_1_V84600010001P0000000002101_39547_JLAB88.fits'))
    pyw = astwcs.WCS(ref[1].header)

    # get positions within the slit and the coresponding lambda
    slit1 = ref[5].data  # y offset on the slit
    lam = ref[4].data

    # filter out locations outside the slit
    cond = np.logical_and(slit1 < .5, slit1 > -.5)
    y, x = cond.nonzero()  # 0-based

    x, y = pyw.wcs_pix2world(x, y, 0)
    # The pipeline works with 0-based coordinates
    x -= 1
    y -= 1

    sca2world = w1.get_transform('sca', 'v2v3')
    ra, dec, lp = sca2world(x, y)
    # w1 now outputs in microns hence the 1e6 factor
    lp *= 1e-6
    lam = lam[cond]
    nan_cond = ~np.isnan(lp)
    assert_allclose(lp[nan_cond], lam[nan_cond], atol=10**-13)
    ref.close()
Beispiel #6
0
def test_functional_ifu_prism():
    """Compare Nirspec instrument model with IDT model for IFU prism."""
    # setup test
    model_file = 'ifu_prism_functional_ESA_v1_20180619.txt'
    hdu1 = create_nirspec_ifu_file(grating='PRISM',
                                   filter='CLEAR',
                                   gwa_xtil=0.35986012,
                                   gwa_ytil=0.13448857,
                                   gwa_tilt=37.1)
    im = datamodels.ImageModel(hdu1)
    refs = create_reference_files(im)
    pipeline = nirspec.create_pipeline(im, refs, slit_y_range=[-0.55, 0.55])
    w = wcs.WCS(pipeline)
    im.meta.wcs = w
    slit_wcs = nirspec.nrs_wcs_set_input(im, 0)  # use slice 0
    ins_file = get_file_path(model_file)
    ins_tab = table.Table.read(ins_file, format='ascii')
    slitx = [0] * 5
    slity = [-.5, -.25, 0, .25, .5]
    lam = np.array([.7e-7, 1e-6, 2e-6, 3e-6, 5e-6])
    order, wrange = nirspec.get_spectral_order_wrange(im,
                                                      refs['wavelengthrange'])
    im.meta.wcsinfo.sporder = order
    im.meta.wcsinfo.waverange_start = wrange[0]
    im.meta.wcsinfo.waverange_end = wrange[1]

    # Slit to MSA entrance
    # This includes the Slicer transform and the IFUFORE transform
    slit2msa = slit_wcs.get_transform('slit_frame', 'msa_frame')
    msax, msay, _ = slit2msa(slitx, slity, lam)
    assert_allclose(slitx, ins_tab['xslitpos'])
    assert_allclose(slity, ins_tab['yslitpos'])
    assert_allclose(msax + 0.0073, ins_tab['xmsapos'],
                    rtol=1e-2)  # expected offset
    assert_allclose(msay + 0.0085, ins_tab['ymaspos'],
                    rtol=1e-2)  # expected offset

    # Slicer
    slit2slicer = slit_wcs.get_transform('slit_frame', 'slicer')
    x_slicer, y_slicer, _ = slit2slicer(slitx, slity, lam)

    # MSA exit
    # Applies the IFUPOST transform to coordinates at the Slicer
    with datamodels.IFUPostModel(refs['ifupost']) as ifupost:
        ifupost_transform = nirspec._create_ifupost_transform(ifupost.slice_0)
    x_msa_exit, y_msa_exit = ifupost_transform(x_slicer, y_slicer, lam)
    assert_allclose(x_msa_exit, ins_tab['xmsapos'])
    assert_allclose(y_msa_exit, ins_tab['ymaspos'])

    # Coordinates at Collimator exit
    # Applies the Collimator forward transform to coordinates at the MSA exit
    with datamodels.open(refs['collimator']) as col:
        colx, coly = col.model.inverse(x_msa_exit, y_msa_exit)
    assert_allclose(colx, ins_tab['xcoll'])
    assert_allclose(coly, ins_tab['ycoll'])

    # After applying direcitonal cosines
    dircos = trmodels.Unitless2DirCos()
    xcolDircosi, ycolDircosi, z = dircos(colx, coly)
    assert_allclose(xcolDircosi, ins_tab['xcolDirCosi'])
    assert_allclose(ycolDircosi, ins_tab['ycolDirCosi'])

    # Slit to GWA entrance
    # applies the Collimator forward, Unitless to Directional and 3D Rotation to MSA exit coordinates
    with datamodels.DisperserModel(refs['disperser']) as disp:
        disperser = nirspec.correct_tilt(disp, im.meta.instrument.gwa_xtilt,
                                         im.meta.instrument.gwa_ytilt)
    collimator2gwa = nirspec.collimator_to_gwa(refs, disperser)
    x_gwa_in, y_gwa_in, z_gwa_in = collimator2gwa(x_msa_exit, y_msa_exit)
    assert_allclose(x_gwa_in, ins_tab['xdispIn'])

    # Slit to GWA out
    # Runs slit--> slicer --> msa_exit --> collimator --> dircos --> rotation --> angle_from_grating equation
    slit2gwa = slit_wcs.get_transform('slit_frame', 'gwa')
    x_gwa_out, y_gwa_out, z_gwa_out = slit2gwa(slitx, slity, lam)
    assert_allclose(x_gwa_out, ins_tab['xdispLaw'])
    assert_allclose(y_gwa_out, ins_tab['ydispLaw'])

    # CAMERA entrance (assuming direction is from sky to detector)
    angles = [
        disperser['theta_x'], disperser['theta_y'], disperser['theta_z'],
        disperser['tilt_y']
    ]
    rotation = trmodels.Rotation3DToGWA(angles,
                                        axes_order="xyzy",
                                        name='rotation')
    dircos2unitless = trmodels.DirCos2Unitless()
    gwa2cam = rotation.inverse | dircos2unitless
    x_camera_entrance, y_camera_entrance = gwa2cam(x_gwa_out, y_gwa_out,
                                                   z_gwa_out)
    assert_allclose(x_camera_entrance, ins_tab['xcamCosi'])
    assert_allclose(y_camera_entrance, ins_tab['ycamCosi'])

    # at FPA
    with datamodels.CameraModel(refs['camera']) as camera:
        x_fpa, y_fpa = camera.model.inverse(x_camera_entrance,
                                            y_camera_entrance)
    assert_allclose(x_fpa, ins_tab['xfpapos'])
    assert_allclose(y_fpa, ins_tab['yfpapos'])

    # at SCA
    slit2sca = slit_wcs.get_transform('slit_frame', 'sca')
    x_sca_nrs1, y_sca_nrs1 = slit2sca(slitx, slity, lam)

    # At NRS2
    with datamodels.FPAModel(refs['fpa']) as fpa:
        x_sca_nrs2, y_sca_nrs2 = fpa.nrs2_model.inverse(x_fpa, y_fpa)
    assert_allclose(x_sca_nrs1 + 1, ins_tab['i'])
    assert_allclose(y_sca_nrs1 + 1, ins_tab['j'])

    # at oteip
    # Goes through slicer, ifufore, and fore transforms
    slit2oteip = slit_wcs.get_transform('slit_frame', 'oteip')
    x_oteip, y_oteip, _ = slit2oteip(slitx, slity, lam)
    assert_allclose(x_oteip, ins_tab['xOTEIP'])
    assert_allclose(y_oteip, ins_tab['yOTEIP'])

    # at v2, v3 [in arcsec]
    slit2v23 = slit_wcs.get_transform('slit_frame', 'v2v3')
    v2, v3, _ = slit2v23(slitx, slity, lam)
    v2 /= 3600
    v3 /= 3600
    assert_allclose(v2, ins_tab['xV2V3'])
    assert_allclose(v3, ins_tab['yV2V3'])
Beispiel #7
0
def test_functional_ifu_grating():
    """Compare Nirspec instrument model with IDT model for IFU grating."""

    # setup test
    model_file = 'ifu_grating_functional_ESA_v1_20180619.txt'
    hdul = create_nirspec_ifu_file(grating='G395H',
                                   filter='F290LP',
                                   gwa_xtil=0.35986012,
                                   gwa_ytil=0.13448857)
    im = datamodels.ImageModel(hdul)
    refs = create_reference_files(im)
    pipeline = nirspec.create_pipeline(im, refs, slit_y_range=[-0.55, 0.55])
    w = wcs.WCS(pipeline)
    im.meta.wcs = w
    slit_wcs = nirspec.nrs_wcs_set_input(im, 0)  # use slice 0
    ins_file = get_file_path(model_file)
    ins_tab = table.Table.read(ins_file, format='ascii')
    slitx = [0] * 5
    slity = [-.5, -.25, 0, .25, .5]
    lam = np.array([2.9, 3.39, 3.88, 4.37, 5]) * 10**-6
    order, wrange = nirspec.get_spectral_order_wrange(im,
                                                      refs['wavelengthrange'])
    im.meta.wcsinfo.sporder = order
    im.meta.wcsinfo.waverange_start = wrange[0]
    im.meta.wcsinfo.waverange_end = wrange[1]

    # Slit to MSA entrance
    # This includes the Slicer transform and the IFUFORE transform
    slit2msa = slit_wcs.get_transform('slit_frame', 'msa_frame')
    msax, msay, _ = slit2msa(slitx, slity, lam)
    assert_allclose(slitx, ins_tab['xslitpos'])
    assert_allclose(slity, ins_tab['yslitpos'])
    assert_allclose(msax + 0.0073, ins_tab['xmsapos'],
                    rtol=1e-2)  # expected offset
    assert_allclose(msay + 0.0085, ins_tab['ymaspos'],
                    rtol=1e-2)  # expected offset

    # Slicer
    slit2slicer = slit_wcs.get_transform('slit_frame', 'slicer')
    x_slicer, y_slicer, _ = slit2slicer(slitx, slity, lam)

    # MSA exit
    # Applies the IFUPOST transform to coordinates at the Slicer
    with datamodels.IFUPostModel(refs['ifupost']) as ifupost:
        ifupost_transform = nirspec._create_ifupost_transform(ifupost.slice_0)
    x_msa_exit, y_msa_exit = ifupost_transform(x_slicer, y_slicer, lam)
    assert_allclose(x_msa_exit, ins_tab['xmsapos'])
    assert_allclose(y_msa_exit, ins_tab['ymaspos'])

    # Computations are done using the eact form of the equations in the reports
    # Part I of the Forward IFU-POST transform - the linear transform
    xc_out = 0.0487158154447
    yc_out = 0.00856211956976
    xc_in = 0.000355277216
    yc_in = -3.0089012e-05
    theta = np.deg2rad(-0.129043957046)
    factor_x = 0.100989874454
    factor_y = 0.100405184145

    # Slicer coordinates
    xS = 0.000399999989895
    yS = -0.00600000005215

    x = xc_out + factor_x * (+cos(theta) * (xS - xc_in) + sin(theta) *
                             (yS - yc_in))
    y = yc_out + factor_y * (-sin(theta) * (xS - xc_in) + cos(theta) *
                             (yS - yc_in))

    # Forward IFU-POST II part - non-linear transform
    lam = 2.9e-6
    coef_names = [
        f'c{x}_{y}' for x in range(6) for y in range(6) if x + y <= 5
    ]
    y_forw = [
        -82.3492267824, 29234.6982762, -540260.780853, 771881.305018,
        -2563462.26848, 29914272.1164, 4513.04082605, -2212869.44311,
        32875633.0303, -29923698.5288, 27293902.5636, -39820.4434726,
        62431493.9962, -667197265.033, 297253538.182, -1838860.86305,
        -777169857.2, 4514693865.7, 42790637.764, 3596423850.94, -260274017.448
    ]
    y_forw_dist = [
        188531839.97, -43453434864.0, 70807756765.8, -308272809909.0,
        159768473071.0, 9712633344590.0, -11762923852.9, 3545938873190.0,
        -4198643655420.0, 12545642983100.0, -11707051591600.0, 173091230285.0,
        -108534069056000.0, 82893348097600.0, -124708740989000.0,
        2774389757990.0, 1476779720300000.0, -545358301961000.0,
        -93101557994100.0, -7536890639430000.0, 646310545048000.0
    ]
    y_coeff = {}
    for i, coef in enumerate(coef_names):
        y_coeff[coef] = y_forw[i] + lam * y_forw_dist[i]
    poly2d = astmodels.Polynomial2D(5, **y_coeff)
    ifupost_y = poly2d(x, y)
    assert_allclose(ifupost_y, ins_tab['ymaspos'][0])
    assert_allclose(ifupost_y, y_msa_exit[0])

    # reset 'lam'
    lam = np.array([2.9, 3.39, 3.88, 4.37, 5]) * 10**-6

    # Coordinates at Collimator exit
    # Applies the Collimator forward transform to coordinates at the MSA exit
    with datamodels.open(refs['collimator']) as col:
        colx, coly = col.model.inverse(x_msa_exit, y_msa_exit)
    assert_allclose(colx, ins_tab['xcoll'])
    assert_allclose(coly, ins_tab['ycoll'])

    # After applying direcitonal cosines
    dircos = trmodels.Unitless2DirCos()
    xcolDircosi, ycolDircosi, z = dircos(colx, coly)
    assert_allclose(xcolDircosi, ins_tab['xcolDirCosi'])
    assert_allclose(ycolDircosi, ins_tab['ycolDirCosi'])

    # Slit to GWA entrance
    # applies the Collimator forward, Unitless to Directional and 3D Rotation to MSA exit coordinates
    with datamodels.DisperserModel(refs['disperser']) as disp:
        disperser = nirspec.correct_tilt(disp, im.meta.instrument.gwa_xtilt,
                                         im.meta.instrument.gwa_ytilt)
    collimator2gwa = nirspec.collimator_to_gwa(refs, disperser)
    x_gwa_in, y_gwa_in, z_gwa_in = collimator2gwa(x_msa_exit, y_msa_exit)
    assert_allclose(x_gwa_in, ins_tab['xdispIn'])

    # Slit to GWA out
    # Runs slit--> slicer --> msa_exit --> collimator --> dircos --> rotation --> angle_from_grating equation
    slit2gwa = slit_wcs.get_transform('slit_frame', 'gwa')
    x_gwa_out, y_gwa_out, z_gwa_out = slit2gwa(slitx, slity, lam)
    assert_allclose(x_gwa_out, ins_tab['xdispLaw'])
    assert_allclose(y_gwa_out, ins_tab['ydispLaw'])

    # CAMERA entrance (assuming direction is from sky to detector)
    angles = [
        disperser['theta_x'], disperser['theta_y'], disperser['theta_z'],
        disperser['tilt_y']
    ]
    rotation = trmodels.Rotation3DToGWA(angles,
                                        axes_order="xyzy",
                                        name='rotation')
    dircos2unitless = trmodels.DirCos2Unitless()
    gwa2cam = rotation.inverse | dircos2unitless
    x_camera_entrance, y_camera_entrance = gwa2cam(x_gwa_out, y_gwa_out,
                                                   z_gwa_out)
    assert_allclose(x_camera_entrance, ins_tab['xcamCosi'])
    assert_allclose(y_camera_entrance, ins_tab['ycamCosi'])

    # at FPA
    with datamodels.CameraModel(refs['camera']) as camera:
        x_fpa, y_fpa = camera.model.inverse(x_camera_entrance,
                                            y_camera_entrance)
    assert_allclose(x_fpa, ins_tab['xfpapos'])
    assert_allclose(y_fpa, ins_tab['yfpapos'])

    # at SCA
    slit2sca = slit_wcs.get_transform('slit_frame', 'sca')
    x_sca_nrs1, y_sca_nrs1 = slit2sca(slitx, slity, lam)

    # At NRS2
    with datamodels.FPAModel(refs['fpa']) as fpa:
        x_sca_nrs2, y_sca_nrs2 = fpa.nrs2_model.inverse(x_fpa, y_fpa)
    assert_allclose(x_sca_nrs1[:3] + 1, ins_tab['i'][:3])
    assert_allclose(y_sca_nrs1[:3] + 1, ins_tab['j'][:3])
    assert_allclose(x_sca_nrs2[3:] + 1, ins_tab['i'][3:])
    assert_allclose(y_sca_nrs2[3:] + 1, ins_tab['j'][3:])

    # at oteip
    # Goes through slicer, ifufore, and fore transforms
    slit2oteip = slit_wcs.get_transform('slit_frame', 'oteip')
    x_oteip, y_oteip, _ = slit2oteip(slitx, slity, lam)
    assert_allclose(x_oteip, ins_tab['xOTEIP'])
    assert_allclose(y_oteip, ins_tab['yOTEIP'])

    # at v2, v3 [in arcsec]
    slit2v23 = slit_wcs.get_transform('slit_frame', 'v2v3')
    v2, v3, _ = slit2v23(slitx, slity, lam)
    v2 /= 3600
    v3 /= 3600
    assert_allclose(v2, ins_tab['xV2V3'])
    assert_allclose(v3, ins_tab['yV2V3'])
Beispiel #8
0
def test_functional_fs_msa(mode):
    #     """
    #     Compare Nirspec instrument model with IDT model for FS and MSA.
    #     """
    if mode == 'fs':
        model_file = 'fixed_slits_functional_ESA_v4_20180618.txt'
        hdul = create_nirspec_fs_file(grating='G395H', filter='F290LP')
        im = datamodels.ImageModel(hdul)
        refs = create_reference_files(im)
        pipeline = nirspec.create_pipeline(im,
                                           refs,
                                           slit_y_range=[-0.55, 0.55])
        w = wcs.WCS(pipeline)
        im.meta.wcs = w
        # Use slit S200A1
        slit_wcs = nirspec.nrs_wcs_set_input(im, 'S200A1')

    if mode == 'msa':
        model_file = 'msa_functional_ESA_v2_20180620.txt'
        hdul = create_nirspec_mos_file(grating='G395H', filt='F290LP')
        im = datamodels.ImageModel(hdul)
        refs = create_reference_files(im)
        slit = trmodels.Slit(name=1,
                             shutter_id=4699,
                             xcen=319,
                             ycen=13,
                             ymin=-0.55000000000000004,
                             ymax=0.55000000000000004,
                             quadrant=3,
                             source_id=1,
                             shutter_state='x',
                             source_name='lamp',
                             source_alias='foo',
                             stellarity=100.0,
                             source_xpos=-0.5,
                             source_ypos=0.5)
        open_slits = [slit]
        pipeline = nirspec.slitlets_wcs(im, refs, open_slits)
        w = wcs.WCS(pipeline)
        im.meta.wcs = w
        slit_wcs = nirspec.nrs_wcs_set_input(im, 1)

    ins_file = get_file_path(model_file)
    ins_tab = table.Table.read(ins_file, format='ascii')

    # Setup the test
    slitx = [0] * 5
    slity = [-.5, -.25, 0, .25, .5]
    lam = np.array([2.9, 3.39, 3.88, 4.37, 5]) * 10**-6

    # Slit to MSA absolute
    slit2msa = slit_wcs.get_transform('slit_frame', 'msa_frame')
    msax, msay, _ = slit2msa(slitx, slity, lam)

    assert_allclose(slitx, ins_tab['xslitpos'])
    assert_allclose(slity, ins_tab['yslitpos'])
    assert_allclose(msax, ins_tab['xmsapos'])
    assert_allclose(msay, ins_tab['ymaspos'])

    # Coordinates at Collimator exit
    # Applies the Collimator forward transform to MSa absolute coordinates
    with datamodels.open(refs['collimator']) as col:
        colx, coly = col.model.inverse(msax, msay)
    assert_allclose(colx, ins_tab['xcoll'])
    assert_allclose(coly, ins_tab['ycoll'])

    # After applying direcitonal cosines
    dircos = trmodels.Unitless2DirCos()
    xcolDircosi, ycolDircosi, z = dircos(colx, coly)
    assert_allclose(xcolDircosi, ins_tab['xcolDirCosi'])
    assert_allclose(ycolDircosi, ins_tab['ycolDirCosi'])

    # MSA to GWA entrance
    # This runs the Collimator forward, Unitless to Directional cosine, and
    # 3D Rotation. It uses the corrected GWA tilt value
    with datamodels.DisperserModel(refs['disperser']) as disp:
        disperser = nirspec.correct_tilt(disp, im.meta.instrument.gwa_xtilt,
                                         im.meta.instrument.gwa_ytilt)
    collimator2gwa = nirspec.collimator_to_gwa(refs, disperser)
    x_gwa_in, y_gwa_in, z_gwa_in = collimator2gwa(msax, msay)
    assert_allclose(x_gwa_in, ins_tab['xdispIn'])
    assert_allclose(y_gwa_in, ins_tab['ydispIn'])

    # Slit to GWA out
    slit2gwa = slit_wcs.get_transform('slit_frame', 'gwa')
    x_gwa_out, y_gwa_out, z_gwa_out = slit2gwa(slitx, slity, lam)
    assert_allclose(x_gwa_out, ins_tab['xdispLaw'])
    assert_allclose(y_gwa_out, ins_tab['ydispLaw'])

    # CAMERA entrance (assuming direction is from sky to detector)
    angles = [
        disperser['theta_x'], disperser['theta_y'], disperser['theta_z'],
        disperser['tilt_y']
    ]
    rotation = trmodels.Rotation3DToGWA(angles,
                                        axes_order="xyzy",
                                        name='rotation')
    dircos2unitless = trmodels.DirCos2Unitless()
    gwa2cam = rotation.inverse | dircos2unitless
    x_camera_entrance, y_camera_entrance = gwa2cam(x_gwa_out, y_gwa_out,
                                                   z_gwa_out)
    assert_allclose(x_camera_entrance, ins_tab['xcamCosi'])
    assert_allclose(y_camera_entrance, ins_tab['ycamCosi'])

    # at FPA
    with datamodels.CameraModel(refs['camera']) as camera:
        x_fpa, y_fpa = camera.model.inverse(x_camera_entrance,
                                            y_camera_entrance)
    assert_allclose(x_fpa, ins_tab['xfpapos'])
    assert_allclose(y_fpa, ins_tab['yfpapos'])

    # at SCA These are 0-based , the IDT results are 1-based
    slit2sca = slit_wcs.get_transform('slit_frame', 'sca')
    x_sca_nrs1, y_sca_nrs1 = slit2sca(slitx, slity, lam)
    # At NRS2
    with datamodels.FPAModel(refs['fpa']) as fpa:
        x_sca_nrs2, y_sca_nrs2 = fpa.nrs2_model.inverse(x_fpa, y_fpa)
    # expect 1 pix difference
    wvlns_on_nrs1 = slice(2)
    wvlns_on_nrs2 = slice(2, 4)
    assert_allclose(x_sca_nrs1[wvlns_on_nrs1] + 1, ins_tab['i'][wvlns_on_nrs1])
    assert_allclose(y_sca_nrs1[wvlns_on_nrs1] + 1, ins_tab['j'][wvlns_on_nrs1])
    assert_allclose(x_sca_nrs2[wvlns_on_nrs2] + 1, ins_tab['i'][wvlns_on_nrs2])
    assert_allclose(y_sca_nrs2[wvlns_on_nrs2] + 1, ins_tab['j'][wvlns_on_nrs2])

    # at oteip
    slit2oteip = slit_wcs.get_transform('slit_frame', 'oteip')
    x_oteip, y_oteip, _ = slit2oteip(slitx, slity, lam)
    assert_allclose(x_oteip, ins_tab['xOTEIP'])
    assert_allclose(y_oteip, ins_tab['yOTEIP'])

    # at v2, v3 [in arcsec]
    slit2v23 = slit_wcs.get_transform('slit_frame', 'v2v3')
    v2, v3, _ = slit2v23(slitx, slity, lam)
    v2 /= 3600
    v3 /= 3600
    assert_allclose(v2, ins_tab['xV2V3'])
    assert_allclose(v3, ins_tab['yV2V3'])
Beispiel #9
0
def test_ifu_bbox():
    bbox = {
        0: ((122.0908542999878, 1586.2584665188083), (773.5411133037417,
                                                      825.1150258966278)),
        1: ((140.3793485788431, 1606.8904629423566), (1190.353197027459,
                                                      1243.0853605832503)),
        2: ((120.0139534379125, 1583.9271768905855), (724.3249534782219,
                                                      775.8104288584977)),
        3: ((142.50252648927454, 1609.3106221382388), (1239.4122720740888,
                                                       1292.288713688988)),
        4: ((117.88884113088403, 1581.5517394150106), (674.9787657901347,
                                                       726.3752061973377)),
        5: ((144.57465414462143, 1611.688447569682), (1288.4808318659427,
                                                      1341.5035313084197)),
        6: ((115.8602297714846, 1579.27471654949), (625.7982466386104,
                                                    677.1147840452901)),
        7: ((146.7944728147906, 1614.2161842198498), (1337.531525654835,
                                                      1390.7050687363856)),
        8: ((113.86384530944383, 1577.0293086386203), (576.5344359685643,
                                                       627.777022204828)),
        9: ((149.0259581360621, 1616.7687282225652), (1386.5118806905086,
                                                      1439.843598490326)),
        10: ((111.91564190274217, 1574.8351095461135), (527.229828693075,
                                                        578.402894851317)),
        11: ((151.3053466801954, 1619.3720722471498), (1435.423685040875,
                                                       1488.917203728964)),
        12: ((109.8957204607345, 1572.570246400894), (477.9699083444277,
                                                      529.0782087498488)),
        13: ((153.5023503173659, 1621.9005029476564), (1484.38405923062,
                                                       1538.0443479389924)),
        14: ((107.98320121613297, 1570.411787034636), (428.6704834494425,
                                                       479.7217241891257)),
        15: ((155.77991404913857, 1624.5184927460925), (1533.169633314481,
                                                        1586.9984359105376)),
        16: ((106.10212081215678, 1568.286103827344), (379.3860245240618,
                                                       430.3780648366697)),
        17: ((158.23149941845386, 1627.305849064835), (1582.0496119714928,
                                                       1636.0513450787032)),
        18: ((104.09366374413436, 1566.030231370944), (330.0822744105267,
                                                       381.01974582564395)),
        19: ((160.4511021152353, 1629.888830991371), (1630.7797743277185,
                                                      1684.9592727079018)),
        20: ((102.25220592881234, 1563.9475099032868), (280.7233309522168,
                                                        331.6093009077988)),
        21: ((162.72784286205734, 1632.5257403739463), (1679.6815760587567,
                                                        1734.03692957156)),
        22: ((100.40115742738622, 1561.8476640376036), (231.35443588323855,
                                                        282.19575854747006)),
        23: ((165.05939163941662, 1635.2270773628682), (1728.511467615387,
                                                        1783.0485841263735)),
        24: ((98.45723949658425, 1559.6499479349648), (182.0417295679079,
                                                       232.83530870639865)),
        25: ((167.44628840053574, 1637.9923229870349), (1777.2512197664128,
                                                        1831.971115503598)),
        26: ((96.56508092457855, 1557.5079027818058), (132.5285162704088,
                                                       183.27350269292484)),
        27: ((169.8529496136358, 1640.778485168005), (1826.028691168028,
                                                      1880.9336718824313)),
        28: ((94.71390837793813, 1555.4048050512263), (82.94691422559131,
                                                       133.63901517357235)),
        29: ((172.3681094850081, 1643.685604697228), (1874.8184744639657,
                                                      1929.9072657798927))
    }

    hdul = create_nirspec_ifu_file("F290LP", "G140M")
    im = datamodels.IFUImageModel(hdul)
    im.meta.filename = "test_ifu.fits"
    refs = create_reference_files(im)

    pipe = nirspec.create_pipeline(im, refs, slit_y_range=[-.5, .5])
    w = wcs.WCS(pipe)
    im.meta.wcs = w

    _, wrange = nirspec.spectral_order_wrange_from_model(im)
    pipe = im.meta.wcs.pipeline

    g2s = pipe[2].transform
    transforms = [pipe[0].transform]
    transforms.append(pipe[1].transform[1:])
    transforms.append(astmodels.Identity(1))
    transforms.append(astmodels.Identity(1))
    transforms.extend([step.transform for step in pipe[4:-1]])

    for sl in range(30):
        transforms[2] = g2s.get_model(sl)
        m = functools.reduce(lambda x, y: x | y,
                             [tr.inverse for tr in transforms[:3][::-1]])
        bbox_sl = nirspec.compute_bounding_box(m, wrange)
        assert_allclose(bbox[sl], bbox_sl)