/** * 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; }
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; }
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; }
/** * 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); }
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); }
/** * 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; }
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); }
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; }
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; }