/** * gwy_data_field_get_raw_correlation_score: * @data_field: A data field. * @kernel_field: Kernel to correlate data field with. * @col: Upper-left column position in the data field. * @row: Upper-left row position in the data field. * @kernel_col: Upper-left column position in kernel field. * @kernel_row: Upper-left row position in kernel field. * @kernel_width: Width of kernel field area. * @kernel_height: Heigh of kernel field area. * @data_avg: Mean value of the effective data field area. * @data_rms: Mean value of the effective kernel field area. * * Calculates a raw correlation score in one point. * * See gwy_data_field_get_correlation_score() for description. This function * is useful if you know the mean values and rms. * * To obtain the score, divide the returned value with the product of rms of * data field area and rms of the kernel. * * Returns: Correlation score (normalized to multiple of kernel and data * area rms). **/ static gdouble gwy_data_field_get_raw_correlation_score(GwyDataField *data_field, GwyDataField *kernel_field, gint col, gint row, gint kernel_col, gint kernel_row, gint kernel_width, gint kernel_height, gdouble data_avg, gdouble kernel_avg) { gint xres, yres, kxres, kyres, i, j; gdouble sumpoints, score; gdouble *data, *kdata; g_return_val_if_fail(GWY_IS_DATA_FIELD(data_field), -1.0); g_return_val_if_fail(GWY_IS_DATA_FIELD(kernel_field), -1.0); xres = data_field->xres; yres = data_field->yres; kxres = kernel_field->xres; kyres = kernel_field->yres; kernel_width = kernel_width; kernel_height = kernel_height; /* correlation request outside kernel */ if (kernel_col > kxres || kernel_row > kyres) return -1; /* correlation request outside data field */ if (col < 0 || row < 0 || col + kernel_width > xres || row + kernel_height > yres) return -1; if (kernel_col < 0 || kernel_row < 0 || kernel_col + kernel_width > kxres || kernel_row + kernel_height > kyres) return -1; score = 0; sumpoints = kernel_width * kernel_height; data = data_field->data; kdata = kernel_field->data; for (j = 0; j < kernel_height; j++) { /* row */ for (i = 0; i < kernel_width; i++) { /* col */ score += (data[(i + col) + xres*(j + row)] - data_avg) * (kdata[(i + kernel_col) + kxres*(j + kernel_row)] - kernel_avg); } } score /= sumpoints; return score; }
/** * gwy_surface_set_from_data_field_mask: * @surface: A surface. * @data_field: A two-dimensional data field. * @mask: Mask of pixels to include from/exclude, or %NULL * @masking: Masking mode to use. * * Fills the data of a surface from a data field, possibly using masking. * * Since: 2.46 **/ void gwy_surface_set_from_data_field_mask(GwySurface *surface, GwyDataField *dfield, GwyDataField *mask, GwyMaskingType masking) { g_return_if_fail(GWY_IS_SURFACE(surface)); g_return_if_fail(GWY_IS_DATA_FIELD(dfield)); g_return_if_fail(!mask || GWY_IS_DATA_FIELD(mask)); copy_field_to_surface(dfield, surface, mask, masking); }
/** * gwy_surface_copy_units_to_data_field: * @surface: A surface. * @data_field: A two-dimensional data field. * * Sets lateral and value units of a data field to match a surface. * * Since: 2.46 **/ void gwy_surface_copy_units_to_data_field(GwySurface *surface, GwyDataField *data_field) { Surface *priv; g_return_if_fail(GWY_IS_SURFACE(surface)); g_return_if_fail(GWY_IS_DATA_FIELD(data_field)); priv = surface->priv; if (priv->si_unit_xy && data_field->si_unit_xy) gwy_serializable_clone(G_OBJECT(priv->si_unit_xy), G_OBJECT(data_field->si_unit_xy)); else if (priv->si_unit_xy && !data_field->si_unit_xy) data_field->si_unit_xy = gwy_si_unit_duplicate(priv->si_unit_xy); else if (!priv->si_unit_xy && data_field->si_unit_xy) GWY_OBJECT_UNREF(data_field->si_unit_xy); if (priv->si_unit_z && data_field->si_unit_z) gwy_serializable_clone(G_OBJECT(priv->si_unit_z), G_OBJECT(data_field->si_unit_z)); else if (priv->si_unit_z && !data_field->si_unit_z) data_field->si_unit_z = gwy_si_unit_duplicate(priv->si_unit_z); else if (!priv->si_unit_z && data_field->si_unit_z) GWY_OBJECT_UNREF(data_field->si_unit_z); }
/** * gwy_data_field_crosscorrelate_init: * @data_field1: A data field. * @data_field2: A data field. * @x_dist: A data field to store x-distances to, or %NULL. * @y_dist: A data field to store y-distances to, or %NULL. * @score: Data field to store correlation scores to, or %NULL. * @search_width: Search area width. * @search_height: Search area height. * @window_width: Correlation window width. * @window_height: Correlation window height. * * Initializes a cross-correlation iterator. * * This iterator reports its state as #GwyComputationStateType. * * Returns: A new cross-correlation iterator. **/ GwyComputationState* gwy_data_field_crosscorrelate_init(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) { GwyCrossCorrelationState *state; g_return_val_if_fail(GWY_IS_DATA_FIELD(data_field1), NULL); g_return_val_if_fail(GWY_IS_DATA_FIELD(data_field2), NULL); g_return_val_if_fail(data_field1->xres == data_field2->xres && data_field1->yres == data_field2->yres, NULL); g_return_val_if_fail(!x_dist || GWY_IS_DATA_FIELD(x_dist), NULL); g_return_val_if_fail(!y_dist || GWY_IS_DATA_FIELD(y_dist), NULL); g_return_val_if_fail(!score || GWY_IS_DATA_FIELD(score), NULL); state = g_new0(GwyCrossCorrelationState, 1); state->cs.state = GWY_COMPUTATION_STATE_INIT; state->cs.fraction = 0.0; state->data_field1 = g_object_ref(data_field1); state->data_field2 = g_object_ref(data_field2); if (x_dist) state->x_dist = g_object_ref(x_dist); if (y_dist) state->y_dist = g_object_ref(y_dist); if (score) state->score = g_object_ref(score); state->search_width = search_width; state->search_height = search_height; state->window_width = window_width; state->window_height = window_height; state->weights = gwy_data_field_new(window_width, window_height, window_width, window_height, 1); gwy_data_field_fill(state->weights, 1); return (GwyComputationState*)state; }
/** * gwy_surface_set_from_data_field: * @surface: A surface. * @data_field: A two-dimensional data field. * * Fills the data of a surface from a data field. * * The number of points in the new surface will be equal to the number of * points in the field. Lateral coordinates will be equal to the corresponding * @data_field coordinates; values will be created in regular grid according to * @data_field's physical size and offset. * * Lateral and value units will correspond to @data_field's units. This means * the field needs to have identical @x and @y units. * * Since: 2.45 **/ void gwy_surface_set_from_data_field(GwySurface *surface, GwyDataField *dfield) { g_return_if_fail(GWY_IS_SURFACE(surface)); g_return_if_fail(GWY_IS_DATA_FIELD(dfield)); copy_field_to_surface(dfield, surface, NULL, GWY_MASK_IGNORE); }
static GwyContainer* gwyfile_load(const gchar *filename) { GObject *object, *dfield; GError *err = NULL; guchar *buffer = NULL; gsize size = 0; gsize pos = 0; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { g_warning("Cannot read file %s", filename); g_clear_error(&err); return NULL; } if (size < MAGIC_SIZE || (memcmp(buffer, MAGIC, MAGIC_SIZE) && memcmp(buffer, MAGIC2, MAGIC_SIZE))) { g_warning("File %s doesn't seem to be a .gwy file", filename); if (!gwy_file_abandon_contents(buffer, size, &err)) { g_critical("%s", err->message); g_clear_error(&err); } return NULL; } if (!memcmp(buffer, MAGIC, MAGIC_SIZE)) object = gwy_serializable_deserialize(buffer + MAGIC_SIZE, size - MAGIC_SIZE, &pos); else object = gwy_container_deserialize2(buffer + MAGIC_SIZE, size - MAGIC_SIZE, &pos); if (!gwy_file_abandon_contents(buffer, size, &err)) { g_critical("%s", err->message); g_clear_error(&err); } if (!object) { g_warning("File %s deserialization failed", filename); return NULL; } if (!GWY_IS_CONTAINER(object)) { g_warning("File %s contains some strange object", filename); g_object_unref(object); return NULL; } dfield = gwy_container_get_object_by_name(GWY_CONTAINER(object), "/0/data"); if (!dfield || !GWY_IS_DATA_FIELD(dfield)) { g_warning("File %s contains no data field", filename); g_object_unref(object); return NULL; } return (GwyContainer*)object; }
/** * gwy_data_field_correlate_init: * @data_field: A data field. * @kernel_field: Kernel to correlate data field with. * @score: Data field to store correlation scores to. * * Creates a new correlation iterator. * * This iterator reports its state as #GwyComputationStateType. * * Returns: A new correlation iterator. **/ GwyComputationState* gwy_data_field_correlate_init(GwyDataField *data_field, GwyDataField *kernel_field, GwyDataField *score) { GwyCorrelationState *state; g_return_val_if_fail(GWY_IS_DATA_FIELD(data_field), NULL); g_return_val_if_fail(GWY_IS_DATA_FIELD(kernel_field), NULL); g_return_val_if_fail(kernel_field->xres <= data_field->xres && kernel_field->yres <= data_field->yres, NULL); g_return_val_if_fail(GWY_IS_DATA_FIELD(score), NULL); state = g_new0(GwyCorrelationState, 1); state->cs.state = GWY_COMPUTATION_STATE_INIT; state->cs.fraction = 0.0; state->data_field = g_object_ref(data_field); state->kernel_field = g_object_ref(kernel_field); state->score = g_object_ref(score); return (GwyComputationState*)state; }
static GdkPixbuf* gwy_layer_basic_paint(GwyPixmapLayer *layer) { GwyDataField *data_field; GwyLayerBasic *basic_layer; GwyContainer *data; gdouble min = 0.0, max = 0.0; gboolean fixedmin, fixedmax; gboolean fixedrange = FALSE; gwy_debug(" "); g_return_val_if_fail(GWY_IS_LAYER_BASIC(layer), NULL); basic_layer = GWY_LAYER_BASIC(layer); data = GWY_DATA_VIEW_LAYER(layer)->data; /* TODO Container */ if (!gwy_container_gis_object_by_name(data, "/0/show", (GObject**)&data_field)) { data_field = GWY_DATA_FIELD(gwy_container_get_object_by_name(data, "/0/data")); fixedrange = TRUE; } g_return_val_if_fail(GWY_IS_DATA_FIELD(data_field), layer->pixbuf); if (fixedrange) { fixedmin = gwy_container_gis_double_by_name(data, "/0/base/min", &min); fixedmax = gwy_container_gis_double_by_name(data, "/0/base/max", &max); if (fixedmin || fixedmax) { if (!fixedmin) min = gwy_data_field_get_min(data_field); if (!fixedmax) max = gwy_data_field_get_max(data_field); } else fixedrange = FALSE; } /* XXX */ /*if (GWY_LAYER_BASIC(layer)->changed)*/ { if (fixedrange) gwy_pixbuf_draw_data_field_with_range(layer->pixbuf, data_field, basic_layer->gradient, min, max); else gwy_pixbuf_draw_data_field(layer->pixbuf, data_field, basic_layer->gradient); basic_layer->changed = FALSE; } return layer->pixbuf; }
/** * gwy_set_data_preview_size: * @data_view: A data view used for module preview. * @max_size: Maximum allowed @data_view size (width and height). * * Sets up data view zoom to not exceed specified size. * * Before calling this function, data keys have be set, data fields and layers * have to be present and physically square mode set in the container. * Sizing of both pixel-wise square and physically square displays is performed * correctly. * * Since: 2.7 **/ void gwy_set_data_preview_size(GwyDataView *data_view, gint max_size) { GwyContainer *container; GwyDataField *data_field; GwyPixmapLayer *layer; gdouble zoomval, scale, xreal, yreal; gboolean realsquare; gint xres, yres; const gchar *prefix; gchar *key; g_return_if_fail(GWY_IS_DATA_VIEW(data_view)); g_return_if_fail(max_size >= 2); container = gwy_data_view_get_data(data_view); g_return_if_fail(GWY_IS_CONTAINER(container)); layer = gwy_data_view_get_base_layer(data_view); g_return_if_fail(GWY_IS_PIXMAP_LAYER(layer)); prefix = gwy_pixmap_layer_get_data_key(layer); g_return_if_fail(prefix); data_field = gwy_container_get_object_by_name(container, prefix); g_return_if_fail(GWY_IS_DATA_FIELD(data_field)); prefix = gwy_data_view_get_data_prefix(data_view); g_return_if_fail(prefix); key = g_strconcat(prefix, "/realsquare", NULL); realsquare = FALSE; gwy_container_gis_boolean_by_name(container, key, &realsquare); g_free(key); xres = gwy_data_field_get_xres(data_field); yres = gwy_data_field_get_yres(data_field); if (!realsquare) zoomval = max_size/(gdouble)MAX(xres, yres); else { xreal = gwy_data_field_get_xreal(data_field); yreal = gwy_data_field_get_yreal(data_field); scale = MAX(xres/xreal, yres/yreal); zoomval = max_size/(scale*MAX(xreal, yreal)); } gwy_data_view_set_zoom(data_view, zoomval); }
static void add_object_id(gpointer hkey, gpointer hvalue, gpointer user_data) { GValue *value = (GValue*)hvalue; FileInfoData *filedata = (FileInfoData*)user_data; const gchar *strkey; gchar *end; gint id; strkey = g_quark_to_string(GPOINTER_TO_UINT(hkey)); if (!strkey || strkey[0] != '/' || !G_VALUE_HOLDS_OBJECT(value)) return; if ((id = strtol(strkey + 1, &end, 10)) >= 0 && gwy_strequal(end, "/data") && GWY_IS_DATA_FIELD(g_value_get_object(value))) { filedata->nchannels++; filedata->channels = g_slist_prepend(filedata->channels, GINT_TO_POINTER(id)); return; } if (g_str_has_prefix(strkey, "/0/graph/graph/") && (id = strtol(strkey + 15, &end, 10)) >= 0 && !*end && GWY_IS_GRAPH_MODEL(g_value_get_object(value))) { filedata->ngraphs++; filedata->graphs = g_slist_prepend(filedata->graphs, GINT_TO_POINTER(id)); return; } if (g_str_has_prefix(strkey, "/sps/") && (id = strtol(strkey + 5, &end, 10)) >= 0 && !*end && GWY_IS_SPECTRA(g_value_get_object(value))) { filedata->nspectra++; filedata->spectra = g_slist_prepend(filedata->spectra, GINT_TO_POINTER(id)); return; } }
static void gwy_app_file_chooser_describe_channel(GwyContainer *container, gint id, GString *str) { GwyDataField *dfield; GwySIUnit *siunit; GwySIValueFormat *vf; GQuark quark; gint xres, yres; gdouble xreal, yreal; gchar *s; g_string_truncate(str, 0); quark = gwy_app_get_data_key_for_id(id); dfield = GWY_DATA_FIELD(gwy_container_get_object(container, quark)); g_return_if_fail(GWY_IS_DATA_FIELD(dfield)); s = gwy_app_get_data_field_title(container, id); g_string_append(str, s); g_free(s); siunit = gwy_data_field_get_si_unit_z(dfield); s = gwy_si_unit_get_string(siunit, GWY_SI_UNIT_FORMAT_MARKUP); g_string_append_printf(str, " [%s]\n", s); g_free(s); xres = gwy_data_field_get_xres(dfield); yres = gwy_data_field_get_yres(dfield); g_string_append_printf(str, "%d×%d px\n", xres, yres); xreal = gwy_data_field_get_xreal(dfield); yreal = gwy_data_field_get_yreal(dfield); siunit = gwy_data_field_get_si_unit_xy(dfield); vf = gwy_si_unit_get_format(siunit, GWY_SI_UNIT_FORMAT_VFMARKUP, sqrt(xreal*yreal), NULL); g_string_append_printf(str, "%.*f×%.*f%s%s", vf->precision, xreal/vf->magnitude, vf->precision, yreal/vf->magnitude, (vf->units && *vf->units) ? " " : "", vf->units); gwy_si_unit_value_format_free(vf); }
/** * gwy_app_data_id_verify_channel: * @id: Numerical identifiers of a channel in data managed by the data browser. * * Checks if numerical channel identifiers correspond to an existing channel. * * If either the data contained referenced in @id or the channel does not exist * the structure is cleared to %GWY_APP_DATA_ID_NONE and the function returns * %FALSE. If it represents an existing channel it is kept intact and the * function return %TRUE. * * Returns: Whether @id refers to an existing channel now. * * Since: 2.41 **/ gboolean gwy_app_data_id_verify_channel(GwyAppDataId *id) { GwyContainer *container; GObject *object; GQuark quark; g_return_val_if_fail(id, FALSE); container = gwy_app_data_browser_get(id->datano); if (!container) return clear_data_id(id); quark = gwy_app_get_data_key_for_id(id->id); if (!gwy_container_gis_object(container, quark, &object)) return clear_data_id(id); return GWY_IS_DATA_FIELD(object); }
static void modify_channel_for_preview(GwyContainer *data, gint id, gboolean plane_level, gboolean row_level) { GwyDataField *field; gdouble a, bx, by; if (!plane_level && !row_level) return; if (!gwy_container_gis_object(data, gwy_app_get_data_key_for_id(id), &field) || !GWY_IS_DATA_FIELD(field)) return; if (plane_level) { gwy_data_field_fit_plane(field, &a, &bx, &by); gwy_data_field_plane_level(field, a, bx, by); } if (row_level) { guint xres = gwy_data_field_get_xres(field); guint yres = gwy_data_field_get_yres(field); gdouble *row = gwy_data_field_get_data(field); gdouble *diffs = g_new(gdouble, xres); guint i, j; for (i = 1; i < yres; i++) { gdouble *prev = row; gdouble median; row += xres; for (j = 0; j < xres; j++) diffs[j] = prev[j] - row[j]; median = gwy_math_median(xres, diffs); for (j = 0; j < xres; j++) row[j] += median; } g_free(diffs); } }
static void add_channel_id(gpointer hkey, gpointer hvalue, gpointer user_data) { GValue *value = (GValue*)hvalue; GSList **list = (GSList**)user_data; const gchar *strkey; gchar *end; gint id; strkey = g_quark_to_string(GPOINTER_TO_UINT(hkey)); if (!strkey) return; if (strkey[0] != '/' || (id = strtol(strkey + 1, &end, 10)) < 0 || !gwy_strequal(end, "/data") || !G_VALUE_HOLDS_OBJECT(value) || !GWY_IS_DATA_FIELD(g_value_get_object(value))) return; *list = g_slist_prepend(*list, GINT_TO_POINTER(id)); }
static void gwy_recent_file_update_thumbnail(GwyRecentFile *rf, GwyContainer *data, gint hint, GdkPixbuf *use_this_pixbuf) { GwyDataField *dfield; GdkPixbuf *pixbuf; GStatBuf st; gchar *fnm; GwySIUnit *siunit; GwySIValueFormat *vf; gdouble xreal, yreal; gchar str_mtime[22]; gchar str_size[22]; gchar str_width[22]; gchar str_height[22]; GError *err = NULL; GQuark quark; gint id; g_return_if_fail(GWY_CONTAINER(data)); if (use_this_pixbuf) { /* If we are given a pixbuf, hint must be the ultimate channel id. * We also ignore the thnumbnail state then. */ g_return_if_fail(GDK_IS_PIXBUF(use_this_pixbuf)); id = hint; pixbuf = g_object_ref(use_this_pixbuf); } else { pixbuf = NULL; id = gwy_recent_file_find_some_channel(data, hint); if (rf->file_state == FILE_STATE_UNKNOWN) gwy_app_recent_file_try_load_thumbnail(rf); } /* Find channel with the lowest id not smaller than hint */ if (id == G_MAXINT) { gwy_debug("There is no channel in the file, cannot make thumbnail."); return; } if (g_stat(rf->file_sys, &st) != 0) { g_warning("File <%s> was just loaded or saved, but it doesn't seem to " "exist any more: %s", rf->file_utf8, g_strerror(errno)); return; } if ((gulong)rf->file_mtime == (gulong)st.st_mtime) return; quark = gwy_app_get_data_key_for_id(id); dfield = GWY_DATA_FIELD(gwy_container_get_object(data, quark)); g_return_if_fail(GWY_IS_DATA_FIELD(dfield)); rf->file_mtime = st.st_mtime; rf->file_size = st.st_size; rf->image_width = gwy_data_field_get_xres(dfield); rf->image_height = gwy_data_field_get_yres(dfield); xreal = gwy_data_field_get_xreal(dfield); yreal = gwy_data_field_get_yreal(dfield); siunit = gwy_data_field_get_si_unit_xy(dfield); vf = gwy_si_unit_get_format(siunit, GWY_SI_UNIT_FORMAT_VFMARKUP, sqrt(xreal*yreal), NULL); g_free(rf->image_real_size); rf->image_real_size = g_strdup_printf("%.*f×%.*f%s%s", vf->precision, xreal/vf->magnitude, vf->precision, yreal/vf->magnitude, (vf->units && *vf->units) ? " " : "", vf->units); rf->file_state = FILE_STATE_OK; gwy_si_unit_value_format_free(vf); if (g_str_has_prefix(rf->file_sys, gwy_recent_file_thumbnail_dir())) { gchar c; c = rf->file_sys[strlen(gwy_recent_file_thumbnail_dir())]; if (!c || G_IS_DIR_SEPARATOR(c)) return; } if (!pixbuf) pixbuf = gwy_app_get_channel_thumbnail(data, id, TMS_NORMAL_THUMB_SIZE, TMS_NORMAL_THUMB_SIZE); g_snprintf(str_mtime, sizeof(str_mtime), "%lu", rf->file_mtime); g_snprintf(str_size, sizeof(str_size), "%lu", rf->file_size); g_snprintf(str_width, sizeof(str_width), "%d", rf->image_width); g_snprintf(str_height, sizeof(str_height), "%d", rf->image_height); /* invent an unique temporary name for atomic save * FIXME: rough, but works on Win32 */ fnm = g_strdup_printf("%s.%u", rf->thumb_sys, getpid()); if (!gdk_pixbuf_save(pixbuf, fnm, "png", &err, KEY_SOFTWARE, PACKAGE_NAME, KEY_THUMB_URI, rf->file_uri, KEY_THUMB_MTIME, str_mtime, KEY_THUMB_FILESIZE, str_size, KEY_THUMB_IMAGE_WIDTH, str_width, KEY_THUMB_IMAGE_HEIGHT, str_height, KEY_THUMB_GWY_REAL_SIZE, rf->image_real_size, NULL)) { g_clear_error(&err); rf->thumb_state = FILE_STATE_FAILED; } #ifndef G_OS_WIN32 chmod(fnm, 0600); #endif g_unlink(rf->thumb_sys); if (g_rename(fnm, rf->thumb_sys) != 0) { g_unlink(fnm); rf->thumb_state = FILE_STATE_FAILED; rf->thumb_mtime = 0; } else { rf->thumb_state = FILE_STATE_UNKNOWN; /* force reload */ rf->thumb_mtime = rf->file_mtime; } g_free(fnm); gwy_object_unref(rf->pixbuf); g_object_unref(pixbuf); }
/** * gwy_data_field_get_weighted_correlation_score: * @data_field: A data field. * @kernel_field: Kernel to correlate data field with. * @weight_field: data field of same size as kernel window size * @col: Upper-left column position in the data field. * @row: Upper-left row position in the data field. * @kernel_col: Upper-left column position in kernel field. * @kernel_row: Upper-left row position in kernel field. * @kernel_width: Width of kernel field area. * @kernel_height: Heigh of kernel field area. * * Calculates a correlation score in one point using weights to center * the used information to the center of kernel. * * Correlation window size is given * by @kernel_col, @kernel_row, @kernel_width, @kernel_height, * postion of the correlation window on data is given by * @col, @row. * * If anything fails (data too close to boundary, etc.), * function returns -1.0 (none correlation).. * * Returns: Correlation score (between -1.0 and 1.0). Value 1.0 denotes * maximum correlation, -1.0 none correlation. **/ gdouble gwy_data_field_get_weighted_correlation_score(GwyDataField *data_field, GwyDataField *kernel_field, GwyDataField *weight_field, gint col, gint row, gint kernel_col, gint kernel_row, gint kernel_width, gint kernel_height) { gint xres, yres, kxres, kyres, wxres, i, j; gdouble rms1, rms2, avg1, avg2, score; gdouble *data, *kdata, *wdata, weightsum; g_return_val_if_fail(GWY_IS_DATA_FIELD(data_field), -10.0); g_return_val_if_fail(GWY_IS_DATA_FIELD(kernel_field), -11.0); g_return_val_if_fail(GWY_IS_DATA_FIELD(weight_field), -12.0); g_return_val_if_fail(kernel_width == weight_field->xres && kernel_height == weight_field->yres, -13); xres = data_field->xres; yres = data_field->yres; kxres = kernel_field->xres; kyres = kernel_field->yres; wxres = weight_field->xres; /* correlation request outside kernel */ if (kernel_col > kxres || kernel_row > kyres) return -2; /* correlation request outside data field */ if (col < 0 || row < 0 || col + kernel_width > xres || row + kernel_height > yres) { printf("error: %d %d %d %d %d %d\n", col, kernel_width, xres, row, kernel_height, yres); return -3; } if (kernel_col < 0 || kernel_row < 0 || kernel_col + kernel_width > kxres || kernel_row + kernel_height > kyres) return -4; data = data_field->data; kdata = kernel_field->data; wdata = weight_field->data; weightsum = gwy_data_field_get_sum(weight_field); avg1 = avg2 = 0; for (j = 0; j < kernel_height; j++) { /* row */ for (i = 0; i < kernel_width; i++) { /* col */ avg1 += data[(i + col) + xres*(j + row)]*wdata[i + wxres*j]; avg2 += kdata[(i + kernel_col) + kxres*(j + kernel_row)]*wdata[i + wxres*j]; } } avg1 /= gwy_data_field_get_sum(weight_field); avg2 /= gwy_data_field_get_sum(weight_field); rms1 = rms2 = 0; for (j = 0; j < kernel_height; j++) { /* row */ for (i = 0; i < kernel_width; i++) { /* col */ rms1 += wdata[i + wxres*j]*(data[(i + col) + xres*(j + row)] - avg1) *(data[(i + col) + xres*(j + row)] - avg1); rms2 += wdata[i + wxres*j]*(kdata[(i + kernel_col) + kxres*(j + kernel_row)] - avg2) *(kdata[(i + kernel_col) + kxres*(j + kernel_row)] - avg2); } } rms1 /= gwy_data_field_get_sum(weight_field); rms2 /= gwy_data_field_get_sum(weight_field); rms1 = sqrt(rms1); rms2 = sqrt(rms2); if (rms1 == 0.0) return 0.0; if (rms2 == 0.0) return 0.0; score = 0; data = data_field->data; kdata = kernel_field->data; for (j = 0; j < kernel_height; j++) { /* row */ for (i = 0; i < kernel_width; i++) { /* col */ score += wdata[i + wxres*j]*(data[(i + col) + xres*(j + row)] - avg1) * (kdata[(i + kernel_col) + kxres*(j + kernel_row)] - avg2); } } //printf("%g %g %g %g = %g\n", rms1, rms2, score, weightsum, score/(rms1 * rms2 * weightsum)); score /= rms1 * rms2 * weightsum; return score; }
/** * file_plugin_proxy_load: * @filename. A file name to load. * @mode: Run mode. * @error: Return location for a #GError (or %NULL). * @name: Plug-in name (i.e. file-loading function) to run. * * The plug-in proxy itself, runs file-loading plug-in @name to load @filename. * * Returns: A newly created data container with the contents of @filename, * or %NULL if it fails. **/ static GwyContainer* file_plugin_proxy_load(const gchar *filename, GwyRunType mode, GError **error, const gchar *name) { FilePluginInfo *info; GwyContainer *data = NULL; GObject *dfield; gchar *tmpname = NULL, *buffer = NULL; GError *err = NULL; gint exit_status; gsize size = 0; FILE *fh; gchar *args[] = { NULL, NULL, NULL, NULL, NULL }; gboolean ok; gwy_debug("called as %s with file `%s'", name, filename); if (mode != GWY_RUN_INTERACTIVE) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_INTERACTIVE, _("Plugin-proxy must be run as interactive.")); return NULL; } if (!(info = file_find_plugin(name, GWY_FILE_OPERATION_LOAD))) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_UNIMPLEMENTED, _("Plug-in `%s' does not implement file loading."), name); return NULL; } if (!(fh = open_temporary_file(&tmpname, error))) return NULL; args[0] = info->file; args[1] = g_strdup(gwy_enum_to_string(GWY_FILE_OPERATION_LOAD, file_op_names, -1)); args[2] = tmpname; 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 (ok) { ok = g_file_get_contents(tmpname, &buffer, &size, &err); if (!ok) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_IO, _("Cannot read temporary file: %s."), err->message); g_clear_error(&err); } } else { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_SPECIFIC, _("Cannot execute plug-in `%s': %s."), name, err->message); g_clear_error(&err); } g_unlink(tmpname); fclose(fh); gwy_debug("ok = %d, exit_status = %d, err = %p", ok, exit_status, err); if (ok && exit_status) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_SPECIFIC, _("Plug-in `%s' returned non-zero exit status: %d."), name, exit_status); ok = FALSE; } if (ok) { data = text_dump_import(buffer, size, error); if (!data) ok = FALSE; } if (ok && (!gwy_container_gis_object_by_name(data, "/0/data", &dfield) || !GWY_IS_DATA_FIELD(dfield))) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Plug-in `%s' did not return any meaningful data."), name); gwy_object_unref(data); } g_free(args[1]); g_free(args[3]); g_free(buffer); g_free(tmpname); return data; }
/** * gwy_data_field_get_correlation_score: * @data_field: A data field. * @kernel_field: Kernel to correlate data field with. * @col: Upper-left column position in the data field. * @row: Upper-left row position in the data field. * @kernel_col: Upper-left column position in kernel field. * @kernel_row: Upper-left row position in kernel field. * @kernel_width: Width of kernel field area. * @kernel_height: Heigh of kernel field area. * * Calculates a correlation score in one point. * * Correlation window size is given * by @kernel_col, @kernel_row, @kernel_width, @kernel_height, * postion of the correlation window on data is given by * @col, @row. * * If anything fails (data too close to boundary, etc.), * function returns -1.0 (none correlation).. * * Returns: Correlation score (between -1.0 and 1.0). Value 1.0 denotes * maximum correlation, -1.0 none correlation. **/ gdouble gwy_data_field_get_correlation_score(GwyDataField *data_field, GwyDataField *kernel_field, gint col, gint row, gint kernel_col, gint kernel_row, gint kernel_width, gint kernel_height) { gint xres, yres, kxres, kyres, i, j; gdouble rms1, rms2, avg1, avg2, sumpoints, score; gdouble *data, *kdata; g_return_val_if_fail(GWY_IS_DATA_FIELD(data_field), -1.0); g_return_val_if_fail(GWY_IS_DATA_FIELD(kernel_field), -1.0); xres = data_field->xres; yres = data_field->yres; kxres = kernel_field->xres; kyres = kernel_field->yres; kernel_width = kernel_width; kernel_height = kernel_height; /* correlation request outside kernel */ if (kernel_col > kxres || kernel_row > kyres) return -1; /* correlation request outside data field */ if (col < 0 || row < 0 || col + kernel_width > xres || row + kernel_height > yres) return -1; if (kernel_col < 0 || kernel_row < 0 || kernel_col + kernel_width > kxres || kernel_row + kernel_height > kyres) return -1; avg1 = gwy_data_field_area_get_avg(data_field, NULL, col, row, kernel_width, kernel_height); avg2 = gwy_data_field_area_get_avg(kernel_field, NULL, kernel_col, kernel_row, kernel_width, kernel_height); rms1 = gwy_data_field_area_get_rms(data_field, NULL, col, row, kernel_width, kernel_height); if (rms1 == 0.0) return 0.0; rms2 = gwy_data_field_area_get_rms(kernel_field, NULL, kernel_col, kernel_row, kernel_width, kernel_height); if (rms2 == 0.0) return 0.0; score = 0; sumpoints = kernel_width * kernel_height; data = data_field->data; kdata = kernel_field->data; for (j = 0; j < kernel_height; j++) { /* row */ for (i = 0; i < kernel_width; i++) { /* col */ score += (data[(i + col) + xres*(j + row)] - avg1) * (kdata[(i + kernel_col) + kxres*(j + kernel_row)] - avg2); } } score /= rms1 * rms2 * sumpoints; return score; }