#include #include "nq_basic.h" #include "nq_structure.h" #include "nq_density.h" #include #include #define NANOQUANTA_DESCRIPTION _("" \ "This plug-in introduces support for\n" \ "NETCDF file format defined by the\n" \ "European network NANOQUANTA.") #define NANOQUANTA_AUTHORS _("Caliste Damien:\n structure/density loading.") static gchar *iconPath; /* Required methods for a loadable module. */ gboolean nanoquantaInit() { RenderingFormatLoad* meth; DBG_fprintf(stderr, "Nanoquanta : loading plug-in 'nanoquanta'...\n"); NQ_ERROR = g_quark_from_string("nanoquanta"); DBG_fprintf(stderr, "Nanoquanta : declare a new rendering load method.\n"); meth = nqStructuralInit(); renderingAtomicAdd_loadMethod(meth); iconPath = g_build_filename(v_sim_pixmaps_dir, "nanoquanta.png", NULL); DBG_fprintf(stderr, "Nanoquanta : declare a new density load method.\n"); nqDensityInit(); return TRUE; } const char* nanoquantaGet_description() { return NANOQUANTA_DESCRIPTION; } const char* nanoquantaGet_authors() { return NANOQUANTA_AUTHORS; } const char* nanoquantaGet_icon() { return iconPath; } gboolean nqOpen_netcdfFile(const char* filename, int *netcdfId, GError **error) { int status, i; char *varsNames[3] = {"file_format", "file_format_version", "Conventions"}; nc_type varsType[3] = {NC_CHAR, NC_FLOAT, NC_CHAR}; nc_type altVarsType[3] = {NC_CHAR, NC_DOUBLE, NC_CHAR}; size_t varsLength[3] = {80, 1, 80}; nc_type readType; size_t readLength[3]; char format[256]; float version; g_return_val_if_fail(error && *error == (GError*)0, FALSE); g_return_val_if_fail(netcdfId && filename, FALSE); /* Open the file as a NETCDF file. */ status = nc_open(filename, NC_NOWRITE, netcdfId); if (status != NC_NOERR) { *error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_OPEN, nc_strerror(status)); return FALSE; } /* From here, the file is opened. */ /* Grep the header variables to check that it is a NETCDF file following rules of NANOQUANTA specifications. */ DBG_fprintf(stderr, "NQ Basic : checking header of file '%s'.\n", filename); /* Check lengths and types. */ for (i = 0; i < 3; i++) { status = nc_inq_att(*netcdfId, NC_GLOBAL, varsNames[i], &readType, readLength + i); if (status != NC_NOERR) { *error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_HEADER, nc_strerror(status)); nqClose_netcdfFile(*netcdfId); return FALSE; } DBG_fprintf(stderr, " | header '%s' : type %d (%d), length %d (%d).\n", varsNames[i], (int)readType, (int)varsType[i], (int)readLength[i], (int)varsLength[i]); if ((readType != varsType[i] && readType != altVarsType[i]) || readLength[i] > varsLength[i]) { *error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_HEADER, _("Global attribute '%s' has a wrong " "length or type.\n"), varsNames[i]); nqClose_netcdfFile(*netcdfId); return FALSE; } } /* Check values. */ status = nc_get_att_text(*netcdfId, NC_GLOBAL, varsNames[0], format); if (status != NC_NOERR) { *error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_HEADER, nc_strerror(status)); nqClose_netcdfFile(*netcdfId); return FALSE; } format[readLength[0]] = '\0'; DBG_fprintf(stderr, " | header '%s' value '%s'.\n", varsNames[0], format); if (strcmp(format, "ETSF Nanoquanta")) { *error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_HEADER, _("Variable 'file_format' should be " "'ETSF Nanoquanta' but is '%s'.\n"), format); nqClose_netcdfFile(*netcdfId); return FALSE; } status = nc_get_att_float(*netcdfId, NC_GLOBAL, varsNames[1], &version); if (status != NC_NOERR) { *error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_HEADER, nc_strerror(status)); nqClose_netcdfFile(*netcdfId); return FALSE; } DBG_fprintf(stderr, " | header '%s' value %f.\n", varsNames[1], version); if (version < 1.2) { *error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_HEADER, _("Supported version are 1.2 and over but" " this file is only %f.\n"), version); nqClose_netcdfFile(*netcdfId); return FALSE; } return TRUE; } gboolean nqClose_netcdfFile(int netcdfId) { int status; status = nc_close(netcdfId); if (status != NC_NOERR) { g_warning(nc_strerror(status)); return FALSE; } return TRUE; } static gboolean nqErrorReport(GError **error, const char *message, ...) { va_list args; gchar *formatted; va_start(args, message); formatted = g_strdup_vprintf(message, args); va_end(args); *error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_FORMAT, formatted); g_free(formatted); return FALSE; } gboolean nqGetDim(int netcdfId, GError **error, char *name, int *varId, size_t *value) { int status; /* Grep the number of elements. */ status = nc_inq_dimid(netcdfId, name, varId); if (status != NC_NOERR) return nqErrorReport(error, _("Reading '%s': %s."), name, nc_strerror(status)); status = nc_inq_dimlen(netcdfId, *varId, value); if (status != NC_NOERR) return nqErrorReport(error, _("Retrieve value for variable '%s': %s."), name, nc_strerror(status)); return TRUE; } gboolean nqCheckVar(int netcdfId, GError **error, char *name, int *varId, nc_type ncType, int nbDims, size_t *nbEleDims) { int status; nc_type localType; char *typeNames[] = {"NAT", "BYTE", "CHAR", "SHORT", "INT", "FLOAT", "DOUBLE"}; int localDims; int *localNbDims; int i; size_t dimSize; status = nc_inq_varid(netcdfId, name, varId); if (status != NC_NOERR) return nqErrorReport(error, _("Reading '%s': %s."), name, nc_strerror(status)); status = nc_inq_vartype(netcdfId, *varId, &localType); if (status != NC_NOERR) return nqErrorReport(error, _("Checking variable '%s': %s."), name, nc_strerror(status)); if (localType != ncType) return nqErrorReport(error, _("Variable '%s' should be of type '%s'."), name, typeNames[ncType]); status = nc_inq_varndims(netcdfId, *varId, &localDims); if (status != NC_NOERR) return nqErrorReport(error, _("Checking variable '%s': %s."), name, nc_strerror(status)); if (localDims != nbDims) return nqErrorReport(error, _("Variable '%s' should be a %d dimension array."), name, nbDims); localNbDims = g_malloc(sizeof(int) * nbDims); status = nc_inq_vardimid(netcdfId, *varId, localNbDims); if (status != NC_NOERR) { g_free(localNbDims); return nqErrorReport(error, _("Checking variable '%s': %s."), name, nc_strerror(status)); } for (i = 0; i< nbDims; i++) { status = nc_inq_dimlen(netcdfId, localNbDims[i], &dimSize); if (status != NC_NOERR) { g_free(localNbDims); return nqErrorReport(error, _("Checking dimension ID %d: %s."), localNbDims[i], nc_strerror(status)); } if (dimSize != nbEleDims[i]) { g_free(localNbDims); return nqErrorReport(error, _("Variable '%s' is not consistent with" " declaration of dimensions."), name); } } g_free(localNbDims); return TRUE; }