示例#1
0
def test_saveload_modelresult_roundtrip(method):
    """Test for modelresult.loads()/dumps() and repeating that"""
    def mfunc(x, a, b):
        return a * (x - b)

    model = Model(mfunc)
    params = model.make_params(a=0.1, b=3.0)
    params['a'].set(min=.01, max=1, brute_step=0.01)
    params['b'].set(min=.01, max=3.1, brute_step=0.01)

    np.random.seed(2020)
    xx = np.linspace(-5, 5, 201)
    yy = 0.5 * (xx - 0.22) + np.random.normal(scale=0.01, size=len(xx))

    result1 = model.fit(yy, params=params, x=xx, method=method)

    result2 = ModelResult(model, Parameters())
    result2.loads(result1.dumps(), funcdefs={'mfunc': mfunc})

    result3 = ModelResult(model, Parameters())
    result3.loads(result2.dumps(), funcdefs={'mfunc': mfunc})

    assert result3 is not None
    assert_allclose(result2.params['a'], 0.5, rtol=1.0e-2)
    assert_allclose(result2.params['b'], 0.22, rtol=1.0e-2)
    assert_allclose(result3.params['a'], 0.50, rtol=1.0e-2)
    assert_allclose(result3.params['b'], 0.22, rtol=1.0e-2)
示例#2
0
def hatchplot_fit(xp: XPS_experiment,
                  region: str,
                  fitRes: ModelResult,
                  lb: str = None,
                  marker='o',
                  ls: str = 'solid',
                  colc: str = None,
                  ax=None,
                  plot_comps: bool = True,
                  flag_fill: bool = False):
    """"Plot fit result with predefined hatch patterns for each component (up to three components)"""
    if ax == None: ax = plt.gca()
    if lb == None: lb = xp.name
    if colc == None: colc = xp.color

    p1 = ax.scatter(xp.dfx[region].energy,
                    xp.dfx[region].counts,
                    marker=marker,
                    label=lb,
                    zorder=1)
    p1.set_color(colc)

    x = xp.dfx[region].dropna().energy

    ax.plot(x,
            fitRes.best_fit,
            linestyle=ls,
            color=colc,
            lw=1.5,
            label='Fit, $\chi^2_N$ = %i' % fitRes.redchi)
    hatch = ['//', 'ox', '+']

    if plot_comps:
        comps = fitRes.eval_components(x=x)
        for i, compo in enumerate(comps):
            posx = fitRes.best_values[compo + 'center']
            ax.text(x=posx,
                    y=comps[compo].max() * 1.02,
                    s='%.1f' % posx,
                    fontsize=12)
            ax.fill_between(x,
                            y1=0,
                            y2=comps[compo],
                            alpha=1,
                            label='Component @ %.1f eV' % posx,
                            facecolor='w',
                            hatch=hatch[i],
                            edgecolor=colc,
                            zorder=-1)
    ax.legend(loc='best')  #, bbox_to_anchor=(1.12, 0.5), fontsize=16)
    cosmetics_plot()
    return ax
示例#3
0
def plot_model(axes: Axes, soil, fit_result: ModelResult):

    # position chi square text
    text_height = 0.02
    x_location = 0.7
    y_ORG = 0.7
    y_MIN = y_ORG - text_height
    y_UNC = y_MIN - text_height
    locations = ((x_location, y_ORG), (x_location, y_MIN), (x_location, y_UNC))
    CHI_SQUARE_LOCATION = dict(zip(SOILS, locations))

    data_kws = {
        'color': COLORS[soil],
        'marker': MARKERS[soil],
        'markersize': 12,
    }

    fit_kws = {
        'color': COLORS[soil],
        'linewidth': 3,
    }

    model = fit_result.model
    parameters = fit_result.params

    X = numpy.arange(DAYS_TO_FIT[0], DAYS_TO_FIT[-1], 1 / 24)  # 24 time points for each day in time_range
    y_fit = model.eval(t=X, params=parameters)

    lines = fit_result.plot_fit(ax=axes, numpoints=480, data_kws=data_kws, fit_kws=fit_kws)

    dely = fit_result.eval_uncertainty(sigma=1, t=X)
    axes.fill_between(X, y_fit - dely, y_fit + dely, color="#ABABAB")

    reduced_chi_square = get_chi_square(fit_result)
    x = CHI_SQUARE_LOCATION[soil][0]
    y = CHI_SQUARE_LOCATION[soil][1]
    axes.text(x, y, str(reduced_chi_square), transform=axes.transAxes)
示例#4
0
def plot_fit_result(xp: XPS_experiment,
                    region: str,
                    fitRes: ModelResult,
                    lb: str = None,
                    ax=None,
                    plot_comps: bool = True,
                    flag_fill: bool = False):
    if ax == None: ax = plt.gca()
    col = plot_region(xp, region, ax=ax, lb=lb).get_color()

    x = xp.dfx[region].dropna().energy

    ax.plot(x,
            fitRes.best_fit,
            '--',
            color=col,
            lw=1.5,
            label='best fit, $\chi^2_N$ = %i' % fitRes.redchi)
    ax.legend()

    if plot_comps:
        comps = fitRes.eval_components(x=x)
        for compo in comps:
            posx = fitRes.best_values[compo + 'center']
            colc = ax.plot(x,
                           comps[compo],
                           ls='dotted',
                           lw=1.5,
                           color=col,
                           label='__nolabel__')[0].get_color()

            ax.vlines(x=posx,
                      ymin=0,
                      ymax=comps[compo].max(),
                      linestyle='dotted',
                      colors=col)
            ax.text(x=posx,
                    y=comps[compo].max() * 0.9,
                    s='%.1f' % posx,
                    fontsize=12)
            if flag_fill:
                ax.fill_between(x,
                                y1=0,
                                y2=comps[compo],
                                alpha=0.3,
                                color=colc)

    return ax
示例#5
0
    def run_preview(data: Table, m_def, pool, state: TaskState):
        def progress_interrupt(_: float):
            if state.is_interruption_requested():
                raise InterruptException

        # Protects against running the task in succession many times, as would
        # happen when adding a preprocessor (there, commit() is called twice).
        # Wait 100 ms before processing - if a new task is started in meanwhile,
        # allow that is easily` cancelled.
        for _ in range(10):
            time.sleep(0.010)
            progress_interrupt(0)

        orig_data = data

        model, parameters = create_composite_model(m_def)

        model_result = {}
        x = getx(data)
        if data is not None and model is not None:

            for row in data:
                progress_interrupt(0)
                res = pool.schedule(pool_fit2,
                                    (row.x, model.dumps(), parameters, x))
                while not res.done():
                    try:
                        progress_interrupt(0)
                    except InterruptException:
                        # CANCEL
                        if multiprocessing.get_start_method(
                        ) != "fork" and res.running():
                            # If slower start methods are used, give the current computation
                            # some time to exit gracefully; this avoids reloading processes
                            concurrent.futures.wait([res], 1.0)
                        if not res.done():
                            res.cancel()
                        raise
                    concurrent.futures.wait([res], 0.05)
                fits = res.result()
                model_result[row.id] = ModelResult(model, parameters).loads(
                    fits, **LMFIT_LOADS_KWARGS)

        progress_interrupt(0)
        return orig_data, data, model_result
def plot_one_week_fit(
    data,
    fit_result: ModelResult,
    figure_number=None,
):

    # model function
    model = fit_result.model

    # time points
    X = data.index.values

    # measured y data
    y = data.values

    # best fit y data
    from_zero = [x - X[0] for x in X]
    X_from_zero = np.linspace(from_zero[0], from_zero[-1], 100)
    best_fit_params = fit_result.params
    best_fit_y = model.eval(params=best_fit_params, t=X_from_zero)
    # pdb.set_trace()

    # new figure
    if figure_number:
        plt.figure(figure_number)

    # plot measured data
    plt.plot(X, y, 'bo')

    # plot best fit curve
    best_fit_X = np.linspace(X[0], X[-1], 100)
    plt.plot(best_fit_X, best_fit_y, 'r-', label='best fit')

    # uncertainty band
    best_fit = fit_result.best_fit
    n_sigma = 1
    error = fit_result.eval_uncertainty(sigma=n_sigma, t=X_from_zero)
    plt.fill_between(
        best_fit_X,
        best_fit_y - error,
        best_fit_y + error,
        color="#ABABAB",
        label=f'{n_sigma}$\sigma$ uncertainty band',
    )
示例#7
0
def test_saveload_modelresult_roundtrip():
    """Test for modelresult.loads()/dumps() and repeating that"""
    def mfunc(x, a, b):
        return a * (x - b)

    model = Model(mfunc)
    params = model.make_params(a=0.0, b=3.0)

    xx = np.linspace(-5, 5, 201)
    yy = 0.5 * (xx - 0.22) + np.random.normal(scale=0.01, size=len(xx))

    result1 = model.fit(yy, params, x=xx)

    result2 = ModelResult(model, Parameters())
    result2.loads(result1.dumps(), funcdefs={'mfunc': mfunc})

    result3 = ModelResult(model, Parameters())
    result3.loads(result2.dumps(), funcdefs={'mfunc': mfunc})

    assert result3 is not None
    assert_param_between(result2.params['a'], 0.48, 0.52)
    assert_param_between(result2.params['b'], 0.20, 0.25)
    assert_param_between(result3.params['a'], 0.48, 0.52)
    assert_param_between(result3.params['b'], 0.20, 0.25)
示例#8
0
def test_saveload_modelresult_roundtrip():
    """Test for modelresult.loads()/dumps() and repeating that"""
    def mfunc(x, a, b):
        return a * (x-b)

    model = Model(mfunc)
    params = model.make_params(a=0.0, b=3.0)

    xx = np.linspace(-5, 5, 201)
    yy = 0.5 * (xx - 0.22) + np.random.normal(scale=0.01, size=len(xx))

    result1 = model.fit(yy, params, x=xx)

    result2 = ModelResult(model, Parameters())
    result2.loads(result1.dumps(), funcdefs={'mfunc': mfunc})

    result3 = ModelResult(model, Parameters())
    result3.loads(result2.dumps(), funcdefs={'mfunc': mfunc})

    assert result3 is not None
    assert_param_between(result2.params['a'], 0.48, 0.52)
    assert_param_between(result2.params['b'], 0.20, 0.25)
    assert_param_between(result3.params['a'], 0.48, 0.52)
    assert_param_between(result3.params['b'], 0.20, 0.25)
示例#9
0
    def run_task(data: Table, m_def, state: TaskState):
        def progress_interrupt(i: float):
            state.set_progress_value(i)
            if state.is_interruption_requested():
                raise InterruptException

        # Protects against running the task in succession many times, as would
        # happen when adding a preprocessor (there, commit() is called twice).
        # Wait 100 ms before processing - if a new task is started in meanwhile,
        # allow that is easily` cancelled.
        for _ in range(10):
            time.sleep(0.010)
            progress_interrupt(0)

        model, parameters = create_composite_model(m_def)

        data_fits = data_anno = data_resid = None
        if data is not None and model is not None:
            orig_data = data
            output = []
            x = getx(data)
            n = len(data)
            fits = []
            residuals = []

            with multiprocessing.Pool(processes=N_PROCESSES,
                                      initializer=pool_initializer,
                                      initargs=(model.dumps(), parameters,
                                                x)) as p:
                res = p.map_async(pool_fit, data.X, chunksize=1)

                def done():
                    try:
                        return n - res._number_left * res._chunksize
                    except AttributeError:
                        return 0

                while not res.ready():
                    progress_interrupt(done() / n * 99)
                    res.wait(0.05)

                fitsr = res.get()

            progress_interrupt(99)

            for fit, bpar, fitted, resid in fitsr:
                out = ModelResult(model,
                                  parameters).loads(fit, **LMFIT_LOADS_KWARGS)
                output.append(bpar)
                fits.append(fitted)
                residuals.append(resid)
                progress_interrupt(99)
            data = fit_results_table(np.vstack(output), out, orig_data)
            data_fits = orig_data.from_table_rows(orig_data,
                                                  ...)  # a shallow copy
            with data_fits.unlocked_reference(data_fits.X):
                data_fits.X = np.vstack(fits)
            data_resid = orig_data.from_table_rows(orig_data,
                                                   ...)  # a shallow copy
            with data_resid.unlocked_reference(data_resid.X):
                data_resid.X = np.vstack(residuals)
            dom_anno = Domain(
                orig_data.domain.attributes,
                orig_data.domain.class_vars,
                orig_data.domain.metas + data.domain.attributes,
            )
            data_anno = orig_data.transform(dom_anno)
            with data_anno.unlocked(data_anno.metas):
                data_anno.metas[:, len(orig_data.domain.metas):] = data.X

        progress_interrupt(100)

        return data, data_fits, data_resid, data_anno
示例#10
0
def plot_figure_for_fit(
        fit_result: ModelResult,
        xlabel: str = 'x',
        ylabel: str = 'y',
        xscale: float = 1.0,
        yscale: float = 1.0,
        title: str = '',
        figsize=DEFAULT_FIG_SIZE,
        axis_fontsize: tuple = DEFAULT_AXIS_FONT_SIZE,
        report_fontsize: float = DEFAULT_REPORT_FONT_SIZE) -> plt.figure:
    """
    Plots fit and residuals from lmfit with residuals *below* fit.
    Also shows fit result text below.

    :param fit_result: lmfit fit result object
    :param xlabel: label for the shared x axis
    :param ylabel: ylabel for fit plot
    :param xscale: xaxis will be divided by xscale
    :param yscale: yaxis will be divided by yscale
    :param title: title of the plot
    :param figsize: size of the plot
    :param axis_fontsize: size of the font
    :param report_fontsize: size of font for the stats report
    :return: matplotlib figure
    """

    # layout subplots for fit plot and residuals
    fig, axs = plt.subplots(nrows=2,
                            ncols=1,
                            sharex=True,
                            gridspec_kw={'height_ratios': (3, 1)},
                            figsize=figsize)

    # add space for fit result text at bottom
    plt.subplots_adjust(hspace=0, top=0.9, bottom=0.3)

    # plot the fits and residuals
    fit_result.plot_fit(ax=axs[0], **FIT_PLOT_KWS)
    fit_result.plot_residuals(ax=axs[1],
                              data_kws=FIT_PLOT_KWS["data_kws"],
                              fit_kws=FIT_PLOT_KWS["fit_kws"])

    # title and labels
    axs[1].set_title('')
    axs[1].set_ylabel('residuals', fontsize=axis_fontsize)
    axs[1].set_xlabel(xlabel, fontsize=axis_fontsize)
    axs[0].set_ylabel(ylabel, fontsize=axis_fontsize)
    axs[0].set_title(title, fontsize=axis_fontsize)

    # residuals don't need a legend
    axs[1].legend().set_visible(False)

    # adjust tick labels for scales
    xticks = ticker.FuncFormatter(lambda x, pos: '{0:g}'.format(x / xscale))
    axs[1].xaxis.set_major_formatter(xticks)
    yticks = ticker.FuncFormatter(lambda y, pos: '{0:g}'.format(y / yscale))
    for ax in axs:
        ax.yaxis.set_major_formatter(yticks)

    # print fit report in space below plot, after dropping first two lines
    report = fit_result.fit_report(show_correl=False)
    report = ''.join(report.splitlines(True)[2:])
    fig.suptitle(report,
                 fontsize=report_fontsize,
                 family='monospace',
                 horizontalalignment='left',
                 x=0.1,
                 y=0.25)

    return fig, axs