1 /* EXTRAITS DE LA LICENCE
2 Copyright CEA, contributeurs : Luc BILLARD et Damien
3 CALISTE, laboratoire L_Sim, (2001-2005)
4
5 Adresse m�l :
6 BILLARD, non joignable par m�l ;
7 CALISTE, damien P caliste AT cea P fr.
8
9 Ce logiciel est un programme informatique servant � visualiser des
10 structures atomiques dans un rendu pseudo-3D.
11
12 Ce logiciel est r�gi par la licence CeCILL soumise au droit fran�ais et
13 respectant les principes de diffusion des logiciels libres. Vous pouvez
14 utiliser, modifier et/ou redistribuer ce programme sous les conditions
15 de la licence CeCILL telle que diffus�e par le CEA, le CNRS et l'INRIA
16 sur le site "http://www.cecill.info".
17
18 Le fait que vous puissiez acc�der � cet en-t�te signifie que vous avez
19 pris connaissance de la licence CeCILL, et que vous en avez accept� les
20 termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
21 */
22
23 /* LICENCE SUM UP
24 Copyright CEA, contributors : Luc BILLARD et Damien
25 CALISTE, laboratoire L_Sim, (2001-2005)
26
27 E-mail address:
28 BILLARD, not reachable any more ;
29 CALISTE, damien P caliste AT cea P fr.
30
31 This software is a computer program whose purpose is to visualize atomic
32 configurations in 3D.
33
34 This software is governed by the CeCILL license under French law and
35 abiding by the rules of distribution of free software. You can use,
36 modify and/ or redistribute the software under the terms of the CeCILL
37 license as circulated by CEA, CNRS and INRIA at the following URL
38 "http://www.cecill.info".
39
40 The fact that you are presently reading this means that you have had
41 knowledge of the CeCILL license and that you accept its terms. You can
42 find a copy of this licence shipped with this software at Documentation/licence.en.txt.
43 */
44
45 #include <netcdf.h>
46 #include <string.h>
47
48 #include "nq_basic.h"
49 #include "nq_structure.h"
50 #include "nq_density.h"
51 #include <visu_tools.h>
52 #include <visu_basic.h>
53 #include <visu_dataatomic.h>
54
55 #define NANOQUANTA_DESCRIPTION _("<span size=\"smaller\">" \
56 "This plug-in introduces support for\n" \
57 "<b>ETSF</b> file format defined by the\n" \
58 "European network <b>NANOQUANTA</b>.</span>")
59 #define NANOQUANTA_AUTHORS _("Caliste Damien:\n structure/density loading.")
60
61 static gchar *iconPath;
62
63 /* Required methods for a loadable module. */
etsfInit()64 gboolean etsfInit()
65 {
66 DBG_fprintf(stderr, "ETSF: loading plug-in 'nanoquanta'...\n");
67
68 DBG_fprintf(stderr, "ETSF: declare a new rendering load method.\n");
69 visu_data_atomic_class_addLoader(visu_data_loader_ETSF_getStatic());
70
71 iconPath = g_build_filename(V_SIM_PIXMAPS_DIR, "nanoquanta.png", NULL);
72
73 DBG_fprintf(stderr, "ETSF: declare a new density load method.\n");
74 nqDensityInit();
75
76 return TRUE;
77 }
78
etsfGet_description()79 const char* etsfGet_description()
80 {
81 return NANOQUANTA_DESCRIPTION;
82 }
83
etsfGet_authors()84 const char* etsfGet_authors()
85 {
86 return NANOQUANTA_AUTHORS;
87 }
88
etsfGet_icon()89 const char* etsfGet_icon()
90 {
91 return iconPath;
92 }
93
nqError_quark()94 GQuark nqError_quark()
95 {
96 return g_quark_from_static_string("nanoquanta");
97 }
98
99
100
nqOpen_netcdfFile(const char * filename,int * netcdfId,GError ** error)101 gboolean nqOpen_netcdfFile(const char* filename, int *netcdfId, GError **error)
102 {
103 int status, i;
104 char *varsNames[3] = {"file_format", "file_format_version", "Conventions"};
105 nc_type varsType[3] = {NC_CHAR, NC_FLOAT, NC_CHAR};
106 nc_type altVarsType[3] = {NC_CHAR, NC_DOUBLE, NC_CHAR};
107 size_t varsLength[3] = {80, 1, 80};
108 nc_type readType;
109 size_t readLength[3];
110 char format[256];
111 float version;
112
113 g_return_val_if_fail(error && *error == (GError*)0, FALSE);
114 g_return_val_if_fail(netcdfId && filename, FALSE);
115
116 DBG_fprintf(stderr, "NQ Basic: opening file '%s' as a NetCDF file.\n", filename);
117 /* Open the file as a NETCDF file. */
118 status = nc_open(filename, NC_NOWRITE, netcdfId);
119 if (status != NC_NOERR)
120 {
121 DBG_fprintf(stderr, " | not a NetCDF file, can't open.\n");
122 *error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_OPEN,
123 "%s", nc_strerror(status));
124 return FALSE;
125 }
126
127 /* From here, the file is opened. */
128
129 /* Grep the header variables to check that it is a NETCDF file
130 following rules of NANOQUANTA specifications. */
131 DBG_fprintf(stderr, "NQ Basic: checking header of file '%s'.\n", filename);
132 /* Check lengths and types. */
133 for (i = 0; i < 3; i++)
134 {
135 status = nc_inq_att(*netcdfId, NC_GLOBAL, varsNames[i], &readType, readLength + i);
136 if (status != NC_NOERR)
137 {
138 DBG_fprintf(stderr, " | cannot read header element %d (%s).\n", i, nc_strerror(status));
139 *error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_HEADER,
140 "inquiring global attribute '%s' raises: %s",
141 varsNames[i], nc_strerror(status));
142 nqClose_netcdfFile(*netcdfId);
143 return FALSE;
144 }
145 DBG_fprintf(stderr, " | header '%s' : type %d (%d), length %d (%d).\n",
146 varsNames[i], (int)readType, (int)varsType[i],
147 (int)readLength[i], (int)varsLength[i]);
148 if ((readType != varsType[i] && readType != altVarsType[i]) ||
149 readLength[i] > varsLength[i])
150 {
151 DBG_fprintf(stderr, " | header not valid.\n");
152 *error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_HEADER,
153 _("Global attribute '%s' has a wrong "
154 "length or type.\n"), varsNames[i]);
155 nqClose_netcdfFile(*netcdfId);
156 return FALSE;
157 }
158 }
159 /* Check values. */
160 status = nc_get_att_text(*netcdfId, NC_GLOBAL, varsNames[0], format);
161 if (status != NC_NOERR)
162 {
163 DBG_fprintf(stderr, " | cannot read format.\n");
164 *error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_HEADER,
165 "reading global attribute '%s' raises: %s",
166 varsNames[0], nc_strerror(status));
167 nqClose_netcdfFile(*netcdfId);
168 return FALSE;
169 }
170 format[readLength[0]] = '\0';
171 DBG_fprintf(stderr, " | header '%s' value '%s'.\n", varsNames[0], format);
172 if (strcmp(format, "ETSF Nanoquanta"))
173 {
174 DBG_fprintf(stderr, " | wrong format '%s'.\n", format);
175 *error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_HEADER,
176 _("Variable 'file_format' should be "
177 "'ETSF Nanoquanta' but is '%s'.\n"), format);
178 nqClose_netcdfFile(*netcdfId);
179 return FALSE;
180 }
181 status = nc_get_att_float(*netcdfId, NC_GLOBAL, varsNames[1], &version);
182 if (status != NC_NOERR)
183 {
184 DBG_fprintf(stderr, " | cannot read version.\n");
185 *error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_HEADER,
186 "reading global attribute '%s' raises: %s",
187 varsNames[1], nc_strerror(status));
188 nqClose_netcdfFile(*netcdfId);
189 return FALSE;
190 }
191 DBG_fprintf(stderr, " | header '%s' value %f.\n", varsNames[1], version);
192 if (version < 1.2)
193 {
194 DBG_fprintf(stderr, " | version too small (%f).\n", version);
195 *error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_HEADER,
196 _("Supported version are 1.2 and over but"
197 " this file is only %f.\n"), version);
198 nqClose_netcdfFile(*netcdfId);
199 return FALSE;
200 }
201
202 return TRUE;
203 }
204
nqClose_netcdfFile(int netcdfId)205 gboolean nqClose_netcdfFile(int netcdfId)
206 {
207 int status;
208
209 status = nc_close(netcdfId);
210 if (status != NC_NOERR)
211 {
212 g_warning("%s", nc_strerror(status));
213 return FALSE;
214 }
215
216 return TRUE;
217 }
218
nqErrorReport(GError ** error,const char * message,...)219 static gboolean nqErrorReport(GError **error, const char *message, ...)
220 {
221 va_list args;
222 gchar *formatted;
223
224 if (error)
225 {
226 va_start(args, message);
227 formatted = g_strdup_vprintf(message, args);
228 va_end(args);
229
230 *error = g_error_new(NQ_ERROR, NQ_ERROR_FILE_FORMAT, "%s", formatted);
231
232 g_free(formatted);
233 }
234
235 return FALSE;
236 }
237
nqGetDim(int netcdfId,GError ** error,char * name,int * varId,size_t * value)238 gboolean nqGetDim(int netcdfId, GError **error, char *name, int *varId, size_t *value)
239 {
240 int status;
241
242 /* Grep the number of elements. */
243 status = nc_inq_dimid(netcdfId, name, varId);
244 if (status != NC_NOERR)
245 return nqErrorReport(error, _("Reading '%s': %s."),
246 name, nc_strerror(status));
247 status = nc_inq_dimlen(netcdfId, *varId, value);
248 if (status != NC_NOERR)
249 return nqErrorReport(error, _("Retrieve value for variable '%s': %s."),
250 name, nc_strerror(status));
251 return TRUE;
252 }
253
nqCheckVar(int netcdfId,GError ** error,char * name,int * varId,nc_type ncType,int nbDims,size_t * nbEleDims)254 gboolean nqCheckVar(int netcdfId, GError **error, char *name, int *varId,
255 nc_type ncType, int nbDims, size_t *nbEleDims)
256 {
257 int status;
258 nc_type localType;
259 char *typeNames[] = {"NAT", "BYTE", "CHAR", "SHORT", "INT", "FLOAT", "DOUBLE"};
260 int localDims;
261 int *localNbDims;
262 int i;
263 size_t dimSize;
264
265 status = nc_inq_varid(netcdfId, name, varId);
266 if (status != NC_NOERR)
267 return nqErrorReport(error, _("Reading '%s': %s."),
268 name, nc_strerror(status));
269 status = nc_inq_vartype(netcdfId, *varId, &localType);
270 if (status != NC_NOERR)
271 return nqErrorReport(error, _("Checking variable '%s': %s."),
272 name, nc_strerror(status));
273 if (localType != ncType)
274 return nqErrorReport(error, _("Variable '%s' should be of type '%s'."),
275 name, typeNames[ncType]);
276 status = nc_inq_varndims(netcdfId, *varId, &localDims);
277 if (status != NC_NOERR)
278 return nqErrorReport(error, _("Checking variable '%s': %s."),
279 name, nc_strerror(status));
280 if (localDims != nbDims)
281 return nqErrorReport(error,
282 _("Variable '%s' should be a %d dimension array."),
283 name, nbDims);
284 localNbDims = g_malloc(sizeof(int) * nbDims);
285 status = nc_inq_vardimid(netcdfId, *varId, localNbDims);
286 if (status != NC_NOERR)
287 {
288 g_free(localNbDims);
289 return nqErrorReport(error, _("Checking variable '%s': %s."),
290 name, nc_strerror(status));
291 }
292 for (i = 0; i< nbDims; i++)
293 {
294 status = nc_inq_dimlen(netcdfId, localNbDims[i], &dimSize);
295 if (status != NC_NOERR)
296 {
297 g_free(localNbDims);
298 return nqErrorReport(error, _("Checking dimension ID %d: %s."),
299 localNbDims[i], nc_strerror(status));
300 }
301 if (dimSize != nbEleDims[i])
302 {
303 g_free(localNbDims);
304 return nqErrorReport(error,
305 _("Variable '%s' is not consistent with"
306 " declaration of dimensions."), name);
307 }
308 }
309 g_free(localNbDims);
310 return TRUE;
311 }
312
313