static const gchar* rhk_sm4_describe_object(RHKObjectType type) { static const GwyEnum types[] = { { "Undefined", RHK_OBJECT_UNDEFINED, }, { "PageIndexHeader", RHK_OBJECT_PAGE_INDEX_HEADER, }, { "PageIndexArray", RHK_OBJECT_PAGE_INDEX_ARRAY, }, { "PageHeader", RHK_OBJECT_PAGE_HEADER, }, { "PageData", RHK_OBJECT_PAGE_DATA, }, { "ImageDriftHeader", RHK_OBJECT_IMAGE_DRIFT_HEADER, }, { "ImageDrift", RHK_OBJECT_IMAGE_DRIFT, }, { "SpecDriftHeader", RHK_OBJECT_SPEC_DRIFT_HEADER, }, { "SpecDriftData", RHK_OBJECT_SPEC_DRIFT_DATA, }, { "ColorInfo", RHK_OBJECT_COLOR_INFO, }, { "StringData", RHK_OBJECT_STRING_DATA, }, { "TipTrackHeader", RHK_OBJECT_TIP_TRACK_HEADER, }, { "TipTrackData", RHK_OBJECT_TIP_TRACK_DATA, }, { "PRM", RHK_OBJECT_PRM, }, { "Thumbnail", RHK_OBJECT_THUMBNAIL, }, { "PRMHeader", RHK_OBJECT_PRM_HEADER, }, { "ThumbnailHeader", RHK_OBJECT_THUMBNAIL_HEADER, }, { "APIInfo", RHK_OBJECT_API_INFO, }, /* Our types */ { "FileHeader", RHK_OBJECT_FILE_HEADER, }, { "PageIndex", RHK_OBJECT_PAGE_INDEX, }, }; const gchar *retval; retval = gwy_enum_to_string(type, types, G_N_ELEMENTS(types)); if (!retval || !*retval) return "Unknown"; return retval; };
static GwyContainer* spmlab_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GwyContainer *container = NULL; guchar *buffer = NULL; gsize size = 0; GError *err = NULL; GwyDataField *dfield = NULL; const gchar *title; gint type; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } /* 2048 is wrong. moreover it differs for r5 and r4, kasigra uses 5752 for * r5 */ if (size < 2048) { err_TOO_SHORT(error); gwy_file_abandon_contents(buffer, size, NULL); return NULL; } if (buffer[0] != '#' || buffer[1] != 'R') { err_FILE_TYPE(error, "Thermicroscopes SpmLab"); gwy_file_abandon_contents(buffer, size, NULL); return NULL; } switch (buffer[2]) { case '3': case '4': case '5': case '6': dfield = read_data_field(buffer, size, buffer[2], &type, error); break; default: g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Unknown format version %c."), buffer[2]); break; } gwy_file_abandon_contents(buffer, size, NULL); if (!dfield) return NULL; container = gwy_container_new(); gwy_container_set_object_by_name(container, "/0/data", dfield); g_object_unref(dfield); title = gwy_enum_to_string(type, spmlab_channel_types, G_N_ELEMENTS(spmlab_channel_types)); if (*title) gwy_container_set_string_by_name(container, "/0/data/title", g_strdup(title)); return container; }
static GwyContainer* apefile_get_metadata(APEFile *apefile) { GwyContainer *meta; gchar *p; meta = gwy_container_new(); HASH_STORE("Version", "%u", version); HASH_STORE("Tip oscilation frequency", "%g Hz", freq_osc_tip); HASH_STORE("Acquire delay", "%.6f s", acquire_delay); HASH_STORE("Raster delay", "%.6f s", raster_delay); HASH_STORE("Tip distance", "%g nm", tip_dist); if (apefile->remark && *apefile->remark && (p = g_convert(apefile->remark, strlen(apefile->remark), "UTF-8", "ISO-8859-1", NULL, NULL, NULL))) gwy_container_set_string_by_name(meta, "Comment", p); gwy_container_set_string_by_name (meta, "SPM mode", g_strdup(gwy_enum_to_string(apefile->spm_mode, spm_modes, G_N_ELEMENTS(spm_modes)))); p = format_vt_date(apefile->scan_date); if (p) gwy_container_set_string_by_name(meta, "Date", p); return meta; }
static void store_metadata(SurfFile *surffile, GwyContainer *container) { char date[20]; g_snprintf(date, sizeof(date), "%d. %d. %d", surffile->day, surffile->month, surffile->year); HASH_STORE("Version", "%u", version); HASH_STORE("Operator name", "%s", operator_name); HASH_STORE("Object name", "%s", object_name); gwy_container_set_string_by_name(container, "/meta/Date", g_strdup(date)); gwy_container_set_string_by_name (container, "/meta/Acquisition type", g_strdup(gwy_enum_to_string(surffile->acquisition, acq_modes, G_N_ELEMENTS(acq_modes)))); }
static GwyContainer* rhkspm32_get_metadata(RHKPage *rhkpage) { GwyContainer *meta; const gchar *s; meta = gwy_container_new(); gwy_container_set_string_by_name(meta, "Tunneling voltage", g_strdup_printf("%g mV", 1e3*rhkpage->iv.offset)); gwy_container_set_string_by_name(meta, "Current", g_strdup_printf("%g nA", 1e9*rhkpage->iv.scale)); if (rhkpage->id) gwy_container_set_string_by_name(meta, "Id", g_strdup_printf("%u", rhkpage->id)); if (rhkpage->date && *rhkpage->date) gwy_container_set_string_by_name(meta, "Date", g_strdup(rhkpage->date)); if (rhkpage->comment && *rhkpage->comment) gwy_container_set_string_by_name(meta, "Comment", g_strdup(rhkpage->comment)); if (rhkpage->label && *rhkpage->label) gwy_container_set_string_by_name(meta, "Label", g_strdup(rhkpage->label)); s = gwy_enum_to_string(rhkpage->page_type, scan_directions, G_N_ELEMENTS(scan_directions)); if (s && *s) gwy_container_set_string_by_name(meta, "Image type", g_strdup(s)); // FIXME - seems one can read 0 for spectra as well, but maybe it's not // that important - it should be clear that this is a nonsense value if (rhkpage->e_alpha) gwy_container_set_string_by_name(meta, "Angle", g_strdup_printf("%g deg", rhkpage->alpha)); return meta; }
static GwyContainer* surffile_get_metadata(SurfFile *surffile) { GwyContainer *meta; char date[40]; meta = gwy_container_new(); g_snprintf(date, sizeof(date), "%d. %d. %d", surffile->day, surffile->month, surffile->year); HASH_STORE("Version", "%u", version); HASH_STORE("Operator name", "%s", operator_name); HASH_STORE("Object name", "%s", object_name); gwy_container_set_string_by_name(meta, "Date", g_strdup(date)); gwy_container_set_string_by_name (meta, "Acquisition type", g_strdup(gwy_enum_to_string(surffile->acquisition, acq_modes, G_N_ELEMENTS(acq_modes)))); return meta; }
static GwyContainer* rhk_sm4_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { RHKFile rhkfile; RHKObject *obj, o; GwyContainer *meta, *container = NULL; guchar *buffer = NULL; gsize size = 0; GError *err = NULL; const guchar *p; GString *key = NULL; guint i, imageid = 0, graphid = 0; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } gwy_clear(&rhkfile, 1); if (size < HEADER_SIZE) { err_TOO_SHORT(error); goto fail; } /* File header */ p = buffer + MAGIC_OFFSET + MAGIC_TOTAL_SIZE; rhkfile.page_count = gwy_get_guint32_le(&p); rhkfile.object_count = gwy_get_guint32_le(&p); rhkfile.object_field_size = gwy_get_guint32_le(&p); gwy_debug("page_count: %u, object_count: %u, object_field_size: %u", rhkfile.page_count, rhkfile.object_count, rhkfile.object_field_size); if (rhkfile.object_field_size != OBJECT_SIZE) g_warning("Object field size %u differs from %u", rhkfile.object_field_size, OBJECT_SIZE); rhkfile.reserved1 = gwy_get_guint32_le(&p); rhkfile.reserved2 = gwy_get_guint32_le(&p); /* Header objects */ if (!(rhkfile.objects = rhk_sm4_read_objects(buffer, p, size, rhkfile.object_count, RHK_OBJECT_FILE_HEADER, error))) goto fail; /* Find page index header */ if (!(obj = rhk_sm4_find_object(rhkfile.objects, rhkfile.object_count, RHK_OBJECT_PAGE_INDEX_HEADER, RHK_OBJECT_FILE_HEADER, error)) || !rhk_sm4_read_page_index_header(&rhkfile.page_index_header, obj, buffer, size, error)) goto fail; /* There, find the page index array. That's a single object in the object * list but it contains a page_count-long sequence of page indices. */ rhkfile.page_indices = g_new0(RHKPageIndex, rhkfile.page_index_header.page_count); if (!(obj = rhk_sm4_find_object(rhkfile.page_index_header.objects, rhkfile.page_index_header.object_count, RHK_OBJECT_PAGE_INDEX_ARRAY, RHK_OBJECT_PAGE_INDEX_HEADER, error))) goto fail; o = *obj; for (i = 0; i < rhkfile.page_index_header.page_count; i++) { if (!rhk_sm4_read_page_index(rhkfile.page_indices + i, &o, buffer, size, error)) goto fail; /* Carefully move to the next page index */ o.offset += o.size + OBJECT_SIZE*rhkfile.page_indices[i].object_count; } container = gwy_container_new(); key = g_string_new(NULL); /* Read pages */ for (i = 0; i < rhkfile.page_index_header.page_count; i++) { RHKPageIndex *pi = rhkfile.page_indices + i; RHKPage *page = &pi->page; /* Page must contain header */ if (!(obj = rhk_sm4_find_object(pi->objects, pi->object_count, RHK_OBJECT_PAGE_HEADER, RHK_OBJECT_PAGE_INDEX, error)) || !rhk_sm4_read_page_header(page, obj, buffer, size, error)) goto fail; /* Page must contain data */ if (!(obj = rhk_sm4_find_object(pi->objects, pi->object_count, RHK_OBJECT_PAGE_DATA, RHK_OBJECT_PAGE_INDEX, error)) || !rhk_sm4_read_page_data(page, obj, buffer, error)) goto fail; /* Page may contain strings */ if (!(obj = rhk_sm4_find_object(page->objects, page->object_count, RHK_OBJECT_STRING_DATA, RHK_OBJECT_PAGE_HEADER, NULL)) || !rhk_sm4_read_string_data(page, obj, pi->page.string_count, buffer)) { g_warning("Failed to read string data in page %u", i); } /* Read the data */ if (pi->data_type == RHK_DATA_IMAGE) { GwyDataField *dfield = rhk_sm4_page_to_data_field(page); GQuark quark = gwy_app_get_data_key_for_id(imageid); const gchar *scandir, *name; gchar *title; gwy_container_set_object(container, quark, dfield); g_object_unref(dfield); if ((name = page->strings[RHK_STRING_LABEL])) { scandir = gwy_enum_to_string(page->scan_dir, scan_directions, G_N_ELEMENTS(scan_directions)); g_string_assign(key, g_quark_to_string(quark)); g_string_append(key, "/title"); if (scandir && *scandir) title = g_strdup_printf("%s [%s]", name, scandir); else title = g_strdup(name); gwy_container_set_string_by_name(container, key->str, title); } meta = rhk_sm4_get_metadata(pi, page); g_string_printf(key, "/%u/meta", imageid); gwy_container_set_object_by_name(container, key->str, meta); g_object_unref(meta); imageid++; } else if (pi->data_type == RHK_DATA_LINE) { GwyGraphModel *gmodel; RHKSpecDriftHeader drift_header; RHKSpecInfo spec_info; G_GNUC_UNUSED gboolean have_header = FALSE, have_info = FALSE; gwy_debug("page_type %u", page->page_type); gwy_debug("line_type %u", page->line_type); gwy_debug("page_sizes %u %u", page->x_size, page->y_size); /* Page may contain drift header */ if ((obj = rhk_sm4_find_object(page->objects, page->object_count, RHK_OBJECT_SPEC_DRIFT_HEADER, RHK_OBJECT_PAGE_HEADER, NULL)) && rhk_sm4_read_drift_header(&drift_header, obj, buffer)) { gwy_debug("drift_header OK"); have_header = TRUE; } if ((obj = rhk_sm4_find_object(page->objects, page->object_count, RHK_OBJECT_SPEC_DRIFT_DATA, RHK_OBJECT_PAGE_HEADER, NULL)) && rhk_sm4_read_spec_info(&spec_info, obj, buffer)) { gwy_debug("spec_info OK"); have_info = TRUE; } /* FIXME: RHK_STRING_PLL_PRO_STATUS may contain interesting * metadata. But we have not place where to put it. */ if ((gmodel = rhk_sm4_page_to_graph_model(page))) { graphid++; gwy_container_set_object(container, gwy_app_get_graph_key_for_id(graphid), gmodel); g_object_unref(gmodel); } } } if (!imageid && !graphid) err_NO_DATA(error); fail: gwy_file_abandon_contents(buffer, size, NULL); rhk_sm4_free(&rhkfile); if (!imageid && !graphid) { gwy_object_unref(container); } if (key) g_string_free(key, TRUE); return container; }
static GwyContainer* rhk_sm4_get_metadata(const RHKPageIndex *pi, const RHKPage *page) { static const gchar hex[] = "0123456789abcdef"; GwyContainer *meta; const gchar *s; gchar *str; guint i, w; meta = gwy_container_new(); s = gwy_enuml_to_string(page->page_type, "Topographic", RHK_PAGE_TOPOGAPHIC, "Current", RHK_PAGE_CURRENT, "Aux", RHK_PAGE_AUX, "Force", RHK_PAGE_FORCE, "Signal", RHK_PAGE_SIGNAL, "FFT transform", RHK_PAGE_FFT, "Noise power spectrum", RHK_PAGE_NOISE_POWER_SPECTRUM, "Line test", RHK_PAGE_LINE_TEST, "Oscilloscope", RHK_PAGE_OSCILLOSCOPE, "IV spectra", RHK_PAGE_IV_SPECTRA, "Image IV 4x4", RHK_PAGE_IV_4x4, "Image IV 8x8", RHK_PAGE_IV_8x8, "Image IV 16x16", RHK_PAGE_IV_16x16, "Image IV 32x32", RHK_PAGE_IV_32x32, "Image IV Center", RHK_PAGE_IV_CENTER, "Interactive spectra", RHK_PAGE_INTERACTIVE_SPECTRA, "Autocorrelation", RHK_PAGE_AUTOCORRELATION, "IZ spectra", RHK_PAGE_IZ_SPECTRA, "4 gain topography", RHK_PAGE_4_GAIN_TOPOGRAPHY, "8 gain topography", RHK_PAGE_8_GAIN_TOPOGRAPHY, "4 gain current", RHK_PAGE_4_GAIN_CURRENT, "8 gain current", RHK_PAGE_8_GAIN_CURRENT, "Image IV 64x64", RHK_PAGE_IV_64x64, "Autocorrelation spectrum", RHK_PAGE_AUTOCORRELATION_SPECTRUM, "Counter data", RHK_PAGE_COUNTER, "Multichannel analyser", RHK_PAGE_MULTICHANNEL_ANALYSER, "AFM using AFM-100", RHK_PAGE_AFM_100, "CITS", RHK_PAGE_CITS, "GBIB", RHK_PAGE_GPIB, "Video channel", RHK_PAGE_VIDEO_CHANNEL, "Image OUT spectra", RHK_PAGE_IMAGE_OUT_SPECTRA, "I_Datalog", RHK_PAGE_I_DATALOG, "I_Ecset", RHK_PAGE_I_ECSET, "I_Ecdata", RHK_PAGE_I_ECDATA, "DSP channel", RHK_PAGE_I_DSP_AD, "Discrete spectroscopy (present pos)", RHK_PAGE_DISCRETE_SPECTROSCOPY_PP, "Image discrete spectroscopy", RHK_PAGE_IMAGE_DISCRETE_SPECTROSCOPY, "Ramp spectroscopy (relative points)", RHK_PAGE_RAMP_SPECTROSCOPY_RP, "Discrete spectroscopy (relative points)", RHK_PAGE_DISCRETE_SPECTROSCOPY_RP, NULL); if (s && *s) gwy_container_set_string_by_name(meta, "Type", g_strdup(s)); s = gwy_enum_to_string(page->scan_dir, scan_directions, G_N_ELEMENTS(scan_directions)); if (s && *s) gwy_container_set_string_by_name(meta, "Scan Direction", g_strdup(s)); s = gwy_enuml_to_string(pi->source, "Raw", RHK_SOURCE_RAW, "Processed", RHK_SOURCE_PROCESSED, "Calculated", RHK_SOURCE_CALCULATED, "Imported", RHK_SOURCE_IMPORTED, NULL); if (s && *s) gwy_container_set_string_by_name(meta, "Source", g_strdup(s)); gwy_container_set_string_by_name(meta, "Bias", g_strdup_printf("%g V", page->bias)); gwy_container_set_string_by_name(meta, "Rotation angle", g_strdup_printf("%f", page->angle)); gwy_container_set_string_by_name(meta, "Period", g_strdup_printf("%f s", page->period)); s = page->strings[RHK_STRING_DATE]; if (s && *s) { str = g_strconcat(s, " ", page->strings[RHK_STRING_TIME], NULL); gwy_container_set_string_by_name(meta, "Date", str); } rhk_sm4_meta_string(page, RHK_STRING_LABEL, "Label", meta); rhk_sm4_meta_string(page, RHK_STRING_PATH, "Path", meta); rhk_sm4_meta_string(page, RHK_STRING_SYSTEM_TEXT, "System comment", meta); rhk_sm4_meta_string(page, RHK_STRING_SESSION_TEXT, "Session comment", meta); rhk_sm4_meta_string(page, RHK_STRING_USER_TEXT, "User comment", meta); str = g_new(gchar, 33); for (i = 0; i < 16; i++) { str[2*i] = hex[pi->id[i]/16]; str[2*i + 1] = hex[pi->id[i] % 16]; } str[32] = '\0'; gwy_container_set_string_by_name(meta, "Page ID", str); str = g_new(gchar, 9); w = page->group_id; for (i = 0; i < 8; i++) { str[7 - i] = hex[w & 0xf]; w = w >> 4; } str[8] = '\0'; gwy_container_set_string_by_name(meta, "Group ID", str); return meta; }
static GwyContainer* rhk_sm3_get_metadata(RHKPage *rhkpage) { GwyContainer *meta; const gchar *s; gchar *str; guint i; meta = gwy_container_new(); s = gwy_enum_to_string(rhkpage->page_type, page_types, G_N_ELEMENTS(page_types)); if (s && *s) gwy_container_set_string_by_name(meta, "Type", g_strdup(s)); s = gwy_enum_to_string(rhkpage->scan_dir, scan_directions, G_N_ELEMENTS(scan_directions)); if (s && *s) gwy_container_set_string_by_name(meta, "Scan Direction", g_strdup(s)); s = gwy_enum_to_string(rhkpage->source_type, page_sources, G_N_ELEMENTS(page_sources)); if (s && *s) gwy_container_set_string_by_name(meta, "Source", g_strdup(s)); gwy_container_set_string_by_name(meta, "Bias", g_strdup_printf("%g V", rhkpage->bias)); gwy_container_set_string_by_name(meta, "Rotation angle", g_strdup_printf("%f", rhkpage->angle)); gwy_container_set_string_by_name(meta, "Period", g_strdup_printf("%f s", rhkpage->period)); s = rhkpage->strings[RHK_STRING_DATE]; if (s && *s) { str = g_strconcat(s, " ", rhkpage->strings[RHK_STRING_TIME], NULL); gwy_container_set_string_by_name(meta, "Date", str); } s = rhkpage->strings[RHK_STRING_LABEL]; if (s && *s) { gwy_container_set_string_by_name(meta, "Label", g_strdup(s)); } s = rhkpage->strings[RHK_STRING_PATH]; if (s && *s) gwy_container_set_string_by_name(meta, "Path", g_strdup(s)); s = rhkpage->strings[RHK_STRING_SYSTEM_TEXT]; if (s && *s) gwy_container_set_string_by_name(meta, "System comment", g_strdup(s)); s = rhkpage->strings[RHK_STRING_SESSION_TEXT]; if (s && *s) gwy_container_set_string_by_name(meta, "Session comment", g_strdup(s)); s = rhkpage->strings[RHK_STRING_USER_TEXT]; if (s && *s) gwy_container_set_string_by_name(meta, "User comment", g_strdup(s)); str = g_new(gchar, 33); for (i = 0; i < 16; i++) { static const gchar hex[] = "0123456789abcdef"; str[2*i] = hex[rhkpage->page_id[i]/16]; str[2*i + 1] = hex[rhkpage->page_id[i] % 16]; } str[32] = '\0'; gwy_container_set_string_by_name(meta, "Page ID", str); return meta; }
static GwyContainer* rhk_sm3_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GPtrArray *rhkfile; RHKPage *rhkpage; GwyContainer *meta, *container = NULL; guchar *buffer = NULL; gsize size = 0; GError *err = NULL; GwyDataField *dfield = NULL; const guchar *p; GString *key; guint i, count; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } if (size < HEADER_SIZE) { err_TOO_SHORT(error); gwy_file_abandon_contents(buffer, size, NULL); return NULL; } rhkfile = g_ptr_array_new(); p = buffer; count = 0; gwy_debug("position %04x", p - buffer); while ((rhkpage = rhk_sm3_read_page(&p, &size, &err))) { gwy_debug("Page #%u read OK", count); count++; rhkpage->pageno = count; gwy_debug("position %04x", p - buffer); if (rhkpage->type != RHK_TYPE_IMAGE) { gwy_debug("Page is not IMAGE, skipping"); rhk_sm3_page_free(rhkpage); continue; } g_ptr_array_add(rhkfile, rhkpage); } /* Be tolerant and don't fail when we were able to import at least * something */ if (!rhkfile->len) { if (err) g_propagate_error(error, err); else err_NO_DATA(error); gwy_file_abandon_contents(buffer, size, NULL); g_ptr_array_free(rhkfile, TRUE); return NULL; } g_clear_error(&err); container = gwy_container_new(); key = g_string_new(""); for (i = 0; i < rhkfile->len; i++) { const gchar *cs; gchar *s; rhkpage = g_ptr_array_index(rhkfile, i); dfield = rhk_sm3_page_to_data_field(rhkpage); g_string_printf(key, "/%d/data", i); gwy_container_set_object_by_name(container, key->str, dfield); g_object_unref(dfield); p = rhkpage->strings[RHK_STRING_LABEL]; cs = gwy_enum_to_string(rhkpage->scan_dir, scan_directions, G_N_ELEMENTS(scan_directions)); if (p && *p) { g_string_append(key, "/title"); if (cs) s = g_strdup_printf("%s [%s]", p, cs); else s = g_strdup(p); gwy_container_set_string_by_name(container, key->str, s); } meta = rhk_sm3_get_metadata(rhkpage); g_string_printf(key, "/%d/meta", i); gwy_container_set_object_by_name(container, key->str, meta); g_object_unref(meta); gwy_app_channel_check_nonsquare(container, i); } g_string_free(key, TRUE); gwy_file_abandon_contents(buffer, size, NULL); for (i = 0; i < rhkfile->len; i++) rhk_sm3_page_free(g_ptr_array_index(rhkfile, i)); g_ptr_array_free(rhkfile, TRUE); return container; }
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; }
static GwyContainer* apefile_get_metadata(APEFile *apefile) { GwyContainer *meta; gchar *p; meta = gwy_container_new(); gwy_container_set_string_by_name(meta, "Version", g_strdup_printf("%u.%u", apefile->version, apefile->subversion)); /* * In SPM_MODE_SNOM or SPM_MODE_AFM_NONCONTACT freq_osc_tip holds the tip * oscillation frequency. * If spm_mode=SPM_MODE_AFM_CONTACT then the freq_osc_tip field holds the * force the tip applies to the sample in nN. * If spm_mode=SPM_MODE_STM then freq_osc_tip holds the bias voltage in * Volts. */ switch (apefile->spm_mode) { case SPM_MODE_SNOM: case SPM_MODE_AFM_NONCONTACT: HASH_STORE("Tip oscillation frequency", "%g Hz", freq_osc_tip); break; case SPM_MODE_AFM_CONTACT: HASH_STORE("Force", "%g nN", freq_osc_tip); break; case SPM_MODE_STM: HASH_STORE("Bias", "%g V", freq_osc_tip); break; default: HASH_STORE("Tip oscillation frequency", "%g Hz", freq_osc_tip); break; } /* We will fetch the HV Amplifier status only if file version>= 2.4*/ if (apefile->version > 1 && apefile->subversion >= 4) { gwy_container_set_string_by_name (meta, "XY HV Status", g_strdup(gwy_enum_to_string(apefile->xy_hv_status, hva_statuses, G_N_ELEMENTS(hva_statuses)))); gwy_container_set_string_by_name (meta, "Z HV Status", g_strdup(gwy_enum_to_string(apefile->z_hv_status, hva_statuses, G_N_ELEMENTS(hva_statuses)))); } HASH_STORE("Acquire delay", "%.6f s", acquire_delay); HASH_STORE("Raster delay", "%.6f s", raster_delay); HASH_STORE("Tip distance", "%g nm", tip_dist); if (apefile->remark && *apefile->remark && (p = g_convert(apefile->remark, strlen(apefile->remark), "UTF-8", "ISO-8859-1", NULL, NULL, NULL))) gwy_container_set_string_by_name(meta, "Comment", p); gwy_container_set_string_by_name (meta, "SPM mode", g_strdup(gwy_enum_to_string(apefile->spm_mode, spm_modes, G_N_ELEMENTS(spm_modes)))); p = format_vt_date(apefile->scan_date); if (p) gwy_container_set_string_by_name(meta, "Date", p); return meta; }
static gboolean unrotate_dialog(UnrotateArgs *args, GwyContainer *data, GwyDataField *dfield, gint id, gdouble *correction, GwyPlaneSymmetry guess) { enum { RESPONSE_RESET = 1 }; GtkWidget *dialog, *table, *label, *hbox; GwyPixmapLayer *layer; UnrotateControls controls; const gchar *s; gint response; gint row; controls.correction = correction; controls.guess = guess; controls.args = args; dialog = gtk_dialog_new_with_buttons(_("Correct Rotation"), NULL, 0, _("_Reset"), RESPONSE_RESET, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); gwy_help_add_to_proc_dialog(GTK_DIALOG(dialog), GWY_HELP_DEFAULT); hbox = gtk_hbox_new(FALSE, 8); gtk_container_set_border_width(GTK_CONTAINER(hbox), 4); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, FALSE, 4); table = gtk_table_new(4, 3, FALSE); gtk_table_set_row_spacings(GTK_TABLE(table), 2); gtk_table_set_col_spacings(GTK_TABLE(table), 6); gtk_container_set_border_width(GTK_CONTAINER(table), 4); gtk_box_pack_start(GTK_BOX(hbox), table, FALSE, FALSE, 0); row = 0; gtk_table_attach(GTK_TABLE(table), gwy_label_new_header(_("Structure")), 0, 3, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; label = gtk_label_new(_("Detected:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); s = gwy_sgettext(gwy_enum_to_string(guess, gwy_plane_symmetry_get_enum(), -1)); label = gtk_label_new(_(s)); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); row++; controls.symmetry = gwy_enum_combo_box_new(gwy_plane_symmetry_get_enum(), -1, G_CALLBACK(unrotate_symmetry_cb), &controls, args->symmetry, TRUE); gwy_table_attach_row(table, row, _("_Assume:"), NULL, controls.symmetry); row++; label = gtk_label_new(_("Correction:")); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); controls.corrlabel = gtk_label_new(NULL); gtk_misc_set_alignment(GTK_MISC(controls.corrlabel), 0.0, 0.5); gtk_table_attach(GTK_TABLE(table), controls.corrlabel, 1, 2, row, row+1, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_table_set_row_spacing(GTK_TABLE(table), row, 8); row++; controls.interp = gwy_enum_combo_box_new(gwy_interpolation_type_get_enum(), -1, G_CALLBACK(unrotate_interp_cb), &controls, args->interp, TRUE); gwy_table_attach_row(table, row, _("_Interpolation type:"), "", controls.interp); controls.data = create_preview_data(data, dfield, id); controls.data_view = gwy_data_view_new(controls.data); g_object_unref(controls.data); layer = gwy_layer_basic_new(); gwy_pixmap_layer_set_data_key(layer, "/0/show"); gwy_layer_basic_set_gradient_key(GWY_LAYER_BASIC(layer), "/0/base/palette"); gwy_data_view_set_data_prefix(GWY_DATA_VIEW(controls.data_view), "/0/data"); gwy_data_view_set_base_layer(GWY_DATA_VIEW(controls.data_view), layer); gtk_box_pack_start(GTK_BOX(hbox), controls.data_view, FALSE, FALSE, 8); unrotate_dialog_update(&controls, args); gtk_widget_show_all(dialog); do { response = gtk_dialog_run(GTK_DIALOG(dialog)); switch (response) { case GTK_RESPONSE_CANCEL: case GTK_RESPONSE_DELETE_EVENT: gtk_widget_destroy(dialog); case GTK_RESPONSE_NONE: return FALSE; break; case GTK_RESPONSE_OK: break; case RESPONSE_RESET: *args = unrotate_defaults; unrotate_dialog_update(&controls, args); break; default: g_assert_not_reached(); break; } } while (response != GTK_RESPONSE_OK); gtk_widget_destroy(dialog); return TRUE; }
/** * file_plugin_proxy_export: * @data: A data container to save. * @filename: A file name to save @data to. * @mode: Run mode. * @error: Return location for a #GError (or %NULL). * @name: Plug-in name (i.e. file-saving function) to run. * * The plug-in proxy itself, runs file-saving plug-in @name to save @filename. * * Returns: Whether it succeeded saving the data. **/ static gboolean file_plugin_proxy_export(GwyContainer *data, const gchar *filename, GwyRunType mode, GError **error, const gchar *name) { FilePluginInfo *info; gchar *tmpname = NULL; GError *err = NULL; gint exit_status; FILE *fh; gchar *args[] = { NULL, NULL, NULL, NULL, NULL }; GQuark dquark, mquark; gboolean ok; gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD_KEY, &dquark, GWY_APP_MASK_FIELD_KEY, &mquark, 0); gwy_debug("called as %s with file `%s'", name, filename); if (mode != GWY_RUN_INTERACTIVE) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_INTERACTIVE, _("Plugin-proxy must be run as interactive.")); return FALSE; } if (!(info = file_find_plugin(name, GWY_FILE_OPERATION_EXPORT))) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_UNIMPLEMENTED, _("Plug-in `%s' does not implement file saving."), name); return FALSE; } fh = text_dump_export(data, dquark, mquark, &tmpname, error); if (!fh) return FALSE; args[0] = info->file; args[1] = g_strdup(gwy_enum_to_string(GWY_FILE_OPERATION_EXPORT, file_op_names, -1)); args[2] = tmpname; args[3] = decode_glib_encoded_filename(filename); gwy_debug("%s %s %s %s", args[0], args[1], args[2], args[3]); ok = g_spawn_sync(NULL, args, NULL, 0, NULL, NULL, NULL, NULL, &exit_status, &err); if (!ok) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_SPECIFIC, _("Cannot execute plug-in `%s': %s."), name, err->message); g_clear_error(&err); } g_unlink(tmpname); fclose(fh); gwy_debug("ok = %d, exit_status = %d, err = %p", ok, exit_status, err); if (ok && exit_status) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_SPECIFIC, _("Plug-in `%s' returned non-zero exit status: %d."), name, exit_status); ok = FALSE; } g_free(args[1]); g_free(args[3]); g_free(tmpname); return ok; }
/** * file_plugin_proxy_load: * @filename. A file name to load. * @mode: Run mode. * @error: Return location for a #GError (or %NULL). * @name: Plug-in name (i.e. file-loading function) to run. * * The plug-in proxy itself, runs file-loading plug-in @name to load @filename. * * Returns: A newly created data container with the contents of @filename, * or %NULL if it fails. **/ static GwyContainer* file_plugin_proxy_load(const gchar *filename, GwyRunType mode, GError **error, const gchar *name) { FilePluginInfo *info; GwyContainer *data = NULL; GObject *dfield; gchar *tmpname = NULL, *buffer = NULL; GError *err = NULL; gint exit_status; gsize size = 0; FILE *fh; gchar *args[] = { NULL, NULL, NULL, NULL, NULL }; gboolean ok; gwy_debug("called as %s with file `%s'", name, filename); if (mode != GWY_RUN_INTERACTIVE) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_INTERACTIVE, _("Plugin-proxy must be run as interactive.")); return NULL; } if (!(info = file_find_plugin(name, GWY_FILE_OPERATION_LOAD))) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_UNIMPLEMENTED, _("Plug-in `%s' does not implement file loading."), name); return NULL; } if (!(fh = open_temporary_file(&tmpname, error))) return NULL; args[0] = info->file; args[1] = g_strdup(gwy_enum_to_string(GWY_FILE_OPERATION_LOAD, file_op_names, -1)); args[2] = tmpname; args[3] = decode_glib_encoded_filename(filename); gwy_debug("%s %s %s %s", args[0], args[1], args[2], args[3]); ok = g_spawn_sync(NULL, args, NULL, 0, NULL, NULL, NULL, NULL, &exit_status, &err); if (ok) { ok = g_file_get_contents(tmpname, &buffer, &size, &err); if (!ok) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_IO, _("Cannot read temporary file: %s."), err->message); g_clear_error(&err); } } else { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_SPECIFIC, _("Cannot execute plug-in `%s': %s."), name, err->message); g_clear_error(&err); } g_unlink(tmpname); fclose(fh); gwy_debug("ok = %d, exit_status = %d, err = %p", ok, exit_status, err); if (ok && exit_status) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_SPECIFIC, _("Plug-in `%s' returned non-zero exit status: %d."), name, exit_status); ok = FALSE; } if (ok) { data = text_dump_import(buffer, size, error); if (!data) ok = FALSE; } if (ok && (!gwy_container_gis_object_by_name(data, "/0/data", &dfield) || !GWY_IS_DATA_FIELD(dfield))) { g_set_error(error, GWY_MODULE_FILE_ERROR, GWY_MODULE_FILE_ERROR_DATA, _("Plug-in `%s' did not return any meaningful data."), name); gwy_object_unref(data); } g_free(args[1]); g_free(args[3]); g_free(buffer); g_free(tmpname); return data; }
/** * proc_plugin_proxy_run: * @data: A data container. * @run: Run mode. * @name: Plug-in name (i.e. data processing function) to run. * * The plug-in proxy itself, runs plug-in @name on @data. * * Returns: Whether it succeeded running the plug-in. **/ static void proc_plugin_proxy_run(GwyContainer *data, GwyRunType run, const gchar *name) { ProcPluginInfo *info; GwyContainer *newdata; gchar *filename, *buffer = NULL; GError *err = NULL; gint exit_status, id, newid; gsize size = 0; FILE *fh; gchar *args[] = { NULL, "run", NULL, NULL, NULL }; GQuark dquark, mquark, squark; gboolean ok; gwy_app_data_browser_get_current(GWY_APP_DATA_FIELD_KEY, &dquark, GWY_APP_MASK_FIELD_KEY, &mquark, GWY_APP_DATA_FIELD_ID, &id, 0); gwy_debug("called as %s with run mode %d", name, run); if (!(info = proc_find_plugin(name, run))) return; fh = text_dump_export(data, dquark, mquark, &filename, NULL); g_return_if_fail(fh); args[0] = info->file; args[2] = g_strdup(gwy_enum_to_string(run, run_mode_names, -1)); args[3] = decode_glib_encoded_filename(filename); gwy_debug("%s %s %s %s", args[0], args[1], args[2], args[3]); ok = g_spawn_sync(NULL, args, NULL, 0, NULL, NULL, NULL, NULL, &exit_status, &err); if (!err) ok &= g_file_get_contents(filename, &buffer, &size, &err); g_unlink(filename); fclose(fh); gwy_debug("ok = %d, exit_status = %d, err = %p", ok, exit_status, err); ok &= !exit_status; if (ok && (newdata = text_dump_import(buffer, size, NULL))) { GwyDataField *dfield; /* Merge data */ if (gwy_container_gis_object_by_name(newdata, "/0/data", &dfield)) g_object_ref(dfield); else { dfield = gwy_container_get_object(data, dquark); dfield = gwy_data_field_duplicate(dfield); } newid = gwy_app_data_browser_add_data_field(dfield, data, TRUE); /* Merge mask */ if (gwy_container_gis_object_by_name(newdata, "/0/mask", &dfield)) g_object_ref(dfield); else if (gwy_container_gis_object(data, mquark, &dfield)) dfield = gwy_data_field_duplicate(dfield); else dfield = NULL; if (dfield) { mquark = gwy_app_get_mask_key_for_id(newid); gwy_container_set_object(data, mquark, dfield); g_object_unref(dfield); } /* Merge presentation */ if (gwy_container_gis_object_by_name(newdata, "/0/show", &dfield)) { squark = gwy_app_get_show_key_for_id(newid); gwy_container_set_object(data, squark, dfield); } /* Merge stuff. XXX: This is brutal and incomplete. */ gwy_app_sync_data_items(data, data, id, newid, FALSE, GWY_DATA_ITEM_GRADIENT, GWY_DATA_ITEM_RANGE_TYPE, GWY_DATA_ITEM_MASK_COLOR, GWY_DATA_ITEM_REAL_SQUARE, 0); gwy_app_sync_data_items(newdata, data, 0, newid, FALSE, GWY_DATA_ITEM_GRADIENT, GWY_DATA_ITEM_RANGE_TYPE, 0); g_object_unref(newdata); } else { g_warning("Cannot run plug-in %s: %s", info->file, err ? err->message : "it returned garbage."); } g_free(args[3]); g_free(args[2]); g_clear_error(&err); g_free(buffer); g_free(filename); }
static GwyContainer* rhkspm32_load(const gchar *filename, G_GNUC_UNUSED GwyRunType mode, GError **error) { GArray *rhkfile; RHKPage *rhkpage; GwyContainer *meta, *container = NULL; guchar *buffer = NULL; gsize size = 0; GError *err = NULL; GwyDataField *dfield = NULL; gsize totalpos, pagesize; GString *key; guint i; if (!gwy_file_get_contents(filename, &buffer, &size, &err)) { err_GET_FILE_CONTENTS(error, &err); return NULL; } if (size < HEADER_SIZE) { err_TOO_SHORT(error); gwy_file_abandon_contents(buffer, size, NULL); return NULL; } // niv - rhkfile is an array of rhkpage's, but buffer is where the actual // raw file data is stored rhkfile = g_array_new(FALSE, TRUE, sizeof(RHKPage)); totalpos = 0; while (totalpos < size) { g_array_set_size(rhkfile, rhkfile->len + 1); rhkpage = &g_array_index(rhkfile, RHKPage, rhkfile->len - 1); rhkpage->buffer = buffer + totalpos; // niv - if the header seems illegal, skip all the next ones as well // (and cancel the element addition to the g_array) if (!rhkspm32_read_header(rhkpage, &err)) { g_warning("failed to read rhk header after %u", rhkfile->len); g_array_set_size(rhkfile, rhkfile->len - 1); break; } pagesize = rhkpage->data_offset + rhkpage->item_size*rhkpage->xres*rhkpage->yres; if (size < totalpos + pagesize) { rhkspm32_free(rhkpage); g_array_set_size(rhkfile, rhkfile->len - 1); break; } totalpos += pagesize; } /* Be tolerant and don't fail when we were able to import at least * something */ if (!rhkfile->len) { if (err) g_propagate_error(error, err); else err_NO_DATA(error); gwy_file_abandon_contents(buffer, size, NULL); g_array_free(rhkfile, TRUE); return NULL; } g_clear_error(&err); container = gwy_container_new(); key = g_string_new(NULL); for (i = 0; i < rhkfile->len; i++) { const gchar *cs; gchar *s; gwy_debug("rhk-spm32: processing page %d of %d\n", i+1, rhkfile->len); rhkpage = &g_array_index(rhkfile, RHKPage, i); if (rhkpage->type == RHK_TYPE_IMAGE) { // niv - just leaving this alone dfield = rhkspm32_read_data(rhkpage); g_string_printf(key, "/%d/data", i); gwy_container_set_object_by_name(container, key->str, dfield); g_object_unref(dfield); g_string_append(key, "/title"); cs = gwy_enum_to_string(rhkpage->scan, scan_directions, G_N_ELEMENTS(scan_directions)); if (rhkpage->label) { if (cs) s = g_strdup_printf("%s [%s]", rhkpage->label, cs); else s = g_strdup(rhkpage->label); gwy_container_set_string_by_name(container, key->str, s); } else gwy_app_channel_title_fall_back(container, i); gwy_file_channel_import_log_add(container, i, NULL, filename); } else if (rhkpage->type == RHK_TYPE_LINE) { // niv - after omicron.c GwySpectra* spectra; GwyGraphModel *gmodel; spectra = rhkspm32_read_spectra(rhkpage); /* converting to graphs, as there is no point in leaving these as * sps - no xy coordinates, so the spectro tool is kinda clueless */ gwy_debug("processing graph in page %d\n", i); if ((gmodel = spectra_to_graph(spectra)) != NULL) { gchar *container_key = NULL; /* add gmodel to container */ container_key = g_strdup_printf("%s/%d", GRAPH_PREFIX, i); gwy_container_set_object_by_name(container, container_key, gmodel); g_free(container_key); } g_object_unref(gmodel); g_object_unref(spectra); } gwy_debug("rhk-spm32: finished parsing page %d \n", i); meta = rhkspm32_get_metadata(rhkpage); if (rhkpage->type == RHK_TYPE_IMAGE) { /* this doesn't really work, but at least the meta data stays with the graph, even if the metadata viewer won't show it*/ g_string_printf(key, "/%d/meta", i); } else if (rhkpage->type == RHK_TYPE_LINE) { g_string_printf(key, "%s/%d/meta", GRAPH_PREFIX, i); } gwy_container_set_object_by_name(container, key->str, meta); g_object_unref(meta); } g_string_free(key, TRUE); gwy_file_abandon_contents(buffer, size, NULL); for (i = 0; i < rhkfile->len; i++) rhkspm32_free(&g_array_index(rhkfile, RHKPage, i)); g_array_free(rhkfile, TRUE); return container; }
static void add_one_distribution(GwyContainer *container, GwyDataField *dfield, gint ngrains, const gint *grains, GwyGrainQuantity quantity, gint resolution) { static const GwyEnum titles[] = { { N_("Grain Projected Area Histogram"), GWY_GRAIN_VALUE_PROJECTED_AREA, }, { N_("Grain Equivalent Square Side Histogram"), GWY_GRAIN_VALUE_EQUIV_SQUARE_SIDE, }, { N_("Grain Equivalent Disc Radius Histogram"), GWY_GRAIN_VALUE_EQUIV_DISC_RADIUS, }, { N_("Grain Surface Area Histogram"), GWY_GRAIN_VALUE_SURFACE_AREA, }, { N_("Grain Maximum Value Histogram"), GWY_GRAIN_VALUE_MAXIMUM, }, { N_("Grain Minimum Value Histogram"), GWY_GRAIN_VALUE_MINIMUM, }, { N_("Grain Mean Value Histogram"), GWY_GRAIN_VALUE_MEAN, }, { N_("Grain Median Value Histogram"), GWY_GRAIN_VALUE_MEDIAN, }, { N_("Grain Projected Boundary Length Histogram"), GWY_GRAIN_VALUE_FLAT_BOUNDARY_LENGTH, }, { N_("Grain Minimum Bounding Size Histogram"), GWY_GRAIN_VALUE_MINIMUM_BOUND_SIZE, }, { N_("Grain Minimum Bounding Direction Histogram"), GWY_GRAIN_VALUE_MINIMUM_BOUND_ANGLE, }, { N_("Grain Maximum Bounding Size Histogram"), GWY_GRAIN_VALUE_MAXIMUM_BOUND_SIZE, }, { N_("Grain Maximum Bounding Direction Histogram"), GWY_GRAIN_VALUE_MAXIMUM_BOUND_ANGLE, }, { N_("Grain Volume (Zero) Histogram"), GWY_GRAIN_VALUE_VOLUME_0, }, { N_("Grain Volume (Minimum) Histogram"), GWY_GRAIN_VALUE_VOLUME_MIN, }, { N_("Grain Volume (Laplacian) Histogram"), GWY_GRAIN_VALUE_VOLUME_LAPLACE, }, }; static const GwyEnum descriptions[] = { { N_("Grain proj. areas"), GWY_GRAIN_VALUE_PROJECTED_AREA, }, { N_("Grain equiv. square sides"), GWY_GRAIN_VALUE_EQUIV_SQUARE_SIDE, }, { N_("Grain equiv. disc radii"), GWY_GRAIN_VALUE_EQUIV_DISC_RADIUS, }, { N_("Grain surf. areas"), GWY_GRAIN_VALUE_SURFACE_AREA, }, { N_("Grain max. values"), GWY_GRAIN_VALUE_MAXIMUM, }, { N_("Grain min. values"), GWY_GRAIN_VALUE_MINIMUM, }, { N_("Grain mean values"), GWY_GRAIN_VALUE_MEAN, }, { N_("Grain median values"), GWY_GRAIN_VALUE_MEDIAN, }, { N_("Grain proj. boundary lengths"), GWY_GRAIN_VALUE_FLAT_BOUNDARY_LENGTH, }, { N_("Grain min. bound. sizes"), GWY_GRAIN_VALUE_MINIMUM_BOUND_SIZE, }, { N_("Grain min. bound. directions"), GWY_GRAIN_VALUE_MINIMUM_BOUND_ANGLE, }, { N_("Grain max. bound. sizes"), GWY_GRAIN_VALUE_MAXIMUM_BOUND_SIZE, }, { N_("Grain max. bound. directions"), GWY_GRAIN_VALUE_MAXIMUM_BOUND_ANGLE, }, { N_("Grain volumes (zero)"), GWY_GRAIN_VALUE_VOLUME_0, }, { N_("Grain volumes (minimum)"), GWY_GRAIN_VALUE_VOLUME_MIN, }, { N_("Grain volumes (laplacian)"), GWY_GRAIN_VALUE_VOLUME_LAPLACE, }, }; GwyGraphCurveModel *cmodel; GwyGraphModel *gmodel; GwyDataLine *dataline; const gchar *s; dataline = gwy_data_field_grains_get_distribution(dfield, NULL, NULL, ngrains, grains, quantity, resolution); gmodel = gwy_graph_model_new(); cmodel = gwy_graph_curve_model_new(); gwy_graph_model_add_curve(gmodel, cmodel); g_object_unref(cmodel); s = gwy_enum_to_string(quantity, titles, G_N_ELEMENTS(titles)); g_object_set(gmodel, "title", _(s), "axis-label-left", _("count"), NULL); gwy_graph_model_set_units_from_data_line(gmodel, dataline); s = gwy_enum_to_string(quantity, descriptions, G_N_ELEMENTS(descriptions)); g_object_set(cmodel, "description", s, NULL); gwy_graph_curve_model_set_data_from_dataline(cmodel, dataline, 0, 0); g_object_unref(dataline); gwy_app_data_browser_add_graph_model(gmodel, container, TRUE); g_object_unref(gmodel); }