static void fit_plot_curve(FitArgs *args) { GwyGraphCurveModel *cmodel; gdouble *xd, *yd; gboolean initial, ok; /* XXX: ignored */ gint i, n; gdouble *param; if (!args->is_fitted && !args->is_estimated) return; initial = !args->is_fitted; n = gwy_nlfit_preset_get_nparams(args->fitfunc); param = g_newa(gdouble, n); for (i = 0; i < n; i++) { FitParamArg *arg; arg = &g_array_index(args->param, FitParamArg, i); param[i] = initial ? arg->init : arg->value; } n = gwy_data_line_get_res(args->xdata); g_return_if_fail(n == gwy_data_line_get_res(args->ydata)); xd = gwy_data_line_get_data(args->xdata); yd = gwy_data_line_get_data(args->ydata); for (i = 0; i < n; i++) yd[i] = gwy_nlfit_preset_get_value(args->fitfunc, xd[i], param, &ok); if (gwy_graph_model_get_n_curves(args->graph_model) == 2) cmodel = gwy_graph_model_get_curve(args->graph_model, 1); else { cmodel = gwy_graph_curve_model_new(); g_object_set(cmodel, "mode", GWY_GRAPH_CURVE_LINE, "color", &args->fitcolor, NULL); gwy_graph_model_add_curve(args->graph_model, cmodel); g_object_unref(cmodel); } g_object_set(cmodel, "description", initial ? gwy_sgettext("Estimate") : gwy_sgettext("Fit"), NULL); gwy_graph_curve_model_set_data(cmodel, xd, yd, n); }
static GwyDataLine* sphrev_make_sphere(gdouble radius, gint maxres) { GwyDataLine *dline; gdouble *data; gint i, size; size = GWY_ROUND(MIN(radius, maxres)); dline = gwy_data_line_new(2*size+1, 1.0, FALSE); data = gwy_data_line_get_data(dline); if (radius/8 > maxres) { /* Pathological case: very flat sphere */ for (i = 0; i <= size; i++) { gdouble u = i/radius; data[size+i] = data[size-i] = u*u/2.0*(1.0 + u*u/4.0*(1 + u*u/2.0)); } } else { /* Normal sphere */ for (i = 0; i <= size; i++) { gdouble u = i/radius; if (G_UNLIKELY(u > 1.0)) data[size+i] = data[size-i] = 1.0; else data[size+i] = data[size-i] = 1.0 - sqrt(1.0 - u*u); } } return dline; }
static void oldmda_read_data(OldMDAFile *mdafile, const gchar *buffer) { GwyBrick *brick; GwyDataField *dfield; GwyDataLine *cal; gdouble *data; gint i, j, k; const guchar *p; p = buffer; brick = gwy_brick_new(mdafile->xres, mdafile->yres, mdafile->zres, mdafile->xreal, mdafile->yreal, mdafile->zres, TRUE); data = gwy_brick_get_data(brick); for (k = 0; k < mdafile->zres; k++) { p = buffer + k * 4; for (i = 0; i < mdafile->yres; i++) for (j = 0; j < mdafile->xres; j++) { *(data + k * mdafile->xres * mdafile->yres + j + (mdafile->yres - i - 1) * mdafile->xres) = (gdouble)gwy_get_gint32_le(&p); p += (mdafile->zres - 1) * 4; } } gwy_brick_set_si_unit_x(brick, mdafile->siunitx); gwy_brick_set_si_unit_y(brick, mdafile->siunity); gwy_brick_set_si_unit_z(brick, mdafile->siunitz); cal = gwy_data_line_new(mdafile->zres, mdafile->zres, FALSE); data = gwy_data_line_get_data(cal); for (k = 0; k < mdafile->zres; k++) { *(data++) = g_array_index(mdafile->xdata, gdouble, k); } gwy_data_line_set_si_unit_y(cal, mdafile->siunitz); gwy_brick_set_zcalibration(brick, cal); g_object_unref(cal); g_object_unref(mdafile->siunitx); g_object_unref(mdafile->siunity); g_object_unref(mdafile->siunitz); dfield = gwy_data_field_new(mdafile->xres, mdafile->yres, mdafile->xreal, mdafile->yreal, TRUE); gwy_container_set_object_by_name(mdafile->data, "/brick/0", brick); gwy_container_set_string_by_name(mdafile->data, "/brick/0/title", g_strdup("MDA data")); gwy_brick_mean_plane(brick, dfield, 0, 0, 0, mdafile->xres, mdafile->yres, -1, FALSE); gwy_container_set_object_by_name(mdafile->data, "/brick/0/preview", dfield); g_object_unref(dfield); g_object_unref(brick); gwy_file_volume_import_log_add(mdafile->data, 0, NULL, mdafile->filename); }
static GwyGraphModel* spectra_to_graph(GwySpectra *spectra) { GwyGraphModel *gmodel; const gchar* graph_title; GwyGraphCurveModel *cmodel; gchar *curve_title = NULL; guint j, k, n_spectra, n_points; GwyDataLine *dline; gdouble *data, *xdata, *ydata, x_offset, x_realsize; GwySIUnit *x_si_unit, *y_si_unit; if (!(n_spectra = gwy_spectra_get_n_spectra(spectra))) { gwy_debug("rhk-spm32: no spectra in rhkpage - something is odd\n"); return NULL; } dline = gwy_spectra_get_spectrum(spectra, 0); n_points = gwy_data_line_get_res(dline); x_si_unit = gwy_data_line_get_si_unit_x(dline); y_si_unit = gwy_data_line_get_si_unit_y(dline); xdata = g_new0(gdouble, n_points); ydata = g_new0(gdouble, n_points); x_offset = gwy_data_line_get_offset(dline); x_realsize = gwy_data_line_get_real(dline); for (j = 0; j < n_points; j++) xdata[j] = x_offset+j*x_realsize; gmodel = gwy_graph_model_new(); g_object_set(gmodel, "si-unit-x", x_si_unit, "si-unit-y", y_si_unit, NULL); graph_title = gwy_spectra_get_title(spectra); g_object_set(gmodel, "title", graph_title, NULL); // tends to obstruct the curves - if there are more than a few - not // good - makes it hard to grab curves? //g_object_set(gmodel, "label-visible", FALSE, NULL); for (k = 1; k <= n_spectra; k++) { dline = gwy_spectra_get_spectrum(spectra, k-1); data = gwy_data_line_get_data(dline); for (j = 0; j < n_points; j++) ydata[j] = data[j]; cmodel = gwy_graph_curve_model_new(); gwy_graph_model_add_curve(gmodel, cmodel); g_object_unref(cmodel); curve_title = g_strdup_printf("%s %d", graph_title, k); g_object_set(cmodel, "description", curve_title, "mode", GWY_GRAPH_CURVE_LINE, "color", gwy_graph_get_preset_color(k), NULL); gwy_graph_curve_model_set_data(cmodel, xdata, ydata, n_points); } g_free(ydata); g_free(xdata); return gmodel; }
static void line_correct_match(GwyContainer *data, GwyRunType run) { GwyDataField *dfield; GwyDataLine *shifts; gint xres, yres, i; gdouble *d, *s; GQuark dquark; g_return_if_fail(run & LINECORR_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, GWY_APP_DATA_FIELD_KEY, &dquark, 0); g_return_if_fail(dfield && dquark); gwy_app_undo_qcheckpointv(data, 1, &dquark); yres = gwy_data_field_get_yres(dfield); xres = gwy_data_field_get_xres(dfield); d = gwy_data_field_get_data(dfield); shifts = gwy_data_line_new(yres, 1.0, TRUE); s = gwy_data_line_get_data(shifts); s[0] = 0.0; for (i = 1; i < yres; i++) { s[i] = find_shift(xres, d + i*xres, d + (i - 1)*xres); g_printerr("%d %g\n", i, s[i]); } gwy_data_line_cumulate(shifts); for (i = 1; i < yres; i++) gwy_data_field_area_add(dfield, 0, i, xres, 1, s[i]); gwy_data_field_add(dfield, -s[yres-1]/(xres*yres)); g_object_unref(shifts); gwy_data_field_data_changed(dfield); }
static void line_correct_median(GwyContainer *data, GwyRunType run) { GwyDataField *dfield; GwyDataLine *line, *modi; gint xres, yres, i; GQuark dquark; gdouble median; g_return_if_fail(run & LINECORR_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, GWY_APP_DATA_FIELD_KEY, &dquark, 0); g_return_if_fail(dfield && dquark); gwy_app_undo_qcheckpointv(data, 1, &dquark); xres = gwy_data_field_get_xres(dfield); line = gwy_data_line_new(xres, 1.0, FALSE); yres = gwy_data_field_get_yres(dfield); modi = gwy_data_line_new(yres, 1.0, FALSE); for (i = 0; i < yres; i++) { gwy_data_field_get_row(dfield, line, i); median = gwy_math_median(xres, gwy_data_line_get_data(line)); gwy_data_line_set_val(modi, i, median); } median = gwy_data_line_get_median(modi); for (i = 0; i < yres; i++) { gwy_data_field_area_add(dfield, 0, i, xres, 1, median - gwy_data_line_get_val(modi, i)); } g_object_unref(modi); g_object_unref(line); gwy_data_field_data_changed(dfield); }
static void preview(EntropyControls *controls) { EntropyArgs *args = controls->args; GwyDataField *dfield = controls->dfield; GwyDataField *mfield = controls->mfield; GwyGraphModel *gmodel; GwyGraphCurveModel *gcmodel; GwyDataLine *ecurve; gchar buf[24]; gdouble S, s, Smax = 0.0; ecurve = gwy_data_line_new(1, 1.0, FALSE); if (args->mode == ENTROPY_VALUES) { S = gwy_data_field_area_get_entropy_at_scales(dfield, ecurve, mfield, args->masking, 0, 0, dfield->xres, dfield->yres, 0); s = gwy_data_field_area_get_rms_mask(dfield, mfield, args->masking, 0, 0, dfield->xres, dfield->yres); Smax = ENTROPY_NORMAL + log(s); } else { GwyDataField *xder = gwy_data_field_new_alike(dfield, FALSE); GwyDataField *yder = gwy_data_field_new_alike(dfield, FALSE); compute_slopes(controls->dfield, args->fit_plane ? args->kernel_size : 0, xder, yder); xder = fake_mask(xder, mfield, args->masking); yder = fake_mask(yder, mfield, args->masking); if (args->mode == ENTROPY_ANGLES) transform_to_sphere(xder, yder); S = gwy_data_field_get_entropy_2d_at_scales(xder, yder, ecurve, 0); if (args->mode == ENTROPY_SLOPES) { s = calculate_sigma2_2d(xder, yder); Smax = ENTROPY_NORMAL_2D + log(s); } g_object_unref(xder); g_object_unref(yder); } g_snprintf(buf, sizeof(buf), "%g", S); gtk_label_set_text(GTK_LABEL(controls->entropy), buf); if (args->mode != ENTROPY_ANGLES) { g_snprintf(buf, sizeof(buf), "%g", Smax - S); gtk_label_set_text(GTK_LABEL(controls->entropydef), buf); } else gtk_label_set_text(GTK_LABEL(controls->entropydef), _("N.A.")); gmodel = gwy_graph_get_model(GWY_GRAPH(controls->graph)); gwy_graph_model_remove_all_curves(gmodel); g_object_set(gmodel, "axis-label-bottom", "log h", "axis-label-left", "S", "label-position", GWY_GRAPH_LABEL_NORTHWEST, NULL); if (gwy_data_line_get_min(ecurve) > -0.5*G_MAXDOUBLE) { gcmodel = gwy_graph_curve_model_new(); g_object_set(gcmodel, "description", _("Entropy at scales"), "mode", GWY_GRAPH_CURVE_LINE_POINTS, "color", gwy_graph_get_preset_color(0), NULL); gwy_graph_curve_model_set_data_from_dataline(gcmodel, ecurve, 0, 0); gwy_graph_model_add_curve(gmodel, gcmodel); g_object_unref(gcmodel); } if (S > -0.5*G_MAXDOUBLE) { GwyDataLine *best = gwy_data_line_duplicate(ecurve); gdouble *ydata = gwy_data_line_get_data(best); guint i, res = gwy_data_line_get_res(best); for (i = 0; i < res; i++) ydata[i] = S; gcmodel = gwy_graph_curve_model_new(); g_object_set(gcmodel, "description", _("Best estimate"), "mode", GWY_GRAPH_CURVE_LINE, "color", gwy_graph_get_preset_color(1), NULL); gwy_graph_curve_model_set_data_from_dataline(gcmodel, best, 0, 0); gwy_graph_model_add_curve(gmodel, gcmodel); g_object_unref(gcmodel); g_object_unref(best); } g_object_unref(ecurve); zoom_in_changed(controls, GTK_TOGGLE_BUTTON(controls->zoom_in)); }
static GwyDataField* sphrev_vertical(Sphrev1DArgs *args, GwyDataField *dfield) { GwyDataField *rfield; GwyDataLine *sphere; gdouble *data, *rdata, *sphdata, *sum, *sum2, *weight, *tmp; gdouble q; gint i, j, k, size, xres, yres; data = gwy_data_field_get_data(dfield); rfield = gwy_data_field_duplicate(dfield); xres = gwy_data_field_get_xres(rfield); yres = gwy_data_field_get_yres(rfield); rdata = gwy_data_field_get_data(rfield); q = gwy_data_field_get_rms(dfield)/sqrt(2.0/3.0 - G_PI/16.0); sphere = sphrev_make_sphere(args->size, gwy_data_field_get_yres(dfield)); /* Scale-freeing. * Data is normalized to have the same RMS as if it was composed from * spheres of radius args->radius. Actually we normalize the sphere * instead, but the effect is the same. */ gwy_data_line_multiply(sphere, -q); sphdata = gwy_data_line_get_data(sphere); size = gwy_data_line_get_res(sphere)/2; sum = g_new(gdouble, 4*yres); sum2 = sum + yres; weight = sum + 2*yres; tmp = sum + 3*yres; /* Weights for RMS filter. The xresl-proof way is to sum 1's. */ for (j = 0; j < yres; j++) weight[j] = 1.0; moving_sums(yres, weight, sum, size); memcpy(weight, sum, yres*sizeof(gdouble)); for (i = 0; i < xres; i++) { gdouble *rcol = rdata + i; gdouble *dcol = data + i; /* Kill data that stick down too much */ for (j = 0; j < yres; j++) tmp[j] = dcol[j*xres]; moving_sums(yres, tmp, sum, size); for (j = 0; j < yres; j++) { /* transform to avg - 2.5*rms */ sum[j] = sum[j]/weight[j]; sum2[j] = 2.5*sqrt(sum2[j]/weight[j] - sum[j]*sum[j]); sum[j] -= sum2[j]; } for (j = 0; j < yres; j++) tmp[j] = MAX(dcol[j*xres], sum[j]); /* Find the touching point */ for (j = 0; j < yres; j++) { gdouble *col = tmp + j; gint from, to, km; gdouble min; from = MAX(0, j-size) - j; to = MIN(j+size, yres-1) - j; min = G_MAXDOUBLE; km = 0; for (k = from; k <= to; k++) { if (-(sphdata[size+k] - col[k]) < min) { min = -(sphdata[size+k] - col[k]); km = k; } } rcol[j*xres] = min; } } g_free(sum); g_object_unref(sphere); return rfield; }
static GwySpectra* rhkspm32_read_spectra(RHKPage *rhkpage) { guint i, j; gdouble *data; GwySIUnit *siunit = NULL; GwyDataLine *dline; GwySpectra *spectra = NULL; GPtrArray *spectrum = NULL; // i'm leaving this alone, though it probably doesn't make sense, // and i should just create graphs straight away - but in case of // future use, i'll just convert the data later to graphs // xres stores number of data points per spectra, // yres stores the number of spectra // reading data gwy_debug("rhk-spm32: %d spectra in this page\n", rhkpage->yres); for (i = 0; i < rhkpage->yres; i++) { dline = gwy_data_line_new(rhkpage->xres, rhkpage->x.scale, FALSE); gwy_data_line_set_offset(dline, (rhkpage->x.offset)); data = gwy_data_line_get_data(dline); // store line data in physical units - which are the z values, not y if ((rhkpage->data_type) == RHK_DATA_INT16) { const guint16 *p = (const guint16*)(rhkpage->buffer + rhkpage->data_offset); for (j = 0; j < rhkpage->xres; j++) { data[j] = GINT16_FROM_LE(p[i*(rhkpage->xres) + j]) *(rhkpage->z.scale)+(rhkpage->z.offset); } } else if ((rhkpage->data_type) == RHK_DATA_SINGLE) { const guchar *p = (const guchar*)(rhkpage->buffer + rhkpage->data_offset); for (j = 0; j < rhkpage->xres; j++) { data[j] = gwy_get_gfloat_le(&p)*rhkpage->z.scale + rhkpage->z.offset; } } siunit = gwy_si_unit_new(rhkpage->x.units); gwy_data_line_set_si_unit_x(dline, siunit); g_object_unref(siunit); // the y units (and data) for a 1D graph are stored in Z in the rhk // spm32 format! /* Fix "/\xfbHz" to "/Hz". * XXX: It might be still wrong as the strange character might mean * sqrt. */ if (g_str_has_suffix(rhkpage->z.units, "/\xfbHz")) { gchar *s = gwy_strkill(g_strdup(rhkpage->z.units), "\xfb"); siunit = gwy_si_unit_new(s); g_free(s); } else siunit = gwy_si_unit_new(rhkpage->z.units); gwy_data_line_set_si_unit_y(dline, siunit); g_object_unref(siunit); if (!spectrum) spectrum = g_ptr_array_sized_new(rhkpage->yres); g_ptr_array_add(spectrum, dline); } gwy_debug("rhk-spm32: finished parsing sps data\n"); spectra = gwy_spectra_new(); for (i = 0; i < rhkpage->yres; i++) { dline = g_ptr_array_index(spectrum, i); // since RHK spm32 does not record where it took the spectra, // i'm setting these to zero gwy_spectra_add_spectrum(spectra, dline, 0, 0); g_object_unref(dline); } gwy_spectra_set_title(spectra, rhkpage->label); if (spectrum) g_ptr_array_free(spectrum, TRUE); return spectra; }
static GwySpectra* omicron_read_cs_data(OmicronFile *ofile, OmicronSpectroChannel *channel, GError **error) { GError *err = NULL; GwyDataLine *dline; GwySIUnit *siunit = NULL, *coord_unit = NULL; GwySpectra *spectra = NULL; GPtrArray *spectrum = NULL; gchar *filename; gdouble *data, x, y; gdouble *coords = NULL; gchar *buffer; gdouble scale; guint i, j; gint power10 = 0; gint ncurves = 0; gchar* line; filename = omicron_fix_file_name(ofile->filename, channel->filename, error); if (!filename) return NULL; gwy_debug("Succeeded with <%s>", filename); if (!g_file_get_contents(filename, &buffer, NULL , &err)) { g_free(filename); err_GET_FILE_CONTENTS(error, &err); return NULL; } g_free(filename); scale = channel->resolution; /* can also be extracted from min&max raw and phys settings */ while ((line = gwy_str_next_line(&buffer))) { if (strstr(line, ";n_curves")) { /* Find number of curves this should appear first in file */ ncurves = g_ascii_strtod(strchr(line, ':')+1, NULL); } if (strstr(line, "BEGIN COORD")) { /* Read in cordinates Spectroscopy Curves */ i = 0; coord_unit = gwy_si_unit_new_parse("nm", &power10); while ((line = gwy_str_next_line(&buffer))) { gchar *val2; if (strstr(line, "END")) { if (i != ncurves) { gwy_debug("Less coords than ncurves"); } break; } if (i == ncurves) { g_critical("More coords than ncurves."); break; } if (!coords) { if (!(coords = g_new0(gdouble, ncurves*2))) { gwy_debug("Failed to allocate mem: coords"); return NULL; } } val2 = line+16; x = g_ascii_strtod(line, &val2) * pow10(power10); y = g_ascii_strtod(val2, NULL) * pow10(power10); gwy_debug("Coord %i: x:%g y:%g", i, x, y); coords[2*i] = x; coords[2*i+1] = y; i++; } /* i is set to 0 and used as a counter for the dline */ i = 0; } if (strstr(line, "BEGIN") && !strstr(line, "COORD")) { /* Read spectroscopy points */ dline = gwy_data_line_new(channel->npoints, channel->end - channel->start, FALSE); gwy_data_line_set_offset(dline, (channel->start)); data = gwy_data_line_get_data(dline); j = 0; while ((line = gwy_str_next_line(&buffer))) { gchar *val2; if (strstr(line, "END") || j >= channel->npoints) break; val2 = line+13; x = g_ascii_strtod(line, &val2); y = g_ascii_strtod(val2, NULL)*scale; data[j] = y; j++; } /* Set Units for the parameter (x) axis */ if ((channel->param[0] == 'V') || (channel->param[0] == 'E')) { siunit = gwy_si_unit_new("V"); power10 = 0; } else if (channel->param[0] == 'I') siunit = gwy_si_unit_new_parse("nA", &power10); else if (channel->param[0] == 'Z') siunit = gwy_si_unit_new_parse("nm", &power10); else { gwy_debug("Parameter unit not recognised"); } if (siunit) { gwy_data_line_set_si_unit_x(dline, siunit); g_object_unref(siunit); } if (power10) { gdouble offset = 0; gdouble realsize = 0; offset = gwy_data_line_get_offset(dline)*pow10(power10); realsize = gwy_data_line_get_real(dline)*pow10(power10); gwy_data_line_set_offset(dline, offset); gwy_data_line_set_real(dline, realsize); } /* Set Units for the Value (y) Axis */ siunit = gwy_si_unit_new_parse(channel->units, &power10); gwy_data_line_set_si_unit_y(dline, siunit); g_object_unref(siunit); if (power10) gwy_data_line_multiply(dline, pow10(power10)); if (!spectrum) spectrum = g_ptr_array_sized_new(ncurves); g_ptr_array_add(spectrum, dline); } } if (!spectrum) spectrum = g_ptr_array_new(); if (spectrum->len < ncurves) { gwy_debug("Less actual spectra than ncurves"); ncurves = spectrum->len; } if (spectrum->len > ncurves) { gwy_debug("More actual spectra than ncurves, " "remaining pos will be set at (0.0,0.0)"); coords = g_renew(gdouble, coords, spectrum->len*2); if (!coords) { g_critical("Could not reallocate mem for coords."); return NULL; } while (spectrum->len > ncurves) { coords[ncurves*2] = 0.0; coords[ncurves*2+1] = 0.0; ncurves++; } } spectra = gwy_spectra_new(); if (coord_unit) { gwy_spectra_set_si_unit_xy(spectra, coord_unit); g_object_unref(coord_unit); } for (i = 0; i < ncurves; i++) { dline = g_ptr_array_index(spectrum, i); gwy_spectra_add_spectrum(spectra, dline, coords[i*2], ofile->yreal - coords[i*2+1]); g_object_unref(dline); } g_ptr_array_free(spectrum, TRUE); g_free(coords); g_free(buffer); return spectra; }
static void line_correct_match(GwyContainer *data, GwyRunType run) { GwyDataField *dfield; GwyDataLine *shifts; gint xres, yres, i, j; gdouble m, wsum, lambda, x; gdouble *d, *s, *w; const gdouble *a, *b; GQuark dquark; g_return_if_fail(run & LINECORR_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, GWY_APP_DATA_FIELD_KEY, &dquark, 0); g_return_if_fail(dfield && dquark); gwy_app_undo_qcheckpointv(data, 1, &dquark); yres = gwy_data_field_get_yres(dfield); xres = gwy_data_field_get_xres(dfield); d = gwy_data_field_get_data(dfield); shifts = gwy_data_line_new(yres, 1.0, TRUE); s = gwy_data_line_get_data(shifts); w = g_new(gdouble, xres-1); for (i = 1; i < yres; i++) { a = d + xres*(i - 1); b = d + xres*i; /* Diffnorm */ wsum = 0.0; for (j = 0; j < xres-1; j++) { x = a[j+1] - a[j] - b[j+1] + b[j]; wsum += fabs(x); } if (wsum == 0) continue; m = wsum/(xres-1); /* Weights */ wsum = 0.0; for (j = 0; j < xres-1; j++) { x = a[j+1] - a[j] - b[j+1] + b[j]; w[j] = exp(-(x*x/(2.0*m))); wsum += w[j]; } /* Correction */ lambda = (a[0] - b[0])*w[0]; for (j = 1; j < xres-1; j++) lambda += (a[j] - b[j])*(w[j-1] + w[j]); lambda += (a[xres-1] - b[xres-1])*w[xres-2]; lambda /= 2.0*wsum; gwy_debug("%g %g %g", m, wsum, lambda); s[i] = lambda; } gwy_data_line_cumulate(shifts); for (i = 1; i < yres; i++) gwy_data_field_area_add(dfield, 0, i, xres, 1, s[i]); gwy_data_field_add(dfield, -s[yres-1]/(xres*yres)); g_object_unref(shifts); g_free(w); gwy_data_field_data_changed(dfield); }