Exemple #1
0
def test_model_binaryres_error(example_oifits):
    param = {"model": "binary_res", "sep": 1, "dm": -1, "theta": 45, "diam": 0.1}
    f_model = amical.analysis.fitting.select_model(param["model"])

    d = amical.loadc(example_oifits)

    model = f_model(d.u, d.v, d.wl, param)
    assert np.isnan(model[0])
Exemple #2
0
def test_model_binaryres(example_oifits):
    param = {"model": "binary_res", "sep": 1, "dm": 1, "theta": 45, "diam": 0.1}
    f_model = amical.analysis.fitting.select_model(param["model"])

    d = amical.loadc(example_oifits)

    model = f_model(d.u, d.v, d.wl, param)
    assert len(d.u) == len(model)
    assert type(model[0]) == np.complex128
Exemple #3
0
def test_calibrate_method(method, cli_datadir, tmp_path, monkeypatch):
    for i in range(2):
        monkeypatch.setattr("builtins.input", lambda _: str(i))

        isz = 78
        ret = main(
            [
                "clean",
                "--datadir",
                str(cli_datadir),
                "--outdir",
                str(tmp_path),
                "--isz",
                str(isz),
            ]
        )
        assert ret == 0
        plt.close("all")

    for i in range(2):
        monkeypatch.setattr("builtins.input", lambda _: str(i))
        ret = main(
            [
                "extract",
                "--datadir",
                str(tmp_path),
                "--outdir",
                str(tmp_path),
                "--peakmethod",
                method,
            ]
        )
        assert ret == 0
        plt.close("all")

    responses = iter(["1", "0"])
    monkeypatch.setattr("builtins.input", lambda msg: next(responses))

    main(["calibrate", "--datadir", str(tmp_path), "--outdir", str(tmp_path)])

    output_file = sorted(Path(tmp_path).glob("*calibrated.fits"))

    cal = loadc(output_file[0])
    cal_keys = list(cal.keys())

    true_value_vis2 = 0.98479018
    true_value_wl = 4.286e-06

    assert len(output_file) == 1
    assert len(cal_keys) == 20
    assert cal.vis2[0] == pytest.approx(true_value_vis2, 1e-3)
    assert cal.wl[0] == pytest.approx(true_value_wl, 1e-9)
Exemple #4
0
def test_model_disk(example_oifits):
    param = {
        "model": "disk",
        "diam": 10,
        "x0": 0,
        "y0": 0,
    }
    f_model = amical.analysis.fitting.select_model(param["model"])

    d = amical.loadc(example_oifits)

    model = f_model(d.u, d.v, d.wl, param)
    assert len(d.u) == len(model)
    assert type(model[0]) == np.complex128
Exemple #5
0
def test_model_Clumpydisk(example_oifits):
    param = {
        "model": "clumpyDebrisDisk",
        "majorAxis": 10,
        "incl": 0,
        "posang": 45,
        "thickness": 1,
        "cr": 0.1,
        "x0": 0,
        "y0": 0,
        "d_clump": 0.5,
        "cr_clump": 10,
    }
    f_model = amical.analysis.fitting.select_model(param["model"])

    d = amical.loadc(example_oifits)

    model = f_model(d.u, d.v, d.wl, param)
    assert len(d.u) == len(model)
    assert type(model[0]) == np.complex128
Exemple #6
0
def test_model_edisk(example_oifits):
    param = {
        "model": "edisk",
        "majorAxis": 10,
        "incl": 0,
        "posang": 45,
        "thickness": 1,
        "cr": 0.1,
        "x0": 0,
        "y0": 0,
    }

    f_model = amical.analysis.fitting.select_model(param["model"])

    d = amical.loadc(example_oifits)

    V2 = amical.analysis.fitting.comput_V2([d.u, d.v, d.wl], param, f_model)

    model = f_model(d.u, d.v, d.wl, param)
    assert len(d.u) == len(model)
    assert len(d.u) == len(V2)
    assert type(model[0]) == np.complex128
def plot_model(
    inputdata,
    param,
    save=False,
    outputfile=None,
    extra_error_v2=0,
    extra_error_cp=0,
    err_scale=1,
    d_freedom=3,
    v2_min=None,
    v2_max=1.1,
    cp_max=None,
    unit="m",
):
    """Plot the model compared to the data (V2 and CP) and the associated
    residuals.

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

    `inputdata`: {str}
        Oifits file,\n
    `param`: {dict}
        Parameters of the fit (**tips**: use fit['best'] if you want to
        use the output of `amical.candid_grid()`.),\n
    `save`: {boolean}
        If True, figure is saved using the inputdata file as name followed
        by '_fit_candid.pdf'. Optionnaly, you can use `outputfile` to
        change the output file name (e.g.: outputfile='my_fit.pdf'),\n
    `extra_error_v2`: {float}
        Additional uncertainty of the V2 (added quadraticaly),\n
    `extra_error_cp`: {float}
        Additional uncertainty of the CP (added quadraticaly),\n
    `err_scale`: {float}
        Scaling factor applied on the CP uncertainties usualy used to
        include the non-independant CP correlation,\n
    `d_freedom` {int}:
        Degree of freedom (3 by default: sep, theta and dm),\n
    v2_min, v2_max, cp_max: {float}
        Limits of the y-axis,\n

    """
    import matplotlib.pyplot as plt

    d = amical.loadc(inputdata)

    e_vis2 = np.sqrt(d.e_vis2**2 + extra_error_v2**2)
    e_cp = np.sqrt(d.e_cp**2 + extra_error_cp**2) * err_scale

    model_target = select_model(param["model"])

    u, v, wl = d.u, d.v, d.wl

    mod_v2 = comput_V2([u, v, wl], param, model_target)

    u1, u2, v1, v2 = d.u1, d.u2, d.v1, d.v2
    u3, v3 = u1 + u2, v1 + v2

    X = [u1, u2, u3, v1, v2, v3, wl]
    mod_cp = comput_CP(X, param, model_target)

    chi2_cp = np.sum((d.cp - mod_cp) ** 2 / (e_cp) ** 2) / (len(e_cp) - (d_freedom - 1))
    chi2_vis2 = np.sum((d.vis2 - mod_v2) ** 2 / (e_vis2) ** 2) / (
        len(e_vis2) - (d_freedom - 1)
    )

    chi2 = (
        np.sum((d.cp - mod_cp) ** 2 / (e_cp) ** 2)
        + np.sum((d.vis2 - mod_v2) ** 2 / (e_vis2) ** 2)
    ) / (len(e_cp) + len(e_vis2) - (d_freedom - 1))

    res_vis2 = (mod_v2 - d.vis2) / e_vis2
    res_cp = (mod_cp - d.cp) / e_cp

    f_unit = {
        "m": 1,
        "lambda": 1 / d.wl / 1e6,
        "arcsec": 1 / d.wl / ((3600 * 180) / np.pi),
    }
    label_unit = {"m": "m", "lambda": r"M$\lambda$", "arcsec": r"arcsec$^{-1}$"}

    x_vis2 = d.bl * f_unit[unit]
    x_cp = d.bl_cp * f_unit[unit]

    fig = plt.figure(constrained_layout=True, figsize=(11, 4))
    axd = fig.subplot_mosaic(
        [["vis", "cp"], ["res_vis2", "res_cp"]],
        gridspec_kw={"width_ratios": [2, 2], "height_ratios": [3, 1]},
    )

    axd["res_vis2"].sharex(axd["vis"])
    axd["res_cp"].sharex(axd["cp"])

    axd["vis"].errorbar(x_vis2, d.vis2, yerr=e_vis2, **err_pts_style, color="#3d84a8")
    axd["vis"].plot(
        x_vis2,
        mod_v2,
        "x",
        color="#f6416c",
        zorder=100,
        ms=10,
        label=r"model ($\chi^2_r=%2.1f$)" % chi2_vis2,
    )
    axd["vis"].legend()

    if v2_min is not None:
        axd["vis"].set_ylim(v2_min, v2_max)
    axd["vis"].grid(alpha=0.2)
    axd["vis"].set_ylabel(r"V$^2$")

    axd["res_vis2"].plot(x_vis2, res_vis2, ".", color="#3d84a8")
    axd["res_vis2"].axhspan(-1, 1, alpha=0.2, color="#418fde")
    axd["res_vis2"].axhspan(-2, 2, alpha=0.2, color="#8bb8e8")
    axd["res_vis2"].axhspan(-3, 3, alpha=0.2, color="#c8d8eb")
    if res_vis2.max() > 5:
        res_mas = res_vis2.max()
    else:
        res_mas = 5
    axd["res_cp"].set_ylim(-res_mas, res_mas)
    axd["res_vis2"].set_ylim(-5, 5)
    axd["res_vis2"].set_ylabel(r"Residual [$\sigma$]")
    axd["res_vis2"].set_xlabel("Sp. Freq. [%s]" % label_unit[unit])

    axd["cp"].errorbar(x_cp, d.cp, yerr=e_cp, **err_pts_style, color="#2ca02c")
    axd["cp"].plot(
        x_cp,
        mod_cp,
        "x",
        color="#f6416c",
        zorder=100,
        ms=10,
        label=r"model ($\chi^2_r=%2.1f$)" % chi2_cp,
    )

    if cp_max is not None:
        axd["cp"].set_ylim(-cp_max, cp_max)
    axd["cp"].grid(alpha=0.2)
    axd["cp"].set_ylabel("Closure phases [deg]")
    axd["cp"].legend()

    axd["res_cp"].plot(x_cp, res_cp, ".", color="#1e7846")
    axd["res_cp"].axhspan(-1, 1, alpha=0.3, color="#28a16c")  # f5c893
    axd["res_cp"].axhspan(-2, 2, alpha=0.2, color="#28a16c")
    axd["res_cp"].axhspan(-3, 3, alpha=0.1, color="#28a16c")
    if res_cp.max() > 5:
        res_mas = res_cp.max()
    else:
        res_mas = 5
    axd["res_cp"].set_ylim(-res_mas, res_mas)
    axd["res_cp"].set_ylabel(r"Residual [$\sigma$]")
    axd["res_cp"].set_xlabel("Sp. Freq. [%s]" % label_unit[unit])

    if save:
        import matplotlib.pyplot as plt

        filename = os.path.basename(inputdata) + "_fit_candid.pdf"
        if outputfile is not None:
            filename = outputfile
        plt.savefig(filename, dpi=300)

    return mod_v2, mod_cp, chi2
def fits2obs(
    inputdata,
    use_flag=True,
    cond_wl=False,
    wl_min=None,
    wl_max=None,
    cond_uncer=False,
    rel_max=None,
    extra_error_v2=0,
    extra_error_cp=0,
    err_scale=1,
    input_rad=False,
    verbose=True,
):
    """
    Convert and select data from an oifits file.

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

    `inputdata`: {str}
        Oifits file,\n
    `use_flag`: {boolean}
        If True, use flag from the original oifits file,\n
    `cond_wl`: {boolean}
        If True, apply wavelenght restriction between wl_min and wl_max,\n
    `wl_min`, `wl_max`: {float}
        if cond_wl, limits of the wavelength domain [µm],\n
    `cond_uncer`: {boolean}
        If True, select the best data according their relative uncertainties (rel_max),\n
    `rel_max`: {float}
        if cond_uncer, maximum sigma uncertainties allowed [%],\n
    `extra_error_v2`: {float}
        Additional uncertainty of the V2 (added quadraticaly),\n
    `extra_error_cp`: {float}
        Additional uncertainty of the CP (added quadraticaly),\n
    `err_scale`: {float}
        Scaling factor applied on the CP uncertainties usualy used to
        include the non-independant CP correlation,\n
    `verbose`: {boolean}
        If True, display useful information about the data selection,\n


    Return:
    -------

    Obs: {tuple}
        Tuple containing all the selected data in an appropriate format to perform the fit.

    """

    data = amical.loadc(inputdata)
    nwl = len(data.wl)

    nbl = data.vis2.shape[0]
    ncp = data.cp.shape[0]

    vis2_data = data.vis2.flatten()  # * 0.97
    e_vis2_data = (data.e_vis2.flatten() ** 2 + extra_error_v2**2) ** 0.5
    flag_V2 = data.flag_vis.flatten()

    if input_rad:
        cp_data = np.rad2deg(data.cp.flatten())
        e_cp_data = np.rad2deg(
            np.sqrt(data.e_cp.flatten() ** 2 + extra_error_cp**2) * err_scale
        )
    else:
        cp_data = data.cp.flatten()
        e_cp_data = np.sqrt(data.e_cp.flatten() ** 2 + extra_error_cp**2) * err_scale

    flag_CP = data.flag_cp.flatten()

    if use_flag:
        pass
    else:
        flag_V2 = [False] * len(vis2_data)
        flag_CP = [False] * len(cp_data)

    u_data, v_data = [], []
    u1_data, v1_data, u2_data, v2_data = [], [], [], []

    for i in range(nbl):
        for _ in range(nwl):
            u_data.append(data.u[i])
            v_data.append(data.v[i])

    for i in range(ncp):
        for _ in range(nwl):
            u1_data.append(data.u1[i])
            v1_data.append(data.v1[i])
            u2_data.append(data.u2[i])
            v2_data.append(data.v2[i])

    u_data = np.array(u_data)
    v_data = np.array(v_data)

    u1_data = np.array(u1_data)
    v1_data = np.array(v1_data)
    u2_data = np.array(u2_data)
    v2_data = np.array(v2_data)

    wl_data = np.array(list(data.wl) * nbl)
    wl_data_cp = np.array(list(data.wl) * ncp)

    obs = []

    for i in range(nbl * nwl):
        if flag_V2[i] & use_flag:
            pass
        else:
            if not cond_wl:
                tmp = [u_data[i], v_data[i], wl_data[i]]
                typ = "V2"
                obser = vis2_data[i]
                err = e_vis2_data[i]
                if cond_uncer:
                    if err / obser <= rel_max * 1e-2:
                        obs.append([tmp, typ, obser, err])
                    else:
                        pass
                else:
                    obs.append([tmp, typ, obser, err])

            else:
                if (wl_data[i] >= wl_min * 1e-6) & (wl_data[i] <= wl_max * 1e-6):
                    tmp = [u_data[i], v_data[i], wl_data[i]]
                    typ = "V2"
                    obser = vis2_data[i]
                    err = e_vis2_data[i]
                    if cond_uncer:
                        if err / obser <= rel_max * 1e-2:
                            obs.append([tmp, typ, obser, err])
                        else:
                            pass
                    else:
                        obs.append([tmp, typ, obser, err])
                else:
                    pass
    N_v2_rest = len(obs)

    for i in range(ncp * nwl):
        if flag_CP[i]:
            pass
        else:
            if not cond_wl:
                tmp = [
                    u1_data[i],
                    u2_data[i],
                    (u1_data[i] + u2_data[i]),
                    v1_data[i],
                    v2_data[i],
                    (v1_data[i] + v2_data[i]),
                    wl_data_cp[i],
                ]
                typ = "CP"
                obser = cp_data[i]
                err = e_cp_data[i]
                if cond_uncer:
                    if err / obser <= rel_max * 1e-2:
                        obs.append([tmp, typ, obser, err])
                    else:
                        pass
                else:
                    obs.append([tmp, typ, obser, err])
            else:
                if (wl_data_cp[i] >= wl_min * 1e-6) & (wl_data_cp[i] <= wl_max * 1e-6):
                    tmp = [
                        u1_data[i],
                        u2_data[i],
                        (u1_data[i] + u2_data[i]),
                        v1_data[i],
                        v2_data[i],
                        (v1_data[i] + v2_data[i]),
                        wl_data_cp[i],
                    ]
                    typ = "CP"
                    obser = cp_data[i]
                    err = e_cp_data[i]
                    if cond_uncer:
                        if err / obser <= rel_max * 1e-2:
                            obs.append([tmp, typ, obser, err])
                        else:
                            pass
                    else:
                        obs.append([tmp, typ, obser, err])
                else:
                    pass

    N_cp_rest = len(obs) - N_v2_rest

    Obs = np.array(obs, dtype=object)

    if verbose:
        print(
            "\nTotal # of data points: %i (%i V2, %i CP)"
            % (len(Obs), N_v2_rest, N_cp_rest)
        )
        if use_flag:
            print("-> Flag in oifits files used.")
        if cond_wl:
            print(
                r"-> Restriction on wavelenght: %2.2f < %s < %2.2f µm"
                % (wl_min, chr(955), wl_max)
            )
        if cond_uncer:
            print(rf"-> Restriction on uncertainties: {chr(949)} < {rel_max:2.1f} %")

    return Obs
Exemple #9
0
def plot_model(inputdata,
               param,
               extra_error_v2=0,
               extra_error_cp=0,
               err_scale=1,
               d_freedom=1,
               v2_min=None,
               v2_max=1.1,
               cp_max=None,
               unit='m',
               display=True):
    """ Plot the model compared to the data (V2 and CP) and the associated 
    residuals. """

    d = amical.loadc(inputdata)

    e_vis2 = np.sqrt(d.e_vis2**2 + extra_error_v2**2)
    e_cp = np.sqrt(d.e_cp**2 + extra_error_cp**2) * err_scale

    model_target = select_model(param['model'])

    u, v, wl = d.u, d.v, d.wl

    mod_v2 = comput_V2([u, v, wl], param, model_target)

    u1, u2, v1, v2 = d.u1, d.u2, d.v1, d.v2
    u3, v3 = u1 + u2, v1 + v2

    X = [u1, u2, u3, v1, v2, v3, wl]
    mod_cp = comput_CP(X, param, model_target)

    chi2_cp = np.sum(((d.cp - mod_cp)**2/(e_cp)**2)) / \
        (len(e_cp) - (d_freedom - 1))
    chi2_vis2 = np.sum(((d.vis2 - mod_v2)**2/(e_vis2)**2)) / \
        (len(e_vis2) - (d_freedom - 1))

    chi2 = (np.sum(((d.cp - mod_cp)**2 / (e_cp)**2)) + np.sum(
        ((d.vis2 - mod_v2)**2 / (e_vis2)**2))) / (len(e_cp) + len(e_vis2) -
                                                  (d_freedom - 1))

    res_vis2 = (mod_v2 - d.vis2) / e_vis2
    res_cp = (mod_cp - d.cp) / e_cp

    f_unit = {
        'm': 1,
        'lambda': 1 / d.wl / 1e6,
        'arcsec': 1 / d.wl / ((3600 * 180) / np.pi)
    }
    label_unit = {
        'm': 'm',
        'lambda': r'M$\lambda$',
        'arcsec': r'arcsec$^{-1}$'
    }

    x_vis2 = d.bl * f_unit[unit]
    x_cp = d.bl_cp * f_unit[unit]

    if display:
        fig = plt.figure(constrained_layout=True, figsize=(11, 4))
        axd = fig.subplot_mosaic([['vis', 'cp'], ['res_vis2', 'res_cp']],
                                 gridspec_kw={
                                     'width_ratios': [2, 2],
                                     'height_ratios': [3, 1]
                                 })

        axd['res_vis2'].sharex(axd['vis'])
        axd['res_cp'].sharex(axd['cp'])

        axd['vis'].errorbar(x_vis2,
                            d.vis2,
                            yerr=e_vis2,
                            **err_pts_style,
                            color='#3d84a8')
        axd['vis'].plot(x_vis2,
                        mod_v2,
                        'x',
                        color='#f6416c',
                        zorder=100,
                        ms=10,
                        label='model ($\chi^2_r=%2.1f$)' % chi2_vis2)
        axd['vis'].legend()

        if v2_min is not None:
            axd['vis'].set_ylim(v2_min, v2_max)
        axd['vis'].grid(alpha=.2)
        axd['vis'].set_ylabel(r'V$^2$')

        axd['res_vis2'].plot(x_vis2, res_vis2, '.', color='#3d84a8')
        axd['res_vis2'].axhspan(-1, 1, alpha=.2, color='#418fde')
        axd['res_vis2'].axhspan(-2, 2, alpha=.2, color='#8bb8e8')
        axd['res_vis2'].axhspan(-3, 3, alpha=.2, color='#c8d8eb')
        if res_vis2.max() > 5:
            res_mas = res_vis2.max()
        else:
            res_mas = 5
        axd['res_cp'].set_ylim(-res_mas, res_mas)
        axd['res_vis2'].set_ylim(-5, 5)
        axd['res_vis2'].set_ylabel('Residual [$\sigma$]')
        axd['res_vis2'].set_xlabel('Sp. Freq. [%s]' % label_unit[unit])

        axd['cp'].errorbar(x_cp,
                           d.cp,
                           yerr=e_cp,
                           **err_pts_style,
                           color='#2ca02c')
        axd['cp'].plot(x_cp,
                       mod_cp,
                       'x',
                       color='#f6416c',
                       zorder=100,
                       ms=10,
                       label='model ($\chi^2_r=%2.1f$)' % chi2_cp)

        if cp_max is not None:
            axd['cp'].set_ylim(-cp_max, cp_max)
        axd['cp'].grid(alpha=.2)
        axd['cp'].set_ylabel('Closure phases [deg]')
        axd['cp'].legend()

        axd['res_cp'].plot(x_cp, res_cp, '.', color='#1e7846')
        axd['res_cp'].axhspan(-1, 1, alpha=.3, color='#28a16c')  # f5c893
        axd['res_cp'].axhspan(-2, 2, alpha=.2, color='#28a16c')
        axd['res_cp'].axhspan(-3, 3, alpha=.1, color='#28a16c')
        if res_cp.max() > 5:
            res_mas = res_cp.max()
        else:
            res_mas = 5
        axd['res_cp'].set_ylim(-res_mas, res_mas)
        axd['res_cp'].set_ylabel('Residual [$\sigma$]')
        axd['res_cp'].set_xlabel('Sp. Freq. [%s]' % label_unit[unit])
    return mod_v2, mod_cp, chi2
Exemple #10
0
def test_loadc_file(example_oifits):
    s = loadc(example_oifits)
    assert isinstance(s, munch.Munch)
Exemple #11
0
def test_loadc_file(filepath):
    s = loadc(filepath)
    assert isinstance(s, munch.Munch)