Example #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;
}
Example #2
0
static void
fix_scales(EZDSection *section,
           gint idx,
           GwyContainer *container)
{
    GwyDataField *dfield;
    GwySIUnit *siunit;
    gchar key[40];
    gint power10;
    gdouble r;

    g_snprintf(key, sizeof(key), "/%d/data", idx);
    dfield = GWY_DATA_FIELD(gwy_container_get_object_by_name(container, key));

    /* Fix value scale */
    siunit = gwy_si_unit_new_parse(section->zrange.unit, &power10);
    gwy_data_field_set_si_unit_z(dfield, siunit);
    g_object_unref(siunit);
    r = pow10(power10);
    gwy_data_field_multiply(dfield, r*section->zrange.range);
    gwy_data_field_add(dfield, r*section->zrange.min);

    /* Fix lateral scale */
    siunit = gwy_si_unit_new_parse(section->xrange.unit, &power10);
    gwy_data_field_set_si_unit_xy(dfield, siunit);
    g_object_unref(siunit);
    gwy_data_field_set_xreal(dfield, pow10(power10)*section->xrange.range);

    siunit = gwy_si_unit_new_parse(section->yrange.unit, &power10);
    gwy_data_field_set_yreal(dfield, pow10(power10)*section->yrange.range);
    g_object_unref(siunit);

    /* Some metadata */
    if (section->zrange.name) {
        const gchar *s;

        switch (section->direction) {
            case SCAN_FORWARD:
            s = " forward";
            break;

            case SCAN_BACKWARD:
            s = " backward";
            break;

            default:
            s = "";
            break;
        }
        g_snprintf(key, sizeof(key), "/%d/data/title", idx);
        gwy_container_set_string_by_name(container, key,
                                         g_strdup_printf("%s%s",
                                                         section->zrange.name,
                                                         s));
    }
}
Example #3
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;
}
Example #4
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;
}
Example #5
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);
}
Example #6
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;
}
Example #7
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);
}
Example #8
0
static gboolean
fill_data_fields(SurfFile *surffile,
                 const guchar *buffer,
                 GError **error)
{
    gdouble *data;

    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:
        gwy_convert_raw_data(buffer, surffile->xres*surffile->yres, 1,
                             GWY_RAW_DATA_SINT16, GWY_BYTE_ORDER_LITTLE_ENDIAN,
                             data, surffile->dz, 0.0);
        break;

        case 32:
        gwy_convert_raw_data(buffer, surffile->xres*surffile->yres, 1,
                             GWY_RAW_DATA_SINT32, GWY_BYTE_ORDER_LITTLE_ENDIAN,
                             data, surffile->dz, 0.0);
        break;

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

    gwy_data_field_set_si_unit_xy(surffile->dfield, surffile->xyunit);
    g_object_unref(surffile->xyunit);

    gwy_data_field_set_si_unit_z(surffile->dfield, surffile->zunit);
    g_object_unref(surffile->zunit);

    return TRUE;
}
Example #9
0
static GwyDataField*
hash_to_data_field(GHashTable *hash,
                   GHashTable *scannerlist,
                   GHashTable *scanlist,
                   NanoscopeFileType file_type,
                   gboolean has_version,
                   guint bufsize,
                   gchar *buffer,
                   gint gxres,
                   gint gyres,
                   gchar **p,
                   GError **error)
{
    NanoscopeValue *val;
    GwyDataField *dfield;
    GwySIUnit *unitz, *unitxy;
    gchar *s, *end;
    gchar un[5];
    gint xres, yres, bpp, offset, size, power10;
    gdouble xreal, yreal, q;
    gdouble *data;
    gboolean size_ok, use_global;

    if (!require_keys(hash, error, "Samps/line", "Number of lines",
                      "Scan size", "Data offset", "Data length", NULL))
        return NULL;

    val = g_hash_table_lookup(hash, "Samps/line");
    xres = GWY_ROUND(val->hard_value);

    val = g_hash_table_lookup(hash, "Number of lines");
    yres = GWY_ROUND(val->hard_value);

    val = g_hash_table_lookup(hash, "Bytes/pixel");
    bpp = val ? GWY_ROUND(val->hard_value) : 2;

    /* scan size */
    val = g_hash_table_lookup(hash, "Scan size");
    xreal = g_ascii_strtod(val->hard_value_str, &end);
    if (errno || *end != ' ') {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Cannot parse `Scan size' field."));
        return NULL;
    }
    gwy_debug("xreal = %g", xreal);
    s = end+1;
    yreal = g_ascii_strtod(s, &end);
    if (errno || *end != ' ') {
        /* Old files don't have two numbers here, assume equal dimensions */
        yreal = xreal;
        end = s;
    }
    gwy_debug("yreal = %g", yreal);
    while (g_ascii_isspace(*end))
        end++;
    if (sscanf(end, "%4s", un) != 1) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Cannot parse `Scan size' field."));
        return NULL;
    }
    gwy_debug("xy unit: <%s>", un);
    unitxy = gwy_si_unit_new_parse(un, &power10);
    q = pow10(power10);
    xreal *= q;
    yreal *= q;

    offset = size = 0;
    if (file_type == NANOSCOPE_FILE_TYPE_BIN) {
        val = g_hash_table_lookup(hash, "Data offset");
        offset = GWY_ROUND(val->hard_value);

        val = g_hash_table_lookup(hash, "Data length");
        size = GWY_ROUND(val->hard_value);

        size_ok = FALSE;
        use_global = FALSE;

        /* Try channel size and local size */
        if (!size_ok && size == bpp*xres*yres)
            size_ok = TRUE;

        if (!size_ok && size == bpp*gxres*gyres) {
            size_ok = TRUE;
            use_global = TRUE;
        }

        /* If they don't match exactly, try whether they at least fit inside */
        if (!size_ok && size > bpp*MAX(xres*yres, gxres*gyres)) {
            size_ok = TRUE;
            use_global = (xres*yres < gxres*gyres);
        }

        if (!size_ok && size > bpp*MIN(xres*yres, gxres*gyres)) {
            size_ok = TRUE;
            use_global = (xres*yres > gxres*gyres);
        }

        if (!size_ok) {
            err_SIZE_MISMATCH(error, size, bpp*xres*yres);
            return NULL;
        }

        if (use_global) {
            if (gxres) {
                xreal *= (gdouble)gxres/xres;
                xres = gxres;
            }
            if (gyres) {
                yreal *= (gdouble)gyres/yres;
                yres = gyres;
            }
        }

        if (offset + size > (gint)bufsize) {
            err_SIZE_MISMATCH(error, offset + size, bufsize);
            return NULL;
        }
    }

    q = 1.0;
    unitz = get_physical_scale(hash, scannerlist, scanlist, has_version,
                               &q, error);
    if (!unitz)
        return NULL;

    dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE);
    data = gwy_data_field_get_data(dfield);
    switch (file_type) {
        case NANOSCOPE_FILE_TYPE_TXT:
        if (!read_ascii_data(xres*yres, data, p, bpp, error)) {
            g_object_unref(dfield);
            return NULL;
        }
        break;

        case NANOSCOPE_FILE_TYPE_BIN:
        if (!read_binary_data(xres*yres, data, buffer + offset, bpp, error)) {
            g_object_unref(dfield);
            return NULL;
        }
        break;

        default:
        g_assert_not_reached();
        break;
    }
    gwy_data_field_multiply(dfield, q);
    gwy_data_field_invert(dfield, TRUE, FALSE, FALSE);
    gwy_data_field_set_si_unit_z(dfield, unitz);
    g_object_unref(unitz);

    gwy_data_field_set_si_unit_xy(dfield, unitxy);
    g_object_unref(unitxy);

    return dfield;
}
Example #10
0
static GwyContainer*
zeiss_load_tiff(const GwyTIFF *tiff, GError **error)
{
    GwyContainer *container = NULL, *meta = NULL;
    GwyDataField *dfield;
    GwySIUnit *siunit;
    GwyTIFFImageReader *reader = NULL;
    GHashTable *hash = NULL;
    gint i, power10;
    gchar *value, *end, *comment = NULL;
    gdouble *data;
    gboolean new_file;
    double factor, dx;

    /* Comment with parameters is common for all data fields */
    if (!gwy_tiff_get_string0(tiff, ZEISS_HEADER_TAG, &comment)) {
        err_FILE_TYPE(error, "Carl Zeiss SEM");
        goto fail;
    }

    if (strstr(comment, MAGIC_COMMENT))
        new_file = TRUE;
    else if (g_str_has_prefix(comment, SOMEWHAT_LESS_MAGIC_COMMENT))
        new_file = FALSE;
    else {
        err_FILE_TYPE(error, "Carl Zeiss SEM");
        goto fail;
    }

    /* Read the comment header. */
    if (new_file) {
        hash = parse_comment(comment);
        if ((value = g_hash_table_lookup(hash, "Image Pixel Size"))) {
            gwy_debug("Using dx from Image Pixel Size: %s", value);
        }
        else if ((value = g_hash_table_lookup(hash, "Pixel Size"))) {
            gwy_debug("Using dx from Pixel Size: %s", value);
        }
        else {
            err_MISSING_FIELD(error, "Pixel Size");
            goto fail;
        }
    }
    else {
        /* The first thing is the pixel size, apparently. */
        value = comment + strlen(SOMEWHAT_LESS_MAGIC_COMMENT);
        gwy_debug("Using dx from old-style comment: %s", value);
    }

    dx = g_ascii_strtod(value, &end);
    /* Use negated positive conditions to catch NaNs */
    if (!((dx = fabs(dx)) > 0)) {
        g_warning("Real pixel size is 0.0, fixing to 1.0");
        dx = 1.0;
    }
    if (!new_file)
        end = "m";

    /* Request a reader, this ensures dimensions and stuff are defined.
     * NB: Newer versions store the image as RGB.  Not useful here; just
     * average the channels.  */
    if (!(reader = gwy_tiff_get_image_reader(tiff, 0, 3, error)))
        goto fail;

    siunit = gwy_si_unit_new_parse(end, &power10);
    factor = pow10(power10);
    dfield = gwy_data_field_new(reader->width, reader->height,
                                reader->width * factor * dx,
                                reader->height * factor * dx,
                                FALSE);
    gwy_data_field_set_si_unit_xy(dfield, siunit);
    g_object_unref(siunit);

    data = gwy_data_field_get_data(dfield);
    if (reader->samples_per_pixel > 1) {
        gdouble *datarow = g_new(gdouble, reader->width);
        gint ch, j, spp = reader->samples_per_pixel;

        gwy_data_field_clear(dfield);
        for (i = 0; i < reader->height; i++) {
            for (ch = 0; ch < spp; ch++) {
                gwy_tiff_read_image_row(tiff, reader, 0, i, 1.0, 0.0, datarow);
                for (j = 0; j < reader->width; j++)
                    data[i*reader->width + j] += datarow[j];
            }
        }
        g_free(datarow);
        gwy_data_field_multiply(dfield, 1.0/spp);
        gwy_data_field_invalidate(dfield);
    }
    else {
        for (i = 0; i < reader->height; i++)
            gwy_tiff_read_image_row(tiff, reader, 0, i, 1.0, 0.0,
                                    data + i*reader->width);
    }

    container = gwy_container_new();
    gwy_container_set_object_by_name(container, "/0/data", dfield);
    g_object_unref(dfield);
    gwy_container_set_string_by_name(container, "/0/data/title",
                                     g_strdup("Secondary electron count"));

    if (new_file) {
        meta = gwy_container_new();
        g_hash_table_foreach(hash, add_meta, meta);
        if (gwy_container_get_n_items(meta))
            gwy_container_set_object_by_name(container, "/0/meta", meta);
        g_object_unref(meta);
    }

fail:
    if (hash)
        g_hash_table_destroy(hash);
    g_free(comment);

    return container;
}
Example #11
0
static GwyDataField*
sensofar_read_data_field(SensofarDataDesc *data_desc,
                         GwyDataField **maskfield,
                         const guchar **p,
                         gsize size,
                         GError **error)
{
    GwyDataField *dfield, *mfield;
    guint xres, yres, i, j, mcount;
    GwySIUnit *units = NULL;
    gdouble *data, *mdata;

    if (maskfield)
        *maskfield = NULL;

    yres = gwy_get_guint32_le(p);
    xres = gwy_get_guint32_le(p);
    gwy_debug("Data size: %dx%d", xres, yres);
    if (err_SIZE_MISMATCH(error, xres*yres*sizeof(gfloat),
                          size - 2*sizeof(guint32), FALSE))
        return NULL;
    if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres))
        return NULL;
    if (!((data_desc->axes_config.mppx
           = fabs(data_desc->axes_config.mppx)) > 0)) {
        g_warning("Real x size is 0.0, fixing to 1.0");
        data_desc->axes_config.mppx = 1.0;
    }
    if (!((data_desc->axes_config.mppy
           = fabs(data_desc->axes_config.mppy)) > 0)) {
        g_warning("Real y size is 0.0, fixing to 1.0");
        data_desc->axes_config.mppy = 1.0;
    }

    dfield = gwy_data_field_new(xres, yres, 
                                data_desc->axes_config.mppx * xres * Micrometer,
                                data_desc->axes_config.mppy * yres * Micrometer,
                                FALSE);
    units = gwy_si_unit_new("m"); // values are in um only
    gwy_data_field_set_si_unit_xy(dfield, units);
    g_object_unref(units);

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

    mfield = gwy_data_field_new_alike(dfield, FALSE);
    gwy_data_field_fill(mfield, 1.0);

    data = gwy_data_field_get_data(dfield);
    mdata = gwy_data_field_get_data(mfield);
    for (i = 0; i < yres; i++) {
        for (j = 0; j < xres; j++) {
            gdouble v = gwy_get_gfloat_le(p);
            if (v == 1000001.0)
                mdata[i*xres + j] = 0.0;
            else
                data[i*xres + j] = v*Micrometer;
        }
    }

    gwy_debug("Offset: %g %g",
              data_desc->axes_config.x_0, data_desc->axes_config.y_0);
    //FIXME: offset later, support of offset determined by version?
    //gwy_data_field_set_xoffset(d, pow10(power10)*data_desc.axes_config.x_0);
    //gwy_data_field_set_yoffset(d, pow10(power10)*data_desc.axes_config.y_0);

    mcount = gwy_app_channel_remove_bad_data(dfield, mfield);

    if (maskfield && mcount)
        *maskfield = mfield;
    else
        g_object_unref(mfield);

    return dfield;
}
Example #12
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;
}
Example #13
0
static GwyDataField*
unisoku_read_data_field(const guchar *buffer,
                        gsize size,
                        UnisokuFile *ufile,
                        GError **error)
{
    gint i, n, power10;
    const gchar *unit;
    GwyDataField *dfield;
    GwySIUnit *siunit;
    gdouble q, pmin, pmax, rmin, rmax;
    gdouble *data;

    n = ufile->xres * ufile->yres;
    if (err_SIZE_MISMATCH(error, n*type_sizes[ufile->data_type], size, FALSE))
        return NULL;

    dfield = gwy_data_field_new(ufile->xres, ufile->yres,
                                fabs((ufile->end_x - ufile->start_x)),
                                fabs((ufile->end_y - ufile->start_y)),
                                FALSE);
    data = gwy_data_field_get_data(dfield);

    /* FIXME: what to do when ascii_flag is set? */
    switch (ufile->data_type) {
        case UNISOKU_UINT8:
        for (i = 0; i < n; i++)
            data[i] = buffer[i];
        break;

        case UNISOKU_SINT8:
        for (i = 0; i < n; i++)
            data[i] = (signed char)buffer[i];
        break;

        case UNISOKU_UINT16:
        {
            const guint16 *pdata = (const guint16*)buffer;

            for (i = 0; i < n; i++)
                data[i] = GUINT16_FROM_LE(pdata[i]);
        }
        break;

        case UNISOKU_SINT16:
        {
            const gint16 *pdata = (const gint16*)buffer;

            for (i = 0; i < n; i++)
                data[i] = GINT16_FROM_LE(pdata[i]);
        }
        break;

        case UNISOKU_FLOAT:
        for (i = 0; i < n; i++)
            data[i] = gwy_get_gfloat_le(&buffer);
        break;

        default:
        g_return_val_if_reached(NULL);
        break;
    }

    unit = ufile->unit_x;
    if (!*unit)
        unit = "nm";
    siunit = gwy_si_unit_new_parse(unit, &power10);
    gwy_data_field_set_si_unit_xy(dfield, siunit);
    q = pow10((gdouble)power10);
    gwy_data_field_set_xreal(dfield, q*gwy_data_field_get_xreal(dfield));
    gwy_data_field_set_yreal(dfield, q*gwy_data_field_get_yreal(dfield));
    g_object_unref(siunit);

    unit = ufile->unit_z;
    /* XXX: No fallback yet, just make z unitless */
    siunit = gwy_si_unit_new_parse(unit, &power10);
    gwy_data_field_set_si_unit_z(dfield, siunit);
    q = pow10((gdouble)power10);
    pmin = q*ufile->min_z;
    pmax = q*ufile->max_z;
    rmin = ufile->min_raw_z;
    rmax = ufile->max_raw_z;
    gwy_data_field_multiply(dfield, (pmax - pmin)/(rmax - rmin));
    gwy_data_field_add(dfield, (pmin*rmax - pmax*rmin)/(rmax - rmin));
    g_object_unref(siunit);

    return dfield;
}
Example #14
0
static GwyContainer*
gxsm_load(const gchar *filename,
          G_GNUC_UNUSED GwyRunType mode,
          GError **error)
{
    static const gchar *dimensions[] = { "time", "value", "dimy", "dimx" };
    GwyContainer *data = NULL;
    GwyDataField *dfield;
    GwySIUnit *siunit;
    NetCDF cdffile;
    const NetCDFDim *dim;
    const NetCDFVar *var;
    const NetCDFAttr *attr;
    gdouble real;
    gint i, power10;

    if (!cdffile_load(&cdffile, filename, error))
        return NULL;

    if (cdffile.nrecs) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("NetCDF records are not supported."));
        goto gxsm_load_fail;
    }

    /* Look for variable "H" or "FloatField".  This seems to be how GXSM calls
     * data. */
    if (!(var = cdffile_get_var(&cdffile, "H"))
        && !(var = cdffile_get_var(&cdffile, "FloatField"))) {
        err_NO_DATA(error);
        goto gxsm_load_fail;
    }

    /* Check the dimensions.  We only know how to handle time=1 and value=1. */
    for (i = 0; i < var->ndims; i++) {
        dim = cdffile.dims + var->dimids[i];
        if (!gwy_strequal(dim->name, dimensions[i])
            || (i < 2 && dim->length != 1)) {
            /* XXX */
            err_NO_DATA(error);
            goto gxsm_load_fail;
        }
    }

    if (err_DIMENSION(error, cdffile.dims[var->dimids[3]].length)
        || err_DIMENSION(error, cdffile.dims[var->dimids[2]].length))
        goto gxsm_load_fail;

    dfield = read_data_field((const guchar*)(cdffile.buffer + var->begin),
                             cdffile.dims[var->dimids[3]].length,
                             cdffile.dims[var->dimids[2]].length,
                             var->type);

    if ((siunit = read_real_size(&cdffile, "rangex", &real, &power10))) {
        /* Use negated positive conditions to catch NaNs */
        if (!((real = fabs(real)) > 0)) {
            g_warning("Real x size is 0.0, fixing to 1.0");
            real = 1.0;
        }
        gwy_data_field_set_xreal(dfield, real*pow10(power10));
        gwy_data_field_set_si_unit_xy(dfield, siunit);
        g_object_unref(siunit);
    }

    if ((siunit = read_real_size(&cdffile, "rangey", &real, &power10))) {
        /* Use negated positive conditions to catch NaNs */
        if (!((real = fabs(real)) > 0)) {
            g_warning("Real y size is 0.0, fixing to 1.0");
            real = 1.0;
        }
        gwy_data_field_set_yreal(dfield, real*pow10(power10));
        /* must be the same gwy_data_field_set_si_unit_xy(dfield, siunit); */
        g_object_unref(siunit);
    }

    if ((siunit = read_real_size(&cdffile, "rangez", &real, &power10))) {
        /* rangez seems to be some bogus value, take only units */
        gwy_data_field_set_si_unit_z(dfield, siunit);
        gwy_data_field_multiply(dfield, pow10(power10));
        g_object_unref(siunit);
    }
    if ((siunit = read_real_size(&cdffile, "dz", &real, &power10))) {
        /* on the other hand the units seem to be bogus here, take the range */
        gwy_data_field_multiply(dfield, real);
        g_object_unref(siunit);
    }

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

    if ((attr = cdffile_get_attr(var->attrs, var->nattrs, "long_name"))
        && attr->type == NC_CHAR
        && attr->nelems) {
        gwy_container_set_string_by_name(data, "/0/data/title",
                                         g_strndup(attr->values, attr->nelems));
    }

gxsm_load_fail:
    gwy_file_abandon_contents(cdffile.buffer, cdffile.size, NULL);
    cdffile_free(&cdffile);

    return data;
}
Example #15
0
static GwyDataField*
read_datafield(const guchar *buffer,
               guint size,
               const StmprgFile *stmprgfile,
               GError **error)
{
    gint xres, yres, bpp;
    gdouble xreal, yreal, q;
    GwyDataField *dfield;
    gdouble *data;
    GwySIUnit *unit;

    bpp = 2;                    /* words, always */

    xres = stmprgfile->mainfield.points;
    yres = stmprgfile->mainfield.lines;
    xreal = Angstrom * stmprgfile->mainfield.field_x;
    yreal = Angstrom * stmprgfile->mainfield.field_y;
    q = stmprgfile->mainfield.sol_z * 1.0e-5;       /* 5 ?? */
    /* resolution of z value in angstrom/bit, 1.0e-10 */

    if (err_SIZE_MISMATCH(error, bpp*xres*yres, size, FALSE))
        return NULL;

    dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE);
    data = gwy_data_field_get_data(dfield);
    if (!read_binary_ubedata(xres * yres, data, buffer, bpp)) {
        err_BPP(error, bpp);
        g_object_unref(dfield);
        return NULL;
    }

    gwy_data_field_multiply(dfield, q);

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

    /* Assuming we are reading channel1... */
    switch (stmprgfile->control.channel1) {
        case STMPRG_CHANNEL_OFF:
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("First channel is switched off."));
        return NULL;

        case STMPRG_CHANNEL_Z:
        unit = gwy_si_unit_new("m");
        break;

        case STMPRG_CHANNEL_I:
        case STMPRG_CHANNEL_I_I0:
        case STMPRG_CHANNEL_I0:
        unit = gwy_si_unit_new("A");
        break;

        case STMPRG_CHANNEL_EXT1:
        case STMPRG_CHANNEL_EXT2:
        case STMPRG_CHANNEL_U0:
        unit = gwy_si_unit_new("V");
        break;

        default:
        g_assert_not_reached();
        break;
    }
    gwy_data_field_set_si_unit_z(dfield, unit);
    g_object_unref(unit);

    return dfield;
}
Example #16
0
static GwyContainer*
lif_load(const gchar *filename,
             G_GNUC_UNUSED GwyRunType mode,
             GError **error)
{
    GwyContainer *container = NULL;
    LIFHeader *header = NULL;
    LIFMemBlock *memblock = NULL;
    LIFFile *file = NULL;
    LIFElement *element = NULL;
    LIFDimension *dimension = NULL;
    LIFChannel *channel = NULL;
    gsize size = 0, memblock_size = 0;
    gint64 remaining = 0;
    gchar *buffer;
    const guchar *p;
    GError *err = NULL;
    GwyDataField *dfield = NULL;
    GwyBrick *brick = NULL;
    gdouble *data = NULL;
    gint i, j, channelno = 0, volumeno = 0;
    gchar *strkey, *lutname;
    GMarkupParser parser = {
        header_start_element,
        header_end_element,
        header_parse_text, NULL, NULL
    };
    GMarkupParseContext *context;
    XMLParserData *xmldata;
    gint x, xres, xstep, y, yres, ystep, z, zres, zstep, offset, res;
    gdouble xreal, yreal, zreal, xoffset, yoffset, zoffset;
    gdouble zscale = 1.0, wscale = 1.0;
    GwySIUnit *siunitxy = NULL, *siunitz = NULL;
    GwySIUnit *siunitx = NULL, *siunity = NULL, *siunitw = NULL;
    gint power10xy = 1;
    gint power10x = 1, power10y = 1, power10z = 1, power10w = 1;

    if (!g_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        goto fail;
    }

    if (size < 13) { /* header too short */
        err_TOO_SHORT(error);
        goto fail;
    }

    p = buffer;
    remaining = size;
    header = g_new0(LIFHeader, 1);
    header->magic = gwy_get_gint32_le(&p);
    gwy_debug("Magic = %d", header->magic);
    header->size = gwy_get_guint32_le(&p);
    gwy_debug("Size = %d", header->size);
    header->testcode = *(p++);
    gwy_debug("Testcode = 0x%x", header->testcode);
    if (header->testcode != TESTCODE) {
        err_FILE_TYPE(error, "Leica LIF");
        goto fail;
    }
    header->xmllen = gwy_get_guint32_le(&p);
    gwy_debug("XML length = %d", header->xmllen);
    if (size < 13 + header->xmllen * 2) {
        err_TOO_SHORT(error);
        goto fail;
    }

    remaining -= 13;

    header->xmlheader = g_convert((const gchar*)p, 2 * header->xmllen,
                                  "UTF-8", "UTF-16", NULL, NULL, NULL);
    p += header->xmllen * 2;

    remaining -= header->xmllen * 2;

    // gwy_debug("%s", header->xmlheader);
    /* Parse XML header */
    xmldata = g_new0(XMLParserData, 1);
    xmldata->file = g_new0(LIFFile, 1);
    xmldata->file->elements = g_array_new(FALSE, TRUE,
                                          sizeof(LIFElement));
    xmldata->elements = g_ptr_array_new();

    context = g_markup_parse_context_new(&parser,
                                         G_MARKUP_TREAT_CDATA_AS_TEXT,
                                         (gpointer)xmldata,
                                         NULL);

    if (!g_markup_parse_context_parse(context, header->xmlheader, -1, &err)
        || !g_markup_parse_context_end_parse(context, &err)) {
        error = &err;
        g_clear_error(&err);
    }
    g_markup_parse_context_free(context);
    file = xmldata->file;
    file->header = header;
    g_ptr_array_free(xmldata->elements, TRUE);
    g_free(xmldata);

    /* Reading memblocks */
    file->memblocks = g_hash_table_new(g_str_hash, g_str_equal);
    while (remaining > 0) {
        memblock = lif_read_memblock(p, &memblock_size, file->version);
        if (!memblock) {
            break;
        }
        remaining -= memblock_size;
        if (remaining >= 0) {
            gwy_debug("remaining = %" G_GUINT64_FORMAT "", remaining);
            p += memblock_size;
            g_hash_table_insert(file->memblocks, memblock->memid,
                                memblock);
        }
    }

    container = gwy_container_new();

    for (i = 0; i < file->elements->len; i++) {
        element = &g_array_index(file->elements, LIFElement, i);

        if ((element->dimensions == NULL)
                                       || (element->channels == NULL)) {
            gwy_debug("Empty element");
            continue;
        }

        gwy_debug("Dimensions = %d channels=%d",
                  element->dimensions->len,
                  element->channels->len);
        gwy_debug("memid=%s", element->memid);

        /* check if we can load this type of data into
         * Gwyddion structures */
        res = 0;
        if ((element->dimensions->len != 2)
                                   && (element->dimensions->len != 3)) {

            /* check for case ndim == 4 && res == 1 */
            for (i = 0; i < element->dimensions->len; i++) {
                dimension = &g_array_index(element->dimensions,
                                           LIFDimension, i);
                xres = dimension->res;
                gwy_debug("dim[%d].res=%d", i, xres);
                if (i == 2) {
                    res = xres;
                }
            }
            if ((element->dimensions->len == 4) && (res == 1)) {
                gwy_debug("4D volume");
            }
            else {
                gwy_debug("not loading");
                continue;
            }
        }

        memblock = (LIFMemBlock *)g_hash_table_lookup(file->memblocks,
                                                      element->memid);
        if (!memblock) {
            gwy_debug("Failed to locate memblock with key %s",
                      element->memid);

            continue;
        }

        p = memblock->data;
        if (element->dimensions->len == 2) { /* Image */
            for (j = 0; j < element->channels->len; j++) {
                dimension = &g_array_index(element->dimensions,
                                           LIFDimension, 0);
                xres = dimension->res;
                xreal = dimension->length;
                xoffset = dimension->origin;
                xstep = dimension->bytesinc;
                siunitxy = gwy_si_unit_new_parse(dimension->unit,
                                                 &power10xy);

                dimension = &g_array_index(element->dimensions,
                                           LIFDimension, 1);
                yres = dimension->res;
                yreal = dimension->length;
                yoffset = dimension->origin;
                ystep = dimension->bytesinc;

                if (xreal <= 0.0)
                    xreal = 1.0;
                if (yreal <= 0.0)
                    yreal = 1.0;

                channel = &g_array_index(element->channels,
                                         LIFChannel, j);
                offset = channel->bytesinc;
                siunitz = gwy_si_unit_new_parse(channel->unit,
                                                &power10z);

                zscale = pow10(power10z);
                if (offset + (xres - 1) * xstep + (yres - 1)* ystep
                                                  > memblock->memsize) {
                    gwy_debug("Memblock too small");
                    gwy_debug("%d %" G_GUINT64_FORMAT "",
                              offset + (xres-1)*xstep + (yres-1)*ystep,
                              memblock->memsize);
                    err_SIZE_MISMATCH(error,
                                      memblock->memsize,
                                      offset+(xres-1)*xstep
                                                        +(yres-1)*ystep,
                                      FALSE);
                    goto fail;
                }

                dfield = gwy_data_field_new(xres, yres,
                                            xreal*pow10(power10xy),
                                            yreal*pow10(power10xy),
                                            TRUE);
                gwy_data_field_set_xoffset(dfield,
                                           xoffset*pow10(power10xy));
                gwy_data_field_set_yoffset(dfield,
                                           yoffset*pow10(power10xy));

                data = gwy_data_field_get_data(dfield);
                for (y = 0; y < yres; y++)
                    for (x = 0; x < xres; x++) {
                        *(data++) = zscale
                           * (gdouble)*(p + offset + x*xstep + y*ystep);
                }

                if (siunitxy) {
                    gwy_data_field_set_si_unit_xy(dfield, siunitxy);
                    g_object_unref(siunitxy);
                }
                if (siunitz) {
                    gwy_data_field_set_si_unit_z(dfield, siunitz);
                    g_object_unref(siunitz);
                }

                strkey = g_strdup_printf("/%d/data", channelno);
                gwy_container_set_object_by_name(container,
                                                 strkey,
                                                 dfield);
                g_object_unref(dfield);
                g_free(strkey);

                if (element->name) {
                    strkey = g_strdup_printf("/%d/data/title",
                                             channelno);
                    gwy_container_set_string_by_name(container, strkey,
                                               g_strdup(element->name));
                    g_free(strkey);
                }

                if (element->metadata) {
                    strkey = g_strdup_printf("/%d/meta",
                                             channelno);
                    gwy_container_set_object_by_name(container,
                                                     strkey,
                                                     element->metadata);
                    g_free(strkey);
                }

                if (channel->lut) {
                    lutname = NULL;
                    if (gwy_strequal(channel->lut, "Red"))
                        lutname = g_strdup_printf("RGB-Red");
                    else if (gwy_strequal(channel->lut, "Green"))
                        lutname = g_strdup_printf("RGB-Green");
                    else if (gwy_strequal(channel->lut, "Blue"))
                        lutname = g_strdup_printf("RGB-Blue");
                    else if (gwy_strequal(channel->lut, "Gray"))
                        lutname = g_strdup_printf("Gray");
                    if (lutname) {
                        strkey = g_strdup_printf("/%u/base/palette",
                                                 channelno);
                        gwy_container_set_string_by_name(container,
                                                         strkey,
                                                         lutname);
                        g_free(strkey);
                    }
                }

                gwy_file_channel_import_log_add(container, channelno,
                                                NULL, filename);

                channelno++;
            }
        }
        else if ((element->dimensions->len == 3)
             || ((element->dimensions->len == 4) && (res == 1))) {
            /* Volume */
            for (j = 0; j < element->channels->len; j++) {
                dimension = &g_array_index(element->dimensions,
                                           LIFDimension, 0);
                xres = dimension->res;
                xreal = dimension->length;
                xoffset = dimension->origin;
                xstep = dimension->bytesinc;
                siunitx = gwy_si_unit_new_parse(dimension->unit,
                                                &power10x);

                dimension = &g_array_index(element->dimensions,
                                           LIFDimension, 1);
                yres = dimension->res;
                yreal = dimension->length;
                yoffset = dimension->origin;
                ystep = dimension->bytesinc;
                siunity = gwy_si_unit_new_parse(dimension->unit,
                                                &power10y);

                if (element->dimensions->len == 3) {
                    dimension = &g_array_index(element->dimensions,
                                               LIFDimension, 2);
                }
                else {
                    dimension = &g_array_index(element->dimensions,
                                               LIFDimension, 3);
                }
                zres = dimension->res;
                zreal = dimension->length;
                zoffset = dimension->origin;
                zstep = dimension->bytesinc;
                siunitz = gwy_si_unit_new_parse(dimension->unit,
                                                &power10z);

                channel = &g_array_index(element->channels,
                                         LIFChannel, j);
                offset = channel->bytesinc;
                siunitw = gwy_si_unit_new_parse(channel->unit,
                                                &power10w);
                wscale = pow10(power10w);

                if (offset
                      + (xres-1)*xstep + (yres-1)*ystep + (zres-1)*zstep
                                                  > memblock->memsize) {
                    gwy_debug("Memblock too small");
                    gwy_debug("%d %" G_GUINT64_FORMAT "",
                              offset + (xres-1)*xstep
                                      + (yres-1)*ystep + (zres-1)*zstep,
                              memblock->memsize);
                    err_SIZE_MISMATCH(error,
                                      memblock->memsize,
                                      offset + (xres-1)*xstep
                                      + (yres-1)*ystep + (zres-1)*zstep,
                                      FALSE);
                    goto fail;
                }
                brick = gwy_brick_new(xres, yres, zres,
                                      xreal*pow10(power10x),
                                      yreal*pow10(power10y),
                                      zreal*pow10(power10z),
                                      TRUE);
                gwy_brick_set_xoffset(brick, xoffset*pow10(power10x));
                gwy_brick_set_yoffset(brick, yoffset*pow10(power10y));
                gwy_brick_set_zoffset(brick, zoffset*pow10(power10z));

                data = gwy_brick_get_data(brick);

                for (z = 0; z < zres; z++)
                    for (y = 0; y < yres; y++)
                        for (x = 0; x < xres; x++) {
                            *(data++) = wscale * (gdouble)*(p + offset
                                         + x*xstep + y*ystep + z*zstep);
                    }

                if (siunitx) {
                    gwy_brick_set_si_unit_x(brick, siunitx);
                    g_object_unref(siunitx);
                }
                if (siunity) {
                    gwy_brick_set_si_unit_y(brick, siunity);
                    g_object_unref(siunity);
                }
                if (siunitz) {
                    gwy_brick_set_si_unit_z(brick, siunitz);
                    g_object_unref(siunitz);
                }
                if (siunitw) {
                    gwy_brick_set_si_unit_w(brick, siunitw);
                    g_object_unref(siunitw);
                }

                strkey = g_strdup_printf("/brick/%d", volumeno);
                gwy_container_set_object_by_name(container,
                                                 strkey,
                                                 brick);
                g_free(strkey);

                if (element->name) {
                    strkey = g_strdup_printf("/brick/%d/title",
                                             volumeno);
                    gwy_container_set_string_by_name(container, strkey,
                                               g_strdup(element->name));
                    g_free(strkey);
                }

                if (element->metadata) {
                    strkey = g_strdup_printf("/brick/%d/meta",
                                             volumeno);
                    gwy_container_set_object_by_name(container,
                                                     strkey,
                                                     element->metadata);
                    g_free(strkey);
                }

                if (channel->lut) {
                    lutname = NULL;
                    if (gwy_strequal(channel->lut, "Red"))
                        lutname = g_strdup_printf("RGB-Red");
                    else if (gwy_strequal(channel->lut, "Green"))
                        lutname = g_strdup_printf("RGB-Green");
                    else if (gwy_strequal(channel->lut, "Blue"))
                        lutname = g_strdup_printf("RGB-Blue");
                    else if (gwy_strequal(channel->lut, "Gray"))
                        lutname = g_strdup_printf("Gray");
                    if (lutname) {
                        strkey = g_strdup_printf("/brick/%d/preview/palette",
                                                 volumeno);
                        gwy_container_set_string_by_name(container,
                                                         strkey,
                                                         lutname);
                        g_free(strkey);
                    }
                }

                dfield = gwy_data_field_new(xres, yres,
                                            xreal, yreal, FALSE);
                gwy_brick_mean_plane(brick, dfield,
                                     0, 0, 0,
                                     xres, yres, -1, FALSE);
                strkey = g_strdup_printf("/brick/%d/preview",
                                         volumeno);
                gwy_container_set_object_by_name(container,
                                                 strkey,
                                                 dfield);
                g_free(strkey);
                g_object_unref(brick);
                g_object_unref(dfield);
                gwy_file_volume_import_log_add(container, volumeno,
                                               NULL, filename);

                volumeno++;
            } /* for (channels) */
        } /* if (volume) */
    }

fail:
    /* freeing all stuff */
    if (file) {
        if (file->memblocks) {
            g_hash_table_foreach_remove(file->memblocks,
                                        lif_remove_memblock,
                                        NULL);
            g_hash_table_unref(file->memblocks);
        }
        if (file->elements) {
            for (i = 0; i < file->elements->len; i++) {
                element = &g_array_index(file->elements, LIFElement, i);
                if (element->dimensions) {
                    for (j = 0; j < element->dimensions->len; j++) {
                        dimension = &g_array_index(element->dimensions,
                                                   LIFDimension, j);
                        if (dimension->unit)
                            g_free(dimension->unit);
                    }
                    g_array_free(element->dimensions, TRUE);
                }
                if (element->channels) {
                    for (j = 0; j < element->channels->len; j++) {
                        channel = &g_array_index(element->channels,
                                                 LIFChannel, j);
                        if (channel->unit)
                            g_free(channel->unit);
                        if (channel->lut)
                            g_free(channel->lut);
                    }
                    g_array_free(element->channels, TRUE);
                }

                if (element->name)
                    g_free(element->name);
                if (element->memid)
                    g_free(element->memid);
                if (element->metadata)
                    g_object_unref(element->metadata);
            }
            g_array_free(file->elements, TRUE);
        }
        g_free(file);
    }
    if (header->xmlheader)
        g_free(header->xmlheader);
    if (header) {
        g_free(header);
    }

    return container;
}
Example #17
0
static GwyContainer*
plt_load(const gchar *filename,
         G_GNUC_UNUSED GwyRunType mode,
         GError **error)
{
    GwyContainer *container = NULL;
    GwyDataField *dfield = NULL;
    GwyTextHeaderParser parser;
    GwySIUnit *xunit, *yunit, *zunit;
    gchar *p, *value, *buffer = NULL;
    GHashTable *hash = NULL;
    gsize size;
    GError *err = NULL;
    G_GNUC_UNUSED gdouble xreal, yreal, zreal;
    gint i, xres, yres;
    gdouble *data;

    if (!g_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        goto fail;
    }

    if (strncmp(buffer, MAGIC1, MIN(size, sizeof(MAGIC1)-1))) {
        err_FILE_TYPE(error, "Nanosurf PLT");
        goto fail;
    }

    /* Find the first line not starting with '#' */
    for (p = buffer; (p - buffer) + 1 < size; p++) {
        if ((p[0] == '\n' || p[0] == '\r')
            && (p[1] != '\n' && p[1] != '#')) {
            break;
        }
    }
    *p = '\0';
    p++;

    gwy_clear(&parser, 1);
    parser.line_prefix = "#";
    parser.key_value_separator = ":";
    hash = gwy_text_header_parse(buffer, &parser, NULL, NULL);
    if (!require_keys(hash, error,
                      "Channel", "Lines", "Points",
                      "XRange", "YRange", "ZRange",
                      NULL))
        goto fail;

    xres = atoi(g_hash_table_lookup(hash, "Points"));
    yres = atoi(g_hash_table_lookup(hash, "Lines"));
    if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres))
        goto fail;

    value = g_hash_table_lookup(hash, "XRange");
    xreal = g_ascii_strtod(value, &value);
    xunit = gwy_si_unit_new(value);

    value = g_hash_table_lookup(hash, "YRange");
    yreal = g_ascii_strtod(value, &value);
    yunit = gwy_si_unit_new(value);

    value = g_hash_table_lookup(hash, "ZRange");
    zreal = g_ascii_strtod(value, &value);
    zunit = gwy_si_unit_new(value);

    /* Use negated positive conditions to catch NaNs */
    if (!((xreal = fabs(xreal)) > 0)) {
        g_warning("Real x size is 0.0, fixing to 1.0");
        xreal = 1.0;
    }
    if (!((yreal = fabs(yreal)) > 0)) {
        g_warning("Real y size is 0.0, fixing to 1.0");
        yreal = 1.0;
    }

    if (!gwy_si_unit_equal(xunit, yunit))
        g_warning("X and Y units differ, using X");

    dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE);
    gwy_data_field_set_si_unit_xy(dfield, xunit);
    gwy_data_field_set_si_unit_z(dfield, zunit);
    g_object_unref(xunit);
    g_object_unref(yunit);
    g_object_unref(zunit);

    data = gwy_data_field_get_data(dfield);
    value = p;
    for (i = 0; i < xres*yres; i++) {
        data[i] = g_ascii_strtod(value, &p);
        value = p;
    }

    container = gwy_container_new();
    gwy_container_set_object(container, gwy_app_get_data_key_for_id(0), dfield);
    g_object_unref(dfield);

    if ((value = g_hash_table_lookup(hash, "Channel")))
        gwy_container_set_string_by_name(container, "/0/data/title",
                                         g_strdup(value));
    else
        gwy_app_channel_title_fall_back(container, 0);

    gwy_file_channel_import_log_add(container, 0, NULL, filename);

fail:
    g_free(buffer);
    g_hash_table_destroy(hash);

    return container;
}
Example #18
0
static GwyDataField*
read_data_field(const guchar *buffer,
                guint size,
                guchar version,
                gchar **title,
                gint *direction,
                GError **error)
{
    enum { MIN_REMAINDER = 2620 };
    /* information offsets in different versions, in r5+ relative to data
     * start, in order:
     * data offset,
     * pixel dimensions,
     * physical dimensions,
     * value multiplier,
     * unit string,
     * data type,       (if zero, use channel title)
     * channel title    (if zero, use data type)
     */
    const guint offsets34[] = {
        0x0104, 0x0196, 0x01a2, 0x01b2, 0x01c2, 0x0400, 0x0000
    };
    const guint offsets56[] = {
        0x0104, 0x025c, 0x0268, 0x0288, 0x02a0, 0x0708, 0x0000
    };
    const guint offsets7[] = {
        0x0104, 0x029c, 0x02a8, 0x02c8, 0x02e0, 0x0000, 0x0b90
    };
    gint xres, yres, doffset, i, power10, type;
    gdouble xreal, yreal, q, z0;
    GwyDataField *dfield;
    GwySIUnit *unitxy, *unitz;
    gdouble *data;
    const guint *offset;
    const guchar *p, *r, *last;
    /* get floats in single precision from r4 but double from r5+ */
    gdouble (*getflt)(const guchar**);

    *title = NULL;
    *direction = -1;

    if (version == '5' || version == '6' || version == '7') {
        /* There are more headers in r5,
         * try to find something that looks like #R5. */
        last = r = buffer;
        while ((p = memchr(r, '#', size - (r - buffer) - MIN_REMAINDER))) {
            if (p[1] == 'R' && p[2] == version && p[3] == '.') {
                gwy_debug("pos: %ld", (long)(p - buffer));
                last = p;
                r = p + MIN_REMAINDER-1;
            }
            else
                r = p + 1;
        }
        offset = (version == '7') ? &offsets7[0] : &offsets56[0];
        buffer = last;
        getflt = &gwy_get_gdouble_le;
    }
    else {
        offset = &offsets34[0];
        getflt = &get_gfloat_le_as_double;
    }

    p = buffer + *(offset++);
    doffset = gwy_get_guint32_le(&p);  /* this appears to be the same number
                                          as in the ASCII miniheader -- so get
                                          it here since it's easier */
    gwy_debug("data offset = %u", doffset);
    p = buffer + *(offset++);
    xres = gwy_get_guint32_le(&p);
    yres = gwy_get_guint32_le(&p);
    if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres))
        return NULL;
    p = buffer + *(offset++);
    xreal = -getflt(&p);
    xreal += getflt(&p);
    yreal = -getflt(&p);
    yreal += getflt(&p);
    if (!((xreal = fabs(xreal)) > 0)) {
        g_warning("Real x size is 0.0, fixing to 1.0");
        xreal = 1.0;
    }
    if (!((yreal = fabs(yreal)) > 0)) {
        g_warning("Real y size is 0.0, fixing to 1.0");
        yreal = 1.0;
    }
    p = buffer + *(offset++);
    q = getflt(&p);
    z0 = getflt(&p);
    gwy_debug("xreal.raw = %g, yreal.raw = %g, q.raw = %g, z0.raw = %g",
              xreal, yreal, q, z0);
    p = buffer + *(offset++);
    unitz = gwy_si_unit_new_parse(p, &power10);
    q *= pow10(power10);
    z0 *= pow10(power10);
    unitxy = gwy_si_unit_new_parse(p + 10, &power10);
    xreal *= pow10(power10);
    yreal *= pow10(power10);
    gwy_debug("xres = %d, yres = %d, xreal = %g, yreal = %g, q = %g, z0 = %g",
              xres, yres, xreal, yreal, q, z0);
    gwy_debug("unitxy = %s, unitz = %s", p, p + 10);

    if (offset[1]) {
        /* We know channel title */
        offset++;
        p = buffer + *(offset++);
        *title = g_strndup(p, size - (p - buffer));
        gwy_debug("title = <%s>", *title);
    }
    else {
        /* We know data type */
        p = buffer + *(offset++);
        type = gwy_get_guint16_le(&p);
        *direction = gwy_get_guint16_le(&p);
        gwy_debug("type = %d, dir = %d", type, *direction);
        offset++;
        *title = type_to_title(type);
    }

    p = buffer + doffset;
    if (err_SIZE_MISMATCH(error, 2*xres*yres, size - (p - buffer), FALSE))
        return NULL;

    dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE);
    gwy_data_field_set_si_unit_xy(dfield, unitxy);
    g_object_unref(unitxy);
    gwy_data_field_set_si_unit_z(dfield, unitz);
    g_object_unref(unitz);
    data = gwy_data_field_get_data(dfield);
    for (i = 0; i < xres*yres; i++)
        data[i] = (p[2*i] + 256.0*p[2*i + 1])*q + z0;

    return dfield;
}
Example #19
0
static GwyContainer*
pni_load(const gchar *filename,
         G_GNUC_UNUSED GwyRunType mode,
         GError **error)
{
    static const GwyEnum titles[] = {
        { "Height", DATA_TYPE_HGT, },
        { "Sens",   DATA_TYPE_SEN, },
        { "Dem",    DATA_TYPE_DEM, },
        { "Error",  DATA_TYPE_ERR, },
        { "L-R",    DATA_TYPE_L_R, },
    };

    GwyContainer *container = NULL;
    guchar *buffer = NULL;
    gsize size = 0;
    GError *err = NULL;
    GwyDataField *dfield = NULL;
    const guchar *p;
    gint i, xres, yres;
    PNIDataType data_type;
    PNIValueType value_type;
    PNIDirection direction;
    gdouble xreal, yreal, zscale;
    gdouble *data;
    const gint16 *d16;
    GwySIUnit *siunit;
    const gchar *title;
    gchar *s;

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

    p = buffer + DATA_HEADER_START + RESOLUTION_OFFSET;
    xres = gwy_get_guint32_le(&p);
    yres = gwy_get_guint32_le(&p);
    gwy_debug("%d %d", xres, yres);
    if (err_DIMENSION(error, xres)
        || err_DIMENSION(error, yres)
        || err_SIZE_MISMATCH(error, DATA_START + 2*xres*yres, size, TRUE)) {
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    p = buffer + DATA_HEADER_START;
    data_type = p[DATA_TYPE_OFFSET];
    value_type = p[VALUE_TYPE_OFFSET];
    direction = p[DIRECTION_OFFSET];

    p = buffer + DATA_HEADER_START + REAL_SIZE_OFFSET;
    xreal = gwy_get_gfloat_le(&p);
    yreal = gwy_get_gfloat_le(&p);
    /* Use negated positive conditions to catch NaNs */
    if (!((xreal = fabs(xreal)) > 0)) {
        g_warning("Real x size is 0.0, fixing to 1.0");
        xreal = 1.0;
    }
    if (!((yreal = fabs(yreal)) > 0)) {
        g_warning("Real y size is 0.0, fixing to 1.0");
        yreal = 1.0;
    }
    xreal *= Micrometer;
    yreal *= Micrometer;

    p = buffer + DATA_HEADER_START + VALUE_SCALE_OFFSET;
    zscale = gwy_get_gfloat_le(&p);

    dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE);
    data = gwy_data_field_get_data(dfield);
    d16 = (const gint16*)(buffer + DATA_START);
    for (i = 0; i < xres*yres; i++)
        data[i] = zscale*GINT16_FROM_LE(d16[i])/65536.0;

    gwy_file_abandon_contents(buffer, size, NULL);

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

    switch (value_type) {
        case VALUE_TYPE_NM:
        siunit = gwy_si_unit_new("m");
        gwy_data_field_multiply(dfield, Nanometer);
        break;

        case VALUE_TYPE_MV:
        siunit = gwy_si_unit_new("V");
        gwy_data_field_multiply(dfield, Milivolt);
        break;

        default:
        g_warning("Value type %d is unknown", value_type);
        siunit = gwy_si_unit_new(NULL);
        break;
    }
    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);
    g_object_unref(dfield);

    title = gwy_enum_to_string(data_type, titles, G_N_ELEMENTS(titles));
    if (title) {
        s = g_strdup_printf("%s (%s)",
                            title,
                            direction ? "Forward" : "Backward");
        gwy_container_set_string_by_name(container, "/0/data/title", s);
    }
    else
        g_warning("Data type %d is unknown", data_type);

    gwy_file_channel_import_log_add(container, 0, NULL, filename);

    return container;
}
Example #20
0
static GwyDataField*
omicron_read_data(OmicronFile *ofile,
                  OmicronTopoChannel *channel,
                  GError **error)
{
    GError *err = NULL;
    GwyDataField *dfield;
    GwySIUnit *siunit;
    gchar *filename;
    gdouble *data;
    guchar *buffer;
    const gint16 *d;
    gdouble scale;
    gsize size;
    guint i, j, n;
    gint power10 = 0;

    filename = omicron_fix_file_name(ofile->filename, channel->filename, error);
    if (!filename)
        return NULL;

    gwy_debug("Succeeded with <%s>", filename);
    if (!gwy_file_get_contents(filename, &buffer, &size, &err)) {
        g_free(filename);
        err_GET_FILE_CONTENTS(error, &err);
        return NULL;
    }
    g_free(filename);

    n = ofile->xres*ofile->yres;
    if (err_SIZE_MISMATCH(error, 2*n, size, TRUE)) {
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    scale = (channel->max_phys - channel->min_phys)
            /(channel->max_raw - channel->min_raw);
    dfield = gwy_data_field_new(ofile->xres, ofile->yres,
                                ofile->xreal, ofile->yreal,
                                FALSE);
    data = gwy_data_field_get_data(dfield);
    d = (const gint16*)buffer;
    for (i = 0; i < ofile->yres; i++) {
        for (j = 0; j < ofile->xres; j++)
            data[(ofile->yres-1 - i)*ofile->xres + j]
                = scale*GINT16_FROM_BE(d[i*ofile->xres + j]);
    }
    gwy_file_abandon_contents(buffer, size, NULL);

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

    siunit = gwy_si_unit_new_parse(channel->units, &power10);
    gwy_data_field_set_si_unit_z(dfield, siunit);
    g_object_unref(siunit);
    if (power10)
        gwy_data_field_multiply(dfield, pow10(power10));

    return dfield;
}
Example #21
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;
}
Example #22
0
static GwyDataField*
read_data_field_old(const guchar *buffer,
                    guint size,
                    GError **error)
{
    gint xres, yres, n, i, j, vx, vy;
    G_GNUC_UNUSED gint vz;
    gdouble xscale, yscale, zscale, xreal, yreal, q;
    G_GNUC_UNUSED gdouble xunit, yunit, zunit;
    GwyDataField *dfield;
    GwySIUnit *siunit;
    gdouble *data, *row;
    const gint16 *pdata;
    const guchar *p;

    p = buffer + RES_OFFSET_OLD;
    xres = gwy_get_guint16_le(&p);
    yres = gwy_get_guint16_le(&p);
    gwy_debug("xres: %d, yres: %d", xres, yres);
    if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres))
        return NULL;

    n = xres*yres;
    if (err_SIZE_MISMATCH(error, 2*n + HEADER_SIZE_OLD, size, TRUE))
        return NULL;

    p = buffer + SCALE_OFFSET_OLD;
    xscale = gwy_get_gdouble_le(&p);
    yscale = gwy_get_gdouble_le(&p);
    zscale = gwy_get_gdouble_le(&p);
    p = buffer + UNIT_OFFSET_OLD;
    xunit = gwy_get_gdouble_le(&p);
    yunit = gwy_get_gdouble_le(&p);
    zunit = gwy_get_gdouble_le(&p);
    p = buffer + SPEED_OFFSET_OLD;
    vx = gwy_get_guint32_le(&p);
    vy = gwy_get_guint32_le(&p);
    vz = gwy_get_guint32_le(&p);

    xreal = xscale * vx;
    yreal = yscale * vy;
    q = zscale;
    gwy_debug("xreal: %g, yreal: %g, zscale: %g", xreal, yreal, q);
    /* Use negated positive conditions to catch NaNs */
    if (!((xreal = fabs(xreal)) > 0)) {
        g_warning("Real x size is 0.0, fixing to 1.0");
        xreal = 1.0;
    }
    if (!((yreal = fabs(yreal)) > 0)) {
        g_warning("Real y size is 0.0, fixing to 1.0");
        yreal = 1.0;
    }

    dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE);
    data = gwy_data_field_get_data(dfield);
    pdata = (const gint16*)(buffer + HEADER_SIZE_OLD);
    for (i = 0; i < yres; i++) {
        row = data + i*xres;
        for (j = 0; j < xres; j++)
            row[j] = GUINT16_FROM_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);

    return dfield;
}
Example #23
0
static GwyContainer*
text_dump_import(gchar *buffer,
                 gsize size,
                 const gchar *filename,
                 GError **error)
{
    gchar *val, *key, *pos, *line, *title;
    GwyContainer *data;
    GwyDataField *dfield;
    gdouble xreal, yreal;
    gint xres, yres, id;
    GwySIUnit *uxy, *uz;
    const guchar *s;
    gdouble *d;
    gsize n;

    data = gwy_container_new();

    pos = buffer;
    while ((line = gwy_str_next_line(&pos)) && *line) {
        val = strchr(line, '=');
        if (!val || *line != '/') {
            g_warning("Garbage key: %s", line);
            continue;
        }
        if ((gsize)(val - buffer) + 1 > size) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("End of file reached when value was expected."));
            goto fail;
        }
        *val = '\0';
        val++;
        if (!gwy_strequal(val, "[") || !pos || *pos != '[') {
            gwy_debug("<%s>=<%s>", line, val);
            if (*val)
                gwy_container_set_string_by_name(data, line, g_strdup(val));
            else
                gwy_container_remove_by_name(data, line);
            continue;
        }

        g_assert(pos && *pos == '[');
        pos++;
        dfield = NULL;
        gwy_container_gis_object_by_name(data, line, &dfield);

        id = 0;
        sscanf(line, "/%d", &id);

        /* get datafield parameters from already read values, failing back
         * to values of original data field */
        key = g_strconcat(line, "/xres", NULL);
        if (gwy_container_gis_string_by_name(data, key, &s))
            xres = atoi(s);
        else if (dfield)
            xres = gwy_data_field_get_xres(dfield);
        else {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("Missing data field width."));
            goto fail;
        }
        g_free(key);

        key = g_strconcat(line, "/yres", NULL);
        if (gwy_container_gis_string_by_name(data, key, &s))
            yres = atoi(s);
        else if (dfield)
            yres = gwy_data_field_get_yres(dfield);
        else {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("Missing data field height."));
            goto fail;
        }
        g_free(key);

        key = g_strconcat(line, "/xreal", NULL);
        if (gwy_container_gis_string_by_name(data, key, &s))
            xreal = g_ascii_strtod(s, NULL);
        else if (dfield)
            xreal = gwy_data_field_get_xreal(dfield);
        else {
            g_warning("Missing real data field width.");
            xreal = 1.0;   /* 0 could cause troubles */
        }
        g_free(key);

        key = g_strconcat(line, "/yreal", NULL);
        if (gwy_container_gis_string_by_name(data, key, &s))
            yreal = g_ascii_strtod(s, NULL);
        else if (dfield)
            yreal = gwy_data_field_get_yreal(dfield);
        else {
            g_warning("Missing real data field height.");
            yreal = 1.0;   /* 0 could cause troubles */
        }
        g_free(key);

        if (!(xres > 0 && yres > 0 && xreal > 0 && yreal > 0)) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("Data field dimensions are not positive numbers."));
            goto fail;
        }

        key = g_strconcat(line, "/unit-xy", NULL);
        if (gwy_container_gis_string_by_name(data, key, &s))
            uxy = gwy_si_unit_new((const gchar*)s);
        else if (dfield) {
            uxy = gwy_data_field_get_si_unit_xy(dfield);
            uxy = gwy_si_unit_duplicate(uxy);
        }
        else {
            g_warning("Missing lateral units.");
            uxy = gwy_si_unit_new("m");
        }
        g_free(key);

        key = g_strconcat(line, "/unit-z", NULL);
        if (gwy_container_gis_string_by_name(data, key, &s))
            uz = gwy_si_unit_new((const gchar*)s);
        else if (dfield) {
            uz = gwy_data_field_get_si_unit_z(dfield);
            uz = gwy_si_unit_duplicate(uz);
        }
        else {
            g_warning("Missing value units.");
            uz = gwy_si_unit_new("m");
        }
        g_free(key);

        key = g_strconcat(line, "/title", NULL);
        title = NULL;
        gwy_container_gis_string_by_name(data, key, (const guchar**)&title);
        /* We got the contained string but that would disappear. */
        title = g_strdup(title);
        g_free(key);

        n = xres*yres*sizeof(gdouble);
        if ((gsize)(pos - buffer) + n + 3 > size) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("End of file reached inside a data field."));
            goto fail;
        }
        dfield = GWY_DATA_FIELD(gwy_data_field_new(xres, yres, xreal, yreal,
                                                   FALSE));
        gwy_data_field_set_si_unit_xy(dfield, GWY_SI_UNIT(uxy));
        gwy_object_unref(uxy);
        gwy_data_field_set_si_unit_z(dfield, GWY_SI_UNIT(uz));
        gwy_object_unref(uz);
        d = gwy_data_field_get_data(dfield);
#if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
        memcpy(d, pos, n);
#else
        gwy_memcpy_byte_swap(pos, (guint8*)d,
                             sizeof(gdouble), xres*yres, sizeof(gdouble)-1);
#endif
        pos += n;
        val = gwy_str_next_line(&pos);
        if (!gwy_strequal(val, "]]")) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("Missing end of data field marker."));
            gwy_object_unref(dfield);
            goto fail;
        }
        gwy_container_remove_by_prefix(data, line);
        gwy_container_set_object_by_name(data, line, dfield);
        g_object_unref(dfield);

        if (title) {
            key = g_strconcat(line, "/title", NULL);
            gwy_container_set_string_by_name(data, key, title);
            g_free(key);
        }

        gwy_file_channel_import_log_add(data, id, NULL, filename);
    }
    return data;

fail:
    gwy_container_remove_by_prefix(data, NULL);
    g_object_unref(data);
    return NULL;
}
Example #24
0
static gboolean
read_aist_raster(const guchar **p, gsize *size, AistContext *context)
{
    AistRaster raster;
    GwyDataField *dfield, *mfield;
    GwySIUnit *xyunit, *zunit;
    gboolean ok = FALSE;
    guint i, j, n, len;
    const guchar *data;
    gchar *s;
    gchar key[32];
    gdouble *d;
    gdouble qxy, qz;

    gwy_clear(&raster, 1);

    gwy_debug("reading common");
    if (!read_aist_common(p, size, &raster.common))
        goto fail;

    gwy_debug("reading raster");
    if (!read_qt_int(p, size, &raster.xres)
        || !read_qt_int(p, size, &raster.yres)
        || !read_qt_double(p, size, &raster.left)
        || !read_qt_double(p, size, &raster.right)
        || !read_qt_double(p, size, &raster.top)
        || !read_qt_double(p, size, &raster.bottom)
        || !read_qt_string(p, size, &raster.xunits)
        || !read_qt_string(p, size, &raster.yunits)
        || !read_qt_string(p, size, &raster.zunits))
        goto fail;

    if (!read_qt_byte_array(p, size, &len, &data))
        goto fail;
    n = raster.xres * raster.yres;
    if (len != n*sizeof(gdouble))
        goto fail;

    xyunit = extract_units(raster.xunits, &qxy);
    zunit = extract_units(raster.zunits, &qz);
    dfield = gwy_data_field_new(raster.xres, raster.yres,
                                qxy*fabs(raster.right - raster.left),
                                qxy*fabs(raster.bottom - raster.top),
                                FALSE);
    gwy_data_field_set_si_unit_xy(dfield, xyunit);
    gwy_data_field_set_si_unit_z(dfield, zunit);
    /* Apparently this is not generally wanted.
    gwy_data_field_set_xoffset(dfield, qxy*MIN(raster.left, raster.right));
    gwy_data_field_set_yoffset(dfield, qxy*MIN(raster.top, raster.bottom));
    */

    g_object_unref(xyunit);
    g_object_unref(zunit);

    d = gwy_data_field_get_data(dfield);
    for (i = 0; i < raster.yres; i++) {
        for (j = 0; j < raster.xres; j++) {
            d[(raster.yres-1 - i)*raster.xres + j]
                = qz*gwy_get_gdouble_le(&data);
        }
    }

    g_snprintf(key, sizeof(key), "/%d/data", context->channel_id);
    gwy_container_set_object_by_name(context->container, key, dfield);
    g_object_unref(dfield);
    gwy_file_channel_import_log_add(context->container, context->channel_id,
                                    NULL, context->filename);

    if ((s = strchr(raster.common.name, '[')))
        s = g_strchomp(g_strndup(raster.common.name, s - raster.common.name));
    else
        s = g_strdup(raster.common.name);
    g_snprintf(key, sizeof(key), "/%d/data/title", context->channel_id);
    gwy_container_set_string_by_name(context->container, key, s);

    g_snprintf(key, sizeof(key), "/%d/mask", context->channel_id);

    context->channel_id++;

    /* At this moment we consider the loading successful. */
    ok = TRUE;

    /* The mask raster is byte-valued.   It contains nonzeroes in points that
     * were measured (the opposite of how we normally create masks upon
     * import). */
    if (read_qt_byte_array(p, size, &len, &data)) {
        if (len == raster.xres*raster.yres) {
            mfield = make_mask_field(dfield, data);
            if (mfield) {
                gwy_app_channel_remove_bad_data(dfield, mfield);
                gwy_container_set_object_by_name(context->container, key,
                                                 mfield);
                g_object_unref(mfield);
            }
        }

        /* Here's something called view data.  It means the data was processed
         * (by whatever means) hence we are not interesed in it. */
        read_qt_byte_array(p, size, &len, &data);
    }

fail:
    free_aist_common(&raster.common);
    g_free(raster.xunits);
    g_free(raster.yunits);
    g_free(raster.zunits);
    return ok;
}
Example #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;
}
Example #26
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);
}
Example #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;
}
Example #28
0
static GwyContainer*
asc_load(const gchar *filename,
         G_GNUC_UNUSED GwyRunType mode,
         GError **error)
{
    GwyContainer *container = NULL;
    GwyDataField *dfield = NULL, *mfield = NULL;
    GwyTextHeaderParser parser;
    GwySIUnit *unit;
    gchar *line, *p, *value, *buffer = NULL;
    GHashTable *hash = NULL;
    gsize size;
    GError *err = NULL;
    gdouble xreal, yreal, q;
    gint i, xres, yres;
    gdouble *data;

    if (!g_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        goto fail;
    }

    p = buffer;
    line = gwy_str_next_line(&p);
    if (!gwy_strequal(line, MAGIC_BARE)) {
        err_FILE_TYPE(error, "SPIP ASCII data");
        goto fail;
    }

    gwy_clear(&parser, 1);
    parser.line_prefix = "#";
    parser.key_value_separator = "=";
    parser.terminator = "# Start of Data:";
    parser.error = &header_error;
    parser.end = &header_end;
    if (!(hash = gwy_text_header_parse(p, &parser, &p, &err))) {
        g_propagate_error(error, err);
        goto fail;
    }
    if (!require_keys(hash, error,
                      "x-pixels", "y-pixels", "x-length", "y-length",
                      NULL))
        goto fail;

    xres = atoi(g_hash_table_lookup(hash, "x-pixels"));
    yres = atoi(g_hash_table_lookup(hash, "y-pixels"));
    if (err_DIMENSION(error, xres) || err_DIMENSION(error, yres))
        goto fail;

    xreal = Nanometer * g_ascii_strtod(g_hash_table_lookup(hash, "x-length"),
                                       NULL);
    yreal = Nanometer * g_ascii_strtod(g_hash_table_lookup(hash, "y-length"),
                                       NULL);
    /* Use negated positive conditions to catch NaNs */
    if (!((xreal = fabs(xreal)) > 0)) {
        g_warning("Real x size is 0.0, fixing to 1.0");
        xreal = 1.0;
    }
    if (!((yreal = fabs(yreal)) > 0)) {
        g_warning("Real y size is 0.0, fixing to 1.0");
        yreal = 1.0;
    }

    dfield = gwy_data_field_new(xres, yres, xreal, yreal, FALSE);

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

    if ((value = g_hash_table_lookup(hash, "z-unit"))) {
        gint power10;

        unit = gwy_si_unit_new_parse(value, &power10);
        gwy_data_field_set_si_unit_z(dfield, unit);
        g_object_unref(unit);
        q = pow10(power10);
    }
    else if ((value = g_hash_table_lookup(hash, "Bit2nm"))) {
        q = Nanometer * g_ascii_strtod(value, NULL);
        unit = gwy_si_unit_new("m");
        gwy_data_field_set_si_unit_z(dfield, unit);
        g_object_unref(unit);
    }
    else
        q = 1.0;

    data = gwy_data_field_get_data(dfield);
    value = p;
    for (i = 0; i < xres*yres; i++) {
        data[i] = q*g_ascii_strtod(value, &p);
        if (p == value && (!*p || g_ascii_isspace(*p))) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("End of file reached when reading sample #%d of %d"),
                        i, xres*yres);
            goto fail;
        }
        if (p == value) {
            g_set_error(error, GWY_MODULE_FILE_ERROR,
                        GWY_MODULE_FILE_ERROR_DATA,
                        _("Malformed data encountered when reading sample "
                          "#%d of %d"),
                        i, xres*yres);
            goto fail;
        }
        value = p;
    }

    if ((value = g_hash_table_lookup(hash, "voidpixels")) && atoi(value)) {
        mfield = gwy_data_field_new_alike(dfield, FALSE);
        data = gwy_data_field_get_data(mfield);
        value = p;
        for (i = 0; i < xres*yres; i++) {
            data[i] = 1.0 - g_ascii_strtod(value, &p);
            value = p;
        }
        if (!gwy_app_channel_remove_bad_data(dfield, mfield))
            GWY_OBJECT_UNREF(mfield);
    }

    container = gwy_container_new();

    gwy_container_set_object(container, gwy_app_get_data_key_for_id(0), dfield);

    if (mfield) {
        gwy_container_set_object(container, gwy_app_get_mask_key_for_id(0),
                                 mfield);
        g_object_unref(mfield);
    }

    gwy_file_channel_import_log_add(container, 0, NULL, filename);

fail:
    GWY_OBJECT_UNREF(dfield);
    g_free(buffer);
    if (hash)
        g_hash_table_destroy(hash);

    return container;
}
Example #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);
}
Example #30
0
static GwyContainer*
burleigh_exp_load(const gchar *filename,
                  G_GNUC_UNUSED GwyRunType mode,
                  GError **error)
{
    GwyContainer *container = NULL;
    gchar *buffer = NULL;
    BurleighExpHeader header;
    gsize size = 0;
    GError *err = NULL;
    GwyDataField *dfield;
    gdouble *data;
    guint i, n;

    if (!g_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        return NULL;
    }
    if (size < MIN_FILE_SIZE + 2) {
        err_TOO_SHORT(error);
        g_free(buffer);
        return NULL;
    }

    if (!burleigh_exp_read_header(&header, buffer, error))
        goto fail;

    n = header.xres * header.yres;
    if (header.binary) {
        if (header.bpp != 16) {
            err_BPP(error, header.bpp);
            goto fail;
        }
        else if (err_SIZE_MISMATCH(error, header.length + 2*n, size, TRUE))
            goto fail;
    }

    dfield = gwy_data_field_new(header.xres, header.yres,
                                header.xscale, header.yscale,
                                FALSE);
    data = gwy_data_field_get_data(dfield);

    if (header.binary) {
        const gint16 *d16 = (const gint16*)(buffer + header.length);

        for (i = 0; i < n; i++)
            data[i] = GINT16_FROM_LE(d16[i]);
    }
    else {
        gchar *p = buffer + header.length;

        for (i = 0; i < n; i++)
            data[i] = strtol(p, &p, 10);
    }

    gwy_data_field_multiply(dfield, header.zscale/32768.0);

    /* Units references released in free_header() */
    gwy_data_field_set_si_unit_xy(dfield, header.xyunits);
    gwy_data_field_set_si_unit_z(dfield, header.zunits);

    container = gwy_container_new();
    gwy_container_set_object(container, gwy_app_get_data_key_for_id(0), dfield);
    g_object_unref(dfield);
    gwy_app_channel_title_fall_back(container, 0);
    gwy_file_channel_import_log_add(container, 0, NULL, filename);

fail:
    free_header(&header);
    g_free(buffer);

    return container;
}