/**
 * gwy_interpolation_get_dval:
 * @x: requested value coordinate
 * @x1_: x coordinate of first value
 * @y1_: y coordinate of first value
 * @x2_: x coordinate of second value
 * @y2_: y coordinate of second value
 * @interpolation: interpolation type
 *
 * This function uses two-point interpolation
 * methods to get interpolated value between
 * two arbitrary data points.
 *
 * Returns: interpolated value
 **/
gdouble
gwy_interpolation_get_dval(gdouble x,
                           gdouble x1_, gdouble y1_,
                           gdouble x2_, gdouble y2_,
                           GwyInterpolationType interpolation)
{
    if (x1_ > x2_) {
        GWY_SWAP(gdouble, x1_, x2_);
        GWY_SWAP(gdouble, y1_, y2_);
    }

    switch (interpolation) {
        case GWY_INTERPOLATION_ROUND:
        if ((x - x1_) < (x2_ - x))
            return y1_;
        else
            return y2_;
        break;


        case GWY_INTERPOLATION_LINEAR:
        return y1_ + (x - x1_)/(x2_ - x1_)*(y2_ - y1_);
        break;

        default:
        g_warning("Interpolation not implemented yet.\n");
        break;
    }

    return 0.0;
}
Exemple #2
0
static GwyEnum*
gwy_combo_box_metric_unit_make_enum(gint from,
                                    gint to,
                                    GwySIUnit *unit,
                                    gint *nentries)
{
    GwyEnum *entries;
    GwySIValueFormat *format = NULL;
    gint i, n;

    from = from/3;
    to = (to + 2)/3;
    if (to < from)
        GWY_SWAP(gint, from, to);

    n = (to - from) + 1;
    entries = g_new(GwyEnum, n + 1);
    for (i = from; i <= to; i++) {
        format = gwy_si_unit_get_format_for_power10(unit,
                                                    GWY_SI_UNIT_FORMAT_MARKUP,
                                                    3*i, format);
        if (*format->units)
            entries[i - from].name = g_strdup(format->units);
        else
            entries[i - from].name = g_strdup("1");
        entries[i - from].value = 3*i;
    }
    entries[n].name = NULL;
    gwy_si_unit_value_format_free(format);

    if (nentries)
        *nentries = n;

    return entries;
}
Exemple #3
0
static guint
fix_serialisation_spec(GwySerializeSpec *spec)
{
    /* Don't serialise spec_xlabel and spec_ylabel if they are NULL. */
    if (!spec[6].value) {
        if (!spec[5].value)
            return 5;
        return 6;
    }
    else if (!spec[5].value) {
        GWY_SWAP(GwySerializeSpec, spec[5], spec[6]);
        return 6;
    }
    return 7;
}
static guint
filter_relevant_edges(EdgeList *edges, gdouble r2, gdouble eps)
{
    Edge *edge = edges->edges, *enear = edges->edges;
    gdouble limitr = sqrt(r2) + 4.0*eps + 0.5, limit = limitr*limitr;

    for (guint i = edges->len; i; i--, edge++) {
        if (edge->r2 <= limit) {
            if (edge != enear)
                GWY_SWAP(Edge, *edge, *enear);
            enear++;
        }
    }

    return enear - edges->edges;
}
Exemple #5
0
/**
 * gwy_math_nlfit_get_correlations:
 * @nlfit: A Marquardt-Levenberg nonlinear fitter.
 * @par1: First parameter index.
 * @par2: Second parameter index.
 *
 * Returns the correlation coefficient between @par1-th and @par2-th parameter.
 *
 * This function makes sense only after a successful fit.
 *
 * Returns: The correlation coefficient.
 **/
gdouble
gwy_math_nlfit_get_correlations(GwyNLFitter *nlfit, gint par1, gint par2)
{
    gdouble Pom;

    g_return_val_if_fail(nlfit->covar, G_MAXDOUBLE);

    if (par1 == par2)
        return 1.0;
    if (par1 < par2)
        GWY_SWAP(gint, par1, par2);

    Pom = SLi(nlfit->covar, par1, par1) * SLi(nlfit->covar, par2, par2);
    if (Pom == 0) {
        g_warning("Zero element in covar matrix");
        return G_MAXDOUBLE;
    }

    return SLi(nlfit->covar, par1, par2)/sqrt(Pom);
}
Exemple #6
0
static void
extract_path_do(GwyContainer *data,
                GwyDataField *dfield, gboolean realsquare,
                GwySelection *selection,
                const ExtrPathArgs *args)
{
    GwyGraphModel *gmodel;
    GwySpline *spline;
    GwyXY *points, *tangents;
    GwySIUnit *xyunit;
    gdouble dx, dy, qx, qy, h, l, length, slackness;
    gdouble *xdata, *ydata;
    guint n, i;
    gboolean closed;

    /* This can only be satisfied in non-interactive use.  Doing nothing is
     * the best option in this case. */
    if (!selection || (n = gwy_selection_get_data(selection, NULL)) < 2)
        return;

    points = rescale_points(selection, dfield, realsquare, &dx, &dy, &qx, &qy);
    h = MIN(dx, dy);
    spline = gwy_spline_new_from_points(points, n);
    g_object_get(selection,
                 "slackness", &slackness,
                 "closed", &closed,
                 NULL);
    gwy_spline_set_closed(spline, closed);
    gwy_spline_set_slackness(spline, slackness);
    g_free(points);

    length = gwy_spline_length(spline);

    /* This would give natural sampling for a straight line along some axis. */
    n = GWY_ROUND(length + 1.0);
    points = g_new(GwyXY, n);
    tangents = g_new(GwyXY, n);
    xdata = g_new(gdouble, n);
    ydata = g_new(gdouble, n);
    gwy_spline_sample_uniformly(spline, points, tangents, n);
    qx *= dx;
    qy *= dy;
    for (i = 0; i < n; i++) {
        points[i].x *= qx;
        points[i].y *= qy;
        GWY_SWAP(gdouble, tangents[i].x, tangents[i].y);
        tangents[i].x *= qx;
        tangents[i].y *= -qy;
        l = sqrt(tangents[i].x*tangents[i].x + tangents[i].y*tangents[i].y);
        if (h > 0.0) {
            tangents[i].x /= l;
            tangents[i].y /= l;
        }
        xdata[i] = i/(n - 1.0)*length*h;
    }

    xyunit = gwy_data_field_get_si_unit_xy(dfield);
    if ((gmodel = create_graph_model(points, xdata, ydata, n,
                                     args->x, args->y))) {
        g_object_set(gmodel,
                     "axis-label-left", _("Position"),
                     "axis-label-bottom", _("Distance"),
                     "si-unit-x", xyunit,
                     "si-unit-y", xyunit,
                     NULL);
        gwy_app_data_browser_add_graph_model(gmodel, data, TRUE);
        g_object_unref(gmodel);
    }

    if ((gmodel = create_graph_model(tangents, xdata, ydata, n,
                                     args->vx, args->vy))) {
        g_object_set(gmodel,
                     "axis-label-left", _("Tangent"),
                     "axis-label-bottom", _("Distance"),
                     "si-unit-x", xyunit,
                     NULL);
        gwy_app_data_browser_add_graph_model(gmodel, data, TRUE);
        g_object_unref(gmodel);
    }

    g_free(ydata);
    g_free(xdata);
    g_free(points);
    g_free(tangents);
}
Exemple #7
0
/**
 * gwy_si_unit_power_multiply:
 * @siunit1: An SI unit.
 * @power1: Power to raise @siunit1 to.
 * @siunit2: An SI unit.
 * @power2: Power to raise @siunit2 to.
 * @result:  An SI unit to set to @siunit1^@power1*@siunit2^@power2.
 *           It is safe to pass @siunit1 or @siunit2.  It can be %NULL too,
 *           a new SI unit is created then and returned.
 *
 * Computes the product of two SI units raised to arbitrary powers.
 *
 * This is the most complex SI unit arithmetic function.  It can be easily
 * chanied when more than two units are to be multiplied.
 *
 * Returns: When @result is %NULL, a newly created SI unit that has to be
 *          dereferenced when no longer used later.  Otherwise @result itself
 *          is simply returned, its reference count is NOT increased.
 *
 * Since: 2.4
 **/
GwySIUnit*
gwy_si_unit_power_multiply(GwySIUnit *siunit1,
                           gint power1,
                           GwySIUnit *siunit2,
                           gint power2,
                           GwySIUnit *result)
{
    GwySIUnit *op2 = NULL;
    GwySimpleUnit *unit, *unit2;
    gint i, j;

    g_return_val_if_fail(GWY_IS_SI_UNIT(siunit1), NULL);
    g_return_val_if_fail(GWY_IS_SI_UNIT(siunit2), NULL);
    g_return_val_if_fail(!result || GWY_IS_SI_UNIT(result), NULL);

    if (!result)
        result = gwy_si_unit_new(NULL);

    /* Try to avoid hard work by making siunit2 the simplier one */
    if (siunit1->units->len < siunit2->units->len
        || (power2 && !power1)
        || (siunit2 == result && siunit1 != result)) {
        GWY_SWAP(GwySIUnit*, siunit1, siunit2);
        GWY_SWAP(gint, power1, power2);
    }
    gwy_si_unit_power_real(siunit1, power1, result);
    if (!power2) {
        gwy_si_unit_canonicalize(result);
        return result;
    }

    /* When the second operand is the same object as the result, we have to
     * operate on a temporary copy */
    if (siunit2 == result) {
        op2 = gwy_si_unit_duplicate(siunit2);
        siunit2 = op2;
    }

    result->power10 += power2*siunit2->power10;
    for (i = 0; i < siunit2->units->len; i++) {
        unit2 = &g_array_index(siunit2->units, GwySimpleUnit, i);

        for (j = 0; j < result->units->len; j++) {
            unit = &g_array_index(result->units, GwySimpleUnit, j);
            gwy_debug("[%d] %u == [%d] %u",
                      i, unit2->unit, j, unit->unit);
            if (unit2->unit == unit->unit) {
                unit->power += power2*unit2->power;
                break;
            }
        }
        if (j == result->units->len) {
            g_array_append_val(result->units, *unit2);
            unit = &g_array_index(result->units, GwySimpleUnit,
                                  result->units->len - 1);
            unit->power *= power2;
        }
    }
    gwy_si_unit_canonicalize(result);
    gwy_object_unref(op2);
    g_signal_emit(result, si_unit_signals[VALUE_CHANGED], 0);

    return result;
}
Exemple #8
0
static void
unrotate(GwyContainer *data, GwyRunType run)
{
    enum { nder = 4800 };
    GwyDataField *dfield, *mfield, *sfield;
    UnrotateArgs args;
    gdouble correction[GWY_SYMMETRY_LAST];
    GwyPlaneSymmetry symm;
    GwyDataLine *derdist;
    GQuark dquark, mquark, squark;
    gdouble phi;
    gboolean ok = TRUE;
    gint id;

    g_return_if_fail(run & UNROTATE_RUN_MODES);
    gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD_KEY, &dquark,
                                     GWY_APP_DATA_FIELD, &dfield,
                                     GWY_APP_DATA_FIELD_ID, &id,
                                     GWY_APP_MASK_FIELD_KEY, &mquark,
                                     GWY_APP_MASK_FIELD, &mfield,
                                     GWY_APP_SHOW_FIELD_KEY, &squark,
                                     GWY_APP_SHOW_FIELD, &sfield,
                                     0);
    g_return_if_fail(dfield && dquark && mquark && squark);

    load_args(gwy_app_settings_get(), &args);
    derdist = GWY_DATA_LINE(gwy_data_line_new(nder, 2*G_PI, FALSE));
    gwy_data_field_slope_distribution(dfield, derdist, 5);
    symm = gwy_data_field_unrotate_find_corrections(derdist, correction);
    g_object_unref(derdist);

    if (run == GWY_RUN_INTERACTIVE) {
        ok = unrotate_dialog(&args, data, dfield, id, correction, symm);
        save_args(gwy_app_settings_get(), &args);
        if (!ok)
            return;
    }

    if (args.symmetry)
        symm = args.symmetry;
    phi = correction[symm];

    if (!mfield)
        mquark = 0;
    if (!sfield)
        squark = 0;
    if (!mfield && sfield)
        GWY_SWAP(GQuark, mquark, squark);
    gwy_app_undo_qcheckpoint(data, dquark, mquark, squark, 0);
    gwy_data_field_rotate(dfield, phi, args.interp);
    gwy_data_field_data_changed(dfield);
    if (mfield) {
        gwy_data_field_rotate(mfield, phi, GWY_INTERPOLATION_ROUND);
        gwy_data_field_data_changed(mfield);
    }
    if (sfield) {
        gwy_data_field_rotate(sfield, phi, args.interp);
        gwy_data_field_data_changed(sfield);
    }
    gwy_app_channel_log_add_proc(data, id, id);
}
Exemple #9
0
static gboolean
gsf_export(GwyContainer *container,
           const gchar *filename,
           G_GNUC_UNUSED GwyRunType mode,
           GError **error)
{
    static const gchar zeroes[4] = { 0, 0, 0, 0 };
    GString *header = NULL;
    gfloat *dfl = NULL;
    guint i, xres, yres, padding;
    gint id;
    GwyDataField *dfield;
    const gdouble *d;
    gdouble v;
    gchar *s;
    GwySIUnit *unit, *emptyunit;
    FILE *fh;

    gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield,
                                     GWY_APP_DATA_FIELD_ID, &id,
                                     0);
    if (!dfield) {
        err_NO_CHANNEL_EXPORT(error);
        return FALSE;
    }

    if (!(fh = g_fopen(filename, "wb"))) {
        err_OPEN_WRITE(error);
        return FALSE;
    }

    xres = gwy_data_field_get_xres(dfield);
    yres = gwy_data_field_get_yres(dfield);

    header = g_string_new(MAGIC);
    g_string_append_printf(header, "XRes = %u\n", xres);
    g_string_append_printf(header, "YRes = %u\n", yres);
    append_num(header, "XReal", gwy_data_field_get_xreal(dfield));
    append_num(header, "YReal", gwy_data_field_get_yreal(dfield));
    if ((v = gwy_data_field_get_xoffset(dfield)))
        append_num(header, "XOffset", v);
    if ((v = gwy_data_field_get_yoffset(dfield)))
        append_num(header, "YOffset", v);

    emptyunit = gwy_si_unit_new(NULL);
    unit = gwy_data_field_get_si_unit_xy(dfield);
    if (!gwy_si_unit_equal(unit, emptyunit)) {
        s = gwy_si_unit_get_string(unit, GWY_SI_UNIT_FORMAT_PLAIN);
        g_string_append_printf(header, "XYUnits = %s\n", s);
        g_free(s);
    }
    unit = gwy_data_field_get_si_unit_z(dfield);
    if (!gwy_si_unit_equal(unit, emptyunit)) {
        s = gwy_si_unit_get_string(unit, GWY_SI_UNIT_FORMAT_PLAIN);
        g_string_append_printf(header, "ZUnits = %s\n", s);
        g_free(s);
    }
    g_object_unref(emptyunit);

    s = gwy_app_get_data_field_title(container, id);
    g_string_append_printf(header, "Title = %s\n", s);
    g_free(s);

    if (fwrite(header->str, 1, header->len, fh) != header->len) {
        err_WRITE(error);
        goto fail;
    }

    padding = 4 - (header->len % 4);
    if (fwrite(zeroes, 1, padding, fh) != padding) {
        err_WRITE(error);
        goto fail;
    }
    g_string_free(header, TRUE);
    header = NULL;

    dfl = g_new(gfloat, xres*yres);
    d = gwy_data_field_get_data_const(dfield);
    for (i = 0; i < xres*yres; i++) {
        union { guchar pp[4]; float f; } z;
        z.f = d[i];
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
        GWY_SWAP(guchar, z.pp[0], z.pp[3]);
        GWY_SWAP(guchar, z.pp[1], z.pp[2]);
#endif
        dfl[i] = z.f;
    }

    if (fwrite(dfl, sizeof(gfloat), xres*yres, fh) != xres*yres) {
        err_WRITE(error);
        goto fail;
    }
    g_free(dfl);
    fclose(fh);

    return TRUE;

fail:
    if (fh)
        fclose(fh);
    g_unlink(filename);
    if (header)
        g_string_free(header, TRUE);
    g_free(dfl);

    return FALSE;
}
Exemple #10
0
static gboolean
aafm_export(G_GNUC_UNUSED GwyContainer *data,
            const gchar *filename,
            G_GNUC_UNUSED GwyRunType mode,
            GError **error)
{
    union { guchar pp[4]; float f; } z;
    guint16 res, r;
    gint16 *x;
    gint16 v;
    gint i, j, xres, yres, n;
    GwyDataField *dfield;
    const gdouble *d;
    gdouble min, max, q, z0;
    FILE *fh;
    gboolean ok = TRUE;

    gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, 0);
    if (!dfield) {
        err_NO_CHANNEL_EXPORT(error);
        return FALSE;
    }

    if (!(fh = gwy_fopen(filename, "wb"))) {
        err_OPEN_WRITE(error);
        return FALSE;
    }

    d = gwy_data_field_get_data_const(dfield);

    xres = gwy_data_field_get_xres(dfield);
    yres = gwy_data_field_get_yres(dfield);
    res = MIN(MIN(xres, yres), 32767);
    n = (gint)res*(gint)res;
    r = GUINT16_TO_LE(res);
    fwrite(&res, 1, sizeof(r), fh);

    gwy_data_field_get_min_max(dfield, &min, &max);
    if (min == max) {
        q = 0.0;
        z0 = 0.0;
    }
    else {
        q = 65533.0/(max - min);
        z0 = -32766.5*(max + min)/(max - min);
    }
    z.f = MIN(gwy_data_field_get_xreal(dfield),
              gwy_data_field_get_yreal(dfield))/Angstrom;
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
    GWY_SWAP(guchar, z.pp[0], z.pp[3]);
    GWY_SWAP(guchar, z.pp[1], z.pp[2]);
#endif
    fwrite(&z, 1, sizeof(z), fh);

    x = g_new(gint16, n);
    for (i = 0; i < res; i++) {
        for (j = 0; j < res; j++) {
            v = GWY_ROUND(d[(res-1 - j)*res + i]*q + z0);
            x[i*res + j] = GINT16_TO_LE(v);
        }
    }

    if (!(ok = (fwrite(x, 1, 2*n, fh) == 2*n))) {
        err_WRITE(error);
        g_unlink(filename);
    }
    else {
        z.f = (max - min)/Angstrom;
#if (G_BYTE_ORDER == G_BIG_ENDIAN)
        GWY_SWAP(guchar, z.pp[0], z.pp[3]);
        GWY_SWAP(guchar, z.pp[1], z.pp[2]);
#endif
        fwrite(&z, 1, sizeof(z), fh);
    }

    fclose(fh);
    g_free(x);

    return ok;
}