Example #1
0
/**
 * 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);
}
Example #2
0
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);
}
Example #3
0
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);
}
Example #4
0
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);
}
Example #5
0
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);
}
Example #6
0
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;
}
Example #7
0
/* 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;
}
Example #8
0
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;
}
Example #9
0
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);
}
Example #10
0
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);
}
Example #11
0
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);
}
Example #12
0
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);
    }
Example #13
0
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;
}
Example #14
0
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);
}
Example #15
0
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"));
}
Example #16
0
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);
}
Example #17
0
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);
}
Example #18
0
/**
 * 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);
}
Example #19
0
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);
}
Example #20
0
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);

}
Example #21
0
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);
}
Example #22
0
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);
}
Example #23
0
/**
 * 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);
}
Example #24
0
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);
}
Example #25
0
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);
    }
}
Example #26
0
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;
}
Example #27
0
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);
}
Example #28
0
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);
}