예제 #1
0
static gboolean
fill_data_fields(SurfFile *surffile,
                 const guchar *buffer,
                 GError **error)
{
    GwySIUnit *siunit;
    gdouble *data;
    guint i, j;

    surffile->dfield = gwy_data_field_new(surffile->xres,
                                          surffile->yres,
                                          surffile->xres*surffile->dx,
                                          surffile->yres*surffile->dy,
                                          FALSE);

    data = gwy_data_field_get_data(surffile->dfield);
    switch (surffile->pointsize) {
        case 16:
        {
            const gint16 *row, *d16 = (const gint16*)buffer;

            for (i = 0; i < surffile->xres; i++) {
                row = d16 + i*surffile->yres;
                for (j = 0; j < surffile->yres; j++)
                    *(data++) = GINT16_FROM_LE(row[j]) * surffile->dz;
            }
        }
        break;

        case 32:
        {
            const gint32 *row, *d32 = (const gint32*)buffer;

            for (i = 0; i < surffile->xres; i++) {
                row = d32 + i*surffile->yres;
                for (j = 0; j < surffile->yres; j++)
                    *(data++) = GINT32_FROM_LE(row[j]) * surffile->dz;
            }
        }
        break;

        default:
        err_BPP(error, surffile->pointsize);
        return FALSE;
        break;
    }

    siunit = gwy_si_unit_new("m");
    gwy_data_field_set_si_unit_xy(surffile->dfield, siunit);
    g_object_unref(siunit);

    siunit = gwy_si_unit_new("m");
    gwy_data_field_set_si_unit_z(surffile->dfield, siunit);
    g_object_unref(siunit);

    return TRUE;
}
예제 #2
0
파일: surface.c 프로젝트: cbuehler/gwyddion
static void
ensure_units(GwySurface *surface)
{
    Surface *priv = surface->priv;

    if (!priv->si_unit_xy)
        priv->si_unit_xy = gwy_si_unit_new(NULL);
    if (!priv->si_unit_z)
        priv->si_unit_z = gwy_si_unit_new(NULL);
}
예제 #3
0
static GwyGraphModel*
rhk_sm4_page_to_graph_model(const RHKPage *page)
{
    GwyGraphModel *gmodel;
    GwyGraphCurveModel *gcmodel;
    GwySIUnit *siunit;
    const gint32 *pdata;
    const gchar *name;
    gint res, ncurves, i, j;
    gdouble *xdata, *ydata;

    res = page->x_size;
    ncurves = page->y_size;

    gmodel = gwy_graph_model_new();
    pdata = (const gint32*)page->data;
    xdata = g_new(gdouble, res);
    ydata = g_new(gdouble, res);
    name = page->strings[RHK_STRING_LABEL];
    for (i = 0; i < ncurves; i++) {
        gcmodel = gwy_graph_curve_model_new();
        for (j = 0; j < res; j++) {
            xdata[j] = j*page->x_scale + page->x_offset;
            ydata[j] = (GINT32_FROM_LE(pdata[i*res + j])*page->z_scale
                        + page->z_offset);
        }
        gwy_graph_curve_model_set_data(gcmodel, xdata, ydata, res);
        g_object_set(gcmodel,
                     "mode", GWY_GRAPH_CURVE_LINE,
                     "color", gwy_graph_get_preset_color(i),
                     NULL);
        if (name)
            g_object_set(gcmodel, "description", name, NULL);
        gwy_graph_model_add_curve(gmodel, gcmodel);
        g_object_unref(gcmodel);
    }
    g_free(ydata);
    g_free(xdata);

    /* Units */
    siunit = gwy_si_unit_new(page->strings[RHK_STRING_X_UNITS]);
    g_object_set(gmodel, "si-unit-x", siunit, NULL);
    g_object_unref(siunit);

    siunit = gwy_si_unit_new(page->strings[RHK_STRING_Z_UNITS]);
    g_object_set(gmodel, "si-unit-y", siunit, NULL);
    g_object_unref(siunit);

    if (name)
        g_object_set(gmodel, "title", name, NULL);

    return gmodel;
}
예제 #4
0
static GwyDataField*
read_text_data(const gchar *buffer,
               gint text_data_start,
               GHashTable *hash,
               GError **error)
{
    const gchar *p;
    gchar *end;
    gint xres, yres, i, power10;
    gdouble xreal, yreal, zscale, xoff, yoff, zoff;
    GwySIUnit *unitxy, *unitz;
    GwyDataField *dfield = NULL;
    gdouble *d;

    unitxy = gwy_si_unit_new(NULL);
    unitz = gwy_si_unit_new(NULL);

    if (!get_scales(hash, TRUE,
                    &xres, &yres, &xreal, &yreal, &xoff, &yoff, unitxy,
                    &zscale, &zoff, unitz, error))
        goto fail;

    p = g_hash_table_lookup(hash, "DATA Unit");
    gwy_si_unit_set_from_string_parse(unitz, p, &power10);
    zscale = pow10(power10);

    dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE);
    gwy_data_field_set_xoffset(dfield, xoff);
    gwy_data_field_set_yoffset(dfield, yoff);
    gwy_data_field_set_si_unit_xy(dfield, unitxy);
    gwy_data_field_set_si_unit_z(dfield, unitz);
    d = gwy_data_field_get_data(dfield);

    p = (const gchar*)buffer + text_data_start;
    for (i = 0; i < xres*yres; i++) {
        d[i] = zscale*g_ascii_strtod(p, &end) + zoff;
        if (end == p) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("Cannot parse data values after %d of %d."),
                        i, xres*yres);
            gwy_object_unref(dfield);
            goto fail;
        }
        p = end + (*end == ',');
    }

fail:
    g_object_unref(unitxy);
    g_object_unref(unitz);
    return dfield;
}
예제 #5
0
static GwyDataField*
rhk_sm3_page_to_data_field(const RHKPage *page)
{
    GwyDataField *dfield;
    GwySIUnit *siunit;
    const gchar *unit;
    gint xres, yres, i;
    const gint32 *pdata;
    gdouble *data;

    xres = page->x_size;
    yres = page->y_size;
    dfield = gwy_data_field_new(xres, yres,
                                xres*fabs(page->x_scale),
                                yres*fabs(page->y_scale),
                                FALSE);
    data = gwy_data_field_get_data(dfield);
    pdata = (const gint32*)page->page_data;
    for (i = 0; i < xres*yres; i++)
        data[i] = GINT32_FROM_LE(pdata[i])*page->z_scale + page->z_offset;

    if (page->strings[RHK_STRING_X_UNITS]
        && page->strings[RHK_STRING_Y_UNITS]) {
        if (!gwy_strequal(page->strings[RHK_STRING_X_UNITS],
                          page->strings[RHK_STRING_Y_UNITS]))
            g_warning("X and Y units are different, using X");
        unit = page->strings[RHK_STRING_X_UNITS];
    }
    else if (page->strings[RHK_STRING_X_UNITS])
        unit = page->strings[RHK_STRING_X_UNITS];
    else if (page->strings[RHK_STRING_Y_UNITS])
        unit = page->strings[RHK_STRING_Y_UNITS];
    else
        unit = "";
    siunit = gwy_si_unit_new(unit);
    gwy_data_field_set_si_unit_xy(dfield, siunit);
    g_object_unref(siunit);

    if (page->strings[RHK_STRING_Z_UNITS])
        unit = page->strings[RHK_STRING_Z_UNITS];
    else
        unit = "";
    /* Fix some silly units */
    if (gwy_strequal(unit, "N/sec"))
        unit = "s^-1";
    siunit = gwy_si_unit_new(unit);
    gwy_data_field_set_si_unit_z(dfield, siunit);
    g_object_unref(siunit);

    return dfield;
}
예제 #6
0
파일: maskops.c 프로젝트: cbuehler/gwyddion
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);
}
예제 #7
0
/* FIXME: this should be the default constructor */
GtkWidget*
gwy_color_axis_new_default(GtkOrientation orientation)
{
    GwyColorAxis *axis;

    gwy_debug(" ");

    axis = (GwyColorAxis*)g_object_new(GWY_TYPE_COLOR_AXIS, NULL);
    axis->orientation = orientation;
    /* TODO: use some font properties, at least */
    if (orientation == GTK_ORIENTATION_VERTICAL)
        axis->par.textarea = 70;
    else
        axis->par.textarea = 20;

    axis->min = 0.0;
    axis->max = 1.0;

    axis->par.font = pango_font_description_from_string("Helvetica 10");
    axis->gradient = gwy_gradients_get_gradient(GWY_GRADIENT_DEFAULT);
    g_object_ref(axis->gradient);
    /* XXX: remove */
    axis->palette = (GwyPalette*)gwy_palette_new(NULL);
    axis->siunit = GWY_SI_UNIT(gwy_si_unit_new("m"));

    return GTK_WIDGET(axis);
}
예제 #8
0
static GObject*
gwy_si_unit_deserialize(const guchar *buffer,
                        gsize size,
                        gsize *position)
{
    gchar *unitstr = NULL;
    GwySerializeSpec spec[] = {
        { 's', "unitstr", &unitstr, NULL, },
    };
    GwySIUnit *si_unit;

    g_return_val_if_fail(buffer, NULL);

    if (!gwy_serialize_unpack_object_struct(buffer, size, position,
                                            GWY_SI_UNIT_TYPE_NAME,
                                            G_N_ELEMENTS(spec), spec)) {
        return NULL;
    }

    if (unitstr && !*unitstr) {
        g_free(unitstr);
        unitstr = NULL;
    }
    si_unit = gwy_si_unit_new(unitstr);
    g_free(unitstr);

    return (GObject*)si_unit;
}
예제 #9
0
static void
sdfile_set_units(SDFile *sdfile,
                 GwyDataField *dfield)
{
    GwySIUnit *siunit;

    gwy_data_field_multiply(dfield, sdfile->zscale);

    siunit = gwy_si_unit_new("m");
    gwy_data_field_set_si_unit_xy(dfield, siunit);
    g_object_unref(siunit);

    siunit = gwy_si_unit_new("m");
    gwy_data_field_set_si_unit_z(dfield, siunit);
    g_object_unref(siunit);
}
예제 #10
0
static void
set_units(GwyDataField *dfield,
          const MProFile *mprofile,
          const gchar *zunit)
{
    GwySIUnit *siunit;

    if (mprofile->camera_res)
        siunit = gwy_si_unit_new("m");
    else
        siunit = gwy_si_unit_new("");
    gwy_data_field_set_si_unit_xy(dfield, siunit);
    g_object_unref(siunit);

    siunit = gwy_si_unit_new(zunit);
    gwy_data_field_set_si_unit_z(dfield, siunit);
    g_object_unref(siunit);
}
예제 #11
0
/**
 * gwy_spectra_get_si_unit_xy:
 * @spectra: A spectra.
 *
 * Gets SI unit used for the location co-ordinates of spectra.
 *
 * Returns: SI unit corresponding to the  the location co-ordinates of spectra
 *          object. Its reference count is not incremented.
 *
 * Since: 2.7
 **/
GwySIUnit*
gwy_spectra_get_si_unit_xy(GwySpectra *spectra)
{
    g_return_val_if_fail(GWY_IS_SPECTRA(spectra), NULL);

    if (!spectra->si_unit_xy)
        spectra->si_unit_xy = gwy_si_unit_new(NULL);

    return spectra->si_unit_xy;
}
예제 #12
0
파일: surface.c 프로젝트: cbuehler/gwyddion
/**
 * gwy_surface_get_si_unit_z:
 * @surface: A surface.
 *
 * Returns value SI unit of a surface.
 *
 * Returns: SI unit corresponding to the "height" (Z) dimension of the surface.
 *          Its reference count is not incremented.
 *
 * Since: 2.45
 **/
GwySIUnit*
gwy_surface_get_si_unit_z(GwySurface *surface)
{
    g_return_val_if_fail(GWY_IS_SURFACE(surface), NULL);

    if (!surface->priv->si_unit_z)
        surface->priv->si_unit_z = gwy_si_unit_new(NULL);

    return surface->priv->si_unit_z;
}
예제 #13
0
static GwyDataField*
create_mask_field(GwyDataField *dfield)
{
    GwyDataField *mfield;
    GwySIUnit *siunit;

    mfield = gwy_data_field_new_alike(dfield, FALSE);
    siunit = gwy_si_unit_new("");
    gwy_data_field_set_si_unit_z(mfield, siunit);
    g_object_unref(siunit);

    return mfield;
}
예제 #14
0
파일: oldmda.c 프로젝트: cbuehler/gwyddion
static void
oldmda_read_params(MDAXMLParams *par, OldMDAFile *mdafile)
{
    MDAAxis axis;
    mdafile->zres = par->res;
    mdafile->xdata = par->xdata;
    axis = g_array_index(par->axes, MDAAxis, 0);
    if (axis.unitname)
        mdafile->siunitz = gwy_si_unit_new(axis.unitname);
    else
        mdafile->siunitz = gwy_si_unit_new("");
    axis = g_array_index(par->axes, MDAAxis, 1);
    if (axis.unitname)
        mdafile->siunitx = gwy_si_unit_new_parse(axis.unitname,
                                                &mdafile->power10x);
    else
        mdafile->siunitx = gwy_si_unit_new("");
    mdafile->xres = axis.maxindex - axis.minindex + 1;
    if (mdafile->xres < 1)
        mdafile->xres = 1;
    if (axis.scale <= 0.0)
        axis.scale = 1.0;
    mdafile->xreal = axis.scale * mdafile->xres
                   * pow(10.0, mdafile->power10x);
    axis = g_array_index(par->axes, MDAAxis, 2);
    if (axis.unitname)
        mdafile->siunity = gwy_si_unit_new_parse(axis.unitname,
                                                &mdafile->power10y);
    else
        mdafile->siunity = gwy_si_unit_new("");
    mdafile->yres = axis.maxindex - axis.minindex + 1;
    if (mdafile->yres < 1)
        mdafile->yres = 1;
    if (axis.scale <= 0.0)
        axis.scale = 1.0;
    mdafile->yreal = axis.scale * mdafile->yres
                   * pow(10.0, mdafile->power10y);
}
예제 #15
0
/**
 * gwy_si_unit_power:
 * @siunit: An SI unit.
 * @power: Power to raise @siunit to.
 * @result:  An SI unit to set to power of @siunit.  It is safe to pass
 *           @siunit itself.  It can be %NULL too, a new SI unit is created
 *           then and returned.
 *
 * Computes a power of an SI unit.
 *
 * Returns: When @result is %NULL, a newly created SI unit that has to be
 *          dereferenced when no longer used later.  Otherwise @result itself
 *          is simply returned, its reference count is NOT increased.
 **/
GwySIUnit*
gwy_si_unit_power(GwySIUnit *siunit,
                  gint power,
                  GwySIUnit *result)
{
    g_return_val_if_fail(GWY_IS_SI_UNIT(siunit), NULL);
    g_return_val_if_fail(!result || GWY_IS_SI_UNIT(result), NULL);

    if (!result)
        result = gwy_si_unit_new(NULL);

    gwy_si_unit_power_real(siunit, power, result);
    g_signal_emit(result, si_unit_signals[VALUE_CHANGED], 0);

    return result;
}
예제 #16
0
static SensolyticsChannel*
create_fields(GHashTable *hash,
              /* Can we obtain any useful information from this? */
              G_GNUC_UNUSED gchar *line,
              gint ndata,
              const Dimensions *dimensions)
{
    SensolyticsChannel *channels;
    GString *str;
    const gchar *value;
    GwySIUnit *unit;
    gint i, power10;

    str = g_string_new(NULL);
    channels = g_new0(SensolyticsChannel, ndata+1);
    for (i = 0; i < ndata; i++) {
        channels[i].dfield = gwy_data_field_new(dimensions->xres,
                                                dimensions->yres,
                                                dimensions->xreal,
                                                dimensions->yreal,
                                                FALSE);
        channels[i].data = gwy_data_field_get_data(channels[i].dfield);

        unit = gwy_si_unit_new("m");
        gwy_data_field_set_si_unit_xy(channels[i].dfield, unit);
        g_object_unref(unit);

        g_string_printf(str, "Channel %d Unit", i+1);
        channels[i].q = 1.0;
        if ((value = g_hash_table_lookup(hash, str->str))) {
            unit = gwy_si_unit_new_parse(value, &power10);
            gwy_data_field_set_si_unit_z(channels[i].dfield, unit);
            g_object_unref(unit);
            channels[i].q = pow10(power10);
        }
        else
            g_warning("Channel %d has no units", i+1);

        g_string_printf(str, "Channel %d Name", i+1);
        if (!(channels[i].name = g_hash_table_lookup(hash, str->str)))
            g_warning("Channel %d has no name", i+1);
    }

    return channels;
}
예제 #17
0
static GByteArray*
gwy_spectra_serialize(GObject *obj,
                      GByteArray *buffer)
{
    GwySpectra *spectra;
    GwyDataLine **curves;
    gdouble *coords;
    guint32 *selected;
    guint32 ncurves, ncoords, nselected;
    GByteArray *retval;

    gwy_debug("");
    g_return_val_if_fail(GWY_IS_SPECTRA(obj), NULL);

    spectra = GWY_SPECTRA(obj);
    if (!spectra->si_unit_xy)
        spectra->si_unit_xy = gwy_si_unit_new(NULL);

    separate_arrays(spectra->spectra,
                    &ncurves, &curves,
                    &ncoords, &coords,
                    &nselected, &selected);

    {
        GwySerializeSpec spec[] = {
            { 's', "title",       &spectra->title,       NULL,       },
            { 'o', "si_unit_xy",  &spectra->si_unit_xy,  NULL,       },
            { 'D', "coords",      &coords,               &ncoords,   },
            { 'I', "selected",    &selected,             &nselected, },
            { 'O', "data",        &curves,               &ncurves,   },
            { 's', "spec_xlabel", &spectra->spec_xlabel, NULL,       },
            { 's', "spec_ylabel", &spectra->spec_ylabel, NULL,       },
        };
        guint nspec = fix_serialisation_spec(spec);

        retval = gwy_serialize_pack_object_struct(buffer,
                                                  GWY_SPECTRA_TYPE_NAME,
                                                  nspec, spec);
    }
    g_free(curves);
    g_free(coords);
    g_free(selected);

    return retval;
}
예제 #18
0
/**
 * gwy_color_axis_new:
 * @orientation: The orientation of the axis.
 * @min: The minimum.
 * @max: The maximum.
 * @pal: The palette the color axis should use.
 *
 * Creates a new color axis.
 *
 * Returns: The newly created color axis as a #GtkWidget.
 **/
GtkWidget*
gwy_color_axis_new(GtkOrientation orientation,
                   gdouble min,
                   gdouble max,
                   GwyPalette *pal)
{
    GwyColorAxis *axis;

    gwy_debug("");
    g_return_val_if_fail(GWY_IS_PALETTE(pal), NULL);

    axis = gtk_type_new(gwy_color_axis_get_type());
    axis->orientation = orientation;
    /* TODO: use some font properties, at least */
    if (orientation == GTK_ORIENTATION_VERTICAL)
        axis->par.textarea = 70;
    else
        axis->par.textarea = 20;
    axis->min = min;
    axis->max = max;

    /* XXX */
    axis->par.font = pango_font_description_new();
    pango_font_description_set_family(axis->par.font, "Helvetica");
    pango_font_description_set_style(axis->par.font, PANGO_STYLE_NORMAL);
    pango_font_description_set_variant(axis->par.font, PANGO_VARIANT_NORMAL);
    pango_font_description_set_weight(axis->par.font, PANGO_WEIGHT_NORMAL);
    pango_font_description_set_size(axis->par.font, 10*PANGO_SCALE);

    axis->gradient = gwy_gradients_get_gradient(GWY_GRADIENT_DEFAULT);
    g_object_ref(axis->gradient);
    /* XXX: remove */
    axis->palette = (GwyPalette*)gwy_palette_new(NULL);
    gwy_color_axis_set_palette(axis, pal);
    axis->siunit = GWY_SI_UNIT(gwy_si_unit_new("m"));

    return GTK_WIDGET(axis);
}
예제 #19
0
static GwyDataField*
read_binary_data(const gchar *buffer,
                 gsize size,
                 GHashTable *hash,
                 GError **error)
{
    ShimadzuDataType data_type;
    gint xres, yres, i;
    guint expected;
    gdouble xreal, yreal, zscale, xoff, yoff, zoff;
    GwySIUnit *unitxy, *unitz;
    GwyDataField *dfield = NULL;
    gdouble *d;
    const gchar *s;

    if (!(s = g_hash_table_lookup(hash, "DataType"))) {
        err_MISSING_FIELD(error, "DataType");
        return NULL;
    }

    if (g_ascii_strcasecmp(s, "short") == 0)
        data_type = SHIMADZU_SHORT;
    else if (g_ascii_strcasecmp(s, "float") == 0)
        data_type = SHIMADZU_FLOAT;
    else {
        err_UNSUPPORTED(error, "DataType");
        return NULL;
    }

    unitxy = gwy_si_unit_new(NULL);
    unitz = gwy_si_unit_new(NULL);

    if (!get_scales(hash, FALSE,
                    &xres, &yres, &xreal, &yreal, &xoff, &yoff, unitxy,
                    &zscale, &zoff, unitz, error))
        goto fail;

    expected = data_type*xres*yres + HEADER_SIZE;
    if (err_SIZE_MISMATCH(error, expected, size, FALSE))
        goto fail;

    dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE);
    gwy_data_field_set_xoffset(dfield, xoff);
    gwy_data_field_set_yoffset(dfield, yoff);
    gwy_data_field_set_si_unit_xy(dfield, unitxy);
    gwy_data_field_set_si_unit_z(dfield, unitz);
    d = gwy_data_field_get_data(dfield);

    if (data_type == SHIMADZU_SHORT) {
        const gint16 *d16 = (const gint16*)(buffer + HEADER_SIZE);

        for (i = 0; i < xres*yres; i++)
            d[i] = zscale*GUINT16_FROM_LE(d16[i]) + zoff;
    }
    else if (data_type == SHIMADZU_FLOAT) {
        const guchar *p = buffer + HEADER_SIZE;

        for (i = 0; i < xres*yres; i++)
            d[i] = zscale*gwy_get_gfloat_le(&p) + zoff;
    }
    else {
        g_assert_not_reached();
    }

    gwy_data_field_invert(dfield, TRUE, FALSE, FALSE);

fail:
    g_object_unref(unitxy);
    g_object_unref(unitz);
    return dfield;
}
예제 #20
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);
}
예제 #21
0
static GwyContainer*
ecs_load(const gchar *filename,
         G_GNUC_UNUSED GwyRunType mode,
         GError **error)
{
    GwyContainer *meta, *container = NULL;
    guchar *buffer = NULL;
    gsize size = 0;
    GError *err = NULL;
    GwyDataField *dfield = NULL;
    gchar *s = NULL, *s2 = NULL;
    GwySIUnit *siunit;
    const guchar *p;
    gdouble *data, *row;
    guint xres, yres, i, j;
    gdouble xreal, q;
    const gint16 *pdata;
    guchar c;

    if (!gwy_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        g_clear_error(&err);
        return NULL;
    }
    if (size < HEADER_SIZE + 2) {
        err_TOO_SHORT(error);
        goto fail;
    }

    p = buffer + ECS_RESOLUTION;
    xres = gwy_get_guint16_le(&p);
    yres = gwy_get_guint16_le(&p);
    gwy_debug("xres: %u, yres: %u", xres, yres);
    if (size != HEADER_SIZE + 2*xres*yres) {
        err_SIZE_MISMATCH(error, HEADER_SIZE + 2*xres*yres, size);
        goto fail;
    }

    /* Scan size */
    p = buffer + ECS_SCAN_SIZE;
    s = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_SCAN_SIZE);
    if (!s) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Scan size header field overlaps with data."));
        goto fail;
    }
    gwy_debug("Scan size str: <%s>", s);
    if (!g_str_has_prefix(s, "Scan Size: ")) {
        err_FILE_TYPE(error, "ECS");
        goto fail;
    }
    if (sscanf(s + strlen("Scan Size: "), "%lf %lf%c", &xreal, &q, &c)
        != 3) {
        err_INVALID(error, "Scan Size");
        goto fail;
    }
    g_free(s);
    s = NULL;
    gwy_debug("xreal: %g q: %g unit: %s",
              xreal, q, c == 0x8f ? "Angstrom" : "Nanometer");

    if (c == 0x8f) {
        xreal *= 1e-10;
        q *= 1e-10;
    }
    else {
        xreal *= 1e-9;
        q *= 1e-9;
    }
    q /= 65536.0;

    /* This does not make much sense when xres != yres, but it is what
     * Snomputz does. */
    dfield = gwy_data_field_new(xres, yres, xreal, xreal, FALSE);
    data = gwy_data_field_get_data(dfield);
    pdata = (const gint16*)(buffer + HEADER_SIZE);
    for (i = 0; i < yres; i++) {
        row = data + (yres-1 - i)*xres;
        for (j = 0; j < xres; j++)
            row[j] = GINT16_TO_LE(pdata[i*xres + j])*q;
    }

    siunit = gwy_si_unit_new("m");
    gwy_data_field_set_si_unit_xy(dfield, siunit);
    g_object_unref(siunit);

    siunit = gwy_si_unit_new("m");
    gwy_data_field_set_si_unit_z(dfield, siunit);
    g_object_unref(siunit);

    container = gwy_container_new();
    gwy_container_set_object_by_name(container, "/0/data", dfield);

    /* Channel title */
    p = buffer + ECS_CHANNEL;
    s = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_CHANNEL);
    if (!s || !*s)
        s = g_strdup("Topography");
    gwy_container_set_string_by_name(container, "/0/data/title", s);
    s = NULL;

    meta = gwy_container_new();

    /* Date & time */
    p = buffer + ECS_DATE;
    s = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_DATE);
    if (s) {
        p = buffer + ECS_TIME;
        s2 = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_TIME);
        if (s2) {
            gwy_container_set_string_by_name(meta, "Date",
                                             g_strconcat(s, " ", s2, NULL));
            g_free(s2);
            s2 = NULL;
        }
        g_free(s);
        s = NULL;
    }

    /* Channel title */
    p = buffer + ECS_CHANNEL;
    s = get_PASCAL_STRING(&p, HEADER_SIZE - ECS_CHANNEL);
    if (s && *s) {
        gwy_container_set_string_by_name(meta, "Comment", s);
        s = NULL;
    }

    if (gwy_container_get_n_items(meta))
        gwy_container_set_object_by_name(container, "/0/meta", meta);
    g_object_unref(meta);

fail:
    g_free(s);
    g_free(s2);
    gwy_object_unref(dfield);
    gwy_file_abandon_contents(buffer, size, NULL);

    return container;
}
예제 #22
0
static GwyGraphModel*
pt3file_extract_decay(const PicoHarpFile *pt3file,
                      const guchar *buf)
{
    GwyGraphModel *gmodel;
    GwyGraphCurveModel *gcmodel;
    GwySIUnit *siunit;
    gdouble *xdata, *ydata;
    guint maxtime, n, i;
    const guchar *p;

    n = pt3file->number_of_records;

    maxtime = 0;
    p = buf;
    for (i = 0; i < n; i++) {
        PicoHarpT3Record rec;

        p = read_t3_record(&rec, p);
        if (rec.channel != 15 && rec.time > maxtime)
            maxtime = rec.time;
    }

    xdata = g_new(gdouble, maxtime+1);
    for (i = 0; i <= maxtime; i++)
        xdata[i] = 1e-9*i*pt3file->board.resolution;
    ydata = g_new0(gdouble, maxtime+1);

    p = buf;
    for (i = 0; i < n; i++) {
        PicoHarpT3Record rec;

        p = read_t3_record(&rec, p);
        if (rec.channel != 15)
            ydata[rec.time] += 1.0;
    }

    gcmodel = gwy_graph_curve_model_new();
    g_object_set(gcmodel,
                 "mode", GWY_GRAPH_CURVE_LINE,
                 "description", "Fluorescence decay",
                 NULL);
    gwy_graph_curve_model_set_data(gcmodel, xdata, ydata, maxtime+1);
    g_free(ydata);
    g_free(xdata);

    siunit = gwy_si_unit_new("s");

    gmodel = gwy_graph_model_new();
    g_object_set(gmodel,
                 "title", "Fluorescence decay",
                 "si-unit-x", siunit,
                 "axis-label-bottom", "time",
                 "axis-label-left", "count",
                 NULL);
    gwy_graph_model_add_curve(gmodel, gcmodel);
    g_object_unref(gcmodel);
    g_object_unref(siunit);

    return gmodel;
}
예제 #23
0
static gboolean
get_scales(GHashTable *hash,
           gboolean is_text,
           gint *xres, gint *yres,
           gdouble *xreal, gdouble *yreal,
           gdouble *xoff, gdouble *yoff,
           GwySIUnit *si_unit_xy,
           gdouble *zscale,
           gdouble *zoff,
           GwySIUnit *si_unit_z,
           GError **error)
{
    GwySIUnit *unit;
    gint power10, zp;
    gchar *p;
    gboolean has_unit = FALSE;

    /* Dimensions are mandatory. */
    if (!require_keys(hash, error,
                      "SCANNING PARAMS::PixelsX",
                      "SCANNING PARAMS::PixelsY",
                      "SCANNING PARAMS::PixelsZ",
                      "SCANNING PARAMS::SizeX",
                      "SCANNING PARAMS::SizeY",
                      "SCANNING PARAMS::SizeZ",
                      NULL))
        return FALSE;

    *xres = atoi(g_hash_table_lookup(hash, "SCANNING PARAMS::PixelsX"));
    if (err_DIMENSION(error, *xres))
        return FALSE;
    *yres = atoi(g_hash_table_lookup(hash, "SCANNING PARAMS::PixelsY"));
    if (err_DIMENSION(error, *yres))
        return FALSE;

    unit = gwy_si_unit_new(NULL);

    p = g_hash_table_lookup(hash, "SCANNING PARAMS::SizeX");
    *xreal = fabs(g_ascii_strtod(p, &p));
    if (!*xreal) {
        g_warning("Real x size is 0.0, fixing to 1.0");
        *xreal = 1.0;
    }
    gwy_si_unit_set_from_string_parse(si_unit_xy, p, &power10);
    *xreal *= pow10(power10);

    p = g_hash_table_lookup(hash, "SCANNING PARAMS::SizeY");
    *yreal = fabs(g_ascii_strtod(p, &p));
    if (!*yreal) {
        g_warning("Real y size is 0.0, fixing to 1.0");
        *yreal = 1.0;
    }
    gwy_si_unit_set_from_string_parse(unit, p, &power10);
    *yreal *= pow10(power10);
    if (!gwy_si_unit_equal(unit, si_unit_xy)) {
        g_warning("X and Y units differ, using X");
    }

    zp = atoi(g_hash_table_lookup(hash, "SCANNING PARAMS::PixelsZ"));
    if (!zp) {
        g_warning("Z pixels is 0, fixing to 1");
        zp = 1;
    }
    p = g_hash_table_lookup(hash, "SCANNING PARAMS::SizeZ");
    *zscale = g_ascii_strtod(p, &p);
    *zoff = 0.0;
    gwy_si_unit_set_from_string_parse(si_unit_z, p, &power10);
    *zscale *= pow10(power10)/zp;
    /* XXX: Version 4 can have UNIT section that takes precedence.  The Conv
     * factor may not be enough.  Apparently, binary phase data need
     * subtracting 180 deg because data are unsinged.  Bite me. */
    if ((p = g_hash_table_lookup(hash, "UNIT::Unit"))) {
        const gchar *s = g_hash_table_lookup(hash, "UNIT::Name");
        has_unit = TRUE;
        gwy_si_unit_set_from_string_parse(si_unit_z, p, &power10);
        *zscale *= pow10(power10);
        if ((p = g_hash_table_lookup(hash, "UNIT::Conv")))
            *zscale *= g_ascii_strtod(p, NULL);

        if (!is_text && gwy_strequal(s, "Phase"))
            *zoff = -180.0;
    }

    /* Offsets are optional. */
    *xoff = 0.0;
    if ((p = g_hash_table_lookup(hash, "SCANNING PARAMS::OffsetX"))) {
        *xoff = g_ascii_strtod(p, &p);
        gwy_si_unit_set_from_string_parse(unit, p, &power10);
        if (gwy_si_unit_equal(unit, si_unit_xy))
            *xoff *= pow10(power10);
        else {
            g_warning("X offset units differ from X size units, ignoring.");
            *xoff = 0.0;
        }
    }

    *yoff = 0.0;
    if ((p = g_hash_table_lookup(hash, "SCANNING PARAMS::OffsetY"))) {
        *yoff = g_ascii_strtod(p, &p);
        gwy_si_unit_set_from_string_parse(unit, p, &power10);
        if (gwy_si_unit_equal(unit, si_unit_xy))
            *yoff *= pow10(power10);
        else {
            g_warning("Y offset units differ from Y size units, ignoring.");
            *yoff = 0.0;
        }
    }

    // Don't know what to do with the offset when UNIT section is present.
    // It seems to be always 0 in wrong units, so skip it.
    if (!has_unit) {
        if ((p = g_hash_table_lookup(hash, "SCANNING PARAMS::OffsetZ"))) {
            *zoff = g_ascii_strtod(p, &p);
            gwy_si_unit_set_from_string_parse(unit, p, &power10);
            if (gwy_si_unit_equal(unit, si_unit_z))
                *zoff *= pow10(power10);
            else {
                g_warning("Z offset units differ from Z size units, ignoring.");
                *zoff = 0.0;
            }
        }
    }

    g_object_unref(unit);

    return TRUE;
}
예제 #24
0
static void
create_profiles(const X3PFile *x3pfile,
                GwyContainer *container)
{
    GwyGraphModel *gmodel;
    GwySIUnit *siunitx, *siunity;
    GArray *validx, *validy;
    GQuark quark;
    gint id;

    gmodel = gwy_graph_model_new();
    siunitx = gwy_si_unit_new("m");
    siunity = gwy_si_unit_new("m");
    g_object_set(gmodel,
                 "title", "Profiles",
                 "si-unit-x", siunitx,
                 "si-unit-y", siunity,
                 NULL);
    g_object_unref(siunity);
    g_object_unref(siunitx);

    validx = g_array_new(FALSE, FALSE, sizeof(gdouble));
    validy = g_array_new(FALSE, FALSE, sizeof(gdouble));
    for (id = 0; id < x3pfile->zres; id++) {
        guint n = x3pfile->xres;
        GwyGraphCurveModel *gcmodel;
        gchar *title;
        guint j;

        g_array_set_size(validx, 0);
        g_array_set_size(validy, 0);
        for (j = 0; j < x3pfile->xres; j++) {
            gdouble v = x3pfile->values[id*n + j];

            if (gwy_isnan(v) || gwy_isinf(v) || !x3pfile->valid[id*n + j])
                continue;

            g_array_append_val(validy, v);
            v = j*x3pfile->dx;
            g_array_append_val(validx, v);
        }

        if (!validx->len)
            continue;

        gcmodel = gwy_graph_curve_model_new();
        title = g_strdup_printf("Profile %u", id+1);
        g_object_set(gcmodel,
                     "mode", GWY_GRAPH_CURVE_LINE,
                     "description", title,
                     "color", gwy_graph_get_preset_color(id),
                     NULL);
        g_free(title);
        gwy_graph_curve_model_set_data(gcmodel,
                                       (gdouble*)validx->data,
                                       (gdouble*)validy->data,
                                       validx->len);
        gwy_graph_model_add_curve(gmodel, gcmodel);
        g_object_unref(gcmodel);
    }

    g_array_free(validy, TRUE);
    g_array_free(validx, TRUE);

    quark = gwy_app_get_graph_key_for_id(0);
    gwy_container_set_object(container, quark, gmodel);
    g_object_unref(gmodel);
}
예제 #25
0
static GwyContainer*
burleigh_load(const gchar *filename)
{
    GwySIUnit *unit;
    GwyContainer *container = NULL;
    guchar *buffer = NULL;
    const guchar *p;
    gsize size = 0;
    GError *err = NULL;
    IMGFile imgfile;
    GwyDataField *dfield;
    gdouble *data;
    const gint16 *d;
    gdouble scale;
    guint i;

    if (!gwy_file_get_contents(filename, &buffer, &size, &err)) {
        g_warning("Cannot get file contents");
        g_clear_error(&err);
        return NULL;
    }
    if (size < HEADER_SIZE_MIN + 2) {
        g_warning("File is too short");
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    memset(&imgfile, 0, sizeof(imgfile));
    p = buffer;
    imgfile.version = get_FLOAT(&p);
    imgfile.version_int = ROUND(10*imgfile.version);
    if (imgfile.version_int == 21) {
        d = burleigh_load_v21(&imgfile, buffer, size);
        if (!d) {
            gwy_file_abandon_contents(buffer, size, NULL);
            return NULL;
        }
    }
    else {
        g_warning("File format version %.f is not supported", imgfile.version);
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    dfield = GWY_DATA_FIELD(gwy_data_field_new(imgfile.xres, imgfile.yres,
                                               Angstrom*imgfile.xrange,
                                               Angstrom*imgfile.yrange,
                                               FALSE));
    data = gwy_data_field_get_data(dfield);
    scale = Angstrom * imgfile.z_gain * imgfile.zrange;
    for (i = 0; i < imgfile.xres*imgfile.yres; i++)
        data[i] = scale * GINT16_FROM_LE(d[i]);

    gwy_file_abandon_contents(buffer, size, NULL);

    unit = GWY_SI_UNIT(gwy_si_unit_new("m"));
    gwy_data_field_set_si_unit_xy(dfield, unit);
    g_object_unref(unit);

    container = GWY_CONTAINER(gwy_container_new());
    switch (imgfile.data_type) {
        case BURLEIGH_CURRENT:
        unit = GWY_SI_UNIT(gwy_si_unit_new("A"));
        gwy_container_set_string_by_name(container, "/filename/title",
                                         g_strdup("Current"));
        break;

        case BURLEIGH_TOPOGRAPHY:
        unit = GWY_SI_UNIT(gwy_si_unit_new("m"));
        gwy_container_set_string_by_name(container, "/filename/title",
                                         g_strdup("Topography"));
        break;

        default:
        unit = GWY_SI_UNIT(gwy_si_unit_new("m"));
        break;
    }
    gwy_data_field_set_si_unit_z(dfield, unit);
    g_object_unref(unit);

    gwy_container_set_object_by_name(container, "/0/data", (GObject*)dfield);
    g_object_unref(dfield);

    return container;
}
예제 #26
0
static GwySpectra*
rhkspm32_read_spectra(RHKPage *rhkpage)
{
    guint i, j;
    gdouble *data;
    GwySIUnit *siunit = NULL;
    GwyDataLine *dline;
    GwySpectra *spectra = NULL;
    GPtrArray *spectrum = NULL;
    // i'm leaving this alone, though it probably doesn't make sense,
    // and i should just create graphs straight away - but in case of
    // future use, i'll just convert the data later to graphs

    // xres stores number of data points per spectra,
    // yres stores the number of spectra

    // reading data
    gwy_debug("rhk-spm32: %d spectra in this page\n", rhkpage->yres);
    for (i = 0; i < rhkpage->yres; i++) {
        dline = gwy_data_line_new(rhkpage->xres, rhkpage->x.scale, FALSE);
        gwy_data_line_set_offset(dline, (rhkpage->x.offset));
        data = gwy_data_line_get_data(dline);
        // store line data in physical units - which are the z values, not y
        if ((rhkpage->data_type) == RHK_DATA_INT16) {
                const guint16 *p = (const guint16*)(rhkpage->buffer
                                                    + rhkpage->data_offset);
                for (j = 0; j < rhkpage->xres; j++) {
                    data[j] = GINT16_FROM_LE(p[i*(rhkpage->xres) + j])
                            *(rhkpage->z.scale)+(rhkpage->z.offset);
                }
        }
        else if ((rhkpage->data_type) == RHK_DATA_SINGLE) {
                const guchar *p = (const guchar*)(rhkpage->buffer
                                                  + rhkpage->data_offset);
                for (j = 0; j < rhkpage->xres; j++) {
                    data[j] = gwy_get_gfloat_le(&p)*rhkpage->z.scale
                              + rhkpage->z.offset;
                }
        }
        siunit = gwy_si_unit_new(rhkpage->x.units);
        gwy_data_line_set_si_unit_x(dline, siunit);
        g_object_unref(siunit);

        // the y units (and data) for a 1D graph are stored in Z in the rhk
        // spm32 format!
        /* Fix "/\xfbHz" to "/Hz".
         * XXX: It might be still wrong as the strange character might mean
         * sqrt. */
        if (g_str_has_suffix(rhkpage->z.units, "/\xfbHz")) {
            gchar *s = gwy_strkill(g_strdup(rhkpage->z.units), "\xfb");
            siunit = gwy_si_unit_new(s);
            g_free(s);
        }
        else
            siunit = gwy_si_unit_new(rhkpage->z.units);
        gwy_data_line_set_si_unit_y(dline, siunit);
        g_object_unref(siunit);

        if (!spectrum)
            spectrum = g_ptr_array_sized_new(rhkpage->yres);
        g_ptr_array_add(spectrum, dline);
    }
    gwy_debug("rhk-spm32: finished parsing sps data\n");
    spectra = gwy_spectra_new();

    for (i = 0; i < rhkpage->yres; i++) {
        dline = g_ptr_array_index(spectrum, i);
        // since RHK spm32 does not record where it took the spectra,
        // i'm setting these to zero
        gwy_spectra_add_spectrum(spectra, dline, 0, 0);
        g_object_unref(dline);
    }
    gwy_spectra_set_title(spectra, rhkpage->label);

    if (spectrum)
        g_ptr_array_free(spectrum, TRUE);

    return spectra;
}
예제 #27
0
static GwyContainer*
burleigh_load(const gchar *filename,
              G_GNUC_UNUSED GwyRunType mode,
              GError **error)
{
    GwySIUnit *unit;
    GwyContainer *container = NULL;
    guchar *buffer = NULL;
    const guchar *p;
    gsize size = 0;
    GError *err = NULL;
    IMGFile imgfile;
    GwyDataField *dfield;
    gdouble *data;
    const gint16 *d;
    gdouble zoom;
    guint i;

    if (!gwy_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        return NULL;
    }
    if (size < HEADER_SIZE_MIN + 2) {
        err_TOO_SHORT(error);
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    gwy_clear(&imgfile, 1);
    p = buffer;
    imgfile.version = gwy_get_gfloat_le(&p);
    imgfile.version_int = GWY_ROUND(10*imgfile.version);
    if (imgfile.version_int == 21) {
        d = burleigh_load_v21(&imgfile, buffer, size, error);
        if (!d) {
            gwy_file_abandon_contents(buffer, size, NULL);
            return NULL;
        }
    }
    else {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("File format version %.1f is not supported."),
                    imgfile.version);
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    zoom = burleigh_get_zoom_v21(&imgfile);
    if (err_DIMENSION(error, imgfile.xres)
        || err_DIMENSION(error, imgfile.yres)) {
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    dfield = gwy_data_field_new(imgfile.xres, imgfile.yres,
                                Angstrom*imgfile.xrange/zoom,
                                Angstrom*imgfile.yrange/zoom,
                                FALSE);
    data = gwy_data_field_get_data(dfield);
    for (i = 0; i < imgfile.xres*imgfile.yres; i++)
        data[i] = GINT16_FROM_LE(d[i])*imgfile.zrange/4095.0;

    gwy_file_abandon_contents(buffer, size, NULL);

    unit = gwy_si_unit_new("m");
    gwy_data_field_set_si_unit_xy(dfield, unit);
    g_object_unref(unit);

    container = gwy_container_new();
    switch (imgfile.data_type) {
        case BURLEIGH_CURRENT:
        unit = gwy_si_unit_new("A");
        gwy_container_set_string_by_name(container, "/0/data/title",
                                         g_strdup("Current"));
        gwy_data_field_multiply(dfield, Picoampere);
        break;

        case BURLEIGH_TOPOGRAPHY:
        unit = gwy_si_unit_new("m");
        gwy_container_set_string_by_name(container, "/0/data/title",
                                         g_strdup("Topography"));
        gwy_data_field_multiply(dfield, Angstrom);
        break;

        default:
        unit = gwy_si_unit_new("m");
        break;
    }
    gwy_data_field_set_si_unit_z(dfield, unit);
    g_object_unref(unit);

    gwy_container_set_object_by_name(container, "/0/data", dfield);
    g_object_unref(dfield);

    gwy_file_channel_import_log_add(container, 0, NULL, filename);

    return container;
}
예제 #28
0
/* FIXME: this function could use some sort of failure indication, if the
 * file is damaged and no data field can be loaded, suspicionless caller can
 * return empty Container */
static void
tiff_load_channel(TIFF *tiff,
                  GwyContainer *container, GwyContainer *meta,
                  gint idx, gint ilen, gint jlen, gdouble ulen, gdouble vlen)
{
    GwyDataField *dfield;
    GwySIUnit *siunit;
    GString *key;
    gdouble *data;
    guchar *buffer;
    gchar *channel;
    const gchar *name = NULL;
    const gchar *slot = NULL;
    const gchar *unit = NULL;
    gboolean retrace = FALSE;
    gboolean reflect = FALSE;
    gdouble mult = 0.0;
    gdouble offset = 0.0;
    gint num_slots = 0;
    gint i, j;

    tiff_get_custom_string(tiff, JPK_TIFFTAG_ChannelFancyName, &name);
    if (!name)
        tiff_get_custom_string(tiff, JPK_TIFFTAG_Channel, &name);
    g_return_if_fail(name != NULL);

    tiff_get_custom_boolean(tiff, JPK_TIFFTAG_Channel_retrace, &retrace);

    channel = g_strdup_printf("%s%s", name, retrace ? " (retrace)" : "");

    gwy_debug("channel: %s", channel);

    tiff_get_custom_integer(tiff, JPK_TIFFTAG_NrOfSlots, &num_slots);
    g_return_if_fail(num_slots > 0);

    gwy_debug("num_slots: %d", num_slots);

    /* Locate the default slot */

    tiff_get_custom_string(tiff, JPK_TIFFTAG_DefaultSlot, &slot);
    g_return_if_fail(slot != NULL);

    gwy_debug("num_slots: %d, default slot: %s", num_slots, slot);

    for (i = 0; i < num_slots; i++) {
        const gchar *string;

        if (tiff_get_custom_string(tiff, JPK_TIFFTAG_Slot_Name(i), &string)
            && string
            && gwy_strequal(string, slot)) {
            tiff_get_custom_string(tiff, JPK_TIFFTAG_Scaling_Type(i), &string);
            g_return_if_fail(gwy_strequal(string, "LinearScaling"));

            tiff_get_custom_double(tiff, JPK_TIFFTAG_Scaling_Multiply(i),
                                   &mult);
            tiff_get_custom_double(tiff, JPK_TIFFTAG_Scaling_Offset(i),
                                   &offset);

            gwy_debug("multipler: %g offset: %g", mult, offset);

            tiff_get_custom_string(tiff, JPK_TIFFTAG_Encoder_Unit(i), &unit);

            break;
        }
    }

    /* Create a new data field */

    dfield = gwy_data_field_new(ilen, jlen, ulen, vlen, FALSE);

    siunit = gwy_si_unit_new("m");
    gwy_data_field_set_si_unit_xy(dfield, siunit);
    g_object_unref(siunit);

    if (unit) {
        siunit = gwy_si_unit_new(unit);
        gwy_data_field_set_si_unit_z(dfield, siunit);
        g_object_unref(siunit);
    }

    /* Read the scan data */

    data = gwy_data_field_get_data(dfield);

    buffer = g_new(guchar, TIFFScanlineSize(tiff));

    tiff_get_custom_boolean(tiff, JPK_TIFFTAG_Grid_Reflect, &reflect);

    if (!reflect)
        data += (jlen - 1) * ilen;

    for (j = 0; j < jlen; j++) {
        const guint16 *src = (const guint16 *)buffer;
        gdouble *dest = data;

        TIFFReadScanline(tiff, buffer, j, 0);

        for (i = 0; i < ilen; i++) {
            guint16 s = *src++;

            *dest++ = offset + mult * (gdouble)s;
        }

        if (reflect)
            data += ilen;
        else
            data -= ilen;
    }

    /* Add the GwyDataField to the container */

    key = g_string_new("");
    g_string_printf(key, "/%d/data", idx);
    gwy_container_set_object_by_name(container, key->str, dfield);
    g_object_unref(dfield);

    g_string_append(key, "/title");
    gwy_container_set_string_by_name(container, key->str, channel);

    if (gwy_container_get_n_items(meta)) {
        GwyContainer *tmp;

        tmp = gwy_container_duplicate(meta);
        g_string_printf(key, "/%d/meta", idx);
        gwy_container_set_object_by_name(container, key->str, tmp);
        g_object_unref(tmp);
    }

    g_string_free(key, TRUE);
}
예제 #29
0
static void
gwy_data_field_facet_distribution(GwyDataField *dfield,
                                  gint kernel_size,
                                  GwyContainer *container)
{
    GwyDataField *dtheta, *dphi, *dist;
    GwySIUnit *siunit;
    gdouble *xd, *yd, *data;
    const gdouble *xdc, *ydc;
    gdouble q, max;
    gint res, hres, i, j, mi, mj, xres, yres;

    if (gwy_container_gis_object_by_name(container, "/theta", &dtheta))
        g_object_ref(dtheta);
    else
        dtheta = gwy_data_field_new_alike(dfield, FALSE);

    if (gwy_container_gis_object_by_name(container, "/phi", &dphi))
        g_object_ref(dphi);
    else
        dphi = gwy_data_field_new_alike(dfield, FALSE);

    compute_slopes(dfield, kernel_size, dtheta, dphi);
    xres = gwy_data_field_get_xres(dfield);
    yres = gwy_data_field_get_yres(dfield);
    xd = gwy_data_field_get_data(dtheta);
    yd = gwy_data_field_get_data(dphi);

    for (i = xres*yres; i; i--, xd++, yd++) {
        gdouble theta, phi;

        slopes_to_angles(*xd, *yd, &theta, &phi);
        *xd = theta;
        *yd = phi;
    }
    q = gwy_data_field_get_max(dtheta);
    q = MIN(q*1.05, G_PI/2.0);
    q = G_SQRT2/(2.0*sin(q/2.0));

    if (gwy_container_gis_object_by_name(container, "/0/data", &dist)) {
        g_object_ref(dist);
        gwy_data_field_clear(dist);
        gwy_data_field_set_xreal(dist, 2.0*G_SQRT2/q);
        gwy_data_field_set_yreal(dist, 2.0*G_SQRT2/q);
    }
    else {
        dist = gwy_data_field_new(FDATA_RES, FDATA_RES,
                                  2.0*G_SQRT2/q, 2.0*G_SQRT2/q,
                                  TRUE);
        siunit = gwy_si_unit_new("");
        gwy_data_field_set_si_unit_z(dist, siunit);
        g_object_unref(siunit);
        /* FIXME */
        siunit = gwy_si_unit_new("");
        gwy_data_field_set_si_unit_xy(dist, siunit);
        g_object_unref(siunit);
    }

    res = FDATA_RES;
    hres = (res - 1)/2;
    data = gwy_data_field_get_data(dist);

    xdc = gwy_data_field_get_data_const(dtheta);
    ydc = gwy_data_field_get_data_const(dphi);
    for (i = xres*yres; i; i--, xdc++, ydc++) {
        gdouble x, y;
        gint xx, yy;

        angles_to_xy(*xdc, *ydc, &x, &y);
        xx = GWY_ROUND(q*x/G_SQRT2*hres) + hres;
        yy = GWY_ROUND(q*y/G_SQRT2*hres) + hres;
        data[yy*res + xx] += 1.0;
    }

    /* Find maxima */
    mi = mj = hres;
    max = 0;
    for (i = 1; i+1 < res; i++) {
        for (j = 1; j+1 < res; j++) {
            gdouble z;

            z = data[i*res + j]
                + 0.3*(data[i*res + j - 1]
                       + data[i*res + j + 1]
                       + data[i*res - res + j]
                       + data[i*res + res + j])
                + 0.1*(data[i*res - res + j - 1]
                       + data[i*res - res + j + 1]
                       + data[i*res + res + j - 1]
                       + data[i*res + res + j + 1]);
            if (G_UNLIKELY(z > max)) {
                max = z;
                mi = i;
                mj = j;
            }
        }
    }

    for (i = res*res; i; i--, data++)
        *data = pow(*data, 0.35);

    gwy_container_set_double_by_name(container, "/q", q);
    {
        gdouble x, y, theta, phi;

        x = (mj - hres)*G_SQRT2/(q*hres);
        y = (mi - hres)*G_SQRT2/(q*hres);
        xy_to_angles(x, y, &theta, &phi);
        gwy_container_set_double_by_name(container, "/theta0", theta);
        gwy_container_set_double_by_name(container, "/phi0", phi);
    }
    gwy_container_set_object_by_name(container, "/0/data", dist);
    g_object_unref(dist);
    gwy_container_set_object_by_name(container, "/theta", dtheta);
    g_object_unref(dtheta);
    gwy_container_set_object_by_name(container, "/phi", dphi);
    g_object_unref(dphi);
    gwy_container_set_string_by_name(container, "/0/base/palette",
                                     g_strdup(FVIEW_GRADIENT));

    gwy_data_field_data_changed(dist);
}
예제 #30
0
static void
selection_finished_cb(GwyUnitoolState *state)
{
    GwyContainer *data;
    GObject *dfield;
    GwyDataField *mask = NULL;
    GwyDataViewLayer *layer;
    ToolControls *controls;
    GwySIUnit *siunit;
    gint isel[4];

    controls = (ToolControls*)state->user_data;
    layer = GWY_DATA_VIEW_LAYER(state->layer);
    data = gwy_data_view_get_data(GWY_DATA_VIEW(layer->parent));
    dfield = gwy_container_get_object_by_name(data, "/0/data");
    gwy_container_gis_object_by_name(data, "/0/mask", (GObject**)&mask);
    gwy_unitool_rect_info_table_fill(state, &controls->labels, NULL, isel);

    switch (controls->mode) {
        case MASK_EDIT_SET:
        gwy_app_undo_checkpoint(data, "/0/mask", NULL);
        if (!mask) {
            mask = GWY_DATA_FIELD(gwy_serializable_duplicate(dfield));
            siunit = GWY_SI_UNIT(gwy_si_unit_new(""));
            gwy_data_field_set_si_unit_z(mask, siunit);
            g_object_unref(siunit);
            gwy_container_set_object_by_name(data, "/0/mask", (GObject*)mask);
            g_object_unref(mask);
        }
        gwy_data_field_fill(mask, 0.0);
        gwy_data_field_area_fill(mask, isel[0], isel[1], isel[2], isel[3],
                                 1.0);
        break;

        case MASK_EDIT_ADD:
        gwy_app_undo_checkpoint(data, "/0/mask", NULL);
        if (!mask) {
            mask = GWY_DATA_FIELD(gwy_serializable_duplicate(dfield));
            siunit = GWY_SI_UNIT(gwy_si_unit_new(""));
            gwy_data_field_set_si_unit_z(mask, siunit);
            g_object_unref(siunit);
            gwy_container_set_object_by_name(data, "/0/mask", (GObject*)mask);
            g_object_unref(mask);
            gwy_data_field_fill(mask, 0.0);
        }
        gwy_data_field_area_fill(mask, isel[0], isel[1], isel[2], isel[3],
                                 1.0);
        break;

        case MASK_EDIT_REMOVE:
        if (mask) {
            gwy_app_undo_checkpoint(data, "/0/mask", NULL);
            gwy_data_field_area_fill(mask, isel[0], isel[1], isel[2], isel[3],
                                     0.0);
        }
        break;

        case MASK_EDIT_INTERSECT:
        if (mask) {
            gwy_app_undo_checkpoint(data, "/0/mask", NULL);
            gwy_data_field_clamp(mask, 0.0, 1.0);
            gwy_data_field_area_add(mask, isel[0], isel[1], isel[2], isel[3],
                                    1.0);
            gwy_data_field_add(mask, -1.0);
            gwy_data_field_clamp(mask, 0.0, 1.0);
        }
        break;

        default:
        break;
    }
    gwy_vector_layer_unselect(GWY_VECTOR_LAYER(layer));
    gwy_app_data_view_update(layer->parent);
}