예제 #1
0
def model_t3amp_uv(tri_uv, ratio, separation, pa, inv_wavl):
    """
    Takes 3 cp uv coords, or a set of them and returns model cps based on
    contrast ratio and position specified, at some wavelength. 
    tri_uv = array( [[u1, v1], [u2, v2], [u3, v3],]  )
    shape: [2, 3, ncp, nwavl]
    contrast, separation, pa all should be len(inv_wavl) or scalar
    """
    uvs = inv_wavl*tri_uv
    model_t3amp = visamp(uvs[:,0, ...], ratio, mas2rad(separation), np.pi*pa/180.) * \
                visamp(uvs[:,1, ...], ratio, mas2rad(separation), np.pi*pa/180.) * \
                visamp(uvs[:,2, ...], ratio, mas2rad(separation), np.pi*pa/180.)
    # Return in deg to match oifits standard
    return model_t3amp
예제 #2
0
def model_allvis_uv(tri_uv, vis_uv, ratio, separation, pa, inv_wavl):
    """
    Same as above but returns visibility information too
    """
    model_cps = model_cp_uv(tri_uv, ratio, separation, pa, inv_wavl)
    uvs = inv_wavl*tri_uv
    uvs_vis = inv_wavl*vis_uv
    model_vis = visamp(uvs_vis, ratio, mas2rad(separation), np.pi*pa/180.)
    return model_cps, model_vis**2
예제 #3
0
def model_pha_uv(uvs, ratio, separation, pa, inv_wavl):
    # uvs are size 2, nwavl
    uvs = inv_wavl*uvs
    #model_visphi = visphase(uvs, ratio, separation, pa)
    #model_visamp = visamp(uvs[:,0, ...], ratio, mas2rad(separation), np.pi*pa/180.)*\
    #              visamp(uvs[:,0, ...], ratio, mas2rad(separation), np.pi*pa/180.)*\
    #              visamp(uvs[:,0, ...], ratio, mas2rad(separation), np.pi*pa/180.)
    model_vispha = visphase(uvs, ratio, mas2rad(separation), np.pi*pa/180.)
    return 180.*model_vispha/np.pi
예제 #4
0
 def set_pscale(self, pscalex_deg=None, pscaley_deg=None):
     """
     Override pixel scale in header
     """
     if pscalex_deg is not None:
         self.pscalex_deg = pscalex_deg
     if pscaley_deg is not None:
         self.pscaley_deg = pscaley_deg
     self.pscale_mas = 0.5 * (pscalex_deg + pscaley_deg) * (60 * 60 * 1000)
     self.pscale_rad = utils.mas2rad(self.pscale_mas)
예제 #5
0
    def updatewithheaderinfo(self, ph, sh):
        """ input: primary header, science header MAST"""

        # The info4oif_dict will get pickled to disk when we write txt files of results.
        # That way we don't drag in objects like InstrumentData into code that reads text results
        # and writes oifits files - a simple built-in dictionary is the only object used in this transfer.
        info4oif_dict = {}
        info4oif_dict['telname'] = self.telname

        info4oif_dict['filt'] = self.filt
        info4oif_dict['lam_c'] = self.lam_c
        info4oif_dict['lam_w'] = self.lam_w
        info4oif_dict['lam_bin'] = self.lam_bin

        # Target information - 5/21 targname UNKNOWN in nis019 rehearsal data
        # Name in the proposal always non-trivial, targname still UNKNOWN...:
        if ph["TARGNAME"] == 'UNKNOWN': objname = ph['TARGPROP']
        else:
            objname = ph[
                'TARGNAME']  # allegedly apt name for archive, standard form
        #
        # if target name has confusing-to-astroquery dash
        self.objname = objname.replace('-', ' ')
        info4oif_dict['objname'] = self.objname
        # AB Dor, ab dor, AB DOR,  ab  dor are all acceptable.
        #
        self.ra = ph["TARG_RA"]
        info4oif_dict['ra'] = self.ra
        self.dec = ph["TARG_DEC"]
        info4oif_dict['dec'] = self.dec

        # / axis 1 DS9 coordinate of the reference pixel (always POS1)
        # / axis 2 DS9 coordinate of the reference pixel (always POS1)
        self.crpix1 = sh["CRPIX1"]
        info4oif_dict['crpix1'] = self.crpix1
        self.crpix2 = sh["CRPIX2"]
        info4oif_dict['crpix2'] = self.crpix2
        # need Paul Goudfrooij's table for actual crval[1,2] for true pointing to detector pixel coords (DS9)

        self.instrument = ph["INSTRUME"]
        info4oif_dict['instrument'] = self.instrument
        self.pupil = ph["PUPIL"]
        info4oif_dict['pupil'] = self.pupil
        # "ImPlaneIA internal mask name" - oifwriter looks for 'mask'...
        self.arrname = "jwst_g7s6c"  # implaneia internal name - historical
        info4oif_dict['arrname'] = 'g7s6'  # for oif
        info4oif_dict['mask'] = info4oif_dict[
            'arrname']  # Soulain mask goes into oif arrname

        # if data was generated on the average pixel scale of the header
        # then this is the right value that gets read in, and used in fringe fitting
        pscalex_deg, pscaley_deg = self.degrees_per_pixel(sh)
        #
        info4oif_dict['pscalex_deg'] = pscalex_deg
        info4oif_dict['pscaley_deg'] = pscaley_deg
        # Whatever we did set is averaged for isotropic pixel scale here
        self.pscale_mas = 0.5 * (pscalex_deg + pscaley_deg) * (60 * 60 * 1000)         \
                info4oif_dict['pscale_mas'] = self.pscale_mas
        self.pscale_rad = utils.mas2rad(self.pscale_mas)
        info4oif_dict['pscale_rad'] = self.pscale_rad

        self.mask = NRM_mask_definitions(
            maskname=self.arrname,
            chooseholes=self.chooseholes,
            holeshape=self.holeshape)  # for STAtions x y in oifs

        self.date = ph["DATE-OBS"] + "T" + ph["TIME-OBS"]
        info4oif_dict['date'] = self.date
        datestr = ph["DATE-OBS"]
        self.year = datestr[:4]
        info4oif_dict['year'] = self.year
        self.month = datestr[5:7]
        info4oif_dict['month'] = self.month
        self.day = datestr[8:10]
        info4oif_dict['day'] = self.day
        self.parangh = sh["ROLL_REF"]
        info4oif_dict['parangh'] = self.parangh
        self.pa = sh["PA_V3"]
        info4oif_dict['pa'] = self.pa
        self.vparity = sh["VPARITY"]
        info4oif_dict['vparity'] = self.vparity

        # An INTegration is NGROUPS "frames", not relevant here but context info.
        # 2d => "cal" file combines all INTegrations (ramps)
        # 3d=> "calints" file is a cube of all INTegrations (ramps)
        if sh["NAXIS"] == 2:
            # all INTegrations or 'ramps'
            self.itime = ph["EFFINTTM"] * ph["NINTS"]
            info4oif_dict['itime'] = self.itime
        elif sh["NAXIS"] == 3:
            # each slice is one INTegration or 'ramp'
            self.itime = ph["EFFINTTM"]
            info4oif_dict['itime'] = self.itime

        np.set_printoptions(precision=5,
                            suppress=True,
                            linewidth=160,
                            formatter={'float': lambda x: "%10.5f," % x})
        self.v3i_yang = sh[
            'V3I_YANG']  # Angle from V3 axis to Ideal y axis (deg)
        # rotate mask hole center coords by PAV3 # RAC 2021
        ctrs_sky = self.mast2sky()
        oifctrs = np.zeros(self.mask.ctrs.shape)
        oifctrs[:, 0] = ctrs_sky[:, 1].copy() * -1
        oifctrs[:, 1] = ctrs_sky[:, 0].copy() * -1
        info4oif_dict[
            'ctrs_eqt'] = oifctrs  # mask centers rotated by PAV3 (equatorial coords)
        info4oif_dict[
            'ctrs_inst'] = self.mask.ctrs  # as-built instrument mask centers
        info4oif_dict['hdia'] = self.mask.hdia
        info4oif_dict[
            'nslices'] = self.nwav  # nwav: number of image slices or IFU cube slices - AMI is imager
        self.info4oif_dict = info4oif_dict  # save it when writing extracted observables txt