#include <netcdf.h>
#include "nq_basic.h"
#include "nq_structure.h"
#include "nq_density.h"
#include <visu_tools.h>
#include <renderingMethods/renderingAtomic.h>
#define NANOQUANTA_DESCRIPTION _("<span size=\"smaller\">" \
"This plug-in introduces support for\n" \
"<b>NETCDF</b> file format defined by the\n" \
"European network <b>NANOQUANTA</b>.</span>")
#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;
}
syntax highlighted by Code2HTML, v. 0.9.1