Пример #1
0
def computeRotatorAngle(obs, SEP, PA, debug=False):
    if debug:
        print "RA, DEC:", obs[0]["RA"], obs[0]["DEC"]
        print np.arcsin(10.0 / SEP) * 180 / np.pi if SEP > 10 else 90
        rot3 = [
            (
                prima.projBaseline(o["B_XYZA"], (o["RA"], o["DEC"]), o["LST"])["parang"]
                + PA
                + (np.arcsin(10.0 / SEP) * 180 / np.pi if SEP > 10 else 90)
                + 180 * o["SWAPPED"]
                + o["AZ3"]
            )
            / 2.0
            for o in obs
        ]
        rot3 = np.array(rot3) % 180
        az3 = [prima.projBaseline(o["B_XYZA"], (o["RA"], o["DEC"]), o["LST"])["az"] for o in obs]

        pyplot.figure(0)
        pyplot.clf()
        pyplot.plot(np.array([o["ROT3"] for o in obs]) - rot3, ".r")
        pyplot.xlabel("index")
        pyplot.ylabel("ROT3 - computed (degrees)")
        pyplot.figure(1)
        pyplot.clf()
        pyplot.plot((np.array([o["AZ3"] for o in obs]) - az3) % 360, ".r")
        pyplot.xlabel("index")
        pyplot.ylabel("AZ - computed (degrees)")
    return
Пример #2
0
def opdFunc(obs, params):
    res = []
    for o in obs:
        res.extend(prima.projBaseline([params['X'],
                                       params['Y'],
                                       params['Z'],
                                       params['A']],
                                      [o['RA'], o['DEC']],
                                      o['LST'],
                                      latitude = params['LAT'])['opd']),
    return np.array(res)
Пример #3
0
def leastsqOPDModel(p_fit, fit, p_fixed, obs):
    try:
        p = np.zeros(fit.size)
        p[np.where(fit)] = p_fit
        p[np.where(1-fit)] = p_fixed
    except:
        p = p_fit
    
    res = []
    for x in obs:
        res.extend(prima.projBaseline(p,[x['RA'], x['DEC']],
                                      x['LST'])['opd']/x['AIRN']-
                   x['DL2-DL1'])
    res = np.array(res)
    print 'B=', p, 'RMS (um)', res.std()*1e6
    return np.array(res)
Пример #4
0
def simu3():
    """
    what if the baseline is different for SS and PS?

    -> for small error in baselines, the residuals are still very
       small but the separation and projection angle of the binary are
       wrong...

    """
    ra = 12.0 # in h
    dec = -32.0 # in deg
    sep = 35.0 # in arcsec
    PA = 135.0 # in deg

    dra = sep*np.cos(PA*np.pi/180.)/(3600.*180.)*np.pi/15. # in h
    ddec = sep*np.sin(PA*np.pi/180.)/(3600.*180.)*np.pi # in deg

    print 'actual binary is SEP=', sep, '(\"), PA=', PA, '(deg)'
    base = np.array([-76.4,49.862,0]) # X,Y,Z in m G2-J2
    print 'actual baseline is:', base, '(m)'
    dbase = np.array([0*100e-6,0,0.0]) # error in Baseline, in m
    lst = np.linspace(12, 16, 50) # in h
    zeroM = 1.0 # in m

    # projected baseline
    projUV = prima.projBaseline(base, [ra, dec], lst)
    projPA = np.arctan(projUV[0], projUV[1])*180/np.pi
    projB = np.sqrt( projUV[0]**2+ projUV[1]**2)

    # projected baseline with offset
    print 'error in baseline is:', dbase, '(m)'
    projUVp = prima.projBaseline(base+dbase, [ra, dec], lst)
    projPAp = np.arctan(projUVp[0], projUVp[1])*180/np.pi
    projBp = np.sqrt( projUVp[0]**2+ projUVp[1]**2)

    # astrometric observables
    dopd = zeroM + \
           (prima.projBaseline(base, [ra, dec], lst)[2] -\
            prima.projBaseline(base+dbase, [ra+dra, dec+ddec], lst)[2])
    print 'dopd PTP=',dopd.ptp()*1e6, 'um'
    # swapped
    dopds = zeroM -\
            (prima.projBaseline(base, [ra, dec], lst)[2] -\
             prima.projBaseline(base+dbase, [ra+dra, dec+ddec], lst)[2])

    # observable
    B = list(projBp)
    B.extend(list(projBp))
    PA = list(projPAp)
    PA.extend(list(projPAp))
    Sw = list(np.zeros(len(projBp)))
    Sw.extend(list(np.ones(len(projBp))))
    dO = list(dopd)
    dO.extend(dopds)

    e = list(np.ones(2*len(dopd))*1e-6)
    parang =  list(np.zeros(2*len(dopd)))
    obs = [np.array(B), np.array(PA), np.array(Sw),
           np.array(parang), np.array(dO), np.array(e)]
    # fit
    param     = [35.0, 135.0, 1.0, 0,0,0]
    fit_param = [1   , 1   , 1   , 0,0,0]
    # prepare the fit
    w_fit  = np.where(np.array(fit_param))
    w_nfit = np.where(1-np.array(fit_param))
    p_fit = np.array(param)[w_fit]
    if not len(p_fit)==len(param):
        p_fixed = np.array(param)[w_nfit]
    else:
        p_fixed = []
    # -- fit
    plsq, cov, info, mesg, ier = \
          scipy.optimize.leastsq(leastsqAstromSepSimple, p_fit,
                                 args=(fit_param,p_fixed,obs,),
                                 epsfcn=1e-5, ftol=0.005, full_output=True)
    #plsq = param
    print 'fitted binary is SEP=', plsq[0], '(\"), PA=', plsq[1], '(deg)'


    # compute model
    dopd_M = np.array([astromSepSimple([projBp[k], projPAp[k], 0],
                                          [plsq[0], plsq[1], plsq[2]])
                          for k in range(len(projBp))])
    dopds_M = np.array([astromSepSimple([projBp[k], projPAp[k]+180, 1],
                                            [plsq[0], plsq[1], plsq[2]])
                            for k in range(len(projBp))])

    residuals = (dopd-dopds - (dopd_M-dopds_M))*1e6
    print 'peak to peak error in delta_dopdc is',\
          residuals.max()-residuals.min(), '(microns)'

    pyplot.figure(0)
    pyplot.clf()
    pyplot.subplot(211)
    pyplot.plot(lst, dopd-dopds, '.k', label='data')
    pyplot.plot(lst, dopd_M-dopds_M, 'k-', label='model')
    pyplot.xlabel('LST (h)')
    pyplot.ylabel('direct - swapped (m)')
    pyplot.legend()
    pyplot.subplot(212)
    pyplot.plot(lst, (dopd-dopds - (dopd_M-dopds_M))*1e6, '.k')
    pyplot.xlabel('LST (h)')
    pyplot.ylabel(r'O-C ($\mu$m)')
    return
Пример #5
0
def interpListOfFiles(list_of_files, data_directory=None,
                      first_guess=None, fit_param=None, shuffle=False,
                      fit_only_files=None, env_file=None, T0=290.0,
                      P0=734.0, plot=False, FSMplots=False,
                      arbitrary_offsets=None, maxPolyOrder=None,
                      maxResiduals=None, quiet=True,
                      sigmaClipping=None, res2fits=False,
                      saveCalibrated=False):
    """
    - read many reduced files

    - re-interpolate baselines and PA using polynomial fit

    - fit separation

    - maxResiduals=4.0: plots residuals betwwen -4 and 4 microns

    - res2fits=True: save residuals to the fit

    - saveCalibrated=True: save calibrated dOPD, i.e. with removed
      zero metrology
    """
    red = [] # tables of atom
    # load all reduced files
    for k, f in enumerate(list_of_files):
        # reduced file:
        rf = f.split('.')[0]+'_RED.fits'
        #  load reduced file
        a = atom(os.path.join(data_directory,rf))

        # print the table of loaded files:
        if not fit_only_files==None:
            if k in fit_only_files:
                fit='X'
            else:
                fit='_'
        else:
            fit = 'X'
        if not quiet: # pretty printing of data
            if k==0:
                N = len(rf)
                print '|idx |fit|INS.MODE | file'+' '*(len(rf)-3)+'| date '\
                      +' '*(len(a.date_obs)-4)+'|'
            print '| %2d | %1s | %7s | %s | %s |' % (k,  fit, a.insmode, rf, a.date_obs)

        red.append(a) # table of reduced files

    # function fo convert MJD to LST: simple linear extrapolation
    mjd2lst = lambda x: (x-red[0].mjd[0])*(23.+56/60.+4/3600.) + red[0].lst[0]

    # re-interpolate all vars(mjd) with start and end, except OPL
    var_poly_c = {}
    for k in red[0].var_start_end.keys():
        if not k[:3]=='OPL2':
            if k=='base' or k=='PA' or k=='airmass':
                nPoly = np.minimum(2*len(red)-2, 10)
            else:
                nPoly = len(red)//2+1
            if not maxPolyOrder is None:
                nPoly = min(nPoly, maxPolyOrder)
            X = [a.mjd_PCR_start for a in red]
            X.extend([a.mjd_PCR_end for a in red])
            Y = [a.var_start_end[k][0] for a in red]
            Y.extend([a.var_start_end[k][1] for a in red])
            X = np.array(X)
            Y = np.array(Y)
            # points to fit
            if k=='seeing' or k=='tau0':
                w = np.where(Y>0)
            else:
                w = range(len(X))
            # save polynomial coef
            var_poly_c[k] = np.polyfit(X[w]-X.mean(), Y[w], nPoly)
            # update each observation
            if k!= 'base' and k!='PA':
                for a in red:
                    a.var_mjd[k] = np.polyval(var_poly_c[k] ,a.mjd-X.mean())

        else:
            var_poly_c[k]= [0]

    if not env_file==None: # load Also environmental data.
        e = prima.env(env_file)
        dopl1 = []
        dopl2 = []
        for a in red:
            P = e.interpVarMJD('SitePressure')(a.mjd)
            # for AT3-G2-DL2(E)
            dist_G2 = a.A1L + a.var_mjd['OPL1']#.mean()

            T_G2   = (e.interpVarMJD('SiteTemp2m')(a.mjd)+
                      e.interpVarMJD('VLTItempSens6')(a.mjd)+
                      e.interpVarMJD('VLTI_HSS_TEMP2')(a.mjd)+
                      e.interpVarMJD('VLTI_HSS_TEMP4')(a.mjd)+
                      e.interpVarMJD('VLTI_HSS_TEMP2')(a.mjd)+
                      e.interpVarMJD('VLTItempSens5')(a.mjd))/6.+272

            dopl_G2   = prima.n_air_P_T(1.0, P, T=T_G2)*dist_G2
            dopl_G2_0 = prima.n_air_P_T(1.0, P0, T0)*dist_G2

            # for AT4-J2-DL4(W)
            dist_J2 = a.A2L + a.var_mjd['OPL2']#.mean()
            T_J2   = (e.interpVarMJD('SiteTemp2m')(a.mjd)+
                      e.interpVarMJD('VLTItempSens16')(a.mjd)+
                      e.interpVarMJD('VLTI_HSS_TEMP2')(a.mjd)+
                      e.interpVarMJD('VLTI_HSS_TEMP1')(a.mjd)+
                      e.interpVarMJD('VLTI_HSS_TEMP2')(a.mjd)+
                      e.interpVarMJD('VLTItempSens5')(a.mjd))/6.+272
            dopl_J2  = prima.n_air_P_T(1.0, P, T=T_J2)*dist_J2
            dopl_J2_0 = prima.n_air_P_T(1.0, P0, T0)*dist_J2

            dopl1.append(dopl_G2 - dopl_G2_0)
            dopl2.append(dopl_J2 - dopl_J2_0)

    # build observations tables for fitting
    base=[]
    PA  =[]
    swap=[]
    d_al=[]
    d_al_err=[]
    parang = []
    rot1 = []
    rot2 = []
    # correct for PRIMET glitches: OBSOLETE!
    #for a in red:
    #    a.d_al -= correctForPrimetJumps_JSa(a.mjd, a.jump)

    # add offset
    if not arbitrary_offsets==None:
        for k in  range(len(red)):
            red[k].d_al += arbitrary_offsets[k]*1e-6

    # default: use all observations
    if fit_only_files==None:
        fit_only_files = range(len(red))

    # all the variables, in separate lists... not very elegant
    for k in fit_only_files:
        base.extend(list(red[k].var_mjd['base']))
        PA.extend(list(red[k].var_mjd['PA']))
        swap.extend(list(red[k].swapped))
        d_al.extend(list(red[k].d_al))
        d_al_err.extend(list(red[k].d_al_err))
        parang.extend(list(red[k].var_mjd['parang']))
        rot1.extend(list(red[k].rot1))
        rot2.extend(list(red[k].rot2))

    base     = np.array(base)
    PA       = np.array(PA)
    swap     = np.array(swap)
    d_al     = np.array(d_al)
    d_al_err = np.array(d_al_err)
    parang   = np.array(parang)
    rot1     = np.array(rot1)
    rot2     = np.array(rot2)
    d_al_err = np.maximum(d_al_err, 1e-7)

    if shuffle:
        if isinstance(shuffle, int) and shuffle>1:
            np.random.seed(shuffle)
        wfit = np.random.randint(len(base), size=len(base))
    else:
        wfit = range(len(base))
    rot1 = 0 # force using parallactic
    if np.any(rot1): # we use rotators positions:
        #print 'USING rotator recordings'
        obs = [base[wfit], PA[wfit], swap[wfit], rot1[wfit], rot2[wfit],
               d_al[wfit], d_al_err[wfit]]
        if first_guess == None:
            param    = [35, 40.0, .015,0,0,0,0]
            fit_param= [1,  1,    1   ,1,1,1,1]
        else:
            param = first_guess
    else: # we use parallactic angle:
        #print 'USING parallactic angle'
        obs = [base[wfit], PA[wfit], swap[wfit], parang[wfit],
               d_al[wfit], d_al_err[wfit]]
        if first_guess == None:
            param    = [35, 40.0, .015,0,0]
            fit_param= [1,  1,    1   ,1,1]
        else:
            param = first_guess
    #print 'PARAMS:', param
    #print 'FIT_PARAM:',fit_param
    # --------- least square fit of the separation vector ---------------
    # prepare the fit
    w_fit  = np.where(np.array(fit_param))
    w_nfit = np.where(1-np.array(fit_param))

    p_fit = np.array(param)[w_fit]
    if not len(p_fit)==len(param):
        p_fixed = np.array(param)[w_nfit]
    else:
        p_fixed = []

    # fit
    if np.sum(fit_param)>0:
        plsq, cov, info, mesg, ier = \
              scipy.optimize.leastsq(leastsqAstromSepSimple, p_fit,
                                     args=(fit_param,p_fixed,obs,),
                                     epsfcn=1e-5, ftol=0.005,
                                     full_output=True)
    else:
        plsq = []

    # rebuild the complete parameter vector
    best = 1.0*np.array(param)
    best[w_fit] = plsq
    if best[0]<0:
        best[0] = abs(best[0])
        best[1] += 180

    chi2 = leastsqAstromSepSimple(best,None,None,obs)**2
    chi2_red = np.sum(chi2)/len(chi2)
    s = chi2.argsort()
    chi2_99pc = np.sum(chi2[s[:int(0.99*len(s))]])/(0.99*len(chi2))
    chi2_95pc = np.sum(chi2[s[:int(0.95*len(s))]])/(0.95*len(chi2))
    chi2_90pc = np.sum(chi2[s[:int(0.90*len(s))]])/(0.90*len(chi2))

    # build error vector
    err = np.zeros(len(param))
    if np.sum(p_fit)>0:
        err[w_fit] = np.sqrt(np.abs(np.diag(cov)*np.sum(chi2)))

    vars_  = ['sep', 'PA ', 'M0 ', 'cos', 'phi', 'cos', 'phi']
    units_ = ['\"',  'deg', 'mm ',  'um/\"', 'rad', 'um/\"', 'rad']
    if not quiet:
        print '+------------+-----------------------+'
        for k in range(len(err)):
            print '| %3s (%4s) | %10.5f +- %7.5f |' %\
                  (vars_[k], units_[k], best[k], err[k])
        print '+------------+-----------------------+'
        print 'PA baseline:', min([x.var_start_end['PA'][0] for x in red]), '->',\
              max([x.var_start_end['PA'][1] for x in red])
        print 'proj baseline:', min([x.var_start_end['base'][0] for x in red]), '->',\
              max([x.var_start_end['base'][1] for x in red])
        print 'CHI2_RED  =', round(chi2_red,2)
        print 'CHI2_[99, 95, 90]%%= [%5.2f, %5.2f, %5.2f]' % \
              (round(chi2_99pc,2), round(chi2_95pc,2) , round(chi2_90pc,2))
        print 'correlation between PA and sep=', cov[0,1]/np.sqrt(cov[0,0]*cov[1,1])
    else:
        return {'param':best, 'err':err, 'vars':vars_[:len(err)],
                'chi2':chi2_red, 'units':units_[:len(err)],
                'B_length':(min([x.var_start_end['base'][0] for x in red]),
                            max([x.var_start_end['base'][0] for x in red])),
                'B_PA':(min([x.var_start_end['PA'][0] for x in red]),
                        max([x.var_start_end['PA'][0] for x in red])),
                'target':red[0].PS_ID+'-'+red[0].SS_ID,
                'MJD-OBS':(min([a.mjd_PCR_start for a in red]), max([a.mjd_PCR_end for a in red]))}

    if res2fits:
        ### export the residuals to the fit as FITS file
        ### compute the residuals:
        mjd_min = []
        mjd_max = []
        all_res = []
        all_mjd = []
        all_lst = []
        all_proj = []
        all_pa = []
        all_parang=[]
        fitted_res = []
        flip_sign = 1.0 # put to -1 to flip sign, 1 otherwise
        for k, a in enumerate(red): # for each files (stored in red):
            mjd_min.append(a.mjd.min())
            mjd_max.append(a.mjd.max())
            all_lst.extend(list(a.lst))
            all_mjd.extend(list(a.mjd))
            UV = prima.projBaseline(red[0].baseXYZ, red[0].radec, a.lst)
            baseB = UV['B']
            all_proj.extend(list(baseB))
            basePA = UV['PA']
            all_pa.extend(list(basePA))
            parang=UV['parang']
            all_parang.extend(list(parang))
            all_res.extend(1e6*(flip_sign)**a.swapped*
                                        (a.d_al-
                                         astromSepSimple([baseB, basePA,
                                                          a.swapped, parang],
                                                         best)))
        # create fits files
        hdu = pyfits.PrimaryHDU(None)
        # list of keywords to propagate from first element of red
        list_of_kw = ['OBJECT', 'RA', 'DEC', 'EQUINOX']
        for k in list_of_kw:
            hdu.header.update(k, red[0].data[0].header[k])
        hdu.header.update('MJDSTART', min(mjd_min))
        hdu.header.update('MJDEND', min(mjd_max))
        print best
        hdu.header.update('FIT_SEP', best[0], 'binary separation in arcsec')
        hdu.header.update('FIT_PA', best[1], 'binary angle in deg')
        hdu.header.update('FIT_ZERO', best[2], 'metrology zero point, in mm')
        for k, a in enumerate(red):
            hdu.header.update('ORIF'+str(k), red[k].data[0].header['ORIGFILE'])
            hdu.header.update('ARCF'+str(k), red[k].data[0].header['ARCFILE'])
        cols = []
        cols.append(pyfits.Column(name='MJD', format='F12.5',
                                  array=all_mjd))
        cols.append(pyfits.Column(name='LST', format='F11.8',
                                  array=all_lst, unit='h'))
        cols.append(pyfits.Column(name='PROJ_BASE', format='F8.4',
                                  array=all_proj, unit='m'))
        cols.append(pyfits.Column(name='PA_BASE', format='F8.4',
                                  array=all_pa, unit='deg'))
        cols.append(pyfits.Column(name='residuals', format='F8.3',
                                  array=all_res, unit='um'))
        hducols = pyfits.ColDefs(cols)
        hdub = pyfits.new_table(hducols)
        hdub.header.update('EXTNAME', 'ASTROM_FIT_RESIDUALS', '')
        thdulist = pyfits.HDUList([hdu, hdub])
        print '--- saving residuals.fits ---'
        thdulist.writeto('residuals.fits')
        # done!

    if saveCalibrated:
        for a in red:
            #Create new file
            cols = [a.data['ASTROMETRY_BINNED'].columns[k] for
                    k in len(a.data['ASTROMETRY_BINNED'].columns)]
            cols.append(pyfits.Column(name='D_AL_ZEROED', format='F12.9',
                                      array=a.data['ASTROMETRY_BINNED'].data.field['D_AL']-
                                      best[2]*1e-3))

    if plot:
        ### x in MJD
        x = np.linspace(min([a.mjd_PCR_start for a in red])-0.003,
                           max([a.mjd_PCR_end for a in red])+0.003,
                           300)
        f = pyplot.figure(0, figsize=(10,7))
        pyplot.clf()
        f.subplots_adjust(hspace=0.05, top=0.95, left=0.13,
                          right=0.98, bottom=0.1)

        ### metrology measurements ####################
        ax1 = pyplot.subplot(211)
        pyplot.title(red[0].PS_ID+'-'+red[0].SS_ID+' (MJD '+
                     str(round(min([a.mjd_PCR_start for a in red]), 3))+
                     ' -> '+
                     str(round(max([a.mjd_PCR_end for a in red]), 3))+')')
        pyplot.setp(ax1.get_xticklabels(), visible=False)
        pyplot.ylabel('PRIMET swapping (mm)')
        # zero point:
        pyplot.hlines(best[2],
                      np.array([a.mjd_PCR_start for a in red]).min()-0.003,
                      np.array([a.mjd_PCR_end for a in red]).max()+0.003,
                      color='g', linestyle='dotted', linewidth=2)
        # model
        UV     = prima.projBaseline(red[0].baseXYZ, red[0].radec, mjd2lst(x))
        baseB  = UV['B']
        basePA = UV['PA']
        parang = UV['parang']
        pyplot.plot(x, 1e3*astromSepSimple([baseB, basePA,
                                            np.zeros(len(x)), parang], best),
                    linestyle='-', linewidth=2, color='y')
        pyplot.plot(x, 1e3*astromSepSimple([baseB, basePA,
                                            np.ones(len(x)), parang], best),
                    linestyle='--', linewidth=2, color='c')
        # measurements
        for k, a in enumerate(red):
            if (k==np.array(fit_only_files)).max():
                style = 'pg' # fitted
            else:
                style = '+r' # not fitted
            #pyplot.errorbar(a.mjd, a.d_al, yerr=a.d_al_err,
            #                color='k', marker=None)
            pyplot.plot(a.mjd, 1e3*a.d_al, style, alpha=0.1)

        ### residuals*(-1)**swapped to model ###################
        flip_sign = -1.0 # put to -1 to flip sign, 1 otherwise
        #flip_sign = 1
        pyplot.subplot(212, sharex=ax1)
        yl = r'residuals '
        if flip_sign == -1:
            yl = yl+' flipped '
        yl = yl+'($\mu$m)'
        pyplot.ylabel(yl)
        # 0-line
        pyplot.hlines([0],
                      np.array([a.mjd_PCR_start for a in red]).min()-0.003,
                      np.array([a.mjd_PCR_end for a in red]).max()+0.003,
                      color='0.5', linewidth=2, linestyle='-')

        ########## compute residuals: #####################
        # data points
        mjd_avg = []
        res_avg = []
        b_lab_f = True
        b_lab_u = True
        # for each reduced file:
        all_res = []
        fitted_res = []


        for k, a in enumerate(red):
            # for each reduced obsering block
            mjd_avg.append(a.mjd.mean())
            if np.any(rot1):
                bam = [a.var_mjd['base'], a.var_mjd['PA'],
                       a.swapped, a.rot1, a.rot2]
            else:
                bam = [a.var_mjd['base'], a.var_mjd['PA'],
                        a.swapped, a.var_mjd['parang']]
            all_res.extend(1e6*(flip_sign)**a.swapped*
                                        (a.d_al-astromSepSimple(bam,best)))
            res_avg.append(np.median(1e6*(flip_sign)**a.swapped*
                                     (a.d_al-astromSepSimple(bam,best))))
            if (k==np.array(fit_only_files)).max():
                style = 'pg' # fitted
                if b_lab_f:
                    label='fitted'
                    b_lab_f=False
                else:
                    label=None
                fitted_res.extend(1e6*(flip_sign)**a.swapped*
                                  (a.d_al-astromSepSimple(bam,best)))
            else:
                style = '+r' # not fitted
                if b_lab_u:
                    label='not fitted'
                    b_lab_u=False
                else:
                    label=None
            # plot residuals for this observing block
            pyplot.plot(a.mjd, 1e6*(flip_sign)**a.swapped*
                (a.d_al-astromSepSimple(bam, best)),
                style, label=label, alpha=0.5)

        sor = np.array(fitted_res)[np.array(fitted_res).argsort()]
        pseudo_std = (sor[int(0.84*len(sor))]-sor[int(0.15*len(sor))])/2
        print 'residuals RMS=', np.array(fitted_res).std(), 'microns'
        print 'residuals pseudo RMS=', pseudo_std , 'microns'
        mjd_avg = np.array(mjd_avg)
        res_avg = np.array(res_avg)
        # 1-position per cluster
        w = np.where(np.array([a.swapped.mean()==0 for a in red]))
        s = mjd_avg[w].argsort()
        w = w[0][s]
        pyplot.plot(mjd_avg[w], res_avg[w], 'sy', linewidth=3,
                    linestyle='-', label='NORMAL', markersize=8, alpha=0.8)
        w = np.where(np.array([a.swapped.mean()==1 for a in red]))
        s = mjd_avg[w].argsort()
        w = w[0][s]
        pyplot.plot(mjd_avg[w], res_avg[w], 'dc', linewidth=3, alpha=0.8,
                    linestyle='dashed', label='SWAPPED', markersize=10)

        if not arbitrary_offsets==None:
            for k in range(len(red)):
                if k==0:
                    label='offsets'
                else:
                    label=None
                pyplot.hlines([(-1)**(red[k].swapped.mean())*arbitrary_offsets[k]],
                              red[k].mjd.min(), red[k].mjd.max(),
                              color=(0.8, 0.3, 0), linewidth=3, label=label)
        # -- plot metrology jumps
        #pyplot.plot(x, correctForPrimetJumps(x, red[0].jump*1e6),
        #            color='m', linestyle='-.', linewidth=2, label='jumps')
        pyplot.legend(loc='upper left', ncol=4, bbox_to_anchor=(.0, 1.02, 1.2, .05))
        if not maxResiduals is None:
            pyplot.ylim(-maxResiduals, maxResiduals)
        pyplot.xlabel('MJD')
        #---------- FSM plots ------------
        if FSMplots:
            pyplot.figure(2, figsize=(10,8))
            pyplot.clf()
            pyplot.subplots_adjust(top=0.95, left=0.05,
                                  right=0.98, bottom=0.05)
            for sts in [1,2]:
                for fsm in [1,2]:
                    pyplot.subplot(220+(sts-1)*2+fsm)
                    pyplot.title('STS'+str(sts)+' FSM'+str(fsm)+':pos in $\mu$m')
                    if sts==1 and fsm==1:
                        # AT3 FSM1
                        fsm_lims = [22,25,20,28]
                        fsm_p = [10.5, -0.285, 10.5, 0.446]
                    elif sts==2 and fsm==1:
                        # AT4 FSM1
                        fsm_lims = [25,28,20,28]
                        #fsm_p = [20, -0.491, 20, 0.315]
                        fsm_p = [20, -0.025, 20, -0.210]
                    elif sts==1 and fsm==2:
                        # AT3 FSM2
                        fsm_lims = [6,9,7,15]
                        fsm_p = [6.5, -0.046, 10.5, -0.063]
                    elif sts==2 and fsm==2:
                        # AT4 FSM2
                        fsm_lims = [8.5,11.5,7,15]
                        #fsm_p = [10, -0.025, 10, -0.210]
                        fsm_p = [10, -0.491, 10, 0.315]

                    xp, yp = np.meshgrid(np.linspace(fsm_lims[0],fsm_lims[1],100),
                                         np.linspace(fsm_lims[2],fsm_lims[3],100))
                    dopd = (xp-fsm_p[0])*fsm_p[1] + (yp-fsm_p[2])*fsm_p[3]
                    print 'dopd:', dopd.min(), dopd.max()
                    pyplot.pcolormesh(xp,yp, dopd, vmin=-2, vmax=5)
                    pyplot.colorbar()
                    for x in red:
                        pyplot.plot([x.data[0].header['ESO ISS PRI STS'+str(sts)+
                                                      ' FSMPOSX'+str(fsm)+' START'],
                                    x.data[0].header['ESO ISS PRI STS'+str(sts)+
                                                     ' FSMPOSX'+str(fsm)+' END']],
                                    [x.data[0].header['ESO ISS PRI STS'+str(sts)+\
                                                      ' FSMPOSY'+str(fsm)+' START'],
                                     x.data[0].header['ESO ISS PRI STS'+str(sts)+\
                                                      ' FSMPOSY'+str(fsm)+' END']],
                                    ('sy-' if x.insmode=='NORMAL' else 'dc-'),
                                    markersize=14)

        return # skip additional plots
        pyplot.figure(2, figsize=(4,4))
        pyplot.clf()
        pyplot.subplot(111, polar=True)
        sortmjd = np.array([x.mjd_PCR_start for x in red]).argsort()
        PAmin = [x.var_start_end['PA'][0] for x in red][sortmjd[0]]
        PAmax = [x.var_start_end['PA'][1] for x in red][sortmjd[-1]]

        pyplot.bar(PAmin*np.pi/180., 1,
                   width =(PAmax-PAmin)*np.pi/180.,
                   color='red', alpha=0.5,
                   label='baseline')
        pyplot.bar(PAmin*np.pi/180.+np.pi, 1,
                   width =(PAmax-PAmin)*np.pi/180.,
                   color='red', alpha=0.5)

        pyplot.plot([best[1]*np.pi/180,best[1]*np.pi/180], [0,1], color='k',
                    alpha=0.8, linewidth=5, label='binary')
        pyplot.legend()

        #return #--------------------------------------------------
        f = pyplot.figure(1, figsize=(14,10))
        pyplot.clf()
        f.subplots_adjust(hspace=0.04, top=0.97, left=0.1,
                          right=0.98, bottom=0.05)

        #### polynomial interpolations ##################
        n = len(var_poly_c.keys())
        ### x in MJD
        x = np.linspace(min([a.mjd_PCR_start for a in red])-0.003,
                           max([a.mjd_PCR_end for a in red])+0.003,
                           300)
        for i,k in enumerate(var_poly_c.keys()):
            if i==0:
                ax0 = pyplot.subplot(n,2,1+2*i)
                pyplot.title('interpolation')
                pyplot.setp(ax0.get_xticklabels(), visible=False)
            else:
                ax1 = pyplot.subplot(n,2,1+2*i, sharex=ax0)
            if not i==(n-1):
                pyplot.setp(ax1.get_xticklabels(), visible=False)
            else:
                pyplot.xlabel('MJD')
            pyplot.ylabel(k)

            if len(var_poly_c[k])>1:
                pyplot.plot(x, np.polyval(var_poly_c[k], x-X.mean()), 'k-')
            for a in red:
                if k=='base' or k=='PA':
                    pyplot.plot(a.mjd, a.var_mjd[k], '.r')
                else:
                    pyplot.plot(a.mjd, a.var_mjd[k], '.y')
                pyplot.plot(a.mjd_PCR_start, a.var_start_end[k][0], 'oy')
                pyplot.plot(a.mjd_PCR_end, a.var_start_end[k][1], 'oy')

            # residuals
            ax2 = pyplot.subplot(n,2,2+2*i, sharex=ax0)
            if not i==(n-1):
                pyplot.setp(ax2.get_xticklabels(), visible=False)
            else:
                pyplot.xlabel('MJD')

            if i==0:
                pyplot.title('residual')

            pyplot.hlines([0],
                          np.array([a.mjd_PCR_start for a in red]).min()-0.003,
                          np.array([a.mjd_PCR_end for a in red]).max()+0.003,
                          color='k')
            if len(var_poly_c[k])>1:
                for a in red:
                    pyplot.plot([a.mjd_PCR_start,a.mjd_PCR_end],
                                [a.var_start_end[k][0]-
                                 np.polyval(var_poly_c[k],
                                               a.mjd_PCR_start-X.mean()),
                                 a.var_start_end[k][1]-
                                 np.polyval(var_poly_c[k],
                                               a.mjd_PCR_end-X.mean())],
                                'oy-')

    return
Пример #6
0
    def __init__(self, filename, debug=False):
        he = 'HIERARCH ESO '
        self.data = pyfits.open(filename)
        self.date_obs = self.data[0].header['DATE-OBS']
        self.targname = self.data[0].header['HIERARCH ESO OBS TARG NAME']
        self.PS_ID = self.data[0].header['HIERARCH ESO OCS PS ID']
        self.SS_ID = self.data[0].header['HIERARCH ESO OCS SS ID']
        self.mjd_obs = self.data[0].header['MJD-OBS']
        self.lst_obs = self.data[0].header['LST']/3600.
        self.mjd= self.data['ASTROMETRY_BINNED'].data.field('MJD')
        # simple linear interpolation
        self.lst = self.lst_obs + (self.mjd - self.mjd_obs)*(23.+56/60.+4/3600.)

        self.d_al= self.data['ASTROMETRY_BINNED'].data.field('D_AL')
        self.d_al_err= self.data['ASTROMETRY_BINNED'].data.field('D_AL_err')
        try:
            self.rot1= self.data['ASTROMETRY_BINNED'].data.field('ROT1')
            self.rot2= self.data['ASTROMETRY_BINNED'].data.field('ROT2')
        except:
            self.rot1= np.zeros(len(self.d_al))
            self.rot2= np.zeros(len(self.d_al))

        self.mjd_PCR_start  = astro.tag2mjd(self.data[0].header[he+'PCR ACQ START'])
        self.mjd_PCR_end    = astro.tag2mjd(self.data[0].header[he+'PCR ACQ END'])
        self.lst_PCR_start = astro.tag2lst(self.data[0].header['ESO PCR ACQ START'],
                                           longitude=self.data[0].header['ESO ISS GEOLON'])
        self.A1L        = self.data[0].header[he+'ISS CONF A1L']
        self.A2L        = self.data[0].header[he+'ISS CONF A2L']
        try:
            self.insmode = self.data[0].header[he+'ISS PRI STS3 GUIDE_MODE']
        except:
            self.insmode    = self.data[0].header[he+'INS MODE']

        cP  = self.data[0].header[he+'ISS PRI MET C'] # in m/s
        dnuP = self.data[0].header[he+'ISS PRI MET F_SHIFT']*1e6 # in Hz
        nuP  = self.data[0].header[he+'ISS PRI MET LASER_F']
        #self.jump =  (cP * dnuP/2/(nuP**2) ) * ( 2**24-1 ) # PRIMET jump in m, COMM14
        self.jump =  (cP * dnuP/2/(nuP**2) ) * ( 2**31-1 ) # PRIMET jump in m, COMM15

        if 'SWAP' in self.insmode: # legacy: was SWAP at some point, now is SWAPPED
            self.swapped = np.ones(len(self.mjd))
        else:
            astro.tag2lst(self.data[0].header['ESO PCR ACQ START'],
                          longitude=self.data[0].header['ESO ISS GEOLON'])
            self.swapped = np.zeros(len(self.mjd))

        # dictionnary of variables(mjd) START
        names = ['base', 'PA', 'OPL1', 'OPL2', 'airmass',
                 'tau0','seeing', 'parang']
        keyw = ['ISS PBL12', 'ISS PBLA12', 'DEL DLT1 OPL',
                'DEL DLT2 OPL', 'ISS AIRM', 'ISS AMBI TAU0',
                'ISS AMBI FWHM', 'ISS PARANG']
        self.var_start_end = {}
        for k in range(len(names)):
            self.var_start_end[names[k]] =(self.data[0].header[he+keyw[k]+' START'],
                                           self.data[0].header[he+keyw[k]+' END'])
        self.var_mjd={}

        # linear interpolation
        for k in self.var_start_end.keys():
            if k != 'base' and k != 'PA':
                self.var_mjd[k] = self.var_start_end[k][0]+\
                                  (self.mjd - self.mjd_PCR_start)/\
                                  (self.mjd_PCR_end - self.mjd_PCR_start)*\
                                  (self.var_start_end[k][1]-
                                   self.var_start_end[k][0])
            else:
                # compute baselines
                self.baseXYZ = [self.data[0].header[he+'ISS CONF T1X']-
                                self.data[0].header[he+'ISS CONF T2X'],
                                self.data[0].header[he+'ISS CONF T1Y']-
                                self.data[0].header[he+'ISS CONF T2Y'],
                                self.data[0].header[he+'ISS CONF T1Z']-
                                self.data[0].header[he+'ISS CONF T2Z'],
                                self.data[0].header[he+'ISS CONF A1L']-
                                self.data[0].header[he+'ISS CONF A2L']]
                # coordinates, corrected for proper motion
                self.radec = [astro.ESOcoord2decimal(self.data[0].header['ESO OCS TARG1 ALPHAPMC']),
                              astro.ESOcoord2decimal(self.data[0].header['ESO OCS TARG2 DELTAPMC'])]
                self.radec = [self.data[0].header['RA']/15.,
                              self.data[0].header['DEC']]
                bb = prima.projBaseline(self.baseXYZ, self.radec, self.lst)
                if k == 'base':
                    self.var_mjd[k] = bb['B']
                    if debug:
                        print 'DEBUG: PBL12 START: computed', self.var_mjd[k][0],\
                              'in header:', self.data[0].header[he+'ISS PBL12 START'], \
                              'DELTA=', self.var_mjd[k][0]-self.data[0].header[he+'ISS PBL12 START']
                        print 'DEBUG: PBL12 END  : computed', self.var_mjd[k][-1],\
                              'in header:', self.data[0].header[he+'ISS PBL12 END'], \
                              'DELTA=', self.var_mjd[k][-1]-self.data[0].header[he+'ISS PBL12 END']
                if k == 'PA':
                    self.var_mjd[k] = bb['PA']
                    if debug:
                        print 'DEBUG: PBLA12 START: computed', self.var_mjd[k][0],\
                              'in header:', self.data[0].header[he+'ISS PBLA12 START'],\
                              'DELTA=', self.var_mjd[k][0]-self.data[0].header[he+'ISS PBLA12 START']
                        print 'DEBUG: PBLA12 END  : computed', self.var_mjd[k][-1],\
                              'in header:', self.data[0].header[he+'ISS PBLA12 END'],\
                              'DELTA=', self.var_mjd[k][-1]-self.data[0].header[he+'ISS PBLA12 END']
        self.data.close()
        return
Пример #7
0
    def __init__(self, filename, debug=False):
        he = "HIERARCH ESO "
        self.data = pyfits.open(filename)
        self.filename = filename
        self.date_obs = self.data[0].header["DATE-OBS"]
        self.targname = self.data[0].header["HIERARCH ESO OBS TARG NAME"]
        self.PS_ID = self.data[0].header["HIERARCH ESO OCS PS ID"]
        self.SS_ID = self.data[0].header["HIERARCH ESO OCS SS ID"]
        self.mjd_obs = self.data[0].header["MJD-OBS"]
        self.lst_obs = self.data[0].header["LST"] / 3600.0
        self.mjd = self.data["ASTROMETRY_BINNED"].data.field("MJD")
        try:
            self.lst = self.data["ASTROMETRY_BINNED"].data.field("LST")
        except:
            print "WARNING: USING BAD LST!"
            self.lst = self.lst_obs + (self.mjd - self.mjd_obs) * (23.0 + 56 / 60.0 + 4 / 3600.0)

        self.d_al = self.data["ASTROMETRY_BINNED"].data.field("D_AL")
        if self.PS_ID == "HD129926" and self.mjd_obs < 56005.0:
            # problem with these observations
            print "WARNING: KLUDGING D_AL -> -DA_L!!!"
            self.d_al *= -1
        self.d_al_err = self.data["ASTROMETRY_BINNED"].data.field("D_AL_err")
        try:
            self.rot3 = self.data["ASTROMETRY_BINNED"].data.field("ROT3")
            self.rot4 = self.data["ASTROMETRY_BINNED"].data.field("ROT4")
            self.az3 = self.data["ASTROMETRY_BINNED"].data.field("AZ3")
            self.az4 = self.data["ASTROMETRY_BINNED"].data.field("AZ4")
            self.alt3 = self.data["ASTROMETRY_BINNED"].data.field("ALT3")
            self.alt4 = self.data["ASTROMETRY_BINNED"].data.field("ALT4")
        except:
            self.rot3 = np.zeros(len(self.d_al))
            self.rot4 = np.zeros(len(self.d_al))
            self.az3 = np.zeros(len(self.d_al))
            self.az4 = np.zeros(len(self.d_al))
            self.alt3 = np.zeros(len(self.d_al))
            self.alt4 = np.zeros(len(self.d_al))

        self.mjd_PCR_start = astro.tag2mjd(self.data[0].header[he + "PCR ACQ START"])
        self.mjd_PCR_end = astro.tag2mjd(self.data[0].header[he + "PCR ACQ END"])
        self.lst_PCR_start = astro.tag2lst(
            self.data[0].header["ESO PCR ACQ START"], longitude=self.data[0].header["ESO ISS GEOLON"]
        )
        self.A1L = self.data[0].header[he + "ISS CONF A1L"]
        self.A2L = self.data[0].header[he + "ISS CONF A2L"]
        try:
            self.insmode = self.data[0].header[he + "ISS PRI STS3 GUIDE_MODE"]
        except:
            self.insmode = self.data[0].header[he + "INS MODE"]

        if not self.insmode in ["NORMAL", "SWAPPED"]:
            # print 'WARNING: unknown INSMODE=', self.insmode
            pass
        if self.insmode == "INCONSISTENT":
            # -- try to guess
            if self.data[0].header[he + "DEL FT SENSOR"] == "FSUB":
                self.insmode = "NORMAL"
            elif self.data[0].header[he + "DEL FT SENSOR"] == "FSUA":
                self.insmode = "SWAPPED"
            # print '  -> guessing: INSMODE=', self.insmode

        cP = self.data[0].header[he + "ISS PRI MET C"]  # in m/s
        dnuP = self.data[0].header[he + "ISS PRI MET F_SHIFT"] * 1e6  # in Hz
        nuP = self.data[0].header[he + "ISS PRI MET LASER_F"]
        # self.jump =  (cP*dnuP/2/(nuP**2))*(2**24-1) # PRIMET jump in m, COMM14
        self.jump = (cP * dnuP / 2 / (nuP ** 2)) * (2 ** 31 - 1)  # PRIMET jump in m, COMM15

        if "SWAP" in self.insmode:  # legacy: was SWAP at some point
            self.swapped = np.ones(len(self.mjd))
        else:
            astro.tag2lst(self.data[0].header["ESO PCR ACQ START"], longitude=self.data[0].header["ESO ISS GEOLON"])
            self.swapped = np.zeros(len(self.mjd))

        # dictionnary of variables(mjd) START
        names = ["base", "PA", "OPL1", "OPL2", "airmass", "tau0", "seeing", "parang"]
        keyw = [
            "ISS PBL12",
            "ISS PBLA12",
            "DEL DLT1 OPL",
            "DEL DLT2 OPL",
            "ISS AIRM",
            "ISS AMBI TAU0",
            "ISS AMBI FWHM",
            "ISS PARANG",
        ]
        self.var_start_end = {}
        for k in range(len(names)):
            self.var_start_end[names[k]] = (
                self.data[0].header[he + keyw[k] + " START"],
                self.data[0].header[he + keyw[k] + " END"],
            )
        self.var_mjd = {}

        # linear interpolation
        for k in self.var_start_end.keys():
            if k != "base" and k != "PA":
                self.var_mjd[k] = self.var_start_end[k][0] + (self.mjd - self.mjd_PCR_start) / (
                    self.mjd_PCR_end - self.mjd_PCR_start
                ) * (self.var_start_end[k][1] - self.var_start_end[k][0])
            else:
                # compute baselines
                self.baseXYZ = [
                    self.data[0].header[he + "ISS CONF T1X"] - self.data[0].header[he + "ISS CONF T2X"],
                    self.data[0].header[he + "ISS CONF T1Y"] - self.data[0].header[he + "ISS CONF T2Y"],
                    self.data[0].header[he + "ISS CONF T1Z"] - self.data[0].header[he + "ISS CONF T2Z"],
                    self.data[0].header[he + "ISS CONF A1L"] - self.data[0].header[he + "ISS CONF A2L"],
                ]
                # coordinates, corrected for proper motion
                try:
                    self.radec = [
                        astro.ESOcoord2decimal(self.data[0].header["ESO OCS TARG1 ALPHAPMC"]),
                        astro.ESOcoord2decimal(self.data[0].header["ESO OCS TARG1 DELTAPMC"]),
                    ]
                except:
                    print "WARNING: could not find precessed coordinates in header!"
                    self.radec = [
                        astro.ESOcoord2decimal(self.data[0].header["ESO ISS REF RA"]),
                        astro.ESOcoord2decimal(self.data[0].header["ESO ISS REF DEC"]),
                    ]
                self.radec = [self.data[0].header["RA"] / 15.0, self.data[0].header["DEC"]]
                bb = prima.projBaseline(self.baseXYZ, self.radec, self.lst)
                if k == "base":
                    self.var_mjd[k] = bb["B"]
                    if debug:
                        print "DEBUG: PBL12 START: computed", self.var_mjd[k][0], "in header:", self.data[0].header[
                            he + "ISS PBL12 START"
                        ], "DELTA=", self.var_mjd[k][0] - self.data[0].header[he + "ISS PBL12 START"]
                        print "DEBUG: PBL12 END  : computed", self.var_mjd[k][-1], "in header:", self.data[0].header[
                            he + "ISS PBL12 END"
                        ], "DELTA=", self.var_mjd[k][-1] - self.data[0].header[he + "ISS PBL12 END"]
                if k == "PA":
                    self.var_mjd[k] = bb["PA"]
                    if debug:
                        print "DEBUG: PBLA12 START: computed", self.var_mjd[k][0], "in header:", self.data[0].header[
                            he + "ISS PBLA12 START"
                        ], "DELTA=", self.var_mjd[k][0] - self.data[0].header[he + "ISS PBLA12 START"]
                        print "DEBUG: PBLA12 END  : computed", self.var_mjd[k][-1], "in header:", self.data[0].header[
                            he + "ISS PBLA12 END"
                        ], "DELTA=", self.var_mjd[k][-1] - self.data[0].header[he + "ISS PBLA12 END"]
        self.data.close()
        return
Пример #8
0
def dOPDfunc(X, prms, addIntermediate=False):
    """
    only works with one target, and one baselines

    X = [{'TARGET':, 'RA':, 'DEC':, 'B_XYZA':, 'lst', 'SWAPPED':, 'MJD'}]
    ---------------------------------------------------------------------

    - RA, DEC: the coordinates in decimal hour and degrees
    - B_XYZA is the baseline vector in meters (length 4)
    - LST in decimal hour
    - SWAPPED: 1, 0, or True, False

    possible parameters:
    --------------------

    angles in degrees, separation in arcsec, M0 in mm

    - params: {'M0':, 'SEP':, 'PA':)

    - params: {'M0':, 'SEP':, 'PA':, 'M0S':} where M0S is the zero
      point in SWAPPED

    - params: {'M0 MJD xxxxxx.xxx xxxxxx.xxx', 'M0 MJD yyyyyy.yyyy
      yyyyyyy.yyy':, 'SEP':, 'PA':} with 2 different zero point, based
      on the MJD (the 2 MJD and the min and max range). Should be
      floats, no ints

    linear drift of separation:
    
    - 'SEP MJD xxxxxx.xx':arcsec, 'PA MJD xxxxxxxxx.xx':degree,
      'LINDIR':degrees, 'LINRATE':uas/day 'SEP ...' and 'PA ...'
      defines the separation and PA at a given date. from there, the
      separation vector evolves at the given rate, in the given
      direction.
      
    - addIntermediate: stores intermediate calculations, such as
      projected baseline, separation, M0 etc. PRIMETphase counts when
      PRIMET has been initialized. Only point with same PRIMETphase
      can be combined.

    """
    global dOPDfuncNiter
    c_ = np.pi / (180 * 3600.0)  # rad / arcsec

    if len(X) < 1:  # case nothing is passed
        return []

    # start with 0 dOPD
    dOPD = np.zeros(len(X))

    # we will need (-1)**swap a few time:
    swap = (-1) ** np.array([x["SWAPPED"] for x in X])

    # compute projected baseline:
    projB = prima.projBaseline(X[0]["B_XYZA"], (X[0]["RA"], X[0]["DEC"]), [x["LST"] for x in X])
    b_p = projB["B"]
    b_pa = projB["PA"]
    if addIntermediate:
        for k in range(len(X)):
            X[k]["fit Bp"] = b_p[k]
            X[k]["fit Bpa"] = b_pa[k]

    # single metrology zero point
    if prms.has_key("M0"):
        dOPD += prms["M0"] * 1e-3
        if addIntermediate:
            for k in range(len(X)):
                X[k]["fit M0"] = prms["M0"] * 1e-3
                X[k]["fit PRIMETphase"] = 0

    # different zero point for SWAPPED and NORMAL
    if prms.has_key("M0S"):
        dOPD = np.array([prms["M0S"] * 1e-3 if x["SWAPPED"] else prms["M0"] for x in X])
        if addIntermediate:
            for k in range(len(X)):
                X[k]["fit M0"] = prms["M0S"] * 1e-3 if X[k]["SWAPPED"] else prms["M0"]
                X[k]["fit PRIMETphase"] = 0  # still considered a single PRIMET phase

    # different M0 by MJD range
    if any([k[:6] == "M0 MJD" for k in prms.keys()]):
        mjd = np.array([x["MJD"] for x in X])
        PRIMETphase = 0
        for k in prms.keys():
            if k[:6] == "M0 MJD":
                MJD_min = float(k.split()[2])
                MJD_max = float(k.split()[3])
                w = np.where((mjd < MJD_max) * (mjd >= MJD_min))
                dOPD[w] = prms[k] * 1e-3
                if addIntermediate:
                    for k in range(len(w[0])):
                        X[w[0][k]]["fit M0"] = dOPD[w][k]
                        X[w[0][k]]["fit PRIMETphase"] = PRIMETphase
                PRIMETphase += 1

    # astrometric modulation: static
    if prms.has_key("SEP") and prms.has_key("PA"):
        dOPD += swap * b_p * prms["SEP"] * c_ * np.cos((b_pa - prms["PA"]) * np.pi / 180)
        if addIntermediate:
            for k in range(len(X)):
                X[k]["fit SEP"] = prms["SEP"]
                X[k]["fit PA"] = prms["PA"]

    # astrometric modulation: linear
    if (
        any(["SEP MJD" in k for k in prms.keys()])
        and any(["PA MJD" in k for k in prms.keys()])
        and prms.has_key("LINDIR")
        and prms.has_key("LINRATE")
    ):
        # get MJD0:
        for k in prms.keys():
            if k[:7] == "SEP MJD":
                MJD0 = float(k.split()[2])
                SEP0 = prms[k]
            if k[:6] == "PA MJD":
                PA0 = prms[k]
        # cartesian separation vector:
        X_ = SEP0 * np.sin(PA0 * np.pi / 180)
        Y_ = SEP0 * np.cos(PA0 * np.pi / 180)
        X_ += 1e-6 * (np.array([x["MJD"] for x in X]) - MJD0) * prms["LINRATE"] * np.sin(prms["LINDIR"] * np.pi / 180)
        Y_ += 1e-6 * (np.array([x["MJD"] for x in X]) - MJD0) * prms["LINRATE"] * np.cos(prms["LINDIR"] * np.pi / 180)
        # compute separation/PA as a function of time:
        SEPt = np.sqrt(X_ ** 2 + Y_ ** 2)
        PAt = np.arctan2(X_, Y_) * 180 / np.pi
        if addIntermediate:
            for k in range(len(X)):
                X[k]["fit SEP"] = SEPt[k]
                X[k]["fit PA"] = PAt[k]
        dOPD += swap * b_p * SEPt * c_ * np.cos((b_pa - PAt) * np.pi / 180)

    if prms.has_key("SEP"):
        # angle between M10 edge and the binary:
        addAngle = np.arcsin(10.0 / prms["SEP"]) * 180 / np.pi if prms["SEP"] > 10 else 90.0
        addAngle += 90  # relative to x
        sx = prms["SEP"] * c_ * np.cos(addAngle / 180.0 * np.pi)  # in rad
        sy = prms["SEP"] * c_ * np.sin(addAngle / 180.0 * np.pi)  # in rad
    else:
        # angle between M10 edge and the binary:
        addAngle = np.arcsin(10.0 / SEP0) * 180 / np.pi if SEP0 > 10 else 90.0
        addAngle += 90  # relative to x
        sx = SEP0 * c_ * np.cos(addAngle / 180.0 * np.pi)  # in rad
        sy = SEP0 * c_ * np.sin(addAngle / 180.0 * np.pi)  # in rad
    if addIntermediate:
        for k in range(len(X)):
            X[k]["fit angleIRIS"] = addAngle

    if prms.has_key("IRIS scale"):
        scale = prms["IRIS scale"]
    else:
        scale = 23.5e-3  #  scale of pupil on IRIS, in m/pix
    if prms.has_key("ATPUP scale"):
        scale *= prms["ATPUP scale"]

    # pupil runout model
    ####################
    px = np.zeros(len(X))
    py = np.zeros(len(X))

    # -- parameters used in the formula
    Pfuhl = ["a0", "a1", "phi0", "phi1", "phi2", "x0", "y0"]
    Bonnet = ["ctX", "stX", "cdX", "sdX", "c2dX", "s2dX", "ctY", "stY", "cdY", "sdY", "c2dY", "s2dY"]
    Ts = ["3", "4"]
    for t in Ts:
        if all([prms.has_key("AT" + t + " " + p) for p in Pfuhl]):
            az = np.array([o["AZ" + t] for o in X])
            rot = np.array([o["ROT" + t] for o in X])
            # built dict of parameters
            tmp = {}
            for z in Pfuhl:
                tmp[z] = prms["AT" + t + " " + z]
            # compute error
            tmpX, tmpY = Pfuhl_pupilPxPy(rot, az, tmp)
            px = -tmpX  # check sign!
            py = -tmpY  # check sign!
        if all([prms.has_key("AT" + t + " " + p) for p in Bonnet]):
            az = np.array([o["AZ" + t] for o in X])
            alt = np.array([o["ALT" + t] for o in X])
            rot = np.array([o["ROT" + t] for o in X])
            # built dict of parameters
            tmp = {}
            for z in Bonnet:
                tmp[z] = prms["AT" + t + " " + z]
            # compute error
            tmpX, tmpY = Bonnet_pupilPxPy(rot, alt, az, tmp)
            px += tmpX
            py += tmpY

    correctionPup = (px * sx + py * sy) * scale

    if addIntermediate:
        for k in range(len(X)):
            X[k]["fit PUPbias"] = correctionPup[k]
    dOPD += correctionPup
    #### done with pupil ##############

    ### finished ###
    dOPDfuncNiter += 1
    if addIntermediate:
        for k in range(len(X)):
            X[k]["fit DOPD"] = dOPD[k]
        return X
    else:
        return dOPD
Пример #9
0
def OPDmodel(loadData=False, bin=10, do_fit=False):
    """
    """
    global opd_model_data
    try:
        print len(opd_model_data)
    except:
        loadData=True
    if loadData:
        files = ['2011-11-21/PACMAN_OBJ_ASTRO_326_00%s.fits'%(f) for f in
                 ['04', '05', '06', '07', '08', '09', '11', '12',
                  '13', '14', '15', '16', '17', '18', '19', '20']]
        opd_model_data = []
        for f in files:
            a = prima.drs(data_directory+f)
            opd_model_data.append(a.expectedOPD(bin=bin))
            a = []

    B = opd_model_data[0]['XYZ']
    fit = np.array([1,1,1,1])
    p_fit = np.array(B)[np.where(np.array(fit))]
    p_fixed = np.array(B)[np.where(1-np.array(fit))]

    obsN = filter(lambda x: x['INSMODE']=='NORMAL',  opd_model_data)
    obsS = filter(lambda x: x['INSMODE']=='SWAPPED', opd_model_data)
    
    plsq = leastsq(leastsqOPDModel, p_fit, args=(fit, p_fixed, obsN), epsfcn=1e-3)
    Bf = np.array(B)
    Bf[np.where(fit)] = plsq[0]

    print np.array(B)-np.array(Bf)

    for x in opd_model_data:
        x['ORIGINAL']=prima.projBaseline(x['XYZA'], [x['RA'], x['DEC']],
                                         x['LST'])['opd']/x['AIRN']-x['DL2-DL1']
        x['RESIDUALS']=prima.projBaseline(Bf, [x['RA'], x['DEC']],
                                          x['LST'])['opd']/x['AIRN']-x['DL2-DL1']
    obsN = filter(lambda x: x['INSMODE']=='NORMAL', opd_model_data)
    obsS = filter(lambda x: x['INSMODE']=='SWAPPED', opd_model_data)
    obs = opd_model_data
    
    pyplot.figure(0)
    pyplot.clf()
    pyplot.subplot(221)
    pyplot.plot([x['AZ'] for x in obsN], [x['RESIDUALS'].mean() for x in obsN], 'ob',
                label='NORMAL')
    pyplot.plot([x['AZ'] for x in obsS], [x['RESIDUALS'].mean() for x in obsS], 'or',
                label='SWAPPED')
    pyplot.plot([x['AZ'] for x in obsN], [x['ORIGINAL'].mean() for x in obsN], '+b',
                label='NORMAL')
    pyplot.plot([x['AZ'] for x in obsS], [x['ORIGINAL'].mean() for x in obsS], '+r',
                label='SWAPPED')
    #pyplot.legend() 
    pyplot.xlabel('AZ')
    pyplot.ylabel('residuals')
    pyplot.subplot(222)
    pyplot.plot([x['ALT'] for x in obsN], [x['RESIDUALS'].mean() for x in obsN], 'ob',
                label='NORMAL')
    pyplot.plot([x['ALT'] for x in obsS], [x['RESIDUALS'].mean() for x in obsS], 'or',
                label='SWAPPED')
    pyplot.plot([x['ALT'] for x in obsN], [x['ORIGINAL'].mean() for x in obsN], '+b',
                label='NORMAL')
    pyplot.plot([x['ALT'] for x in obsS], [x['ORIGINAL'].mean() for x in obsS], '+r',
                label='SWAPPED')
    #pyplot.legend() 
    pyplot.xlabel('ALT')
    pyplot.ylabel('residuals')
    pyplot.subplot(223)
    pyplot.plot(range(len(obs)), [x['RESIDUALS'].mean() for x in obs], 'ok',
                label='NORMAL')
    pyplot.plot(range(len(obs)), [x['ORIGINAL'].mean() for x in obs], '+k',
                label='NORMAL')
    #pyplot.legend() 
    pyplot.xlabel('N')
    pyplot.ylabel('residuals')
    return opd_model_data