static GwyDataField* rhkspm32_read_data(RHKPage *rhkpage) { GwyDataField *dfield; const guint16 *p; GwySIUnit *siunit; gdouble *data; const gchar *s; gdouble q; gint power10; guint i, j, xres, yres; p = (const guint16*)(rhkpage->buffer + rhkpage->data_offset); xres = rhkpage->xres; yres = rhkpage->yres; // the scales are no longer gurunteed to be positive, // so they must be "fixed" here (to enable spectra) dfield = gwy_data_field_new(xres, yres, xres*fabs(rhkpage->x.scale), yres*fabs(rhkpage->y.scale), FALSE); data = gwy_data_field_get_data(dfield); for (i = 0; i < yres; i++) { for (j = 0; j < xres; j++) data[i*xres + xres-1 - j] = GINT16_FROM_LE(p[i*xres + j]); } siunit = gwy_data_field_get_si_unit_xy(dfield); gwy_si_unit_set_from_string_parse(siunit, rhkpage->x.units, &power10); if (power10) { q = pow10(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)); } siunit = gwy_data_field_get_si_unit_z(dfield); s = rhkpage->z.units; /* Fix some silly units */ if (gwy_strequal(s, "N/sec")) s = "s^-1"; gwy_si_unit_set_from_string_parse(siunit, s, &power10); q = pow10(power10); gwy_data_field_multiply(dfield, q*fabs(rhkpage->z.scale)); gwy_data_field_add(dfield, q*rhkpage->z.offset); return dfield; }
/** * gwy_si_unit_set_from_string: * @siunit: An SI unit. * @unit_string: Unit string to set @siunit from (it can be %NULL for an empty * unit). * * Sets string that represents unit. * * It must be base unit with no prefixes (e. g. "m", "N", "A", etc.). **/ void gwy_si_unit_set_from_string(GwySIUnit *siunit, const gchar *unit_string) { g_return_if_fail(GWY_IS_SI_UNIT(siunit)); gwy_si_unit_set_from_string_parse(siunit, unit_string, NULL); }
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; }
static gboolean get_scales(GHashTable *hash, gboolean is_text, gint *xres, gint *yres, gdouble *xreal, gdouble *yreal, gdouble *xoff, gdouble *yoff, GwySIUnit *si_unit_xy, gdouble *zscale, gdouble *zoff, GwySIUnit *si_unit_z, GError **error) { GwySIUnit *unit; gint power10, zp; gchar *p; gboolean has_unit = FALSE; /* Dimensions are mandatory. */ if (!require_keys(hash, error, "SCANNING PARAMS::PixelsX", "SCANNING PARAMS::PixelsY", "SCANNING PARAMS::PixelsZ", "SCANNING PARAMS::SizeX", "SCANNING PARAMS::SizeY", "SCANNING PARAMS::SizeZ", NULL)) return FALSE; *xres = atoi(g_hash_table_lookup(hash, "SCANNING PARAMS::PixelsX")); if (err_DIMENSION(error, *xres)) return FALSE; *yres = atoi(g_hash_table_lookup(hash, "SCANNING PARAMS::PixelsY")); if (err_DIMENSION(error, *yres)) return FALSE; unit = gwy_si_unit_new(NULL); p = g_hash_table_lookup(hash, "SCANNING PARAMS::SizeX"); *xreal = fabs(g_ascii_strtod(p, &p)); if (!*xreal) { g_warning("Real x size is 0.0, fixing to 1.0"); *xreal = 1.0; } gwy_si_unit_set_from_string_parse(si_unit_xy, p, &power10); *xreal *= pow10(power10); p = g_hash_table_lookup(hash, "SCANNING PARAMS::SizeY"); *yreal = fabs(g_ascii_strtod(p, &p)); if (!*yreal) { g_warning("Real y size is 0.0, fixing to 1.0"); *yreal = 1.0; } gwy_si_unit_set_from_string_parse(unit, p, &power10); *yreal *= pow10(power10); if (!gwy_si_unit_equal(unit, si_unit_xy)) { g_warning("X and Y units differ, using X"); } zp = atoi(g_hash_table_lookup(hash, "SCANNING PARAMS::PixelsZ")); if (!zp) { g_warning("Z pixels is 0, fixing to 1"); zp = 1; } p = g_hash_table_lookup(hash, "SCANNING PARAMS::SizeZ"); *zscale = g_ascii_strtod(p, &p); *zoff = 0.0; gwy_si_unit_set_from_string_parse(si_unit_z, p, &power10); *zscale *= pow10(power10)/zp; /* XXX: Version 4 can have UNIT section that takes precedence. The Conv * factor may not be enough. Apparently, binary phase data need * subtracting 180 deg because data are unsinged. Bite me. */ if ((p = g_hash_table_lookup(hash, "UNIT::Unit"))) { const gchar *s = g_hash_table_lookup(hash, "UNIT::Name"); has_unit = TRUE; gwy_si_unit_set_from_string_parse(si_unit_z, p, &power10); *zscale *= pow10(power10); if ((p = g_hash_table_lookup(hash, "UNIT::Conv"))) *zscale *= g_ascii_strtod(p, NULL); if (!is_text && gwy_strequal(s, "Phase")) *zoff = -180.0; } /* Offsets are optional. */ *xoff = 0.0; if ((p = g_hash_table_lookup(hash, "SCANNING PARAMS::OffsetX"))) { *xoff = g_ascii_strtod(p, &p); gwy_si_unit_set_from_string_parse(unit, p, &power10); if (gwy_si_unit_equal(unit, si_unit_xy)) *xoff *= pow10(power10); else { g_warning("X offset units differ from X size units, ignoring."); *xoff = 0.0; } } *yoff = 0.0; if ((p = g_hash_table_lookup(hash, "SCANNING PARAMS::OffsetY"))) { *yoff = g_ascii_strtod(p, &p); gwy_si_unit_set_from_string_parse(unit, p, &power10); if (gwy_si_unit_equal(unit, si_unit_xy)) *yoff *= pow10(power10); else { g_warning("Y offset units differ from Y size units, ignoring."); *yoff = 0.0; } } // Don't know what to do with the offset when UNIT section is present. // It seems to be always 0 in wrong units, so skip it. if (!has_unit) { if ((p = g_hash_table_lookup(hash, "SCANNING PARAMS::OffsetZ"))) { *zoff = g_ascii_strtod(p, &p); gwy_si_unit_set_from_string_parse(unit, p, &power10); if (gwy_si_unit_equal(unit, si_unit_z)) *zoff *= pow10(power10); else { g_warning("Z offset units differ from Z size units, ignoring."); *zoff = 0.0; } } } g_object_unref(unit); return TRUE; }
static GwyDataField* igor_read_data_field(const IgorFile *igorfile, const guchar *buffer, guint i, const gchar *zunits, gboolean imaginary) { const IgorWaveHeader5 *wave5; guint n, xres, yres, skip; GwyDataField *dfield; GwySIUnit *unit; gdouble *data; const guchar *p; gint power10; gdouble q; wave5 = &igorfile->wave5; xres = wave5->n_dim[0]; yres = wave5->n_dim[1]; p = buffer + igorfile->headers_size + xres*yres*igorfile->type_size*i; n = xres*yres; dfield = gwy_data_field_new(xres, yres, wave5->sfA[0]*xres, wave5->sfA[1]*yres, FALSE); data = gwy_data_field_get_data(dfield); g_return_val_if_fail(!imaginary || (wave5->type & IGOR_COMPLEX), dfield); skip = imaginary ? igorfile->type_size/2 : 0; if (imaginary) p += skip; /* TODO: Support extended units */ unit = gwy_data_field_get_si_unit_xy(dfield); gwy_si_unit_set_from_string_parse(unit, wave5->dim_units[0], &power10); gwy_data_field_set_xreal(dfield, pow10(power10)*wave5->sfA[0]*xres); gwy_data_field_set_yreal(dfield, pow10(power10)*wave5->sfA[1]*yres); unit = gwy_data_field_get_si_unit_z(dfield); gwy_si_unit_set_from_string_parse(unit, zunits ? zunits : wave5->data_units, &power10); q = pow10(power10); switch ((guint)wave5->type) { case IGOR_INT8: { const gint8 *ps = (const gint8*)buffer; while (n--) { *(data++) = *(ps++) * q; ps += skip; } } break; case IGOR_INT8 | IGOR_UNSIGNED: while (n--) { *(data++) = *(p++) * q; p += skip; } break; case IGOR_INT16: while (n--) { *(data++) = igorfile->get_gint16(&p) * q; p += skip; } break; case IGOR_INT16 | IGOR_UNSIGNED: while (n--) { *(data++) = igorfile->get_guint16(&p) * q; p += skip; } break; case IGOR_INT32: while (n--) { *(data++) = igorfile->get_gint32(&p) * q; p += skip; } break; case IGOR_INT32 | IGOR_UNSIGNED: while (n--) { *(data++) = igorfile->get_guint32(&p) * q; p += skip; } break; case IGOR_SINGLE: while (n--) { *(data++) = igorfile->get_gfloat(&p) * q; p += skip; } break; case IGOR_DOUBLE: while (n--) { *(data++) = igorfile->get_gdouble(&p) * q; p += skip; } break; default: g_return_val_if_reached(NULL); break; } gwy_data_field_invert(dfield, TRUE, FALSE, FALSE); return dfield; }
static GwyContainer* fits_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *container = NULL; fitsfile *fptr = NULL; GwyDataField *field = NULL, *mask; gint status = 0; /* Must be initialised to zero! */ gint hdutype, naxis, anynull, nkeys, k; glong res[3]; /* First index is the fast looping one. */ char strvalue[FLEN_VALUE]; gchar *invalid = NULL; gdouble real, off; if (fits_open_image(&fptr, filename, READONLY, &status)) { err_FITS(error, status); return NULL; } if (fits_get_hdu_type(fptr, &hdutype, &status)) { err_FITS(error, status); goto fail; } gwy_debug("hdutype %d", hdutype); if (hdutype != IMAGE_HDU) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Only two-dimensional images are supported.")); goto fail; } if (fits_get_img_dim(fptr, &naxis, &status)) { err_FITS(error, status); goto fail; } gwy_debug("naxis %d", naxis); if (naxis != 2 && naxis != 3) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Only two-dimensional images are supported.")); goto fail; } if (fits_get_img_size(fptr, naxis, res, &status)) { err_FITS(error, status); goto fail; } if (naxis == 3 && res[2] != 1) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Only two-dimensional images are supported.")); goto fail; } gwy_debug("xres %ld, yres %ld", res[0], res[1]); if (err_DIMENSION(error, res[0]) || err_DIMENSION(error, res[1])) goto fail; field = gwy_data_field_new(res[0], res[1], res[0], res[1], FALSE); invalid = g_new(gchar, res[0]*res[1]); if (fits_read_imgnull(fptr, TDOUBLE, 1, res[0]*res[1], field->data, invalid, &anynull, &status)) { err_FITS(error, status); goto fail; } container = gwy_container_new(); gwy_container_set_object_by_name(container, "/0/data", field); /* Failures here are non-fatal. We already have an image. */ if (fits_get_hdrspace(fptr, &nkeys, NULL, &status)) { g_warning("Cannot get the first hdrspace."); goto fail; } if (!fits_read_key(fptr, TSTRING, "BUINT ", strvalue, NULL, &status)) { gint power10; gwy_debug("BUINT = <%s>", strvalue); gwy_si_unit_set_from_string_parse(gwy_data_field_get_si_unit_z(field), strvalue, &power10); if (power10) gwy_data_field_multiply(field, pow10(power10)); } status = 0; if (get_real_and_offset(fptr, 1, res[0], &real, &off)) { if (real < 0.0) { off += real; real = -real; gwy_data_field_invert(field, FALSE, TRUE, FALSE); } gwy_data_field_set_xreal(field, real); gwy_data_field_set_xoffset(field, off); } if (get_real_and_offset(fptr, 2, res[1], &real, &off)) { if (real < 0.0) { off += real; real = -real; gwy_data_field_invert(field, TRUE, FALSE, FALSE); } gwy_data_field_set_yreal(field, real); gwy_data_field_set_yoffset(field, off); } /* Create a mask of invalid data. */ for (k = 0; k < field->xres*field->yres; k++) { if (invalid[k]) field->data[k] = NAN; } if ((mask = gwy_app_channel_mask_of_nans(field, TRUE))) { gwy_container_set_object_by_name(container, "/0/mask", mask); g_object_unref(mask); } fail: fits_close_file(fptr, &status); gwy_object_unref(field); g_free(invalid); return container; }