Example #1
0
def find_bad_holes(res_c, n_holes, bl2h_ix, bmax=6, verbose=False, display=False):
    """ Find bad apertures using a linear fit of the v2 vs. spatial frequencies.

    Parameters
    ----------
    `res_c` : {class}
        Class containing NRM data of the calibrator (bispect.py),\n
    `n_holes` : {int}
        Number of apertures,\n
    `bl2h_ix` : {array}
        Baselines to apertures (holes) indices,\n
    `bmax` : {int}, optional
        Maximum baseline used to plot the fit, by default 6,\n
    `verbose` : {bool}, optional
        If True, print useful informations , by default False,\n
    `display` : {bool}, optional
        If True, display figures, by default False.

    Returns
    -------
    `bad_holes`: {array}
        List of determined bad holes,
    """
    u = res_c.u/res_c.wl
    v = res_c.v/res_c.wl
    X = np.sqrt(u**2+v**2)
    Y = np.log(res_c.v2)

    param = {'a': 1,
             'b': 0}

    fit = leastsqFit(linear, X, param, Y, verbose=verbose)

    xm = np.linspace(0, bmax, 100)/res_c.wl
    ym = linear(xm, fit['best'])

    pfit = list(fit['best'].values())

    if display:
        plt.figure()
        plt.plot(X/1e6, Y, '.', label='data')
        plt.plot(xm/1e6, ym, '--', label='fit (a=%2.1e, b=%2.2f)' %
                 (pfit[0], pfit[1]))
        plt.grid(alpha=.1)
        plt.legend()
        plt.xlim(0, xm.max()/1e6)
        plt.ylabel(r'$\log(V^2)$ (calibrator)')
        plt.xlabel(r'Sp. Freq. [M$\lambda$]')
        plt.tight_layout()

    bad_holes = []
    for j in range(n_holes):
        pass
        w = np.where((bl2h_ix[0, :] == j) | (bl2h_ix[1, :] == j))
        if (np.mean(res_c.v2[w]/np.exp(fit['model'][w]))) <= 0.3:
            bad_holes.append(j)

    bad_holes = np.unique(bad_holes)

    return bad_holes
Example #2
0
def find_bad_holes(bs, bmax=6, verbose=False, display=False):
    """Find bad apertures using a linear fit of the v2 vs. spatial frequencies.

    Parameters
    ----------
    `bs` : {class}
        Class containing NRM data (bispect.py),\n
    `bmax` : {int}, optional
        Maximum baseline used to plot the fit, by default 6,\n
    `verbose` : {bool}, optional
        If True, print useful informations , by default False,\n
    `display` : {bool}, optional
        If True, display figures, by default False.

    Returns
    -------
    `bad_holes`: {array}
        List of determined bad holes,
    """
    u = bs.u / bs.wl
    v = bs.v / bs.wl
    X = np.sqrt(u**2 + v**2)
    Y = np.log(bs.vis2)

    n_holes = bs.mask.n_holes
    bl2h_ix = bs.mask.bl2h_ix

    param = {"a": 1, "b": 0}

    fit = leastsqFit(linear, X, param, Y, verbose=verbose)

    xm = np.linspace(0, bmax, 100) / bs.wl
    ym = linear(xm, fit["best"])

    pfit = list(fit["best"].values())

    if display:
        plt.figure()
        plt.plot(X / 1e6, Y, ".", label="data")
        plt.plot(xm / 1e6,
                 ym,
                 "--",
                 label=f"fit (a={pfit[0]:2.1e}, b={pfit[1]:2.2f})")
        plt.grid(alpha=0.1)
        plt.legend()
        plt.xlim(0, xm.max() / 1e6)
        plt.ylabel(r"$\log(V^2)$ (calibrator)")
        plt.xlabel(r"Sp. Freq. [M$\lambda$]")
        plt.tight_layout()

    bad_holes = []
    for j in range(n_holes):
        w = np.where((bl2h_ix[0, :] == j) | (bl2h_ix[1, :] == j))
        if (np.mean(bs.vis2[w] / np.exp(fit["model"][w]))) <= 0.3:
            bad_holes.append(j)

    bad_holes = np.unique(bad_holes)

    return bad_holes
Example #3
0
def _calc_correction_atm_vis2(data,
                              corr_const=1,
                              nf=100,
                              display=False,
                              verbose=False,
                              normalizedUncer=False):
    """
    This function corrects V^2 for seeing and windshake. Use this on source and 
    cal before division. Returns a multiplicative correction to the V^2.

    Parameters:
    -----------
    `data` {class}:
        class like containting results from extract_bs function,
    `corr_const` {float}: 
        Correction constant (0.4 is good for V for NIRC experiment).
    Returns:
    --------
    `correction` {array}:
        Correction factor to apply.

    """

    vis = data.vis2
    avar = data.matrix.avar
    u = data.u
    v = data.v

    err_avar = data.matrix.err_avar
    err_vis = data.e_vis2

    w = np.where((vis == 0) | (avar == 0))

    if len(w) == 0:
        print('Cannot continue - divide by zero imminent...')
        correction = None

    normvar = avar / vis**2
    w0 = np.where(u**2 + v**2 >= 0)

    param = {'a': 0, 'b': 0, 'c': 0, 'd': 0, 'e': 0}

    if (len(err_avar) == 0):
        err_avar = normvar * 2.0 / np.sqrt(nf)
    if (len(err_vis) != 0):
        err_avar = abs(normvar) * np.sqrt(err_avar**2 / avar**2 +
                                          2.0 * err_vis**2 / vis**2)

    X = [u[w0], v[w0]]
    fit = leastsqFit(_v2varfunc,
                     X,
                     param,
                     normvar[w0],
                     err_avar[w0],
                     verbose=verbose,
                     normalizedUncer=normalizedUncer)

    correction = np.ones(vis.shape)
    correction[w0] = np.exp(fit['model'] * corr_const)

    if display:
        plt.figure()
        plt.errorbar((X[0]**2 + X[1]**2)**0.5,
                     normvar[w0],
                     yerr=err_avar[w0],
                     ls='None',
                     ecolor='lightgray',
                     marker='.',
                     label='data')
        plt.plot((X[0]**2 + X[1]**2)**0.5, fit['model'], 'rs')
        plt.show(block=False)

    return correction
def smartfit(
    obs,
    first_guess,
    doNotFit=None,
    fitOnly=None,
    follow=None,
    multiproc=False,
    ftol=1e-4,
    epsfcn=1e-7,
    normalizeErrors=False,
    scale_err=1,
    fitCP=True,
    onlyCP=False,
    verbose=True,
):
    """
    Perform the fit of V2 and CP data contained in the obs tuple.

    Parameters:
    -----------

    obs: {tuple}
        Tuple containing all the selected data fromOiClass2Obs function.\n
    first_guess: {dict}
        Parameters of the model.\n
    fitOnly: {list}
        fitOnly is a LIST of keywords to fit. By default, it fits all parameters in 'first_guess'.\n
    follow: {list}
        List of parameters to "follow" in the fit, i.e. to print in verbose mode.\n
    multiproc: {boolean}
        If True, use ModelM to compute the model with pool (12 cores by default).\n
    normalizeErrors: {boolean}
        If True, give the same weight for the V2 and CP data (even if only few CP compare to V2).\n
    fitCP: {boolean}
        If True, fit the CP data. If not fit only the V2 data.\n

    """

    save_obs = obs.copy()

    if onlyCP:
        cond = save_obs[:, 1] == "CP"
        obs = save_obs[cond]

    if not fitCP and not onlyCP:
        cond = save_obs[:, 1] == "V2"
        obs = save_obs[cond]

    errs = [o[-1] for o in obs]
    if normalizeErrors:
        errs = _normalize_err_obs(obs, verbose=False)

    # -- avoid fitting string parameters
    tmp = list(filter(lambda x: isinstance(first_guess[x], str), first_guess.keys()))

    if len(tmp) > 0:
        if doNotFit is None:
            doNotFit = tmp
        else:
            doNotFit.extend(tmp)
        try:
            fitOnly = list(
                filter(lambda x: not isinstance(first_guess[x], str), fitOnly)
            )
        except Exception:
            pass

    if multiproc:
        M = model_parallelized
    else:
        M = model_standard

    lfit = leastsqFit(
        M,
        obs,
        first_guess,
        [o[2] for o in obs],
        err=np.array(errs) * scale_err,
        doNotFit=doNotFit,
        fitOnly=fitOnly,
        follow=follow,
        normalizedUncer=False,
        verbose=verbose,
        ftol=ftol,
        epsfcn=epsfcn,
    )

    return lfit