예제 #1
0
static gboolean
check_params(const SDFile *sdfile,
             guint len,
             GError **error)
{
    if (sdfile->data_type >= SDF_NTYPES) {
        err_DATA_TYPE(error, sdfile->data_type);
        return FALSE;
    }
    if (err_DIMENSION(error, sdfile->xres)
        || err_DIMENSION(error, sdfile->yres))
        return FALSE;
    if (err_SIZE_MISMATCH(error, sdfile->expected_size, len, FALSE))
        return FALSE;
    if (sdfile->compression) {
        err_UNSUPPORTED(error, "Compression");
        return FALSE;
    }
    if (sdfile->check_type) {
        err_UNSUPPORTED(error, "CheckType");
        return FALSE;
    }

    return TRUE;
}
예제 #2
0
static GwyContainer*
unisoku_load(const gchar *filename,
             G_GNUC_UNUSED GwyRunType mode,
             GError **error)
{
    UnisokuFile ufile;
    GwyContainer *meta, *container = NULL;
    guchar *buffer = NULL;
    gchar *text = NULL;
    gsize i, size = 0;
    GError *err = NULL;
    GwyDataField *dfield = NULL;
    gchar *data_name;

    if (!g_file_get_contents(filename, &text, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        return NULL;
    }

    for (i = 0; i < size; i++) {
        if (!text[i])
            text[i] = ' ';
    }

    gwy_clear(&ufile, 1);
    if (!unisoku_read_header(text, &ufile, error)) {
        unisoku_file_free(&ufile);
        g_free(text);
        return NULL;
    }
    g_free(text);

    if (ufile.data_type < UNISOKU_UINT8
        || ufile.data_type > UNISOKU_FLOAT
        || type_sizes[ufile.data_type] == 0) {
        err_DATA_TYPE(error, ufile.data_type);
        unisoku_file_free(&ufile);
        return NULL;
    }

    if (!(data_name = unisoku_find_data_name(filename))) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("No corresponding data file was found for header file."));
        unisoku_file_free(&ufile);
        return NULL;
    }

    if (!gwy_file_get_contents(data_name, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        unisoku_file_free(&ufile);
        g_free(data_name);
        return NULL;
    }

    dfield = unisoku_read_data_field(buffer, size, &ufile, error);
    gwy_file_abandon_contents(buffer, size, NULL);

    if (!dfield) {
        unisoku_file_free(&ufile);
        g_free(data_name);
        return NULL;
    }

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

    meta = unisoku_get_metadata(&ufile);
    gwy_container_set_object_by_name(container, "/0/meta", meta);
    g_object_unref(meta);

    gwy_file_channel_import_log_add(container, 0, NULL, data_name);

    unisoku_file_free(&ufile);
    g_free(data_name);

    return container;
}
예제 #3
0
static GwyContainer*
sensofar_load(const gchar *filename,
              G_GNUC_UNUSED GwyRunType mode,
              GError **error)
{
    SensofarDataDesc data_desc;
    GwyContainer *container = NULL;
    GwyDataField *dfield, *mfield;
    GwyGraphModel *gmodel;
    guchar *buffer = NULL;
    gsize size = 0;
    GError *err = NULL;
    const guchar *p;

    if (!gwy_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        return NULL;
    }
    if (size < HEADER_SIZE + 12) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("File header is truncated"));
        gwy_file_abandon_contents(buffer, size, NULL);
        return NULL;
    }

    /* Date block */
    p = buffer;
    memcpy(&data_desc.date.str, p, DATE_SIZE);
    data_desc.date.str[DATE_SIZE-1] = '\0';
    p += DATE_SIZE;
    data_desc.date.t = gwy_get_guint32_le(&p);

    /* Comment block */
    memcpy(&data_desc.user_comment, p, COMMENT_SIZE);
    data_desc.user_comment[COMMENT_SIZE-1] = '\0';
    p += COMMENT_SIZE;

    /* Calbration block */
    data_desc.axes_config.yres = gwy_get_guint32_le(&p);
    data_desc.axes_config.xres = gwy_get_guint32_le(&p);
    data_desc.axes_config.N_tall = gwy_get_guint32_le(&p);
    data_desc.axes_config.dy_multip = gwy_get_gfloat_le(&p);
    data_desc.axes_config.mppx = gwy_get_gfloat_le(&p);
    data_desc.axes_config.mppy = gwy_get_gfloat_le(&p);
    data_desc.axes_config.x_0 = gwy_get_gfloat_le(&p);
    data_desc.axes_config.y_0 = gwy_get_gfloat_le(&p);
    data_desc.axes_config.mpp_tall = gwy_get_gfloat_le(&p);
    data_desc.axes_config.z_0 = gwy_get_gfloat_le(&p);

    /* Measurement block */
    data_desc.measure_config.type = gwy_get_guint32_le(&p);
    data_desc.measure_config.algorithm = gwy_get_guint32_le(&p);
    data_desc.measure_config.method = gwy_get_guint32_le(&p);
    data_desc.measure_config.objective = gwy_get_guint32_le(&p);
    data_desc.measure_config.area = gwy_get_guint32_le(&p);
    data_desc.measure_config.xres_area = gwy_get_guint32_le(&p);
    data_desc.measure_config.yres_area = gwy_get_guint32_le(&p);
    data_desc.measure_config.xres = gwy_get_guint32_le(&p);
    data_desc.measure_config.yres = gwy_get_guint32_le(&p);
    data_desc.measure_config.na = gwy_get_guint32_le(&p);
    data_desc.measure_config.incr_z = gwy_get_gdouble_le(&p);
    data_desc.measure_config.range = gwy_get_gfloat_le(&p);
    data_desc.measure_config.n_planes = gwy_get_guint32_le(&p);
    data_desc.measure_config.tpc_umbral_F = gwy_get_guint32_le(&p);
    data_desc.measure_config.restore = gwy_get_gboolean8(&p);
    data_desc.measure_config.num_layers = *(p++);
    data_desc.measure_config.version = *(p++);
    data_desc.measure_config.config_hardware = *(p++);
    data_desc.measure_config.stack_im_num = *(p++);
    data_desc.measure_config.reserved = *(p++);
    p += 2; // struct padding
    data_desc.measure_config.factor_delmacio = gwy_get_guint32_le(&p);

    gwy_debug("File date=<%s>, data type=%d, xres=%d, yres=%d, version=%d", 
              data_desc.date.str, 
              data_desc.measure_config.type, 
              data_desc.measure_config.xres, 
              data_desc.measure_config.yres,
              data_desc.measure_config.version);

    switch (data_desc.measure_config.type) {
        case MES_TOPO:
        case MES_IMATGE:
        dfield = sensofar_read_data_field(&data_desc, &mfield,
                                          &p, size - (p - buffer), error);
        if (!dfield) {
            gwy_file_abandon_contents(buffer, size, NULL);
            return NULL;
        }

        container = gwy_container_new();
        gwy_container_set_object(container, gwy_app_get_data_key_for_id(0),
                                 dfield);
        g_object_unref(dfield);
        if (mfield) {
            gwy_container_set_object(container, gwy_app_get_mask_key_for_id(0),
                                     mfield);
            g_object_unref(mfield);
        }
        gwy_app_channel_title_fall_back(container, 0);
        break;

        case MES_PERFIL:
        case MES_GRUIX:
        gmodel = sensofar_read_profile(&data_desc,
                                       &p, size - (p - buffer), error);
        if (!gmodel) {
            gwy_file_abandon_contents(buffer, size, NULL);
            return NULL;
        }

        container = gwy_container_new();
        gwy_container_set_object(container, gwy_app_get_graph_key_for_id(0),
                                 gmodel);
        g_object_unref(gmodel);
        break;

        default:
        err_DATA_TYPE(error, data_desc.measure_config.type);
        break;
    }

    return container;
}
예제 #4
0
static gboolean
cdffile_read_var_array(NetCDFVar **pvars,
                       gint *pnvars,
                       NetCDFVersion version,
                       const guchar *buf,
                       gsize size,
                       const guchar **p,
                       GError **error)
{
    NetCDFVar *vars;
    gint nvars, n, i, ts, offset_size;

    if (!cdffile_check_size(error, "var_array", buf, size, *p, 8))
        return FALSE;

    n = gwy_get_guint32_be(p);
    gwy_debug("vars (%d)", n);
    if (n != 0 && n != NC_VARIABLE) {
        err_CDF_EXPECTED(error, "NC_VARIABLE");
        return FALSE;
    }
    nvars = gwy_get_guint32_be(p);
    if (nvars && !n) {
        err_CDF_ZELEMENTS(error, "var_array");
        return FALSE;
    }
    gwy_debug("nvars: %d", nvars);

    if (!nvars)
        return TRUE;

    switch (version) {
        case NETCDF_CLASSIC:
        offset_size = 4;
        break;

        case NETCDF_64BIT:
        offset_size = 8;
        break;

        default:
        g_return_val_if_reached(FALSE);
        break;
    }

    vars = g_new0(NetCDFVar, nvars);
    *pvars = vars;
    *pnvars = nvars;
    for (i = 0; i < nvars; i++) {
        if (!cdffile_check_size(error, "var_array", buf, size, *p, 4))
            return FALSE;
        n = gwy_get_guint32_be(p);
        ALIGN4(n);
        if (!cdffile_check_size(error, "var_array", buf, size, *p, n + 4))
            return FALSE;
        vars[i].name = g_strndup((const gchar*)*p, n);
        *p += n;
        vars[i].ndims = gwy_get_guint32_be(p);
        gwy_debug("var_array[%d]: <%s> %d", i, vars[i].name, vars[i].ndims);
        if (!cdffile_check_size(error, "var_array", buf, size, *p,
                                4*vars[i].ndims))
            return FALSE;
        vars[i].dimids = g_new(gint, vars[i].ndims);
        for (n = 0; n < vars[i].ndims; n++) {
            vars[i].dimids[n] = gwy_get_guint32_be(p);
            gwy_debug("var_array[%d][%d]: %d", i, n, vars[i].dimids[n]);
        }
        if (!cdffile_read_attr_array(&vars[i].attrs, &vars[i].nattrs,
                                     buf, size, p, error))
            return FALSE;
        if (!cdffile_check_size(error, "var_array", buf, size, *p,
                                8 + offset_size))
            return FALSE;
        vars[i].type = gwy_get_guint32_be(p);
        ts = cdffile_type_size(vars[i].type);
        if (!ts) {
            err_DATA_TYPE(error, vars[i].type);
            return FALSE;
        }
        vars[i].vsize = gwy_get_guint32_be(p);
        switch (version) {
            case NETCDF_CLASSIC:
            vars[i].begin = gwy_get_guint32_be(p);
            break;

            case NETCDF_64BIT:
            vars[i].begin = gwy_get_guint64_be(p);
            break;
        }
    }

    return TRUE;
}
예제 #5
0
static gboolean
cdffile_read_attr_array(NetCDFAttr **pattrs,
                        gint *pnattrs,
                        const guchar *buf,
                        gsize size,
                        const guchar **p,
                        GError **error)
{
    NetCDFAttr *attrs;
    gint nattrs, n, ts, i;

    if (!cdffile_check_size(error, "attr_array", buf, size, *p, 8))
        return FALSE;

    n = gwy_get_guint32_be(p);
    gwy_debug("attrs (%d)", n);
    if (n != 0 && n != NC_ATTRIBUTE) {
        err_CDF_EXPECTED(error, "NC_ATTRIBUTE");
        return FALSE;
    }
    nattrs = gwy_get_guint32_be(p);
    if (nattrs && !n) {
        err_CDF_ZELEMENTS(error, "attr_array");
        return FALSE;
    }
    gwy_debug("nattrs: %d", nattrs);

    if (!nattrs)
        return TRUE;

    attrs = g_new0(NetCDFAttr, nattrs);
    *pattrs = attrs;
    *pnattrs = nattrs;
    for (i = 0; i < nattrs; i++) {
        if (!cdffile_check_size(error, "attr_array", buf, size, *p, 4))
            return FALSE;
        n = gwy_get_guint32_be(p);
        n += (4 - n % 4) % 4;
        if (!cdffile_check_size(error, "attr_array", buf, size, *p, n + 8))
            return FALSE;
        attrs[i].name = g_strndup((const gchar*)*p, n);
        *p += n;
        attrs[i].type = gwy_get_guint32_be(p);
        attrs[i].nelems = gwy_get_guint32_be(p);
        gwy_debug("attr_array[%d]: <%s> %d of %d",
                  i, attrs[i].name, attrs[i].nelems, attrs[i].type);
        ts = cdffile_type_size(attrs[i].type);
        if (!ts) {
            err_DATA_TYPE(error, attrs[i].type);
            return FALSE;
        }
        n = ts*attrs[i].nelems;
        ALIGN4(n);
        if (!cdffile_check_size(error, "attr_array", buf, size, *p, n))
            return FALSE;
        attrs[i].values = *p;
        *p += n;
    }

    return TRUE;
}
예제 #6
0
static GwyContainer*
igor_load(const gchar *filename,
          G_GNUC_UNUSED GwyRunType mode,
          GError **error)
{
    GwyContainer *meta = NULL, *container = NULL;
    GwyDataField *dfield = NULL, *maskfield = NULL;
    GwyTextHeaderParser parser;
    IgorFile igorfile;
    IgorWaveHeader5 *wave5;
    GError *err = NULL;
    guchar *p, *buffer = NULL;
    gint xres, yres;
    gsize expected_size, size = 0;
    gchar *note = NULL;
    const gchar *value;
    gchar key[64];
    guint i, chid;
    GQuark quark;
    guint nlabels;

    if (!gwy_file_get_contents(filename, &buffer, &size, &err)) {
        err_GET_FILE_CONTENTS(error, &err);
        return NULL;
    }

    gwy_clear(&igorfile, 1);
    if (!igor_read_headers(&igorfile, buffer, size, FALSE, error))
        goto fail;

    /* Only accept v5 files because older do not support 2D data */
    if (igorfile.header.version != 5) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Format version is %d.  Only version 5 is supported."),
                    igorfile.header.version);
        goto fail;
    }

    /* Detect Asylum research files, leave it at generic if not detected. */
    if (memcmp(buffer + size-5, "MFP3D", 5) == 0)
        igorfile.variant = IGOR_ASYLUM_MPF3D;
    else if (memcmp(buffer + size-5, "Force", 5) == 0)
        igorfile.variant = IGOR_ASYLUM_FORCE;
    gwy_debug("producer variant %u", igorfile.variant);

    /* Must have exactly 3 dims: xres, yres, nchannels */
    wave5 = &igorfile.wave5;
    xres = wave5->n_dim[0];
    yres = wave5->n_dim[1];
    igorfile.nchannels = wave5->n_dim[2];
    if (igorfile.nchannels==0) igorfile.nchannels=1;

    if (!xres || !yres || !igorfile.nchannels || wave5->n_dim[3]) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Only two-dimensional data are supported."));
        goto fail;
    }

    igorfile.type_size = igor_data_type_size(wave5->type);
    if (!igorfile.type_size) {
        err_DATA_TYPE(error, wave5->type);
        goto fail;
    }

    if (wave5->npts != xres*yres*igorfile.nchannels) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Number of data points %u does not match resolutions "
                      "%u×%u×%u."),
                    wave5->npts, xres, yres, igorfile.nchannels);
        goto fail;
    }

    if (igorfile.header.wfm_size <= igorfile.wave_header_size) {
        err_INVALID(error, "wfmSize");
        goto fail;
    }

    expected_size = igorfile.header.wfm_size - igorfile.wave_header_size;
    if (expected_size != wave5->npts*igorfile.type_size) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Data size %u does not match "
                      "the number of data points %u×%u."),
                    (guint)expected_size, wave5->npts, igorfile.type_size);
    }

    if (err_SIZE_MISMATCH(error, expected_size + igorfile.headers_size, size,
                          FALSE))
        goto fail;

    p = buffer + igorfile.headers_size + expected_size;
    gwy_debug("remaning data size: %lu", (gulong)(size - (p - buffer)));

    p += igorfile.header.formula_size;
    if ((igorfile.variant == IGOR_ASYLUM_FORCE
         || igorfile.variant == IGOR_ASYLUM_MPF3D)
        && igorfile.header.note_size
        && (p - buffer) + igorfile.header.note_size <= size) {
        note = g_strndup((const gchar*)p, size);
        gwy_clear(&parser, 1);
        parser.key_value_separator = ":";
        igorfile.meta = gwy_text_header_parse(note, &parser, NULL, NULL);
    }
    p += igorfile.header.note_size;

    /* FIXME: Support extended units for non-Asylum files! */
    p += igorfile.header.data_e_units_size;
    for (i = 0; i < MAXDIMS; i++)
        p += igorfile.header.dim_e_units_size[i];

    /* Skip labels of x and y dimension, we don't know what to do with them. */
    for (i = 0; i < 2; i++)
        p += igorfile.header.dim_labels_size[i];

    /* FIXME: The labels are mandatory only in Asylum Research files. */
    nlabels = igorfile.header.dim_labels_size[2]/(MAX_WAVE_NAME5+1);
    expected_size = (MAX_WAVE_NAME5 + 1)*(nlabels);
    if ((p - buffer) + expected_size > size ) {
        g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA,
                    _("Cannot read channel labels."));
        goto fail;
    }
    igorfile.titles = read_channel_labels(p, igorfile.nchannels+1, nlabels);
    p += igorfile.header.dim_labels_size[2];

    if (igorfile.meta) {
        igorfile.channel_info = g_new0(AsylumChannelInfo, igorfile.nchannels);
        for (i = 0; i < igorfile.nchannels; i++) {
            AsylumChannelInfo *chinfo = igorfile.channel_info + i;
            const gchar *title = g_ptr_array_index(igorfile.titles, i+1);

            if (title) {
                chinfo->name = canonicalize_title(title);
                g_snprintf(key, sizeof(key), "%sUnit", chinfo->name);
                value = g_hash_table_lookup(igorfile.meta, key);
                if (value)
                    chinfo->units = value;
                else
                    chinfo->units = channel_title_to_units(chinfo->name);
            }
        }
    }

    container = gwy_container_new();

    for (i = chid = 0; i < igorfile.nchannels; i++, chid++) {
        const gchar *title = g_ptr_array_index(igorfile.titles, i+1);
        const gchar *zunits = NULL;

        if (igorfile.channel_info) {
            AsylumChannelInfo *chinfo = igorfile.channel_info + i;
            zunits = chinfo->units;
            meta = igor_get_metadata(&igorfile, i + 1);
        }
        dfield = igor_read_data_field(&igorfile, buffer, i, zunits, FALSE);
        maskfield = gwy_app_channel_mask_of_nans(dfield, TRUE);
        quark = gwy_app_get_data_key_for_id(chid);
        gwy_container_set_object(container, quark, dfield);
        g_object_unref(dfield);
        if (maskfield) {
            g_snprintf(key, sizeof(key), "/%d/mask", chid);
            gwy_container_set_object_by_name(container, key, maskfield);
        }
        if (meta) {
            g_snprintf(key, sizeof(key), "/%d/meta", chid);
            gwy_container_set_object_by_name(container, key, meta);
        }

        if (title) {
            g_snprintf(key, sizeof(key), "/%d/data/title", chid);
            gwy_container_set_string_by_name(container, key, g_strdup(title));
        }
        gwy_app_channel_title_fall_back(container,chid);

        if (wave5->type & IGOR_COMPLEX) {
            chid++;
            dfield = igor_read_data_field(&igorfile, buffer, i, zunits, TRUE);
            quark = gwy_app_get_data_key_for_id(chid);
            gwy_container_set_object(container, quark, dfield);
            g_object_unref(dfield);
            if (meta) {
                g_snprintf(key, sizeof(key), "/%d/meta", chid);
                /* container still holds a reference */
                g_object_unref(meta);
                meta = gwy_container_duplicate(meta);
                gwy_container_set_object_by_name(container, key, meta);
            }
            if (maskfield) {
                g_snprintf(key, sizeof(key), "/%d/mask", chid);
                /* container still holds a reference */
                g_object_unref(maskfield);
                maskfield = gwy_data_field_duplicate(maskfield);
                gwy_container_set_object_by_name(container, key, maskfield);
            }

            if (title) {
                g_snprintf(key, sizeof(key), "/%d/data/title", chid);
                gwy_container_set_string_by_name(container, key, g_strdup(title));
            };
            gwy_app_channel_title_fall_back(container,chid);
        }
        gwy_object_unref(meta);
        gwy_object_unref(maskfield);

        gwy_file_channel_import_log_add(container, chid, NULL, filename);
    }

fail:
    gwy_file_abandon_contents(buffer, size, NULL);
    g_free(note);
    if (igorfile.channel_info) {
        for (i = 0; i < igorfile.nchannels; i++)
            g_free(igorfile.channel_info[i].name);
        g_free(igorfile.channel_info);
    }
    if (igorfile.meta)
        g_hash_table_destroy(igorfile.meta);
    if (igorfile.titles) {
        g_ptr_array_foreach(igorfile.titles, (GFunc)g_free, NULL);
        g_ptr_array_free(igorfile.titles, TRUE);
    }

    return container;
}