static gboolean prepare_fields(GwyDataField *tipfield, GwyDataField *surface, gint xres, gint yres) { gint xoldres, yoldres; /*set real sizes corresponding to actual data*/ gwy_data_field_set_xreal(tipfield, gwy_data_field_get_xmeasure(surface) *gwy_data_field_get_xres(tipfield)); gwy_data_field_set_yreal(tipfield, gwy_data_field_get_ymeasure(surface) *gwy_data_field_get_yres(tipfield)); /*if user has changed tip size, change it*/ if ((xres != gwy_data_field_get_xres(tipfield)) || (yres != gwy_data_field_get_yres(tipfield))) { xoldres = gwy_data_field_get_xres(tipfield); yoldres = gwy_data_field_get_yres(tipfield); gwy_data_field_resample(tipfield, xres, yres, GWY_INTERPOLATION_NONE); gwy_data_field_set_xreal(tipfield, gwy_data_field_get_xreal(tipfield) /xoldres*xres); gwy_data_field_set_yreal(tipfield, gwy_data_field_get_yreal(tipfield) /yoldres*yres); gwy_data_field_clear(tipfield); return FALSE; } return TRUE; }
static void line_correct_step(GwyContainer *data, GwyRunType run) { GwyDataField *dfield, *mask; 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); gwy_data_field_absdiff_line_correct(dfield); mask = gwy_data_field_new_alike(dfield, TRUE); line_correct_step_iter(dfield, mask); gwy_data_field_clear(mask); line_correct_step_iter(dfield, mask); g_object_unref(mask); gwy_data_field_filter_conservative(dfield, 5); gwy_data_field_data_changed(dfield); }
static void facet_view_recompute(GtkAdjustment *adj, FacetsControls *controls) { GwyVectorLayer *layer; GwyDataField *dfield; GwySelection *selection; const gchar *key; controls->args->kernel_size = gwy_adjustment_get_int(adj); gwy_app_wait_cursor_start(GTK_WINDOW(controls->dialog)); dfield = gwy_container_get_object_by_name(controls->mydata, "/0/data"); gwy_data_field_facet_distribution(dfield, 2*controls->args->kernel_size + 1, controls->fdata); /* XXX: Clear selections since we cannot recalculate it properly */ if (gwy_container_gis_object_by_name(controls->mydata, "/0/mask", &dfield)) { gwy_data_field_clear(dfield); gwy_data_field_data_changed(dfield); } layer = gwy_data_view_get_top_layer(GWY_DATA_VIEW(controls->fview)); key = gwy_vector_layer_get_selection_key(layer); selection = gwy_container_get_object_by_name(controls->fdata, key); gwy_selection_clear(selection); gwy_app_wait_cursor_finish(GTK_WINDOW(controls->dialog)); facets_invalidate(controls); }
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 delta(GwyDataField *tip, gdouble height, G_GNUC_UNUSED gdouble radius, G_GNUC_UNUSED gdouble rotation, G_GNUC_UNUSED gdouble *params) { gwy_data_field_clear(tip); tip->data[tip->xres/2 + tip->xres*tip->yres/2] = height; }
static void reset(TipBlindControls *controls, TipBlindArgs *args) { GwyGraphModel *gmodel; gwy_data_field_clear(controls->tip); if (args->stripetips) { guint i; for (i = 0; i < controls->oldnstripes; i++) gwy_data_field_clear(args->stripetips[i]); } controls->good_tip = FALSE; gmodel = gwy_graph_model_new(); gwy_graph_set_model(GWY_GRAPH(controls->graph), gmodel); g_object_unref(gmodel); gtk_dialog_set_response_sensitive(GTK_DIALOG(controls->dialog), GTK_RESPONSE_OK, controls->good_tip); tip_update(controls); }
static void preview(NoiseSynthControls *controls) { NoiseSynthArgs *args = controls->args; GwyDataField *dfield; dfield = GWY_DATA_FIELD(gwy_container_get_object_by_name(controls->mydata, "/0/data")); if (controls->dims->args->add && controls->surface) gwy_data_field_copy(controls->surface, dfield, FALSE); else gwy_data_field_clear(dfield); noise_synth_do(args, controls->dims->args, dfield); gwy_data_field_data_changed(dfield); }
static void facet_view_reset_maximum(FacetsControls *controls) { GwyDataField *mask = NULL; FacetsArgs *args; args = controls->args; args->theta0 = gwy_container_get_double_by_name(controls->fdata, "/theta0"); args->phi0 = gwy_container_get_double_by_name(controls->fdata, "/phi0"); facet_view_select_angle(controls, args->theta0, args->phi0); gtk_label_set_text(GTK_LABEL(controls->mtheta_label), ""); gtk_label_set_text(GTK_LABEL(controls->mphi_label), ""); if (gwy_container_gis_object_by_name(controls->fdata, "/0/mask", &mask)) { gwy_data_field_clear(mask); gwy_data_field_data_changed(mask); } }
static void poly_level_update_preview(PolyLevelControls *controls, PolyLevelArgs *args) { GwyDataField *source, *leveled, *bg, *mask = NULL; gwy_container_gis_object_by_name(controls->data, "/source", &source); gwy_container_gis_object_by_name(controls->data, "/mask", &mask); gwy_container_gis_object_by_name(controls->data, "/0/data", &leveled); gwy_container_gis_object_by_name(controls->data, "/1/data", &bg); gwy_data_field_copy(source, leveled, FALSE); gwy_data_field_clear(bg); if (mask && args->masking != GWY_MASK_IGNORE) poly_level_do_with_mask(source, mask, leveled, bg, args); else if (args->independent) poly_level_do_independent(source, leveled, bg, args->col_degree, args->row_degree); else poly_level_do_maximum(source, leveled, bg, args->max_degree); }
static void tip_blind_dialog(TipBlindArgs *args) { GtkWidget *dialog, *table, *hbox, *vbox, *label; GwyContainer *data; GwyGraphModel *gmodel; GwyGraphArea *area; TipBlindControls controls; GwyPixmapLayer *layer; GwyDataField *dfield; GQuark quark; GwySIUnit *unit; gint response, row; dialog = gtk_dialog_new_with_buttons(_("Blind Tip Estimation"), NULL, 0, _("Run _Partial"), RESPONSE_ESTIMATE, _("Run _Full"), RESPONSE_REFINE, _("_Reset Tip"), RESPONSE_RESET, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); gwy_help_add_to_proc_dialog(GTK_DIALOG(dialog), GWY_HELP_DEFAULT); controls.args = args; controls.in_update = TRUE; controls.good_tip = FALSE; controls.dialog = dialog; gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), GTK_RESPONSE_OK, controls.good_tip); hbox = gtk_hbox_new(FALSE, 4); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, FALSE, 4); controls.vxres = 240; controls.vyres = 240; controls.oldnstripes = args->nstripes; /* set initial tip properties */ data = gwy_app_data_browser_get(args->source.datano); quark = gwy_app_get_data_key_for_id(args->source.id); dfield = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); controls.tip = gwy_data_field_new_alike(dfield, TRUE); gwy_data_field_resample(controls.tip, args->xres, args->yres, GWY_INTERPOLATION_NONE); gwy_data_field_clear(controls.tip); /* set up data of rescaled image of the tip */ controls.vtip = gwy_container_new(); gwy_app_sync_data_items(data, controls.vtip, args->source.id, 0, FALSE, GWY_DATA_ITEM_PALETTE, 0); dfield = gwy_data_field_new_alike(controls.tip, TRUE); gwy_data_field_resample(dfield, controls.vxres, controls.vyres, GWY_INTERPOLATION_ROUND); gwy_container_set_object_by_name(controls.vtip, "/0/data", dfield); g_object_unref(dfield); /* set up rescaled image of the tip */ vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 4); controls.view = gwy_data_view_new(controls.vtip); layer = gwy_layer_basic_new(); gwy_pixmap_layer_set_data_key(layer, "/0/data"); gwy_layer_basic_set_gradient_key(GWY_LAYER_BASIC(layer), "/0/base/palette"); gwy_data_view_set_base_layer(GWY_DATA_VIEW(controls.view), layer); /* set up tip estimation controls */ gtk_box_pack_start(GTK_BOX(vbox), controls.view, FALSE, FALSE, 0); gmodel = gwy_graph_model_new(); controls.graph = gwy_graph_new(gmodel); g_object_unref(gmodel); gwy_axis_set_visible(gwy_graph_get_axis(GWY_GRAPH(controls.graph), GTK_POS_LEFT), FALSE); gwy_axis_set_visible(gwy_graph_get_axis(GWY_GRAPH(controls.graph), GTK_POS_BOTTOM), FALSE); area = GWY_GRAPH_AREA(gwy_graph_get_area(GWY_GRAPH(controls.graph))); gtk_widget_set_no_show_all(gwy_graph_area_get_label(area), TRUE); g_signal_connect_after(gwy_graph_area_get_label(area), "map", G_CALLBACK(gtk_widget_hide), NULL); gtk_box_pack_start(GTK_BOX(vbox), controls.graph, TRUE, TRUE, 0); table = gtk_table_new(13, 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, FALSE, FALSE, 4); row = 0; controls.data = gwy_data_chooser_new_channels(); gwy_data_chooser_set_filter(GWY_DATA_CHOOSER(controls.data), tip_blind_source_filter, &args->orig, NULL); gwy_data_chooser_set_active_id(GWY_DATA_CHOOSER(controls.data), &args->source); g_signal_connect(controls.data, "changed", G_CALLBACK(data_changed), &args->source); gwy_table_attach_hscale(table, row, _("Related _data:"), NULL, GTK_OBJECT(controls.data), GWY_HSCALE_WIDGET); gtk_table_set_row_spacing(GTK_TABLE(table), row, 8); row++; label = gtk_label_new(_("Estimated Tip Size")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 4, row, row+1, GTK_FILL, 0, 0, 0); row++; controls.xres = gtk_adjustment_new(args->xres, MIN_RES, MAX_RES, 1, 10, 0); gwy_table_attach_hscale(table, row, _("_Width:"), "px", controls.xres, 0); g_object_set_data(G_OBJECT(controls.xres), "controls", &controls); g_signal_connect(controls.xres, "value-changed", G_CALLBACK(width_changed), &controls); row++; controls.yres = gtk_adjustment_new(args->yres, MIN_RES, MAX_RES, 1, 10, 0); gwy_table_attach_hscale(table, row, _("_Height:"), "px", controls.yres, 0); g_object_set_data(G_OBJECT(controls.yres), "controls", &controls); g_signal_connect(controls.yres, "value-changed", G_CALLBACK(height_changed), &controls); row++; controls.same_resolution = gtk_check_button_new_with_mnemonic(_("_Same resolution")); gtk_table_attach(GTK_TABLE(table), controls.same_resolution, 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.same_resolution), args->same_resolution); g_signal_connect(controls.same_resolution, "toggled", G_CALLBACK(same_resolution_changed), &controls); gtk_table_set_row_spacing(GTK_TABLE(table), row, 8); row++; gtk_table_attach(GTK_TABLE(table), gwy_label_new_header(_("Options")), 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; controls.threshold = gtk_adjustment_new(1.0, 0.01, 1000.0, 0.01, 1.0, 0.0); controls.threshold_spin = gtk_spin_button_new(GTK_ADJUSTMENT(controls.threshold), 0.1, 2); gtk_table_attach(GTK_TABLE(table), controls.threshold_spin, 2, 3, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); label = gtk_label_new_with_mnemonic(_("Noise suppression t_hreshold:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_label_set_mnemonic_widget(GTK_LABEL(label), controls.threshold_spin); gtk_table_attach(GTK_TABLE(table), label, 0, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); unit = gwy_data_field_get_si_unit_z(dfield); controls.threshold_unit = gwy_combo_box_metric_unit_new(G_CALLBACK(thresh_changed), &controls, -12, -3, unit, -9); gtk_table_attach(GTK_TABLE(table), controls.threshold_unit, 3, 4, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); g_signal_connect(controls.threshold, "value-changed", G_CALLBACK(thresh_changed), &controls); sci_entry_set_value(GTK_ADJUSTMENT(controls.threshold), GTK_COMBO_BOX(controls.threshold_unit), args->thresh); row++; controls.boundaries = gtk_check_button_new_with_mnemonic(_("Use _boundaries")); gtk_table_attach(GTK_TABLE(table), controls.boundaries, 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.boundaries), args->use_boundaries); g_signal_connect(controls.boundaries, "toggled", G_CALLBACK(bound_changed), args); gtk_table_set_row_spacing(GTK_TABLE(table), row, 8); row++; gtk_table_attach(GTK_TABLE(table), gwy_label_new_header(_("Stripes")), 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; controls.nstripes = gtk_adjustment_new(args->nstripes, MIN_STRIPES, MAX_STRIPES, 1, 10, 0); gwy_table_attach_hscale(table, row, _("_Split to stripes:"), NULL, controls.nstripes, GWY_HSCALE_CHECK); controls.split_to_stripes = gwy_table_hscale_get_check(controls.nstripes); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.split_to_stripes), !args->split_to_stripes); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.split_to_stripes), args->split_to_stripes); g_signal_connect(controls.split_to_stripes, "toggled", G_CALLBACK(split_to_stripes_changed), &controls); g_signal_connect(controls.nstripes, "value-changed", G_CALLBACK(nstripes_changed), &controls); row++; controls.stripeno = gtk_adjustment_new(1, 1, args->nstripes, 1, 10, 0); gwy_table_attach_hscale(table, row, _("_Preview stripe:"), NULL, controls.stripeno, GWY_HSCALE_DEFAULT); g_signal_connect(controls.stripeno, "value-changed", G_CALLBACK(stripeno_changed), &controls); row++; controls.plot_size_graph = gtk_check_button_new_with_mnemonic(_("Plot size _graph")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.plot_size_graph), args->plot_size_graph); gtk_table_attach(GTK_TABLE(table), controls.plot_size_graph, 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); g_signal_connect(controls.plot_size_graph, "toggled", G_CALLBACK(plot_size_graph_changed), &controls); row++; controls.create_images = gtk_check_button_new_with_mnemonic(_("Create tip i_mages")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(controls.create_images), args->create_images); gtk_table_attach(GTK_TABLE(table), controls.create_images, 0, 4, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); g_signal_connect(controls.create_images, "toggled", G_CALLBACK(create_images_changed), &controls); row++; controls.tipdone = FALSE; controls.in_update = FALSE; split_to_stripes_changed(GTK_TOGGLE_BUTTON(controls.split_to_stripes), &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: gtk_widget_destroy(dialog); case GTK_RESPONSE_NONE: tip_blind_dialog_abandon(&controls); tip_blind_save_args(gwy_app_settings_get(), args); return; break; case GTK_RESPONSE_OK: tip_blind_save_args(gwy_app_settings_get(), args); tip_blind_do(&controls, args); break; case RESPONSE_RESET: reset(&controls, args); break; case RESPONSE_ESTIMATE: tip_blind_run(&controls, args, FALSE); break; case RESPONSE_REFINE: tip_blind_run(&controls, args, TRUE); break; default: g_assert_not_reached(); break; } } while (response != GTK_RESPONSE_OK); gtk_widget_destroy(dialog); tip_blind_dialog_abandon(&controls); return; }
static GwyContainer* zeiss_load_tiff(const GwyTIFF *tiff, GError **error) { GwyContainer *container = NULL, *meta = NULL; GwyDataField *dfield; GwySIUnit *siunit; GwyTIFFImageReader *reader = NULL; GHashTable *hash = NULL; gint i, power10; gchar *value, *end, *comment = NULL; gdouble *data; gboolean new_file; double factor, dx; /* Comment with parameters is common for all data fields */ if (!gwy_tiff_get_string0(tiff, ZEISS_HEADER_TAG, &comment)) { err_FILE_TYPE(error, "Carl Zeiss SEM"); goto fail; } if (strstr(comment, MAGIC_COMMENT)) new_file = TRUE; else if (g_str_has_prefix(comment, SOMEWHAT_LESS_MAGIC_COMMENT)) new_file = FALSE; else { err_FILE_TYPE(error, "Carl Zeiss SEM"); goto fail; } /* Read the comment header. */ if (new_file) { hash = parse_comment(comment); if ((value = g_hash_table_lookup(hash, "Image Pixel Size"))) { gwy_debug("Using dx from Image Pixel Size: %s", value); } else if ((value = g_hash_table_lookup(hash, "Pixel Size"))) { gwy_debug("Using dx from Pixel Size: %s", value); } else { err_MISSING_FIELD(error, "Pixel Size"); goto fail; } } else { /* The first thing is the pixel size, apparently. */ value = comment + strlen(SOMEWHAT_LESS_MAGIC_COMMENT); gwy_debug("Using dx from old-style comment: %s", value); } dx = g_ascii_strtod(value, &end); /* Use negated positive conditions to catch NaNs */ if (!((dx = fabs(dx)) > 0)) { g_warning("Real pixel size is 0.0, fixing to 1.0"); dx = 1.0; } if (!new_file) end = "m"; /* Request a reader, this ensures dimensions and stuff are defined. * NB: Newer versions store the image as RGB. Not useful here; just * average the channels. */ if (!(reader = gwy_tiff_get_image_reader(tiff, 0, 3, error))) goto fail; siunit = gwy_si_unit_new_parse(end, &power10); factor = pow10(power10); dfield = gwy_data_field_new(reader->width, reader->height, reader->width * factor * dx, reader->height * factor * dx, FALSE); gwy_data_field_set_si_unit_xy(dfield, siunit); g_object_unref(siunit); data = gwy_data_field_get_data(dfield); if (reader->samples_per_pixel > 1) { gdouble *datarow = g_new(gdouble, reader->width); gint ch, j, spp = reader->samples_per_pixel; gwy_data_field_clear(dfield); for (i = 0; i < reader->height; i++) { for (ch = 0; ch < spp; ch++) { gwy_tiff_read_image_row(tiff, reader, 0, i, 1.0, 0.0, datarow); for (j = 0; j < reader->width; j++) data[i*reader->width + j] += datarow[j]; } } g_free(datarow); gwy_data_field_multiply(dfield, 1.0/spp); gwy_data_field_invalidate(dfield); } else { for (i = 0; i < reader->height; i++) gwy_tiff_read_image_row(tiff, reader, 0, i, 1.0, 0.0, data + i*reader->width); } container = gwy_container_new(); gwy_container_set_object_by_name(container, "/0/data", dfield); g_object_unref(dfield); gwy_container_set_string_by_name(container, "/0/data/title", g_strdup("Secondary electron count")); if (new_file) { meta = gwy_container_new(); g_hash_table_foreach(hash, add_meta, meta); if (gwy_container_get_n_items(meta)) gwy_container_set_object_by_name(container, "/0/meta", meta); g_object_unref(meta); } fail: if (hash) g_hash_table_destroy(hash); g_free(comment); return container; }
static GwyContainer* aafm_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwySIUnit *unit; GwyContainer *container = NULL; guchar *buffer = NULL; const guchar *p; gsize size = 0; GError *err = NULL; AFMFile afmfile; GwyDataField *dfield; gdouble min, max; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } if (size < 12) { err_TOO_SHORT(error); gwy_file_abandon_contents(buffer, size, NULL); return NULL; } p = buffer; afmfile.res = gwy_get_guint16_le(&p); if (err_DIMENSION(error, afmfile.res)) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } if (err_SIZE_MISMATCH(error, afmfile.res * afmfile.res + 10, size, FALSE)) { gwy_file_abandon_contents(buffer, size, NULL); return NULL; } afmfile.real = Angstrom*gwy_get_gfloat_le(&p); if (!(afmfile.real = fabs(afmfile.real))) { g_warning("Real size is 0.0, fixing to 1.0"); afmfile.real = 1.0; } dfield = gwy_data_field_new(afmfile.res, afmfile.res, afmfile.real, afmfile.real, FALSE); read_binary_data(afmfile.res, gwy_data_field_get_data(dfield), p); p += 2*afmfile.res*afmfile.res; afmfile.range = gwy_get_gfloat_le(&p); gwy_data_field_get_min_max(dfield, &min, &max); if (min == max) gwy_data_field_clear(dfield); else gwy_data_field_multiply(dfield, afmfile.range/(max - min)*Angstrom); unit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_xy(dfield, unit); g_object_unref(unit); unit = gwy_si_unit_new("m"); gwy_data_field_set_si_unit_z(dfield, unit); g_object_unref(unit); container = gwy_container_new(); gwy_container_set_object_by_name(container, "/0/data", dfield); gwy_container_set_string_by_name(container, "/0/data/title", g_strdup("Topography")); g_object_unref(dfield); gwy_file_channel_import_log_add(container, 0, NULL, filename); gwy_file_abandon_contents(buffer, size, NULL); return container; }
/** * gwy_data_field_crosscorrelate_iteration: * @state: Cross-correlation iterator. * * Performs one iteration of cross-correlation. * * Cross-correlation matches two different images of the same object under * changes. * * It does not use any special features * for matching. It simply searches for all points (with their neighbourhood) * of @data_field1 within @data_field2. Parameters @search_width and * @search_height determine maimum area where to search for points. * The area is cenetered in the @data_field2 at former position of points at * @data_field1. * * A cross-correlation iterator can be created with * gwy_data_field_crosscorrelate_init(). When iteration ends, either * by finishing or being aborted, gwy_data_field_crosscorrelate_finalize() * must be called to release allocated resources. **/ void gwy_data_field_crosscorrelate_iteration(GwyComputationState *cstate) { GwyCrossCorrelationState *state = (GwyCrossCorrelationState*)cstate; gint xres, yres, m, n, col, row, colmax, rowmax; gdouble cormax, lscore; gdouble zm, zp, z0, ipos, jpos; xres = state->data_field1->xres; yres = state->data_field1->yres; if (state->cs.state == GWY_COMPUTATION_STATE_INIT) { if (state->x_dist) gwy_data_field_clear(state->x_dist); if (state->y_dist) gwy_data_field_clear(state->y_dist); if (state->score) gwy_data_field_clear(state->score); state->cs.state = GWY_COMPUTATION_STATE_ITERATE; state->cs.fraction = 0.0; state->i = state->search_height/2; state->j = state->search_width/2; } else if (state->cs.state == GWY_COMPUTATION_STATE_ITERATE) { /*iterate over search area in the second datafield */ row = rowmax = state->i; col = colmax = state->j; cormax = -1.0; for (m = row - state->search_height/2; m < (row + state->search_height/2 - state->window_height + 1); m++) { for (n = col - state->search_width/2; n < (col + state->search_width/2 - state->window_width + 1); n++) { lscore = gwy_data_field_get_correlation_score (state->data_field1, state->data_field2, col - state->window_width/2, row - state->window_height/2, n, m, state->window_width, state->window_height); /* add a little to score at exactly same point * - to prevent problems on flat data */ if (m == row - state->search_height/2 && n == col - state->search_width/2) lscore *= 1.01; if (lscore > cormax) { cormax = lscore; colmax = n + state->window_width/2; rowmax = m + state->window_height/2; } } } if (state->score) state->score->data[col + xres * row] = cormax; if (state->x_dist) { z0 = zp = zm = cormax; zm = gwy_data_field_get_correlation_score(state->data_field1, state->data_field2, col - state->window_width/2, row - state->window_height/2, colmax - state->window_width/2 - 1, rowmax - state->window_height/2, state->window_width, state->window_height); zp = gwy_data_field_get_correlation_score(state->data_field1, state->data_field2, col - state->window_width/2, row - state->window_height/2, colmax - state->window_width/2 + 1, rowmax - state->window_height/2, state->window_width, state->window_height); ipos = colmax + (zm - zp)/(zm + zp - 2*z0)/2.0; state->x_dist->data[col + xres * row] = (ipos - col)*state->data_field1->xreal/state->data_field1->xres; } if (state->y_dist) { z0 = zp = zm = cormax; zm = gwy_data_field_get_correlation_score(state->data_field1, state->data_field2, col - state->window_width/2, row - state->window_height/2, colmax - state->window_width/2, rowmax - state->window_height/2 - 1, state->window_width, state->window_height); zp = gwy_data_field_get_correlation_score(state->data_field1, state->data_field2, col - state->window_width/2, row - state->window_height/2, colmax - state->window_width/2, rowmax - state->window_height/2 + 1, state->window_width, state->window_height); jpos = rowmax + (zm - zp)/(zm + zp - 2*z0)/2.0; state->y_dist->data[col + xres * row] = (jpos - row)*state->data_field1->yreal/state->data_field1->yres; } state->j++; if (state->j == xres - (state->search_width - state->search_width/2)) { state->j = state->search_width/2; state->i++; if (state->i == yres - (state->search_height - state->search_height/2)) { state->cs.state = GWY_COMPUTATION_STATE_FINISHED; } } state->cs.fraction += 1.0/(xres - state->search_width + 1) /(yres - state->search_height + 1); state->cs.fraction = MIN(state->cs.fraction, 1.0); } else if (state->cs.state == GWY_COMPUTATION_STATE_FINISHED) return; if (state->score) gwy_data_field_invalidate(state->score); if (state->x_dist) gwy_data_field_invalidate(state->x_dist); if (state->y_dist) gwy_data_field_invalidate(state->y_dist); }
/** * gwy_data_field_crosscorrelate: * @data_field1: A data field. * @data_field2: A data field. * @x_dist: A data field to store x-distances to. * @y_dist: A data field to store y-distances to. * @score: Data field to store correlation scores to. * @search_width: Search area width. * @search_height: Search area height. * @window_width: Correlation window width. * @window_height: Correlation window height. * * Algorithm for matching two different images of the same object under changes. * * It does not use any special features * for matching. It simply searches for all points (with their neighbourhood) * of @data_field1 within @data_field2. Parameters @search_width and * @search_height * determine maimum area where to search for points. The area is cenetered * in the @data_field2 at former position of points at @data_field1. **/ void gwy_data_field_crosscorrelate(GwyDataField *data_field1, GwyDataField *data_field2, GwyDataField *x_dist, GwyDataField *y_dist, GwyDataField *score, gint search_width, gint search_height, gint window_width, gint window_height) { gint xres, yres, i, j, m, n; gint imax, jmax; gdouble cormax, lscore; gdouble zm, zp, z0, ipos, jpos; g_return_if_fail(data_field1 != NULL && data_field2 != NULL); xres = data_field1->xres; yres = data_field1->yres; g_return_if_fail(xres == data_field2->xres && yres == data_field2->yres); gwy_data_field_clear(x_dist); gwy_data_field_clear(y_dist); gwy_data_field_clear(score); /*iterate over all the points */ for (i = (search_width/2); i < (xres - search_height/2); i++) { for (j = (search_height/2); j < (yres - search_height/2); j++) { /*iterate over search area in the second datafield */ imax = i; jmax = j; cormax = -1; for (m = (i - search_width); m < i; m++) { for (n = (j - search_height); n < j; n++) { lscore = gwy_data_field_get_correlation_score(data_field1, data_field2, i-search_width/2, j-search_height/2, m, n, m + search_width, n + search_height); /* add a little to score at exactly same point * - to prevent problems on flat data */ if (m == (i - search_width/2) && n == (j - search_height/2)) lscore *= 1.0001; if (cormax < lscore) { cormax = lscore; imax = m + search_width/2; jmax = n + search_height/2; } } } score->data[i + xres * j] = cormax; z0 = cormax; zm = gwy_data_field_get_correlation_score(data_field1, data_field2, i-search_width/2, j-search_height/2, imax - search_width/2 - 1, jmax - search_height/2, imax + search_width/2 - 1, jmax + search_height/2); zp = gwy_data_field_get_correlation_score(data_field1, data_field2, i-search_width/2, j-search_height/2, imax - search_width/2 + 1, jmax - search_height/2, imax + search_width/2 + 1, jmax + search_height/2); ipos = imax + (zm - zp)/(zm + zp - 2*z0)/2.0; x_dist->data[i + xres * j] = (gdouble)(ipos - i)*data_field1->xreal/data_field1->xres; zm = gwy_data_field_get_correlation_score(data_field1, data_field2, i-search_width/2, j-search_height/2, imax - search_width/2, jmax - search_height/2 - 1, imax + search_width/2, jmax + search_height/2 - 1); zp = gwy_data_field_get_correlation_score(data_field1, data_field2, i-search_width/2, j-search_height/2, imax - search_width/2, jmax - search_height/2 + 1, imax + search_width/2, jmax + search_height/2 + 1); jpos = jmax + (zm - zp)/(zm + zp - 2*z0)/2.0; y_dist->data[i + xres * j] = (gdouble)(jpos - j)*data_field1->yreal/data_field1->yres; } } gwy_data_field_invalidate(score); gwy_data_field_invalidate(x_dist); gwy_data_field_invalidate(y_dist); }
static void tip_model_dialog(TipModelArgs *args) { enum { RESPONSE_RESET = 1, RESPONSE_PREVIEW = 2 }; GtkWidget *dialog, *table, *hbox, *spin; TipModelControls controls; GwyPixmapLayer *layer; GwyDataField *dfield; GwySIUnit *unit; GQuark quark; gint response, row; dialog = gtk_dialog_new_with_buttons(_("Model Tip"), 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), _("_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); hbox = gtk_hbox_new(FALSE, 3); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, FALSE, 4); controls.args = args; controls.vxres = 200; controls.vyres = 200; /* set up initial tip field */ quark = gwy_app_get_data_key_for_id(args->object.id); dfield = GWY_DATA_FIELD(gwy_container_get_object(args->object.data, quark)); controls.tip = gwy_data_field_new_alike(dfield, TRUE); gwy_data_field_resample(controls.tip, controls.vxres, controls.vyres, GWY_INTERPOLATION_NONE); gwy_data_field_clear(controls.tip); /*set up data of rescaled image of the tip*/ controls.vtip = gwy_container_new(); gwy_app_sync_data_items(args->object.data, controls.vtip, args->object.id, 0, FALSE, GWY_DATA_ITEM_PALETTE, 0); dfield = gwy_data_field_new_alike(controls.tip, TRUE); gwy_container_set_object_by_name(controls.vtip, "/0/data", dfield); g_object_unref(dfield); /* set up resampled view */ controls.view = gwy_data_view_new(controls.vtip); layer = gwy_layer_basic_new(); gwy_pixmap_layer_set_data_key(layer, "/0/data"); gwy_layer_basic_set_gradient_key(GWY_LAYER_BASIC(layer), "/0/base/palette"); gwy_data_view_set_base_layer(GWY_DATA_VIEW(controls.view), layer); /* set up tip model controls */ gtk_box_pack_start(GTK_BOX(hbox), controls.view, FALSE, FALSE, 4); table = gtk_table_new(6, 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, FALSE, FALSE, 4); row = 0; controls.type = create_preset_menu(G_CALLBACK(tip_type_cb), &controls, args->type); gwy_table_attach_hscale(table, row, _("Tip _type:"), NULL, GTK_OBJECT(controls.type), GWY_HSCALE_WIDGET); row++; controls.nsides = gtk_adjustment_new(args->nsides, 3, 24, 1, 5, 0); gwy_table_attach_hscale(table, row, _("_Number of sides:"), NULL, controls.nsides, 0); row++; controls.angle = gtk_adjustment_new(args->angle, 0.1, 89.9, 0.1, 1, 0); spin = gwy_table_attach_hscale(table, row, _("Tip _slope:"), _("deg"), controls.angle, 0); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), 2); row++; controls.theta = gtk_adjustment_new(args->theta, 0, 360, 0.1, 1, 0); spin = gwy_table_attach_hscale(table, row, _("Tip _rotation:"), _("deg"), controls.theta, 0); gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), 2); row++; controls.radius = gtk_adjustment_new(1.0, 0.01, 1000.0, 0.01, 1.0, 0.0); controls.radius_spin = gtk_spin_button_new(GTK_ADJUSTMENT(controls.radius), 0.1, 2); gtk_table_attach(GTK_TABLE(table), controls.radius_spin, 2, 3, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.radius_label = gtk_label_new_with_mnemonic(_("Tip _apex radius:")); gtk_misc_set_alignment(GTK_MISC(controls.radius_label), 0.0, 0.5); gtk_label_set_mnemonic_widget(GTK_LABEL(controls.radius_label), controls.radius_spin); gtk_table_attach(GTK_TABLE(table), controls.radius_label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); unit = gwy_data_field_get_si_unit_xy(dfield); controls.radius_unit = gwy_combo_box_metric_unit_new(G_CALLBACK(radius_changed_cb), &controls, -12, -3, unit, -9); gtk_table_attach(GTK_TABLE(table), controls.radius_unit, 3, 4, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); g_signal_connect(controls.radius, "value-changed", G_CALLBACK(radius_changed_cb), &controls); row++; controls.labsize = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.labsize), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.labsize, 0, 3, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; controls.tipdone = FALSE; tip_model_dialog_update_controls(&controls, args); preview(&controls, args); gtk_widget_show_all(dialog); do { response = gtk_dialog_run(GTK_DIALOG(dialog)); switch (response) { case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_DELETE_EVENT: tip_model_dialog_update_values(&controls, args); gtk_widget_destroy(dialog); tip_model_dialog_abandon(&controls); case GTK_RESPONSE_NONE: return; break; case GTK_RESPONSE_OK: tip_model_do(args, &controls); break; case RESPONSE_RESET: args->nsides = tip_model_defaults.nsides; args->angle = tip_model_defaults.angle; args->radius = tip_model_defaults.radius; args->theta = tip_model_defaults.theta; args->type = tip_model_defaults.type; tip_model_dialog_update_controls(&controls, args); break; case RESPONSE_PREVIEW: tip_model_dialog_update_values(&controls, args); preview(&controls, args); break; default: g_assert_not_reached(); break; } } while (response != GTK_RESPONSE_OK); tip_model_dialog_update_values(&controls, args); gtk_widget_destroy(dialog); tip_model_dialog_abandon(&controls); }
void gwy_data_field_crosscorrelate_iteration(GwyComputationState *cstate) { GwyCrossCorrelationState *state = (GwyCrossCorrelationState*)cstate; gint xres, yres, m, n, k, col, row, colmax, rowmax; gdouble cormax, lscore; gdouble ipos, jpos, scores[9]; gdouble xmaximum, ymaximum; xres = state->data_field1->xres; yres = state->data_field1->yres; if (state->cs.state == GWY_COMPUTATION_STATE_INIT) { if (state->x_dist) gwy_data_field_clear(state->x_dist); if (state->y_dist) gwy_data_field_clear(state->y_dist); if (state->score) gwy_data_field_clear(state->score); state->cs.state = GWY_COMPUTATION_STATE_ITERATE; state->cs.fraction = 0.0; state->i = state->window_width/2 + 1; state->j = state->window_height/2 + 1; } else if (state->cs.state == GWY_COMPUTATION_STATE_ITERATE) { //iterate over search area in the second datafield col = colmax = state->i; row = rowmax = state->j; cormax = -G_MAXDOUBLE; for (m = MAX(0, row - state->search_height/2 - state->window_height/2); m < MIN(yres-state->window_height, (row + state->search_height/2 - state->window_height/2)); m++) { for (n = MAX(0, col - state->search_width/2 - state->window_width/2); n < MIN(xres-state->window_width, (col + state->search_width/2 - state->window_width/2)); n++) { lscore = gwy_data_field_get_weighted_correlation_score (state->data_field1, state->data_field2, state->weights, col-state->window_width/2, row-state->window_height/2, n, m, state->window_width, state->window_height); // add a little to score at exactly same point - to prevent problems on flat data if (m == 0 && n == 0) lscore *= 1.0001; if (lscore > cormax) { cormax = lscore; colmax = n + state->window_width/2; rowmax = m + state->window_height/2; } } } if (state->score) state->score->data[col + xres * row] = cormax; if (state->x_dist || state->x_dist) { k = 0; for (m=-1; m<=1; m++) { for (n=-1; n<=1; n++) { if (m==0 && n==0) scores[k++] = cormax; else scores[k++] = gwy_data_field_get_weighted_correlation_score(state->data_field1, state->data_field2, state->weights, col - state->window_width/2, row - state->window_height/2, colmax - state->window_width/2 + n, rowmax - state->window_height/2 + m, state->window_width, state->window_height); } } if (gwy_math_refine_maximum(scores, &xmaximum, &ymaximum)) { ipos = colmax + xmaximum; jpos = rowmax + ymaximum; } else { ipos = colmax; jpos = rowmax; } state->x_dist->data[col + xres * row] = (ipos - col)*state->data_field1->xreal/state->data_field1->xres; state->y_dist->data[col + xres * row] = (jpos - row)*state->data_field1->yreal/state->data_field1->yres; } state->i++; if (state->i == (xres - state->window_width/2 - 1)) { state->i = state->window_width/2 + 1; state->j++; if (state->j == (yres - state->window_height/2 - 1)) { state->cs.state = GWY_COMPUTATION_STATE_FINISHED; } } state->cs.fraction += 1.0/(xres - state->window_width - 2) /(yres - state->window_height - 2); state->cs.fraction = MIN(state->cs.fraction, 1.0); } else if (state->cs.state == GWY_COMPUTATION_STATE_FINISHED) return; if (state->score) gwy_data_field_invalidate(state->score); if (state->x_dist) gwy_data_field_invalidate(state->x_dist); if (state->y_dist) gwy_data_field_invalidate(state->y_dist); }
static void gwy_data_field_facet_distribution(GwyDataField *dfield, gint kernel_size, GwyContainer *container) { GwyDataField *dtheta, *dphi, *dist; GwySIUnit *siunit; gdouble *xd, *yd, *data; const gdouble *xdc, *ydc; gdouble q, max; gint res, hres, i, j, mi, mj, xres, yres; if (gwy_container_gis_object_by_name(container, "/theta", &dtheta)) g_object_ref(dtheta); else dtheta = gwy_data_field_new_alike(dfield, FALSE); if (gwy_container_gis_object_by_name(container, "/phi", &dphi)) g_object_ref(dphi); else dphi = gwy_data_field_new_alike(dfield, FALSE); compute_slopes(dfield, kernel_size, dtheta, dphi); xres = gwy_data_field_get_xres(dfield); yres = gwy_data_field_get_yres(dfield); xd = gwy_data_field_get_data(dtheta); yd = gwy_data_field_get_data(dphi); for (i = xres*yres; i; i--, xd++, yd++) { gdouble theta, phi; slopes_to_angles(*xd, *yd, &theta, &phi); *xd = theta; *yd = phi; } q = gwy_data_field_get_max(dtheta); q = MIN(q*1.05, G_PI/2.0); q = G_SQRT2/(2.0*sin(q/2.0)); if (gwy_container_gis_object_by_name(container, "/0/data", &dist)) { g_object_ref(dist); gwy_data_field_clear(dist); gwy_data_field_set_xreal(dist, 2.0*G_SQRT2/q); gwy_data_field_set_yreal(dist, 2.0*G_SQRT2/q); } else { dist = gwy_data_field_new(FDATA_RES, FDATA_RES, 2.0*G_SQRT2/q, 2.0*G_SQRT2/q, TRUE); siunit = gwy_si_unit_new(""); gwy_data_field_set_si_unit_z(dist, siunit); g_object_unref(siunit); /* FIXME */ siunit = gwy_si_unit_new(""); gwy_data_field_set_si_unit_xy(dist, siunit); g_object_unref(siunit); } res = FDATA_RES; hres = (res - 1)/2; data = gwy_data_field_get_data(dist); xdc = gwy_data_field_get_data_const(dtheta); ydc = gwy_data_field_get_data_const(dphi); for (i = xres*yres; i; i--, xdc++, ydc++) { gdouble x, y; gint xx, yy; angles_to_xy(*xdc, *ydc, &x, &y); xx = GWY_ROUND(q*x/G_SQRT2*hres) + hres; yy = GWY_ROUND(q*y/G_SQRT2*hres) + hres; data[yy*res + xx] += 1.0; } /* Find maxima */ mi = mj = hres; max = 0; for (i = 1; i+1 < res; i++) { for (j = 1; j+1 < res; j++) { gdouble z; z = data[i*res + j] + 0.3*(data[i*res + j - 1] + data[i*res + j + 1] + data[i*res - res + j] + data[i*res + res + j]) + 0.1*(data[i*res - res + j - 1] + data[i*res - res + j + 1] + data[i*res + res + j - 1] + data[i*res + res + j + 1]); if (G_UNLIKELY(z > max)) { max = z; mi = i; mj = j; } } } for (i = res*res; i; i--, data++) *data = pow(*data, 0.35); gwy_container_set_double_by_name(container, "/q", q); { gdouble x, y, theta, phi; x = (mj - hres)*G_SQRT2/(q*hres); y = (mi - hres)*G_SQRT2/(q*hres); xy_to_angles(x, y, &theta, &phi); gwy_container_set_double_by_name(container, "/theta0", theta); gwy_container_set_double_by_name(container, "/phi0", phi); } gwy_container_set_object_by_name(container, "/0/data", dist); g_object_unref(dist); gwy_container_set_object_by_name(container, "/theta", dtheta); g_object_unref(dtheta); gwy_container_set_object_by_name(container, "/phi", dphi); g_object_unref(dphi); gwy_container_set_string_by_name(container, "/0/base/palette", g_strdup(FVIEW_GRADIENT)); gwy_data_field_data_changed(dist); }
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); }