Пример #1
0
def test_sky_to_tel():
    """Test application of the attitude matrix"""

    # test with quantities
    ra = ra_deg * u.deg
    dec = dec_deg * u.deg
    pa = pa_deg * u.deg
    v2 = v2_arcsec * u.arcsec
    v3 = v3_arcsec * u.arcsec

    attitude = rotations.attitude_matrix(v2, v3, ra, dec, pa)
    ra_2, dec_2 = rotations.tel_to_sky(
        attitude, *rotations.sky_to_tel(attitude, ra, dec))
    assert np.abs((ra - ra_2).to(u.milliarcsecond).value) < 1e-6
    assert np.abs((dec - dec_2).to(u.milliarcsecond).value) < 1e-6

    # test without quantities
    attitude = rotations.attitude_matrix(v2_arcsec, v3_arcsec, ra_deg, dec_deg,
                                         pa_deg)
    ra_2, dec_2 = rotations.tel_to_sky(
        attitude, *rotations.sky_to_tel(attitude, ra_deg, dec_deg))
    assert np.abs(ra_deg - ra_2.to(u.deg).value) * u.deg.to(
        u.milliarcsecond) < 1e-6
    assert np.abs(dec_deg - dec_2.to(u.deg).value) * u.deg.to(
        u.milliarcsecond) < 1e-6

    # test array inputs
    n_side = 3
    span = 2 * u.arcmin
    x_width = span.to(u.deg).value
    centre_deg = (ra_deg, dec_deg)
    ra_array_deg, dec_array_deg = tools.get_grid_coordinates(
        n_side, centre_deg, x_width)

    ra_array_2, dec_array_2 = rotations.tel_to_sky(
        attitude,
        *rotations.sky_to_tel(attitude, ra_array_deg * u.deg,
                              dec_array_deg * u.deg))
    assert np.all(
        np.abs(ra_array_deg * u.deg - ra_array_2) < 1e-6 * u.milliarcsecond)
    assert np.all(
        np.abs(dec_array_deg * u.deg - dec_array_2) < 1e-6 * u.milliarcsecond)

    ra_array_2, dec_array_2 = rotations.tel_to_sky(
        attitude, *rotations.sky_to_tel(attitude, ra_array_deg, dec_array_deg))
    assert np.all(
        np.abs(ra_array_deg * u.deg - ra_array_2) < 1e-6 * u.milliarcsecond)
    assert np.all(
        np.abs(dec_array_deg * u.deg - dec_array_2) < 1e-6 * u.milliarcsecond)
Пример #2
0
def test_attitude_matrix():
    """Compare original and new attitude matrix generator functions."""

    ra = ra_deg * u.deg
    dec = dec_deg * u.deg
    pa = pa_deg * u.deg
    v2 = v2_arcsec * u.arcsec
    v3 = v3_arcsec * u.arcsec

    attitude = rotations.attitude(v2_arcsec, v3_arcsec, ra_deg, dec_deg,
                                  pa_deg)
    attitude_matrix = rotations.attitude_matrix(v2, v3, ra, dec, pa)

    assert np.all(attitude == attitude_matrix)
Пример #3
0
def lrsFieldSim(ra, dec, binComp=''):
    """ Produce a Grism Time Series field simulation for a target.
    Parameters
    ----------
    ra : float
        The RA of the target.
    dec : float
        The Dec of the target.
    binComp : sequence
        The parameters of a binary companion.

    Returns
    -------
    simuCube : np.ndarray
        The simulated data cube. Index 0 and 1 (axis=0) show the trace of
        the target for orders 1 and 2 (respectively). Index 2-362 show the trace
        of the target at every position angle (PA) of the instrument.
    """
    #############################INSTRUMENT PARAMETERS######################
    ########################################################################
    # Instantiate a pySIAF object
    siaf = pysiaf.Siaf('MIRI')
    aper = siaf.apertures['MIRIM_SLITLESSPRISM']
    full = siaf.apertures['MIRIM_FULL']

    # Calling the variables
    deg2rad = np.pi / 180
    subX, subY = aper.XSciSize, aper.YSciSize
    rad = 2.0  # arcmins
    pixel_scale = 0.11  # arsec/pixel
    V3PAs = np.arange(0, 360, 1)
    nPA = len(V3PAs)
    # Generate cube of field simulation at every degree of APA rotation
    simuCube = np.zeros([nPA + 1, subY, subX])
    xSweet, ySweet = aper.reference_point('det')
    add_to_v3pa = aper.V3IdlYAngle
    # MIRI Full Frame dimensions
    rows, cols = full.corners('det')
    minrow, maxrow = rows.min(), rows.max()
    mincol, maxcol = cols.min(), cols.max()

    #############################STEP 1#####################################
    ########################################################################
    # Converting to degrees
    targetcrd = crd.SkyCoord(ra=ra, dec=dec, unit=(u.hour, u.deg))
    targetRA = targetcrd.ra.value
    targetDEC = targetcrd.dec.value

    # Querying for neighbors with 2MASS IRSA's fp_psc (point-source catalog)
    info = Irsa.query_region(targetcrd,
                             catalog='fp_psc',
                             spatial='Cone',
                             radius=rad * u.arcmin)

    # Coordinates of all the stars in FOV, including target
    allRA = info['ra'].data.data
    allDEC = info['dec'].data.data

    # Initiating a dictionary to hold all relevant star information
    stars = {}
    stars['RA'], stars['DEC'] = allRA, allDEC

    #############################STEP 2#####################################
    ########################################################################
    sindRA = (targetRA - stars['RA']) * np.cos(targetDEC)
    cosdRA = targetDEC - stars['DEC']
    distance = np.sqrt(sindRA**2 + cosdRA**2)
    if np.min(distance) > 1.0 * (10**-4):
        coords = crd.SkyCoord(ra=ra, dec=dec,
                              unit=(u.hour, u.deg)).to_string('decimal')
        ra, dec = coords.split(' ')[0], coords.split(' ')[1]
        raise Exception(
            'Unable to detect a source with coordinates [RA: {}, DEC: {}] within IRSA`s 2MASS Point-Source Catalog. Please enter different coordinates or contact the JWST help desk.'
            .format(str(ra), str(dec)))

    targetIndex = np.argmin(distance)

    # Restoring model parameters
    modelParam = readsav(os.path.join(TRACES_PATH, 'NIRISS', 'modelsInfo.sav'),
                         verbose=False)
    models = modelParam['models']
    modelPadX = modelParam['modelpadx']
    modelPadY = modelParam['modelpady']
    dimXmod = modelParam['dimxmod']
    dimYmod = modelParam['dimymod']
    jhMod = modelParam['jhmod']
    hkMod = modelParam['hkmod']
    teffMod = modelParam['teffmod']

    #############################STEP 3#####################################
    ########################################################################
    # JHK bands of all stars in FOV, including target
    Jmag = info['j_m'].data.data
    Hmag = info['h_m'].data.data
    Kmag = info['k_m'].data.data
    # J-H band, H-K band. This will be used to derive the Teff
    J_Hobs = Jmag - Hmag
    H_Kobs = Hmag - Kmag

    # Add any missing companion
    if binComp != '':
        bb = binComp[0] / 3600 / np.cos(allDEC[targetIndex] * deg2rad)
        allRA = np.append(allRA, (allRA[targetIndex] + bb))
        allDEC = np.append(allDEC, (allDEC[targetIndex] + binComp[1] / 3600))
        Jmag = np.append(Jmag, binComp[2])
        Hmag = np.append(Kmag, binComp[3])
        Kmag = np.append(Kmag, binComp[4])
        J_Hobs = Jmag - Hmag
        H_Kobs = Hmag - Kmag

    # Number of stars
    nStars = stars['RA'].size

    # Find/assign Teff of each star
    starsT = np.empty(nStars)
    for j in range(nStars):
        color_separation = (J_Hobs[j] - jhMod)**2 + (H_Kobs[j] - hkMod)**2
        min_separation_ind = np.argmin(color_separation)
        starsT[j] = teffMod[min_separation_ind]

    # Record keeping
    stars['Temp'] = starsT
    stars['Jmag'] = Jmag

    #############################STEP 4#####################################
    ########################################################################
    # Calculate corresponding V2/V3 (TEL) coordinates for Sweetspot
    v2targ, v3targ = aper.det_to_tel(xSweet, ySweet)

    for V3PA in range(0, nPA, 1):
        # Get APA from V3PA
        APA = V3PA + add_to_v3pa
        if APA > 360:
            APA = APA - 360
        elif APA < 0:
            APA = APA + 360

        print('Generating field at APA : {}'.format(str(APA)))

        # Get target's attitude matrix for each Position Angle
        attitude = rotations.attitude_matrix(v2targ, v3targ, targetRA,
                                             targetDEC, APA)

        xdet, ydet = [], []
        xsci, ysci = [], []
        for starRA, starDEC in zip(stars['RA'], stars['DEC']):
            # Get the TEL coordinates of each star w attitude matrix
            V2, V3 = rotations.sky_to_tel(attitude, starRA, starDEC)
            # Convert to arcsec and turn to a float
            V2, V3 = V2.to(u.arcsec).value, V3.to(u.arcsec).value

            XDET, YDET = aper.tel_to_det(V2, V3)
            XSCI, YSCI = aper.det_to_sci(XDET, YDET)

            xdet.append(XDET)
            ydet.append(YDET)
            xsci.append(XSCI)
            ysci.append(YSCI)

        # Record keeping
        stars['xdet'], stars['ydet'] = np.array(xdet), np.array(ydet)
        stars['xsci'], stars['ysci'] = np.array(xsci), np.array(ysci)

        sci_targx, sci_targy = stars['xsci'][targetIndex],\
            stars['ysci'][targetIndex]
        #############################STEP 5#####################################
        ########################################################################
        inFOV = []
        for star in range(0, nStars):

            x, y = stars['xdet'][star], stars['ydet'][star]
            if (mincol < x) & (x < maxcol) & (minrow < y) & (y < maxrow):
                inFOV.append(star)

        inFOV = np.array(inFOV)

        #############################STEP 6#####################################
        ########################################################################
        fitsFiles = glob.glob(os.path.join(TRACES_PATH, 'MIRI', 'LOW*.fits'))
        fitsFiles = np.sort(fitsFiles)

        for idx in inFOV:

            sci_dx = round(sci_targx - stars['xsci'][idx])
            sci_dy = round(sci_targy - stars['ysci'][idx])

            temp = stars['Temp'][idx]

            for file in fitsFiles:
                if str(temp) in file:
                    trace = fits.getdata(file)[0]

            fluxscale = 10.0**(-0.4 * \
                               (stars['Jmag'][idx] - stars['Jmag'][targetIndex]))

            # Padding array
            pad_trace = np.pad(trace,
                               pad_width=5000,
                               mode='constant',
                               constant_values=0)

            # Determine the highest pixel value of trace
            maxY, maxX = np.where(pad_trace == pad_trace.max())
            peakY, peakX = maxY[0], maxX[0]

            # Use relative distances (sci_dx, sci_dy) to find target
            # xTarg,yTarg are essentially the "sweetspot" in the PADDED arr
            xTarg = peakX + sci_dx
            yTarg = peakY + sci_dy

            # Use the (xTarg, yTarg) coordinates to slice out subarray
            # remember X is columns, Y is rows
            dimX0, dimX1 = xTarg - sci_targx, xTarg + subX - sci_targx
            dimY0, dimY1 = yTarg - sci_targy, yTarg + subY - sci_targy

            if dimX0 < 0:
                dimX0 = 0
                dimX1 = subX
            if dimY0 < 0:
                dimY0 = 0
                dimY1 = subY

            traceX, traceY = np.shape(pad_trace)[1], np.shape(pad_trace)[0]
            if dimX1 > traceX:
                dimX1 = traceX
                dimX0 = traceX - subX
            if dimY1 > traceY:
                dimY1 = traceY
                dimY0 = traceY - subY

            if (dimX1 < 0) or (dimY1 < 0):
                continue

            # -1 because pySIAF is 1-indexed
            mx0, mx1 = int(dimX0) - 1, int(dimX1) - 1
            my0, my1 = int(dimY0) - 1, int(dimY1) - 1

            # Fleshing out index 0 of the simulation cube (trace of target)
            if (sci_dx == 0) & (sci_dy == 0):  # this is the target

                tr = pad_trace[my0:my1, mx0:mx1] * fluxscale
                trX, trY = np.shape(tr)[1], np.shape(tr)[0]

                simuCube[0, 0:trY, 0:trX] = tr

            # Fleshing out indexes 1-361 of the simulation cube
            # (trace of neighboring stars at every position angle)
            else:

                tr = pad_trace[my0:my1, mx0:mx1] * fluxscale
                trX, trY = np.shape(tr)[1], np.shape(tr)[0]
                simuCube[V3PA + 1, 0:trY, 0:trX] += tr

    return simuCube