/** * gwy_data_field_correlate_iteration: * @state: Correlation iterator. * * Performs one iteration of correlation. * * An iterator can be created with gwy_data_field_correlate_init(). * When iteration ends, either by finishing or being aborted, * gwy_data_field_correlate_finalize() must be called to release allocated * resources. **/ void gwy_data_field_correlate_iteration(GwyComputationState *cstate) { GwyCorrelationState *state = (GwyCorrelationState*)cstate; gint xres, yres, kxres, kyres, k, xoff, yoff; gdouble s, davg, drms; xres = state->data_field->xres; yres = state->data_field->yres; kxres = state->kernel_field->xres; kyres = state->kernel_field->yres; xoff = (kxres - 1)/2; yoff = (kyres - 1)/2; if (state->cs.state == GWY_COMPUTATION_STATE_INIT) { gwy_data_field_fill(state->score, -1); state->kavg = gwy_data_field_get_avg(state->kernel_field); state->krms = gwy_data_field_get_rms(state->kernel_field); state->avg = gwy_data_field_duplicate(state->data_field); state->rms = gwy_data_field_duplicate(state->data_field); calculate_normalization(state->avg, state->rms, kxres, kyres); state->cs.state = GWY_COMPUTATION_STATE_ITERATE; state->cs.fraction = 0.0; state->i = yoff; state->j = xoff; } else if (state->cs.state == GWY_COMPUTATION_STATE_ITERATE) { k = state->i*xres + state->j; davg = state->avg->data[k]; drms = state->rms->data[k]; if (drms && state->krms) { s = gwy_data_field_get_raw_correlation_score(state->data_field, state->kernel_field, state->j - xoff, state->i - yoff, 0, 0, kxres, kyres, davg, state->kavg); state->score->data[k] = s/(drms*state->krms); } else state->score->data[k] = 0.0; state->j++; if (state->j + kxres - xoff > xres) { state->j = xoff; state->i++; if (state->i + kyres - yoff > yres) state->cs.state = GWY_COMPUTATION_STATE_FINISHED; } state->cs.fraction += 1.0/((xres - kxres + 1)*(yres - kyres + 1)); state->cs.fraction = MIN(state->cs.fraction, 1.0); } else if (state->cs.state == GWY_COMPUTATION_STATE_FINISHED) return; gwy_data_field_invalidate(state->score); }
static void mask_extract(GwyContainer *data, GwyRunType run) { GwyDataField *dfield; GwySIUnit *siunit; gint oldid, newid; g_return_if_fail(run & MASKOPS_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_MASK_FIELD, &dfield, GWY_APP_DATA_FIELD_ID, &oldid, 0); g_return_if_fail(dfield); dfield = gwy_data_field_duplicate(dfield); gwy_data_field_clamp(dfield, 0.0, 1.0); /* Other functions should set the units correctly, but do not trust them */ siunit = gwy_si_unit_new(""); gwy_data_field_set_si_unit_z(dfield, siunit); g_object_unref(siunit); newid = gwy_app_data_browser_add_data_field(dfield, data, TRUE); g_object_unref(dfield); gwy_app_set_data_field_title(data, newid, _("Mask")); gwy_app_channel_log_add_proc(data, oldid, newid); }
static void plot_correlated(GwyDataField *retfield, gint xsize, gint ysize, gdouble threshold) { GwyDataField *tmp; gint xres, yres, i, j, col, row, w, h; const gdouble *data; tmp = gwy_data_field_duplicate(retfield); gwy_data_field_clear(retfield); xres = gwy_data_field_get_xres(retfield); yres = gwy_data_field_get_yres(retfield); data = gwy_data_field_get_data_const(tmp); /* FIXME: this is very inefficient */ for (i = 0; i < yres; i++) { row = MAX(i - ysize/2, 0); h = MIN(i + ysize - ysize/2, yres) - row; for (j = 0; j < xres; j++) { if (data[i*xres + j] > threshold) { col = MAX(j - xsize/2, 0); w = MIN(j + xsize - xsize/2, xres) - col; gwy_data_field_area_fill(retfield, col, row, w, h, 1.0); } } } g_object_unref(tmp); }
static void presentation_logscale(GwyContainer *data, GwyRunType run) { GwyDataField *dfield, *sfield; GQuark squark; gdouble *d; gdouble min, max, m0; gint xres, yres, i, zeroes, id; g_return_if_fail(run & PRESENTATIONOPS_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, GWY_APP_SHOW_FIELD_KEY, &squark, GWY_APP_SHOW_FIELD, &sfield, GWY_APP_DATA_FIELD_ID, &id, 0); g_return_if_fail(dfield && squark); xres = gwy_data_field_get_xres(dfield); yres = gwy_data_field_get_yres(dfield); gwy_app_undo_qcheckpointv(data, 1, &squark); if (!sfield) { sfield = gwy_data_field_duplicate(dfield); gwy_container_set_object(data, squark, sfield); g_object_unref(sfield); } else { gwy_data_field_resample(sfield, xres, yres, GWY_INTERPOLATION_NONE); gwy_data_field_copy(dfield, sfield, FALSE); } d = gwy_data_field_get_data(sfield); zeroes = 0; max = 0; min = G_MAXDOUBLE; for (i = 0; i < xres*yres; i++) { d[i] = ABS(d[i]); if (G_UNLIKELY(d[i] > max)) max = d[i]; if (d[i] == 0.0) zeroes++; else if (G_UNLIKELY(d[i] < min)) min = d[i]; } if (min == max || zeroes == xres*yres) return; if (!zeroes) { for (i = 0; i < xres*yres; i++) d[i] = log(d[i]); } else { m0 = log(min) - log(max/min)/512.0; for (i = 0; i < xres*yres; i++) d[i] = d[i] ? log(d[i]) : m0; } gwy_data_field_data_changed(sfield); gwy_app_channel_log_add_proc(data, id, id); }
static void laplace(GwyContainer *data, GwyRunType run) { GwyDataField *dfield, *mfield, *buffer; GQuark dquark; gdouble error, cor, maxer, lastfrac, frac, starter; gint i, id; gboolean cancelled = FALSE; g_return_if_fail(run & LAPLACE_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD_KEY, &dquark, GWY_APP_DATA_FIELD, &dfield, GWY_APP_MASK_FIELD, &mfield, GWY_APP_DATA_FIELD_ID, &id, 0); g_return_if_fail(dfield && dquark && mfield); maxer = gwy_data_field_get_rms(dfield)/1.0e4; gwy_app_wait_start(gwy_app_find_window_for_channel(data, id), _("Laplace interpolation...")); dfield = gwy_data_field_duplicate(dfield); buffer = gwy_data_field_new_alike(dfield, TRUE); gwy_data_field_correct_average(dfield, mfield); cor = 0.2; error = 0.0; lastfrac = 0.0; starter = 0.0; for (i = 0; i < 5000; i++) { gwy_data_field_correct_laplace_iteration(dfield, mfield, buffer, cor, &error); if (error < maxer) break; if (!i) starter = error; frac = log(error/starter)/log(maxer/starter); if ((i/(gdouble)(5000)) > frac) frac = i/(gdouble)(5000); if (lastfrac > frac) frac = lastfrac; if (!gwy_app_wait_set_fraction(frac)) { cancelled = TRUE; break; } lastfrac = frac; } gwy_app_wait_finish(); if (!cancelled) { gwy_app_undo_qcheckpointv(data, 1, &dquark); gwy_container_set_object(data, dquark, dfield); gwy_app_channel_log_add_proc(data, id, id); } g_object_unref(dfield); g_object_unref(buffer); }
static GwyDataField* median_background(gint size, GwyDataField *dfield) { GwyDataField *rfield; gint *circle; gdouble *data, *rdata, *buffer; gint i, j, xres, yres, buflen; 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); buflen = 0; circle = median_make_circle(size); for (i = 0; i < 2*size + 1; i++) buflen += 2*circle[i] + 1; buffer = g_new(gdouble, buflen); for (i = 0; i < yres; i++) { for (j = 0; j < xres; j++) { gint n, k, from, to; n = 0; for (k = MAX(0, i - size); k <= MIN(yres - 1, i + size); k++) { gdouble *row = data + k*xres; from = MAX(0, j - circle[k - i + size]); to = MIN(xres - 1, j + circle[k - i + size]); memcpy(buffer + n, row + from, (to - from + 1)*sizeof(gdouble)); n += to - from + 1; } rdata[i*xres + j] = gwy_math_median(n, buffer); } if (i % 10 == 0 && !gwy_app_wait_set_fraction((gdouble)i/yres)) { g_free(circle); g_object_unref(rfield); return NULL; } } g_free(circle); return rfield; }
/* create a smaller copy of data */ static GwyContainer* create_preview_data(GwyContainer *data) { GwyContainer *preview; GwyDataField *dfield, *dfield_show; gint oldid; gint xres, yres; gdouble zoomval; preview = gwy_container_new(); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, GWY_APP_DATA_FIELD_ID, &oldid, 0); dfield = gwy_data_field_duplicate(dfield); dfield_show = gwy_data_field_duplicate(dfield); xres = gwy_data_field_get_xres(dfield); yres = gwy_data_field_get_yres(dfield); zoomval = (gdouble)PREVIEW_SIZE/MAX(xres, yres); gwy_data_field_resample(dfield, xres*zoomval, yres*zoomval, GWY_INTERPOLATION_LINEAR); dfield_show = gwy_data_field_duplicate(dfield); gwy_container_set_object_by_name(preview, "/0/data", dfield); g_object_unref(dfield); gwy_container_set_object_by_name(preview, "/0/show", dfield_show); g_object_unref(dfield_show); gwy_app_sync_data_items(data, preview, oldid, 0, FALSE, GWY_DATA_ITEM_GRADIENT, GWY_DATA_ITEM_RANGE, GWY_DATA_ITEM_MASK_COLOR, 0); return preview; }
static GwyDataField* prof_sqrt(GwyDataField *dfield) { gint xres, yres, i; gdouble *data; dfield = gwy_data_field_duplicate(dfield); xres = gwy_data_field_get_xres(dfield); yres = gwy_data_field_get_yres(dfield); data = gwy_data_field_get_data(dfield); for (i = 0; i < xres*yres; i++) data[i] = sqrt(data[i]); return dfield; }
static void tip_update(TipModelControls *controls, G_GNUC_UNUSED TipModelArgs *args) { GwyDataField *vtipfield, *buffer; buffer = gwy_data_field_duplicate(controls->tip); gwy_data_field_resample(buffer, controls->vxres, controls->vyres, GWY_INTERPOLATION_ROUND); vtipfield = GWY_DATA_FIELD(gwy_container_get_object_by_name(controls->vtip, "/0/data")); gwy_data_field_copy(buffer, vtipfield, FALSE); g_object_unref(buffer); gwy_data_field_data_changed(vtipfield); }
static void presentation_attach_do(const GwyAppDataId *source, const GwyAppDataId *target) { GwyContainer *sourcedata, *targetdata; GwyDataField *dfield; GQuark quark; sourcedata = gwy_app_data_browser_get(source->datano); targetdata = gwy_app_data_browser_get(target->datano); quark = gwy_app_get_data_key_for_id(source->id); dfield = GWY_DATA_FIELD(gwy_container_get_object(sourcedata, quark)); dfield = gwy_data_field_duplicate(dfield); quark = gwy_app_get_show_key_for_id(target->id); gwy_app_undo_qcheckpointv(targetdata, 1, &quark); gwy_container_set_object(targetdata, quark, dfield); g_object_unref(dfield); }
static void presentation_extract(GwyContainer *data, GwyRunType run) { GwyDataField *dfield; GQuark quark; gint oldid, newid; g_return_if_fail(run & PRESENTATIONOPS_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD_ID, &oldid, GWY_APP_SHOW_FIELD_KEY, &quark, GWY_APP_SHOW_FIELD, &dfield, 0); g_return_if_fail(dfield && quark); dfield = gwy_data_field_duplicate(dfield); newid = gwy_app_data_browser_add_data_field(dfield, data, TRUE); g_object_unref(dfield); gwy_app_sync_data_items(data, data, oldid, newid, FALSE, GWY_DATA_ITEM_GRADIENT, 0); gwy_app_set_data_field_title(data, newid, NULL); gwy_app_channel_log_add_proc(data, oldid, newid); }
static void prepare_stripe_fields(TipBlindControls *controls, gboolean keep) { TipBlindArgs *args = controls->args; guint i; if (!args->split_to_stripes) { free_stripe_results(args); return; } if (!keep || args->nstripes != controls->oldnstripes) free_stripe_results(args); if (!args->stripetips) { args->stripetips = g_new(GwyDataField*, args->nstripes); args->goodtip = g_new0(gboolean, args->nstripes); /* This can potentially initialise all the stripe tips from the global * one which is probably what we want. */ for (i = 0; i < args->nstripes; i++) args->stripetips[i] = gwy_data_field_duplicate(controls->tip); }
static GwyContainer* igor_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *meta = NULL, *container = NULL; GwyDataField *dfield = NULL, *maskfield = NULL; GwyTextHeaderParser parser; IgorFile igorfile; IgorWaveHeader5 *wave5; GError *err = NULL; guchar *p, *buffer = NULL; gint xres, yres; gsize expected_size, size = 0; gchar *note = NULL; const gchar *value; gchar key[64]; guint i, chid; GQuark quark; guint nlabels; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } gwy_clear(&igorfile, 1); if (!igor_read_headers(&igorfile, buffer, size, FALSE, error)) goto fail; /* Only accept v5 files because older do not support 2D data */ if (igorfile.header.version != 5) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Format version is %d. Only version 5 is supported."), igorfile.header.version); goto fail; } /* Detect Asylum research files, leave it at generic if not detected. */ if (memcmp(buffer + size-5, "MFP3D", 5) == 0) igorfile.variant = IGOR_ASYLUM_MPF3D; else if (memcmp(buffer + size-5, "Force", 5) == 0) igorfile.variant = IGOR_ASYLUM_FORCE; gwy_debug("producer variant %u", igorfile.variant); /* Must have exactly 3 dims: xres, yres, nchannels */ wave5 = &igorfile.wave5; xres = wave5->n_dim[0]; yres = wave5->n_dim[1]; igorfile.nchannels = wave5->n_dim[2]; if (igorfile.nchannels==0) igorfile.nchannels=1; if (!xres || !yres || !igorfile.nchannels || wave5->n_dim[3]) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Only two-dimensional data are supported.")); goto fail; } igorfile.type_size = igor_data_type_size(wave5->type); if (!igorfile.type_size) { err_DATA_TYPE(error, wave5->type); goto fail; } if (wave5->npts != xres*yres*igorfile.nchannels) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Number of data points %u does not match resolutions " "%u×%u×%u."), wave5->npts, xres, yres, igorfile.nchannels); goto fail; } if (igorfile.header.wfm_size <= igorfile.wave_header_size) { err_INVALID(error, "wfmSize"); goto fail; } expected_size = igorfile.header.wfm_size - igorfile.wave_header_size; if (expected_size != wave5->npts*igorfile.type_size) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Data size %u does not match " "the number of data points %u×%u."), (guint)expected_size, wave5->npts, igorfile.type_size); } if (err_SIZE_MISMATCH(error, expected_size + igorfile.headers_size, size, FALSE)) goto fail; p = buffer + igorfile.headers_size + expected_size; gwy_debug("remaning data size: %lu", (gulong)(size - (p - buffer))); p += igorfile.header.formula_size; if ((igorfile.variant == IGOR_ASYLUM_FORCE || igorfile.variant == IGOR_ASYLUM_MPF3D) && igorfile.header.note_size && (p - buffer) + igorfile.header.note_size <= size) { note = g_strndup((const gchar*)p, size); gwy_clear(&parser, 1); parser.key_value_separator = ":"; igorfile.meta = gwy_text_header_parse(note, &parser, NULL, NULL); } p += igorfile.header.note_size; /* FIXME: Support extended units for non-Asylum files! */ p += igorfile.header.data_e_units_size; for (i = 0; i < MAXDIMS; i++) p += igorfile.header.dim_e_units_size[i]; /* Skip labels of x and y dimension, we don't know what to do with them. */ for (i = 0; i < 2; i++) p += igorfile.header.dim_labels_size[i]; /* FIXME: The labels are mandatory only in Asylum Research files. */ nlabels = igorfile.header.dim_labels_size[2]/(MAX_WAVE_NAME5+1); expected_size = (MAX_WAVE_NAME5 + 1)*(nlabels); if ((p - buffer) + expected_size > size ) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Cannot read channel labels.")); goto fail; } igorfile.titles = read_channel_labels(p, igorfile.nchannels+1, nlabels); p += igorfile.header.dim_labels_size[2]; if (igorfile.meta) { igorfile.channel_info = g_new0(AsylumChannelInfo, igorfile.nchannels); for (i = 0; i < igorfile.nchannels; i++) { AsylumChannelInfo *chinfo = igorfile.channel_info + i; const gchar *title = g_ptr_array_index(igorfile.titles, i+1); if (title) { chinfo->name = canonicalize_title(title); g_snprintf(key, sizeof(key), "%sUnit", chinfo->name); value = g_hash_table_lookup(igorfile.meta, key); if (value) chinfo->units = value; else chinfo->units = channel_title_to_units(chinfo->name); } } } container = gwy_container_new(); for (i = chid = 0; i < igorfile.nchannels; i++, chid++) { const gchar *title = g_ptr_array_index(igorfile.titles, i+1); const gchar *zunits = NULL; if (igorfile.channel_info) { AsylumChannelInfo *chinfo = igorfile.channel_info + i; zunits = chinfo->units; meta = igor_get_metadata(&igorfile, i + 1); } dfield = igor_read_data_field(&igorfile, buffer, i, zunits, FALSE); maskfield = gwy_app_channel_mask_of_nans(dfield, TRUE); quark = gwy_app_get_data_key_for_id(chid); gwy_container_set_object(container, quark, dfield); g_object_unref(dfield); if (maskfield) { g_snprintf(key, sizeof(key), "/%d/mask", chid); gwy_container_set_object_by_name(container, key, maskfield); } if (meta) { g_snprintf(key, sizeof(key), "/%d/meta", chid); gwy_container_set_object_by_name(container, key, meta); } if (title) { g_snprintf(key, sizeof(key), "/%d/data/title", chid); gwy_container_set_string_by_name(container, key, g_strdup(title)); } gwy_app_channel_title_fall_back(container,chid); if (wave5->type & IGOR_COMPLEX) { chid++; dfield = igor_read_data_field(&igorfile, buffer, i, zunits, TRUE); quark = gwy_app_get_data_key_for_id(chid); gwy_container_set_object(container, quark, dfield); g_object_unref(dfield); if (meta) { g_snprintf(key, sizeof(key), "/%d/meta", chid); /* container still holds a reference */ g_object_unref(meta); meta = gwy_container_duplicate(meta); gwy_container_set_object_by_name(container, key, meta); } if (maskfield) { g_snprintf(key, sizeof(key), "/%d/mask", chid); /* container still holds a reference */ g_object_unref(maskfield); maskfield = gwy_data_field_duplicate(maskfield); gwy_container_set_object_by_name(container, key, maskfield); } if (title) { g_snprintf(key, sizeof(key), "/%d/data/title", chid); gwy_container_set_string_by_name(container, key, g_strdup(title)); }; gwy_app_channel_title_fall_back(container,chid); } gwy_object_unref(meta); gwy_object_unref(maskfield); gwy_file_channel_import_log_add(container, chid, NULL, filename); } fail: gwy_file_abandon_contents(buffer, size, NULL); g_free(note); if (igorfile.channel_info) { for (i = 0; i < igorfile.nchannels; i++) g_free(igorfile.channel_info[i].name); g_free(igorfile.channel_info); } if (igorfile.meta) g_hash_table_destroy(igorfile.meta); if (igorfile.titles) { g_ptr_array_foreach(igorfile.titles, (GFunc)g_free, NULL); g_ptr_array_free(igorfile.titles, TRUE); } return container; }
static void gfilter_dialog(GFilterArgs *args, GwyContainer *data, GwyDataField *dfield, GwyDataField *mfield, gint id, GQuark mquark) { GtkWidget *dialog, *table, *vbox, *hbox, *scwin, *hbox2, *label; GtkTreeView *treeview; GtkTreeSelection *selection; GFilterControls controls; gint response, row, i; GwySIUnit *siunit; GwyPixmapLayer *layer; controls.args = args; controls.mask = mfield; controls.in_init = TRUE; controls.computed = FALSE; siunit = gwy_si_unit_new(NULL); for (i = 0; i < NQUANTITIES; i++) { controls.vf[i] = gwy_si_unit_get_format_with_digits(siunit, GWY_SI_UNIT_FORMAT_VFMARKUP, 1.0, 4, NULL); } g_object_unref(siunit); dialog = gtk_dialog_new_with_buttons(_("Filter Grains"), NULL, 0, NULL); gtk_dialog_add_action_widget(GTK_DIALOG(dialog), gwy_stock_like_button_new(_("_Update"), GTK_STOCK_EXECUTE), RESPONSE_PREVIEW); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), RESPONSE_PREVIEW, !args->update); gwy_help_add_to_proc_dialog(GTK_DIALOG(dialog), GWY_HELP_DEFAULT); controls.dialog = dialog; hbox = gtk_hbox_new(FALSE, 2); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 4); vbox = gtk_vbox_new(FALSE, 4); gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 4); controls.mydata = gwy_container_new(); gwy_container_set_object_by_name(controls.mydata, "/0/data", dfield); mfield = gwy_data_field_duplicate(mfield); gwy_container_set_object_by_name(controls.mydata, "/0/mask", mfield); g_object_unref(mfield); gwy_app_sync_data_items(data, controls.mydata, id, 0, FALSE, GWY_DATA_ITEM_PALETTE, GWY_DATA_ITEM_MASK_COLOR, GWY_DATA_ITEM_RANGE, GWY_DATA_ITEM_REAL_SQUARE, 0); controls.view = gwy_data_view_new(controls.mydata); layer = gwy_layer_basic_new(); g_object_set(layer, "data-key", "/0/data", "gradient-key", "/0/base/palette", "range-type-key", "/0/base/range-type", "min-max-key", "/0/base", NULL); gwy_data_view_set_data_prefix(GWY_DATA_VIEW(controls.view), "/0/data"); gwy_data_view_set_base_layer(GWY_DATA_VIEW(controls.view), layer); layer = gwy_layer_mask_new(); gwy_pixmap_layer_set_data_key(layer, "/0/mask"); gwy_layer_mask_set_color_key(GWY_LAYER_MASK(layer), "/0/mask"); gwy_data_view_set_alpha_layer(GWY_DATA_VIEW(controls.view), layer); gwy_set_data_preview_size(GWY_DATA_VIEW(controls.view), PREVIEW_SIZE); gtk_box_pack_start(GTK_BOX(vbox), controls.view, FALSE, FALSE, 0); controls.update = gtk_check_button_new_with_mnemonic(_("I_nstant updates")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.update), args->update); gtk_box_pack_start(GTK_BOX(vbox), controls.update, FALSE, FALSE, 0); g_signal_connect_swapped(controls.update, "toggled", G_CALLBACK(update_changed), &controls); hbox2 = gtk_hbox_new(FALSE, 6); gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0); label = gtk_label_new_with_mnemonic(_("_Mask color:")); gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); controls.color_button = gwy_color_button_new(); gwy_color_button_set_use_alpha(GWY_COLOR_BUTTON(controls.color_button), TRUE); load_mask_color(controls.color_button, gwy_data_view_get_data(GWY_DATA_VIEW(controls.view))); gtk_label_set_mnemonic_widget(GTK_LABEL(label), controls.color_button); gtk_box_pack_start(GTK_BOX(hbox2), controls.color_button, FALSE, FALSE, 0); g_signal_connect(controls.color_button, "clicked", G_CALLBACK(mask_color_changed), &controls); table = gtk_table_new(10, 4, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 2); gtk_table_set_col_spacings(GTK_TABLE(table), 6); gtk_container_set_border_width(GTK_CONTAINER(table), 4); gtk_box_pack_start(GTK_BOX(hbox), table, TRUE, TRUE, 4); controls.table = table; row = 0; scwin = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scwin), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_table_attach(GTK_TABLE(table), scwin, 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0); controls.values = gwy_grain_value_tree_view_new(FALSE, "name", "symbol_markup", NULL); treeview = GTK_TREE_VIEW(controls.values); gtk_widget_set_size_request(scwin, -1, 120); gtk_tree_view_set_headers_visible(treeview, FALSE); selection = gtk_tree_view_get_selection(treeview); gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE); gwy_grain_value_tree_view_set_same_units(treeview, args->units_equal); gwy_grain_value_tree_view_set_expanded_groups(treeview, args->expanded); gtk_container_add(GTK_CONTAINER(scwin), controls.values); row++; hbox2 = gtk_hbox_new(FALSE, 0); for (i = 0; i < NQUANTITIES; i++) { gchar buf[2]; buf[0] = 'A' + i; buf[1] = '\0'; controls.set_as[i] = gtk_button_new_with_label(buf); gtk_box_pack_start(GTK_BOX(hbox2), controls.set_as[i], FALSE, FALSE, 0); g_object_set_data(G_OBJECT(controls.set_as[i]), "id", GUINT_TO_POINTER(i)); g_signal_connect_swapped(controls.set_as[i], "clicked", G_CALLBACK(set_as_clicked), &controls); } gwy_table_attach_hscale(table, row++, _("Set selected as:"), NULL, GTK_OBJECT(hbox2), GWY_HSCALE_WIDGET_NO_EXPAND); controls.logical_op = gwy_enum_combo_box_newl(G_CALLBACK(logical_op_changed), &controls, args->logical, "A", GRAIN_LOGICAL_A, "A ∧ B", GRAIN_LOGICAL_A_AND_B, "A ∨ B", GRAIN_LOGICAL_A_OR_B, "A ∧ B ∧ C", GRAIN_LOGICAL_A_AND_B_AND_C, "A ∨ B ∨ C", GRAIN_LOGICAL_A_OR_B_OR_C, "(A ∧ B) ∨ C", GRAIN_LOGICAL_A_AND_B_OR_C, "(A ∨ B) ∧ C", GRAIN_LOGICAL_A_OR_B_AND_C, NULL); gwy_table_attach_hscale(table, row++, _("Keep grains satisfying:"), NULL, GTK_OBJECT(controls.logical_op), GWY_HSCALE_WIDGET); for (i = 0; i < NQUANTITIES; i++) { gtk_table_set_row_spacing(GTK_TABLE(table), row-1, 8); controls.header[i] = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.header[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.header[i], 0, 4, row, row+1, GTK_FILL, 0, 0, 0); row++; /* The values are set properly later. */ controls.lower_label[i] = gtk_label_new(_("Lower threshold:")); gtk_misc_set_alignment(GTK_MISC(controls.lower_label[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.lower_label[i], 0, 1, row, row+1, GTK_FILL, 0, 0, 0); controls.lower[i] = gtk_adjustment_new(0.0, 0.0, 0.0, 1.0, 10.0, 0.0); g_object_set_data(G_OBJECT(controls.lower[i]), "id", GUINT_TO_POINTER(i)); g_signal_connect_swapped(controls.lower[i], "value-changed", G_CALLBACK(threshold_changed), &controls); controls.lower_scale[i] = gtk_hscale_new(GTK_ADJUSTMENT(controls.lower[i])); gtk_scale_set_draw_value(GTK_SCALE(controls.lower_scale[i]), FALSE); gtk_widget_set_size_request(controls.lower_scale[i], GWY_HSCALE_WIDTH, -1); gtk_table_attach(GTK_TABLE(table), controls.lower_scale[i], 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.lower_entry[i] = gtk_entry_new(); gtk_entry_set_width_chars(GTK_ENTRY(controls.lower_entry[i]), 8); gtk_table_attach(GTK_TABLE(table), controls.lower_entry[i], 2, 3, row, row+1, GTK_FILL, 0, 0, 0); gwy_widget_set_activate_on_unfocus(controls.lower_entry[i], TRUE); g_object_set_data(G_OBJECT(controls.lower_entry[i]), "id", GUINT_TO_POINTER(i)); g_signal_connect_swapped(controls.lower_entry[i], "activate", G_CALLBACK(threshold_activated), &controls); controls.lower_units[i] = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.lower_units[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.lower_units[i], 3, 4, row, row+1, GTK_FILL, 0, 0, 0); row++; controls.upper_label[i] = gtk_label_new(_("Upper threshold:")); gtk_misc_set_alignment(GTK_MISC(controls.upper_label[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.upper_label[i], 0, 1, row, row+1, GTK_FILL, 0, 0, 0); controls.upper[i] = gtk_adjustment_new(0.0, 0.0, 0.0, 1.0, 10.0, 0.0); g_object_set_data(G_OBJECT(controls.upper[i]), "id", GUINT_TO_POINTER(i | IS_UPPER)); g_signal_connect_swapped(controls.upper[i], "value-changed", G_CALLBACK(threshold_changed), &controls); controls.upper_scale[i] = gtk_hscale_new(GTK_ADJUSTMENT(controls.upper[i])); gtk_scale_set_draw_value(GTK_SCALE(controls.upper_scale[i]), FALSE); gtk_widget_set_size_request(controls.upper_scale[i], GWY_HSCALE_WIDTH, -1); gtk_table_attach(GTK_TABLE(table), controls.upper_scale[i], 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.upper_entry[i] = gtk_entry_new(); gtk_entry_set_width_chars(GTK_ENTRY(controls.upper_entry[i]), 8); gtk_table_attach(GTK_TABLE(table), controls.upper_entry[i], 2, 3, row, row+1, GTK_FILL, 0, 0, 0); gwy_widget_set_activate_on_unfocus(controls.upper_entry[i], TRUE); g_object_set_data(G_OBJECT(controls.upper_entry[i]), "id", GUINT_TO_POINTER(i | IS_UPPER)); g_signal_connect_swapped(controls.upper_entry[i], "activate", G_CALLBACK(threshold_activated), &controls); controls.upper_units[i] = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.upper_units[i]), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.upper_units[i], 3, 4, row, row+1, GTK_FILL, 0, 0, 0); row++; } for (i = 0; i < NQUANTITIES; i++) { GwyInventory *inventory; GwyGrainValue *gvalue; inventory = gwy_grain_values(); gvalue = gwy_inventory_get_item(inventory, args->ranges[i].quantity); set_up_quantity(&controls, gvalue, i); } logical_op_changed(GTK_COMBO_BOX(controls.logical_op), &controls); /* finished initializing, allow instant updates */ controls.in_init = FALSE; gfilter_invalidate(&controls); gtk_widget_show_all(dialog); do { response = gtk_dialog_run(GTK_DIALOG(dialog)); switch (response) { case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_DELETE_EVENT: args->expanded = gwy_grain_value_tree_view_get_expanded_groups (GTK_TREE_VIEW(controls.values)); for (i = 0; i < NQUANTITIES; i++) gwy_si_unit_value_format_free(controls.vf[i]); gtk_widget_destroy(dialog); case GTK_RESPONSE_NONE: g_object_unref(controls.mydata); gfilter_save_args(gwy_app_settings_get(), args); return; break; case GTK_RESPONSE_OK: break; case RESPONSE_PREVIEW: preview(&controls); break; default: g_assert_not_reached(); break; } } while (response != GTK_RESPONSE_OK); for (i = 0; i < NQUANTITIES; i++) gwy_si_unit_value_format_free(controls.vf[i]); args->expanded = gwy_grain_value_tree_view_get_expanded_groups (GTK_TREE_VIEW(controls.values)); gwy_app_sync_data_items(controls.mydata, data, 0, id, FALSE, GWY_DATA_ITEM_MASK_COLOR, 0); gtk_widget_destroy(dialog); gfilter_save_args(gwy_app_settings_get(), args); if (controls.computed) { mfield = gwy_container_get_object_by_name(controls.mydata, "/0/mask"); gwy_app_undo_qcheckpointv(data, 1, &mquark); gwy_container_set_object(data, mquark, mfield); g_object_unref(controls.mydata); } else { g_object_unref(controls.mydata); run_noninteractive(args, data, controls.mask, mquark); } gwy_app_channel_log_add_proc(data, id, id); }
static void cwt(GwyContainer *data, GwyRunType run) { GtkWidget *dialog; GwyDataField *dfield; CWTArgs args; gboolean ok; gint xsize, ysize; gint newsize; gint oldid, newid; g_return_if_fail(run & CWT_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, GWY_APP_DATA_FIELD_ID, &oldid, 0); g_return_if_fail(dfield); xsize = gwy_data_field_get_xres(dfield); ysize = gwy_data_field_get_yres(dfield); if (xsize != ysize) { dialog = gtk_message_dialog_new (gwy_app_find_window_for_channel(data, oldid), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("%s: Data must be square."), "CWT"); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return; } cwt_load_args(gwy_app_settings_get(), &args); if (run == GWY_RUN_INTERACTIVE) { ok = cwt_dialog(&args); cwt_save_args(gwy_app_settings_get(), &args); if (!ok) return; } dfield = gwy_data_field_duplicate(dfield); newsize = gwy_fft_find_nice_size(xsize); gwy_data_field_resample(dfield, newsize, newsize, args.interp); gwy_data_field_cwt(dfield, args.interp, args.scale, args.wavelet); if (args.preserve) gwy_data_field_resample(dfield, xsize, ysize, args.interp); newid = gwy_app_data_browser_add_data_field(dfield, data, TRUE); gwy_app_sync_data_items(data, data, oldid, newid, FALSE, GWY_DATA_ITEM_GRADIENT, GWY_DATA_ITEM_MASK_COLOR, 0); g_object_unref(dfield); gwy_app_set_data_field_title(data, newid, _("CWT")); }
static void level_grains_do(const LevelGrainsArgs *args, GwyContainer *data, GQuark dquark, gint id, GwyDataField *dfield, GwyDataField *mfield) { GwyDataField *buffer, *background, *invmask; gdouble error, cor, maxerr, lastfrac, frac, starterr; gdouble *heights, *bgdata; gint *grains; gboolean cancelled = FALSE; gint i, xres, yres, ngrains; xres = gwy_data_field_get_xres(mfield); yres = gwy_data_field_get_yres(mfield); grains = g_new0(gint, xres*yres); ngrains = gwy_data_field_number_grains(mfield, grains); if (!ngrains) { g_free(grains); return; } heights = g_new(gdouble, ngrains+1); gwy_data_field_grains_get_values(dfield, heights, ngrains, grains, args->base); heights[0] = 0.0; background = gwy_data_field_new_alike(dfield, FALSE); bgdata = gwy_data_field_get_data(background); for (i = 0; i < xres*yres; i++) bgdata[i] = -heights[grains[i]]; invmask = gwy_data_field_duplicate(mfield); gwy_data_field_multiply(invmask, -1.0); gwy_data_field_add(invmask, 1.0); maxerr = gwy_data_field_get_rms(dfield)/1.0e4; gwy_app_wait_start(gwy_app_find_window_for_channel(data, id), _("Laplace interpolation...")); g_free(heights); g_free(grains); buffer = gwy_data_field_new_alike(background, TRUE); gwy_data_field_correct_average(background, invmask); cor = 0.2; error = 0.0; lastfrac = 0.0; starterr = 0.0; for (i = 0; i < 5000; i++) { gwy_data_field_correct_laplace_iteration(background, invmask, buffer, cor, &error); if (error < maxerr) break; if (!i) starterr = error; frac = log(error/starterr)/log(maxerr/starterr); if ((i/(gdouble)(5000)) > frac) frac = i/(gdouble)(5000); if (lastfrac > frac) frac = lastfrac; if (!gwy_app_wait_set_fraction(frac)) { cancelled = TRUE; break; } lastfrac = frac; } gwy_app_wait_finish(); if (!cancelled) { gwy_data_field_invert(background, FALSE, FALSE, TRUE); gwy_app_undo_qcheckpointv(data, 1, &dquark); gwy_data_field_subtract_fields(dfield, dfield, background); gwy_data_field_data_changed(dfield); if (args->do_extract) { gint newid; newid = gwy_app_data_browser_add_data_field(background, data, TRUE); gwy_app_sync_data_items(data, data, id, newid, FALSE, GWY_DATA_ITEM_GRADIENT, 0); gwy_app_set_data_field_title(data, newid, _("Background")); } } g_object_unref(buffer); g_object_unref(invmask); g_object_unref(background); }
static void immerse_do(ImmerseArgs *args) { GwyDataField *resampled, *image, *detail, *result; GwyContainer *data; gint newid; gint kxres, kyres; gint x, y, w, h; gdouble iavg, davg; GQuark quark; data = gwy_app_data_browser_get(args->image.datano); quark = gwy_app_get_data_key_for_id(args->image.id); image = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); data = gwy_app_data_browser_get(args->detail.datano); quark = gwy_app_get_data_key_for_id(args->detail.id); detail = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); davg = gwy_data_field_get_avg(detail); kxres = gwy_data_field_get_xres(detail); kyres = gwy_data_field_get_yres(detail); switch (args->sampling) { case GWY_IMMERSE_SAMPLING_DOWN: result = gwy_data_field_duplicate(image); x = gwy_data_field_rtoj(image, args->xpos); y = gwy_data_field_rtoi(image, args->ypos); w = GWY_ROUND(gwy_data_field_get_xreal(detail) /gwy_data_field_get_xmeasure(image)); h = GWY_ROUND(gwy_data_field_get_yreal(detail) /gwy_data_field_get_ymeasure(image)); w = MAX(w, 1); h = MAX(h, 1); gwy_debug("w: %d, h: %d", w, h); resampled = gwy_data_field_new_resampled(detail, w, h, GWY_INTERPOLATION_LINEAR); if (args->leveling == GWY_IMMERSE_LEVEL_MEAN) { iavg = gwy_data_field_area_get_avg(result, NULL, x, y, w, h); gwy_data_field_add(resampled, iavg - davg); } gwy_data_field_area_copy(resampled, result, 0, 0, w, h, x, y); g_object_unref(resampled); break; case GWY_IMMERSE_SAMPLING_UP: w = GWY_ROUND(gwy_data_field_get_xreal(image) /gwy_data_field_get_xmeasure(detail)); h = GWY_ROUND(gwy_data_field_get_yreal(image) /gwy_data_field_get_ymeasure(detail)); gwy_debug("w: %d, h: %d", w, h); result = gwy_data_field_new_resampled(image, w, h, GWY_INTERPOLATION_LINEAR); x = gwy_data_field_rtoj(result, args->xpos); y = gwy_data_field_rtoi(result, args->ypos); if (args->leveling == GWY_IMMERSE_LEVEL_MEAN) { iavg = gwy_data_field_area_get_avg(result, NULL, x, y, kxres, kyres); gwy_data_field_area_copy(detail, result, 0, 0, kxres, kyres, x, y); gwy_data_field_area_add(result, x, y, kxres, kyres, iavg - davg); } else gwy_data_field_area_copy(detail, result, 0, 0, kxres, kyres, x, y); break; default: g_return_if_reached(); break; } gwy_app_data_browser_get_current(GWY_APP_CONTAINER, &data, 0); newid = gwy_app_data_browser_add_data_field(result, data, TRUE); gwy_app_set_data_field_title(data, newid, _("Immersed detail")); g_object_unref(result); gwy_app_channel_log_add_proc(data, args->image.id, newid); }
/** * gwy_data_field_correlate: * @data_field: A data field. * @kernel_field: Correlation kernel. * @score: Data field to store correlation scores to. * @method: Correlation score calculation method. * * Computes correlation score for all positions in a data field. * * Correlation score is compute for all points in data field @data_field * and full size of correlation kernel @kernel_field. * * The points in @score correspond to centers of kernel. More precisely, the * point ((@kxres-1)/2, (@kyres-1)/2) in @score corresponds to kernel field * top left corner coincident with data field top left corner. Points outside * the area where the kernel field fits into the data field completely are * set to -1 for %GWY_CORRELATION_NORMAL. **/ void gwy_data_field_correlate(GwyDataField *data_field, GwyDataField *kernel_field, GwyDataField *score, GwyCorrelationType method) { gint xres, yres, kxres, kyres, i, j, k, fftxres, fftyres; GwyDataField *data_in_re, *data_out_re, *data_out_im; GwyDataField *kernel_in_re, *kernel_out_re, *kernel_out_im; gdouble norm; g_return_if_fail(data_field != NULL && kernel_field != NULL); xres = data_field->xres; yres = data_field->yres; kxres = kernel_field->xres; kyres = kernel_field->yres; if (kxres <= 0 || kyres <= 0) { g_warning("Correlation kernel has nonpositive size."); return; } switch (method) { case GWY_CORRELATION_NORMAL: gwy_data_field_fill(score, -1); /*correlation request outside kernel */ if (kxres > xres || kyres > yres) { return; } { GwyDataField *avg, *rms; gdouble s, davg, drms, kavg, krms; gint xoff, yoff; /* The number of pixels the correlation kernel extends to the * negative direction */ xoff = (kxres - 1)/2; yoff = (kyres - 1)/2; kavg = gwy_data_field_get_avg(kernel_field); krms = gwy_data_field_get_rms(kernel_field); avg = gwy_data_field_duplicate(data_field); rms = gwy_data_field_duplicate(data_field); calculate_normalization(avg, rms, kxres, kyres); for (i = yoff; i + kyres - yoff <= yres; i++) { for (j = xoff; j + kxres - xoff <= xres; j++) { k = i*xres + j; davg = avg->data[k]; drms = rms->data[k]; if (!krms || !drms) { score->data[k] = 0.0; continue; } s = gwy_data_field_get_raw_correlation_score(data_field, kernel_field, j - xoff, i - yoff, 0, 0, kxres, kyres, davg, kavg); score->data[k] = s/(drms*krms); } } g_object_unref(avg); g_object_unref(rms); } break; case GWY_CORRELATION_FFT: case GWY_CORRELATION_POC: fftxres = gwy_fft_find_nice_size(xres); fftyres = gwy_fft_find_nice_size(yres); data_in_re = gwy_data_field_new_resampled(data_field, fftxres, fftyres, GWY_INTERPOLATION_BILINEAR); kernel_in_re = gwy_data_field_new_alike(data_field, TRUE); gwy_data_field_area_copy(kernel_field, kernel_in_re, 0, 0, kernel_field->xres, kernel_field->yres, kernel_in_re->xres/2 - kernel_field->xres/2, kernel_in_re->yres/2 - kernel_field->yres/2); gwy_data_field_resample(kernel_in_re, fftxres, fftyres, GWY_INTERPOLATION_BILINEAR); gwy_data_field_resample(score, fftxres, fftyres, GWY_INTERPOLATION_NONE); data_out_re = gwy_data_field_new_alike(data_in_re, TRUE); data_out_im = gwy_data_field_new_alike(data_in_re, TRUE); kernel_out_re = gwy_data_field_new_alike(data_in_re, TRUE); kernel_out_im = gwy_data_field_new_alike(data_in_re, TRUE); gwy_data_field_2dfft(data_in_re, NULL, data_out_re, data_out_im, GWY_WINDOWING_NONE, GWY_TRANSFORM_DIRECTION_FORWARD, GWY_INTERPOLATION_BILINEAR, FALSE, FALSE); gwy_data_field_2dfft(kernel_in_re, NULL, kernel_out_re, kernel_out_im, GWY_WINDOWING_NONE, GWY_TRANSFORM_DIRECTION_FORWARD, GWY_INTERPOLATION_BILINEAR, FALSE, FALSE); for (i = 0; i < fftxres*fftyres; i++) { /*NOTE: now we construct new "complex field" from data * and kernel fields, just to save memory*/ data_in_re->data[i] = data_out_re->data[i]*kernel_out_re->data[i] + data_out_im->data[i]*kernel_out_im->data[i]; kernel_in_re->data[i] = -data_out_re->data[i]*kernel_out_im->data[i] + data_out_im->data[i]*kernel_out_re->data[i]; if (method == GWY_CORRELATION_POC) { norm = hypot(data_in_re->data[i], kernel_in_re->data[i]); data_in_re->data[i] /= norm; kernel_in_re->data[i] /= norm; } } gwy_data_field_2dfft(data_in_re, kernel_in_re, score, data_out_im, GWY_WINDOWING_NONE, GWY_TRANSFORM_DIRECTION_BACKWARD, GWY_INTERPOLATION_BILINEAR, FALSE, FALSE); gwy_data_field_2dfft_humanize(score); /*TODO compute it and put to score field*/ g_object_unref(data_in_re); g_object_unref(data_out_re); g_object_unref(data_out_im); g_object_unref(kernel_in_re); g_object_unref(kernel_out_re); g_object_unref(kernel_out_im); break; } gwy_data_field_invalidate(score); }
static void maskcor_do(MaskcorArgs *args) { enum { WORK_PER_UPDATE = 50000000 }; GwyDataField *dfield, *kernel, *retfield, *score; GwyContainer *data, *kerneldata; GwyComputationState *state; GQuark quark; gint newid, work, wpi; kerneldata = gwy_app_data_browser_get(args->kernel.datano); quark = gwy_app_get_data_key_for_id(args->kernel.id); kernel = GWY_DATA_FIELD(gwy_container_get_object(kerneldata, quark)); data = gwy_app_data_browser_get(args->data.datano); quark = gwy_app_get_data_key_for_id(args->data.id); dfield = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); retfield = gwy_data_field_new_alike(dfield, FALSE); /* FIXME */ if (args->method == GWY_CORRELATION_NORMAL) { gwy_app_wait_start(gwy_app_find_window_for_channel(data, args->data.id), _("Initializing...")); state = gwy_data_field_correlate_init(dfield, kernel, retfield); gwy_app_wait_set_message(_("Correlating...")); work = 0; wpi = gwy_data_field_get_xres(kernel)*gwy_data_field_get_yres(kernel); wpi = MIN(wpi, WORK_PER_UPDATE); do { gwy_data_field_correlate_iteration(state); work += wpi; if (work > WORK_PER_UPDATE) { work -= WORK_PER_UPDATE; if (!gwy_app_wait_set_fraction(state->fraction)) { gwy_data_field_correlate_finalize(state); gwy_app_wait_finish(); g_object_unref(retfield); return; } } } while (state->state != GWY_COMPUTATION_STATE_FINISHED); gwy_data_field_correlate_finalize(state); gwy_app_wait_finish(); } else gwy_data_field_correlate(dfield, kernel, retfield, args->method); /* score - do new data with score */ if (args->result == GWY_MASKCOR_SCORE) { score = gwy_data_field_duplicate(retfield); newid = gwy_app_data_browser_add_data_field(score, data, TRUE); gwy_app_sync_data_items(data, data, args->data.id, newid, FALSE, GWY_DATA_ITEM_GRADIENT, 0); gwy_app_set_data_field_title(data, newid, _("Correlation score")); g_object_unref(score); gwy_app_channel_log_add_proc(data, args->data.id, newid); } else { /* add mask */ quark = gwy_app_get_mask_key_for_id(args->data.id); gwy_app_undo_qcheckpointv(data, 1, &quark); if (args->result == GWY_MASKCOR_OBJECTS) plot_correlated(retfield, gwy_data_field_get_xres(kernel), gwy_data_field_get_yres(kernel), args->threshold); else if (args->result == GWY_MASKCOR_MAXIMA) gwy_data_field_threshold(retfield, args->threshold, 0.0, 1.0); gwy_container_set_object(data, quark, retfield); gwy_app_channel_log_add_proc(data, args->data.id, args->data.id); } g_object_unref(retfield); }
static void preview(DepositControls *controls, DepositArgs *args) { GwyDataField *dfield, *lfield, *zlfield, *zdfield; gint xres, yres, oxres, oyres; gint add, i, ii, m, k; gdouble size, width; gint xdata[10000]; gint ydata[10000]; gdouble disizes[10000]; gdouble rdisizes[10000]; gdouble rx[10000]; gdouble ry[10000]; gdouble rz[10000]; gdouble ax[10000]; gdouble ay[10000]; gdouble az[10000]; gdouble vx[10000]; gdouble vy[10000]; gdouble vz[10000]; gdouble fx[10000]; gdouble fy[10000]; gdouble fz[10000]; gint xpos, ypos, ndata, too_close; gdouble disize, mdisize; gdouble xreal, yreal, oxreal, oyreal; gdouble diff; gdouble mass = 1; gint presetval; gint nloc, maxloc = 1; gint max = 5000000; gdouble rxv, ryv, rzv, timestep = 3e-7; //5e-7 deposit_dialog_update_values(controls, args); dfield = GWY_DATA_FIELD(gwy_container_get_object_by_name(controls->mydata, "/0/data")); gwy_container_set_object_by_name(controls->mydata, "/0/data", gwy_data_field_duplicate(controls->old_dfield)); dfield = GWY_DATA_FIELD(gwy_container_get_object_by_name(controls->mydata, "/0/data")); if (controls->in_init) { gwy_data_field_data_changed(dfield); while (gtk_events_pending()) gtk_main_iteration(); return; } oxres = gwy_data_field_get_xres(dfield); oyres = gwy_data_field_get_yres(dfield); oxreal = gwy_data_field_get_xreal(dfield); oyreal = gwy_data_field_get_yreal(dfield); diff = oxreal/oxres/10; size = args->size*5e-9; // width = args->width*5e-9 + 2*size; //increased manually to fill boundaries width = 2*size; add = gwy_data_field_rtoi(dfield, size + width); mdisize = gwy_data_field_rtoi(dfield, size); xres = oxres + 2*add; yres = oyres + 2*add; xreal = oxreal + 2*(size+width); yreal = oyreal + 2*(size+width); // printf("For field of size %g and particle nominak %g, real %g (%g), the final size will change from %d to %d\n", // gwy_data_field_get_xreal(dfield), args->size, size, disize, oxres, xres); /*make copy of datafield, with mirrored boundaries*/ lfield = gwy_data_field_new(xres, yres, gwy_data_field_itor(dfield, xres), gwy_data_field_jtor(dfield, yres), TRUE); gwy_data_field_area_copy(dfield, lfield, 0, 0, oxres, oyres, add, add); gwy_data_field_invert(dfield, 1, 0, 0); gwy_data_field_area_copy(dfield, lfield, 0, oyres-add-1, oxres, add, add, 0); gwy_data_field_area_copy(dfield, lfield, 0, 0, oxres, add, add, yres-add-1); gwy_data_field_invert(dfield, 1, 0, 0); gwy_data_field_invert(dfield, 0, 1, 0); gwy_data_field_area_copy(dfield, lfield, oxres-add-1, 0, add, oyres, 0, add); gwy_data_field_area_copy(dfield, lfield, 0, 0, add, oyres, xres-add-1, add); gwy_data_field_invert(dfield, 0, 1, 0); gwy_data_field_invert(dfield, 1, 1, 0); gwy_data_field_area_copy(dfield, lfield, oxres-add-1, oyres-add-1, add, add, 0, 0); gwy_data_field_area_copy(dfield, lfield, 0, 0, add, add, xres-add-1, yres-add-1); gwy_data_field_area_copy(dfield, lfield, oxres-add-1, 0, add, add, 0, yres-add-1); gwy_data_field_area_copy(dfield, lfield, 0, oyres-add-1, add, add, xres-add-1, 0); gwy_data_field_invert(dfield, 1, 1, 0); zlfield = gwy_data_field_duplicate(lfield); zdfield = gwy_data_field_duplicate(dfield); /*determine number of spheres necessary for given coverage*/ for (i=0; i<10000; i++) { ax[i] = ay[i] = az[i] = vx[i] = vy[i] = vz[i] = 0; } srand ( time(NULL) ); ndata = 0; /* for test only */ /* disize = mdisize; xpos = oxres/2 - 2*disize; ypos = oyres/2; xdata[ndata] = xpos; ydata[ndata] = ypos; disizes[ndata] = disize; rdisizes[ndata] = size; rx[ndata] = (gdouble)xpos*oxreal/(gdouble)oxres; ry[ndata] = (gdouble)ypos*oyreal/(gdouble)oyres; rz[ndata] = 2.0*gwy_data_field_get_val(lfield, xpos, ypos) + rdisizes[ndata]; ndata++; xpos = oxres/2 + 2*disize; ypos = oyres/2; xdata[ndata] = xpos; ydata[ndata] = ypos; disizes[ndata] = disize; rdisizes[ndata] = size; rx[ndata] = (gdouble)xpos*oxreal/(gdouble)oxres; ry[ndata] = (gdouble)ypos*oyreal/(gdouble)oyres; rz[ndata] = 2.0*gwy_data_field_get_val(lfield, xpos, ypos) + rdisizes[ndata]; ndata++; */ /*end of test*/ i = 0; presetval = args->coverage*10; while (ndata < presetval && i<max) { //disize = mdisize*(0.8+(double)(rand()%20)/40.0); disize = mdisize; xpos = disize+(rand()%(xres-2*(gint)(disize+1))) + 1; ypos = disize+(rand()%(yres-2*(gint)(disize+1))) + 1; i++; { too_close = 0; /*sync real to integer positions*/ for (k=0; k<ndata; k++) { if (((xpos-xdata[k])*(xpos-xdata[k]) + (ypos-ydata[k])*(ypos-ydata[k]))<(4*disize*disize)) { too_close = 1; break; } } if (too_close) continue; if (ndata>=10000) { break; } xdata[ndata] = xpos; ydata[ndata] = ypos; disizes[ndata] = disize; rdisizes[ndata] = size; rx[ndata] = (gdouble)xpos*oxreal/(gdouble)oxres; ry[ndata] = (gdouble)ypos*oyreal/(gdouble)oyres; //printf("surface at %g, particle size %g\n", gwy_data_field_get_val(lfield, xpos, ypos), rdisizes[ndata]); rz[ndata] = 1.0*gwy_data_field_get_val(lfield, xpos, ypos) + rdisizes[ndata]; //2 ndata++; } }; // if (i==max) printf("Maximum reached, only %d particles depositd instead of %d\n", ndata, presetval); // else printf("%d particles depositd\n", ndata); /*refresh shown data and integer positions (necessary in md calculation)*/ gwy_data_field_copy(zlfield, lfield, 0); showit(lfield, zdfield, rdisizes, rx, ry, rz, xdata, ydata, ndata, oxres, oxreal, oyres, oyreal, add, xres, yres); gwy_data_field_area_copy(lfield, dfield, add, add, oxres, oyres, 0, 0); gwy_data_field_data_changed(dfield); for (i=0; i<(20*args->revise); i++) { // printf("###### step %d of %d ##########\n", i, (gint)(20*args->revise)); /*try to add some particles if necessary, do this only for first half of molecular dynamics*/ if (ndata<presetval && i<(10*args->revise)) { ii = 0; nloc = 0; while (ndata < presetval && ii<(max/1000) && nloc<maxloc) { disize = mdisize; xpos = disize+(rand()%(xres-2*(gint)(disize+1))) + 1; ypos = disize+(rand()%(yres-2*(gint)(disize+1))) + 1; ii++; { too_close = 0; rxv = ((gdouble)xpos*oxreal/(gdouble)oxres); ryv = ((gdouble)ypos*oyreal/(gdouble)oyres); rzv = gwy_data_field_get_val(zlfield, xpos, ypos) + 5*size; for (k=0; k<ndata; k++) { if (((rxv-rx[k])*(rxv-rx[k]) + (ryv-ry[k])*(ryv-ry[k]) + (rzv-rz[k])*(rzv-rz[k]))<(4.0*size*size)) { too_close = 1; break; } } if (too_close) continue; if (ndata>=10000) { // printf("Maximum reached!\n"); break; } xdata[ndata] = xpos; ydata[ndata] = ypos; disizes[ndata] = disize; rdisizes[ndata] = size; rx[ndata] = rxv; ry[ndata] = ryv; rz[ndata] = rzv; vz[ndata] = -0.01; ndata++; nloc++; } }; // if (ii==(max/100)) printf("Maximum reached, only %d particles now present instead of %d\n", ndata, presetval); // else printf("%d particles now at surface\n", ndata); } /*test succesive LJ steps on substrate (no relaxation)*/ for (k=0; k<ndata; k++) { fx[k] = fy[k] = fz[k] = 0; /*calculate forces for all particles on substrate*/ if (gwy_data_field_rtoi(lfield, rx[k])<0 || gwy_data_field_rtoj(lfield, ry[k])<0 || gwy_data_field_rtoi(lfield, rx[k])>=xres || gwy_data_field_rtoj(lfield, ry[k])>=yres) continue; for (m=0; m<ndata; m++) { if (m==k) continue; // printf("(%g %g %g) on (%g %g %g)\n", rx[m], ry[m], rz[m], rx[k], ry[k], rz[k]); fx[k] -= (get_lj_potential_spheres(rx[m], ry[m], rz[m], rx[k]+diff, ry[k], rz[k], gwy_data_field_itor(dfield, disizes[k])) -get_lj_potential_spheres(rx[m], ry[m], rz[m], rx[k]-diff, ry[k], rz[k], gwy_data_field_itor(dfield, disizes[k])))/2/diff; fy[k] -= (get_lj_potential_spheres(rx[m], ry[m], rz[m], rx[k], ry[k]+diff, rz[k], gwy_data_field_itor(dfield, disizes[k])) -get_lj_potential_spheres(rx[m], ry[m], rz[m], rx[k], ry[k]-diff, rz[k], gwy_data_field_itor(dfield, disizes[k])))/2/diff; fz[k] -= (get_lj_potential_spheres(rx[m], ry[m], rz[m], rx[k], ry[k], rz[k]+diff, gwy_data_field_itor(dfield, disizes[k])) -get_lj_potential_spheres(rx[m], ry[m], rz[m], rx[k], ry[k], rz[k]-diff, gwy_data_field_itor(dfield, disizes[k])))/2/diff; } fx[k] -= (integrate_lj_substrate(zlfield, rx[k]+diff, ry[k], rz[k], rdisizes[k]) - integrate_lj_substrate(zlfield, rx[k]-diff, ry[k], rz[k], rdisizes[k]))/2/diff; fy[k] -= (integrate_lj_substrate(zlfield, rx[k], ry[k]-diff, rz[k], rdisizes[k]) - integrate_lj_substrate(zlfield, rx[k], ry[k]+diff, rz[k], rdisizes[k]))/2/diff; fz[k] -= (integrate_lj_substrate(zlfield, rx[k], ry[k], rz[k]+diff, rdisizes[k]) - integrate_lj_substrate(zlfield, rx[k], ry[k], rz[k]-diff, rdisizes[k]))/2/diff; } for (k=0; k<ndata; k++) { if (gwy_data_field_rtoi(lfield, rx[k])<0 || gwy_data_field_rtoj(lfield, ry[k])<0 || gwy_data_field_rtoi(lfield, rx[k])>=xres || gwy_data_field_rtoj(lfield, ry[k])>=yres) continue; /*move all particles*/ rx[k] += vx[k]*timestep + 0.5*ax[k]*timestep*timestep; vx[k] += 0.5*ax[k]*timestep; ax[k] = fx[k]/mass; vx[k] += 0.5*ax[k]*timestep; vx[k] *= 0.9; if (fabs(vx[k])>0.01) vx[k] = 0; //0.2 ry[k] += vy[k]*timestep + 0.5*ay[k]*timestep*timestep; vy[k] += 0.5*ay[k]*timestep; ay[k] = fy[k]/mass; vy[k] += 0.5*ay[k]*timestep; vy[k] *= 0.9; if (fabs(vy[k])>0.01) vy[k] = 0; //0.2 rz[k] += vz[k]*timestep + 0.5*az[k]*timestep*timestep; vz[k] += 0.5*az[k]*timestep; az[k] = fz[k]/mass; vz[k] += 0.5*az[k]*timestep; vz[k] *= 0.9; if (fabs(vz[k])>0.01) vz[k] = 0; if (rx[k]<=gwy_data_field_itor(dfield, disizes[k])) rx[k] = gwy_data_field_itor(dfield, disizes[k]); if (ry[k]<=gwy_data_field_itor(dfield, disizes[k])) ry[k] = gwy_data_field_itor(dfield, disizes[k]); if (rx[k]>=(xreal-gwy_data_field_itor(dfield, disizes[k]))) rx[k] = xreal-gwy_data_field_itor(dfield, disizes[k]); if (ry[k]>=(yreal-gwy_data_field_itor(dfield, disizes[k]))) ry[k] = yreal-gwy_data_field_itor(dfield, disizes[k]); } gwy_data_field_copy(zlfield, lfield, 0); showit(lfield, zdfield, rdisizes, rx, ry, rz, xdata, ydata, ndata, oxres, oxreal, oyres, oyreal, add, xres, yres); gwy_data_field_area_copy(lfield, dfield, add, add, oxres, oyres, 0, 0); gwy_data_field_data_changed(dfield); while (gtk_events_pending()) gtk_main_iteration(); } gwy_data_field_area_copy(lfield, dfield, add, add, oxres, oyres, 0, 0); gwy_data_field_data_changed(dfield); args->computed = TRUE; gwy_object_unref(lfield); gwy_object_unref(zlfield); gwy_object_unref(zdfield); }
static void rotate(GwyContainer *data, GwyRunType run) { GwyDataField *dfields[3]; GQuark quark; gint oldid, newid; RotateArgs args; gboolean ok; g_return_if_fail(run & ROTATE_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, dfields + 0, GWY_APP_MASK_FIELD, dfields + 1, GWY_APP_SHOW_FIELD, dfields + 2, GWY_APP_DATA_FIELD_ID, &oldid, 0); g_return_if_fail(dfields[0]); rotate_load_args(gwy_app_settings_get(), &args); if (run == GWY_RUN_INTERACTIVE) { ok = rotate_dialog(&args, data); rotate_save_args(gwy_app_settings_get(), &args); if (!ok) return; } dfields[0] = gwy_data_field_duplicate(dfields[0]); rotate_datafield(dfields[0], &args); if (dfields[1]) { GwyInterpolationType interp = args.interp; dfields[1] = gwy_data_field_duplicate(dfields[1]); args.interp = GWY_INTERPOLATION_ROUND; rotate_datafield(dfields[1], &args); args.interp = interp; } if (dfields[2]) { dfields[2] = gwy_data_field_duplicate(dfields[2]); rotate_datafield(dfields[2], &args); } newid = gwy_app_data_browser_add_data_field(dfields[0], data, TRUE); g_object_unref(dfields[0]); gwy_app_sync_data_items(data, data, oldid, newid, FALSE, GWY_DATA_ITEM_GRADIENT, GWY_DATA_ITEM_RANGE, GWY_DATA_ITEM_MASK_COLOR, 0); if (dfields[1]) { quark = gwy_app_get_mask_key_for_id(newid); gwy_container_set_object(data, quark, dfields[1]); g_object_unref(dfields[1]); } if (dfields[2]) { quark = gwy_app_get_show_key_for_id(newid); gwy_container_set_object(data, quark, dfields[2]); g_object_unref(dfields[2]); } gwy_app_set_data_field_title(data, newid, _("Rotated Data")); gwy_app_channel_log_add_proc(data, oldid, newid); }
static void square_samples(GwyContainer *data, GwyRunType run) { GwyDataField *dfield, *dfields[3]; gdouble xreal, yreal, qx, qy; gint oldid, newid, xres, yres; GQuark quark; g_return_if_fail(run & BASICOPS_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, dfields + 0, GWY_APP_MASK_FIELD, dfields + 1, GWY_APP_SHOW_FIELD, dfields + 2, GWY_APP_DATA_FIELD_ID, &oldid, 0); dfield = dfields[0]; xres = gwy_data_field_get_xres(dfield); yres = gwy_data_field_get_yres(dfield); xreal = gwy_data_field_get_xreal(dfield); yreal = gwy_data_field_get_yreal(dfield); qx = xres/xreal; qy = yres/yreal; if (fabs(log(qx/qy)) > 1.0/hypot(xres, yres)) { /* Resample */ if (qx < qy) xres = MAX(GWY_ROUND(xreal*qy), 1); else yres = MAX(GWY_ROUND(yreal*qx), 1); dfields[0] = gwy_data_field_new_resampled(dfields[0], xres, yres, GWY_INTERPOLATION_BSPLINE); if (dfields[1]) { dfields[1] = gwy_data_field_new_resampled(dfields[1], xres, yres, GWY_INTERPOLATION_ROUND); } if (dfields[2]) { dfields[2] = gwy_data_field_new_resampled(dfields[2], xres, yres, GWY_INTERPOLATION_BSPLINE); } } else { /* Ratios are equal, just duplicate */ dfields[0] = gwy_data_field_duplicate(dfields[0]); if (dfields[1]) dfields[1] = gwy_data_field_duplicate(dfields[1]); if (dfields[2]) dfields[2] = gwy_data_field_duplicate(dfields[2]); } newid = gwy_app_data_browser_add_data_field(dfields[0], data, TRUE); g_object_unref(dfields[0]); gwy_app_sync_data_items(data, data, oldid, newid, FALSE, GWY_DATA_ITEM_GRADIENT, GWY_DATA_ITEM_RANGE, GWY_DATA_ITEM_MASK_COLOR, 0); if (dfields[1]) { quark = gwy_app_get_mask_key_for_id(newid); gwy_container_set_object(data, quark, dfields[1]); g_object_unref(dfields[1]); } if (dfields[2]) { quark = gwy_app_get_show_key_for_id(newid); gwy_container_set_object(data, quark, dfields[2]); g_object_unref(dfields[2]); } gwy_app_channel_log_add_proc(data, oldid, newid); }
/** * proc_plugin_proxy_run: * @data: A data container. * @run: Run mode. * @name: Plug-in name (i.e. data processing function) to run. * * The plug-in proxy itself, runs plug-in @name on @data. * * Returns: Whether it succeeded running the plug-in. **/ static void proc_plugin_proxy_run(GwyContainer *data, GwyRunType run, const gchar *name) { ProcPluginInfo *info; GwyContainer *newdata; gchar *filename, *buffer = NULL; GError *err = NULL; gint exit_status, id, newid; gsize size = 0; FILE *fh; gchar *args[] = { NULL, "run", NULL, NULL, NULL }; GQuark dquark, mquark, squark; gboolean ok; gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD_KEY, &dquark, GWY_APP_MASK_FIELD_KEY, &mquark, GWY_APP_DATA_FIELD_ID, &id, 0); gwy_debug("called as %s with run mode %d", name, run); if (!(info = proc_find_plugin(name, run))) return; fh = text_dump_export(data, dquark, mquark, &filename, NULL); g_return_if_fail(fh); args[0] = info->file; args[2] = g_strdup(gwy_enum_to_string(run, run_mode_names, -1)); args[3] = decode_glib_encoded_filename(filename); gwy_debug("%s %s %s %s", args[0], args[1], args[2], args[3]); ok = g_spawn_sync(NULL, args, NULL, 0, NULL, NULL, NULL, NULL, &exit_status, &err); if (!err) ok &= g_file_get_contents(filename, &buffer, &size, &err); g_unlink(filename); fclose(fh); gwy_debug("ok = %d, exit_status = %d, err = %p", ok, exit_status, err); ok &= !exit_status; if (ok && (newdata = text_dump_import(buffer, size, NULL))) { GwyDataField *dfield; /* Merge data */ if (gwy_container_gis_object_by_name(newdata, "/0/data", &dfield)) g_object_ref(dfield); else { dfield = gwy_container_get_object(data, dquark); dfield = gwy_data_field_duplicate(dfield); } newid = gwy_app_data_browser_add_data_field(dfield, data, TRUE); /* Merge mask */ if (gwy_container_gis_object_by_name(newdata, "/0/mask", &dfield)) g_object_ref(dfield); else if (gwy_container_gis_object(data, mquark, &dfield)) dfield = gwy_data_field_duplicate(dfield); else dfield = NULL; if (dfield) { mquark = gwy_app_get_mask_key_for_id(newid); gwy_container_set_object(data, mquark, dfield); g_object_unref(dfield); } /* Merge presentation */ if (gwy_container_gis_object_by_name(newdata, "/0/show", &dfield)) { squark = gwy_app_get_show_key_for_id(newid); gwy_container_set_object(data, squark, dfield); } /* Merge stuff. XXX: This is brutal and incomplete. */ gwy_app_sync_data_items(data, data, id, newid, FALSE, GWY_DATA_ITEM_GRADIENT, GWY_DATA_ITEM_RANGE_TYPE, GWY_DATA_ITEM_MASK_COLOR, GWY_DATA_ITEM_REAL_SQUARE, 0); gwy_app_sync_data_items(newdata, data, 0, newid, FALSE, GWY_DATA_ITEM_GRADIENT, GWY_DATA_ITEM_RANGE_TYPE, 0); g_object_unref(newdata); } else { g_warning("Cannot run plug-in %s: %s", info->file, err ? err->message : "it returned garbage."); } g_free(args[3]); g_free(args[2]); g_clear_error(&err); g_free(buffer); g_free(filename); }
static void dwt_denoise(GwyContainer *data, GwyRunType run) { GtkWidget *dialog; GwyDataField *dfield; GwyDataLine *wtcoefs; DWTDenoiseArgs args; gboolean ok; gint xsize, ysize, newsize; gint oldid, newid; g_return_if_fail(run & DWT_DENOISE_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD, &dfield, GWY_APP_DATA_FIELD_ID, &oldid, 0); g_return_if_fail(dfield); xsize = gwy_data_field_get_xres(dfield); ysize = gwy_data_field_get_yres(dfield); if (xsize != ysize) { dialog = gtk_message_dialog_new (GTK_WINDOW(gwy_app_data_window_get_current()), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, _("%s: Data must be square."), _("DWT Denoise")); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); return; } dwt_denoise_load_args(gwy_app_settings_get(), &args); if (run == GWY_RUN_INTERACTIVE) { ok = dwt_denoise_dialog(&args); dwt_denoise_save_args(gwy_app_settings_get(), &args); if (!ok) return; } dfield = gwy_data_field_duplicate(dfield); newsize = gwy_fft_find_nice_size(xsize); gwy_data_field_add(dfield, -gwy_data_field_get_avg(dfield)); gwy_data_field_resample(dfield, newsize, newsize, GWY_INTERPOLATION_BILINEAR); wtcoefs = gwy_data_line_new(10, 10, TRUE); wtcoefs = gwy_dwt_set_coefficients(wtcoefs, args.wavelet); gwy_data_field_dwt_denoise(dfield, wtcoefs, TRUE, 20, args.method); if (args.preserve) gwy_data_field_resample(dfield, xsize, ysize, args.interp); newid = gwy_app_data_browser_add_data_field(dfield, data, TRUE); gwy_app_copy_data_items(data, data, oldid, newid, GWY_DATA_ITEM_GRADIENT, GWY_DATA_ITEM_MASK_COLOR, 0); g_object_unref(dfield); gwy_app_set_data_field_title(data, newid, _("DWT denoised")); g_object_unref(wtcoefs); }
static void deposit_dialog(DepositArgs *args, GwyContainer *data, GwyDataField *dfield, gint id) { GtkWidget *dialog, *table, *hbox, *label, *pivot; DepositControls controls; gint response; GwyPixmapLayer *layer; gint row, newid; GwyDataField *rfield; controls.args = args; dialog = gtk_dialog_new_with_buttons(_("Deposit spherical particles"), NULL, 0, NULL); gtk_dialog_add_action_widget(GTK_DIALOG(dialog), gwy_stock_like_button_new(_("_Start"), GTK_STOCK_EXECUTE), RESPONSE_PREVIEW); gtk_dialog_add_button(GTK_DIALOG(dialog), _("_Reset"), RESPONSE_RESET); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK); gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); controls.dialog = dialog; hbox = gtk_hbox_new(FALSE, 2); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, FALSE, 4); controls.mydata = gwy_container_duplicate_by_prefix(data, "/0/data/", "/0/base/palette", "/0/base/range-type", "/0/base/", NULL); gwy_container_set_object_by_name(controls.mydata, "/0/data", gwy_data_field_duplicate(dfield)); controls.old_dfield = gwy_data_field_duplicate(dfield); controls.view = gwy_data_view_new(controls.mydata); layer = gwy_layer_basic_new(); g_object_set(layer, "data-key", "/0/data", "gradient-key", "/0/base/palette", "range-type-key", "/0/base/range-type", "min-max-key", "/0/base", NULL); gwy_data_view_set_data_prefix(GWY_DATA_VIEW(controls.view), "/0/data"); gwy_data_view_set_base_layer(GWY_DATA_VIEW(controls.view), layer); gwy_set_data_preview_size(GWY_DATA_VIEW(controls.view), PREVIEW_SIZE); gtk_box_pack_start(GTK_BOX(hbox), controls.view, FALSE, FALSE, 4); table = gtk_table_new(10, 4, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 2); gtk_table_set_col_spacings(GTK_TABLE(table), 6); gtk_container_set_border_width(GTK_CONTAINER(table), 4); gtk_box_pack_start(GTK_BOX(hbox), table, TRUE, TRUE, 4); row = 0; gtk_table_attach(GTK_TABLE(table), gwy_label_new_header(_("Deposition parameters:")), 0, 3, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; table_attach_threshold(table, &row, _("_Size"), &controls.size, args->size, &controls); pivot = gwy_table_hscale_get_scale(controls.size); controls.value_size = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.value_size), 1.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.value_size, 2, 3, row, row+1, GTK_FILL, 0, 0, 0); g_signal_connect_swapped(controls.size, "value-changed", G_CALLBACK(update_threshold_size), &controls); gwy_widget_sync_sensitivity(pivot, controls.value_size); controls.format_size = gwy_data_field_get_value_format_z(dfield, GWY_SI_UNIT_FORMAT_VFMARKUP, NULL); label = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_label_set_markup(GTK_LABEL(label), controls.format_size->units); gtk_table_attach(GTK_TABLE(table), label, 3, 4, row, row+1, GTK_FILL, 0, 0, 0); gwy_widget_sync_sensitivity(pivot, label); gtk_table_set_row_spacing(GTK_TABLE(table), row, 8); row++; /* table_attach_threshold(table, &row, _("_Distribution width"), &controls.width, args->width, &controls); pivot = gwy_table_hscale_get_scale(controls.width); controls.value_width = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.value_width), 1.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.value_width, 2, 3, row, row+1, GTK_FILL, 0, 0, 0); g_signal_connect_swapped(controls.width, "value-changed", G_CALLBACK(update_threshold_width), &controls); gwy_widget_sync_sensitivity(pivot, controls.value_width); controls.format_width = gwy_data_field_get_value_format_z(dfield, GWY_SI_UNIT_FORMAT_VFMARKUP, NULL); label = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_label_set_markup(GTK_LABEL(label), controls.format_width->units); gtk_table_attach(GTK_TABLE(table), label, 3, 4, row, row+1, GTK_FILL, 0, 0, 0); gwy_widget_sync_sensitivity(pivot, label); gtk_table_set_row_spacing(GTK_TABLE(table), row, 8); row++; */ table_attach_threshold(table, &row, _("_Coverage:"), &controls.coverage, args->coverage, &controls); table_attach_threshold(table, &row, _("_Revise after settle"), &controls.revise, args->revise, &controls); gtk_table_set_row_spacing(GTK_TABLE(table), row-1, 8); deposit_invalidate(&controls); update_threshold_size(&controls); //update_threshold_width(&controls); /* finished initializing, allow instant updates */ controls.in_init = FALSE; /* show initial preview if instant updates are on */ gtk_widget_show_all(dialog); do { response = gtk_dialog_run(GTK_DIALOG(dialog)); switch (response) { case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_DELETE_EVENT: deposit_dialog_update_values(&controls, args); gtk_widget_destroy(dialog); case GTK_RESPONSE_NONE: g_object_unref(controls.mydata); gwy_si_unit_value_format_free(controls.format_size); //gwy_si_unit_value_format_free(controls.format_width); return; break; case GTK_RESPONSE_OK: break; case RESPONSE_RESET: *args = deposit_defaults; deposit_dialog_update_controls(&controls, args); controls.in_init = TRUE; preview(&controls, args); controls.in_init = FALSE; break; case RESPONSE_PREVIEW: deposit_dialog_update_values(&controls, args); preview(&controls, args); break; default: g_assert_not_reached(); break; } } while (response != GTK_RESPONSE_OK); deposit_dialog_update_values(&controls, args); gwy_app_sync_data_items(controls.mydata, data, 0, id, FALSE, GWY_DATA_ITEM_MASK_COLOR, 0); gtk_widget_destroy(dialog); gwy_si_unit_value_format_free(controls.format_size); //gwy_si_unit_value_format_free(controls.format_width); if (args->computed) { rfield = gwy_container_get_object_by_name(controls.mydata, "/0/data"); newid = gwy_app_data_browser_add_data_field(rfield, data, TRUE); gwy_app_sync_data_items(data, data, id, newid, FALSE, GWY_DATA_ITEM_GRADIENT, GWY_DATA_ITEM_MASK_COLOR, GWY_DATA_ITEM_REAL_SQUARE, GWY_DATA_ITEM_SELECTIONS, 0); gwy_app_set_data_field_title(data, newid, _("Particles")); g_object_unref(controls.mydata); } }
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 void do_level(GwyContainer *data, GwyRunType run, LevelMethod level_type, const gchar *dialog_title) { GwyDataField *dfield; GwyDataField *mfield; LevelArgs args; gdouble c, bx, by; GQuark quark; gint id; g_return_if_fail(run & LEVEL_RUN_MODES); gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD_KEY, &quark, GWY_APP_DATA_FIELD, &dfield, GWY_APP_DATA_FIELD_ID, &id, GWY_APP_MASK_FIELD, &mfield, 0); g_return_if_fail(dfield && quark); load_args(gwy_app_settings_get(), &args); if (run != GWY_RUN_IMMEDIATE && mfield) { gboolean ok = level_dialog(&args, dialog_title); save_args(gwy_app_settings_get(), &args); if (!ok) return; } if (args.masking == GWY_MASK_IGNORE) mfield = NULL; if (mfield) { if (args.masking == GWY_MASK_EXCLUDE) { mfield = gwy_data_field_duplicate(mfield); gwy_data_field_multiply(mfield, -1.0); gwy_data_field_add(mfield, 1.0); } else g_object_ref(mfield); } gwy_app_undo_qcheckpoint(data, quark, NULL); if (mfield) gwy_data_field_area_fit_plane(dfield, mfield, 0, 0, gwy_data_field_get_xres(dfield), gwy_data_field_get_yres(dfield), &c, &bx, &by); else gwy_data_field_fit_plane(dfield, &c, &bx, &by); switch (level_type) { case LEVEL_SUBTRACT: c = -0.5*(bx*gwy_data_field_get_xres(dfield) + by*gwy_data_field_get_yres(dfield)); gwy_data_field_plane_level(dfield, c, bx, by); break; case LEVEL_ROTATE: bx = gwy_data_field_rtoj(dfield, bx); by = gwy_data_field_rtoi(dfield, by); gwy_data_field_plane_rotate(dfield, atan2(bx, 1), atan2(by, 1), GWY_INTERPOLATION_LINEAR); gwy_debug("b = %g, alpha = %g deg, c = %g, beta = %g deg", bx, 180/G_PI*atan2(bx, 1), by, 180/G_PI*atan2(by, 1)); break; default: g_assert_not_reached(); break; } gwy_app_channel_log_add_proc(data, id, id); gwy_data_field_data_changed(dfield); gwy_object_unref(mfield); }
static void run_noninteractive(NoiseSynthArgs *args, const GwyDimensionArgs *dimsargs, GwyContainer *data, GwyDataField *dfield, gint oldid, GQuark quark) { GwySIUnit *siunit; gboolean replace = dimsargs->replace && dfield; gboolean add = dimsargs->add && dfield; gint newid; if (args->randomize) args->seed = g_random_int() & 0x7fffffff; if (replace) { /* Always take a reference so that we can always unref. */ g_object_ref(dfield); gwy_app_undo_qcheckpointv(data, 1, &quark); if (!add) gwy_data_field_clear(dfield); gwy_app_channel_log_add_proc(data, oldid, oldid); } else { if (add) dfield = gwy_data_field_duplicate(dfield); else { gdouble mag = pow10(dimsargs->xypow10) * dimsargs->measure; dfield = gwy_data_field_new(dimsargs->xres, dimsargs->yres, mag*dimsargs->xres, mag*dimsargs->yres, TRUE); siunit = gwy_data_field_get_si_unit_xy(dfield); gwy_si_unit_set_from_string(siunit, dimsargs->xyunits); siunit = gwy_data_field_get_si_unit_z(dfield); gwy_si_unit_set_from_string(siunit, dimsargs->zunits); } } noise_synth_do(args, dimsargs, dfield); if (replace) gwy_data_field_data_changed(dfield); else { if (data) { newid = gwy_app_data_browser_add_data_field(dfield, data, TRUE); if (oldid != -1) gwy_app_sync_data_items(data, data, oldid, newid, FALSE, GWY_DATA_ITEM_GRADIENT, 0); } else { newid = 0; data = gwy_container_new(); gwy_container_set_object(data, gwy_app_get_data_key_for_id(newid), dfield); gwy_app_data_browser_add(data); gwy_app_data_browser_reset_visibility(data, GWY_VISIBILITY_RESET_SHOW_ALL); g_object_unref(data); } gwy_app_set_data_field_title(data, newid, _("Generated")); gwy_app_channel_log_add_proc(data, add ? oldid : -1, newid); } g_object_unref(dfield); }