1 /* EXTRAITS DE LA LICENCE
2 Copyright CEA, contributeurs : Damien
3 CALISTE, laboratoire L_Sim, (2016)
4
5 Adresse mèl :
6 CALISTE, damien P caliste AT cea P fr.
7
8 Ce logiciel est un programme informatique servant à visualiser des
9 structures atomiques dans un rendu pseudo-3D.
10
11 Ce logiciel est régi par la licence CeCILL soumise au droit français et
12 respectant les principes de diffusion des logiciels libres. Vous pouvez
13 utiliser, modifier et/ou redistribuer ce programme sous les conditions
14 de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
15 sur le site "http://www.cecill.info".
16
17 Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
18 pris connaissance de la licence CeCILL, et que vous en avez accepté les
19 termes (cf. le fichier Documentation/licence.fr.txt fourni avec ce logiciel).
20 */
21
22 /* LICENCE SUM UP
23 Copyright CEA, contributors : Damien
24 CALISTE, laboratoire L_Sim, (2016)
25
26 E-mail address:
27 CALISTE, damien P caliste AT cea P fr.
28
29 This software is a computer program whose purpose is to visualize atomic
30 configurations in 3D.
31
32 This software is governed by the CeCILL license under French law and
33 abiding by the rules of distribution of free software. You can use,
34 modify and/ or redistribute the software under the terms of the CeCILL
35 license as circulated by CEA, CNRS and INRIA at the following URL
36 "http://www.cecill.info".
37
38 The fact that you are presently reading this means that you have had
39 knowledge of the CeCILL license and that you accept its terms. You can
40 find a copy of this licence shipped with this software at Documentation/licence.en.txt.
41 */
42
43 #include "visu_dataspin.h"
44
45 #include "coreTools/toolFortran.h"
46
47 /**
48 * SECTION: visu_dataspin
49 * @short_description: a class of nodes representing spin data and
50 * providing associated loading methods.
51 *
52 * <para>This class provides #VisuDataLoader for spin data representation.</para>
53 */
54
55 #define SPIN_PROP_ID _("Spin (\316\270, \317\206, mod.)")
56 #define SPIN_MAX_MOD_ID "spin_max_modulus_id"
57
58 enum
59 {
60 PROP_0,
61 PROP_FILE,
62 PROP_FORMAT,
63 N_PROP,
64 PROP_LABEL,
65 N_PROP_TOT
66 };
67 static GParamSpec *_properties[N_PROP];
68
69 struct _VisuDataSpinPrivate
70 {
71 gchar *file;
72 VisuDataLoader *format;
73
74 /* These are cached pointers to the values. */
75 GArray *maxModulus;
76 VisuNodeValuesVector *spin;
77 };
78
79 static GList *_spinFormats = NULL;
80
81
82 static void visu_data_spin_finalize (GObject* obj);
83 static void visu_data_spin_get_property(GObject* obj, guint property_id,
84 GValue *value, GParamSpec *pspec);
85 static void visu_data_spin_set_property(GObject* obj, guint property_id,
86 const GValue *value, GParamSpec *pspec);
87 static const gchar* visu_data_spin_getFilename(const VisuDataLoadable *self,
88 guint fileType);
89 static gboolean visu_data_spin_load(VisuDataLoadable *self, guint iSet,
90 GCancellable *cancel, GError **error);
91
92 static gboolean read_spin_file(VisuDataLoader *loader, VisuDataLoadable *data,
93 guint type, guint nSet,
94 GCancellable *cancel, GError **error);
95 static gboolean read_binary_file(VisuDataLoader *loader, VisuDataLoadable *data,
96 guint type, guint nSet,
97 GCancellable *cancel, GError **error);
98
_initSpinFormats(void)99 static void _initSpinFormats(void)
100 {
101 const gchar *typeSpin[] = {"*.spin", "*.sp", NULL};
102 const gchar *typeBinary[] = {"*.bspin", "*.bsp", NULL};
103
104 visu_data_spin_class_addLoader(visu_data_loader_new
105 (_("Ascii spin files"), typeSpin, FALSE,
106 read_spin_file, 100));
107 visu_data_spin_class_addLoader(visu_data_loader_new
108 (_("Binary spin files"), typeBinary, FALSE,
109 read_binary_file, 10));
110 }
111
112 /* Local methods. */
113
G_DEFINE_TYPE_WITH_CODE(VisuDataSpin,visu_data_spin,VISU_TYPE_DATA_ATOMIC,G_ADD_PRIVATE (VisuDataSpin))114 G_DEFINE_TYPE_WITH_CODE(VisuDataSpin, visu_data_spin, VISU_TYPE_DATA_ATOMIC,
115 G_ADD_PRIVATE(VisuDataSpin))
116
117 static void visu_data_spin_class_init(VisuDataSpinClass *klass)
118 {
119 /* Connect the overloading methods. */
120 G_OBJECT_CLASS(klass)->finalize = visu_data_spin_finalize;
121 G_OBJECT_CLASS(klass)->get_property = visu_data_spin_get_property;
122 G_OBJECT_CLASS(klass)->set_property = visu_data_spin_set_property;
123 VISU_DATA_LOADABLE_CLASS(klass)->load = visu_data_spin_load;
124 VISU_DATA_LOADABLE_CLASS(klass)->getFilename = visu_data_spin_getFilename;
125
126 g_object_class_override_property(G_OBJECT_CLASS(klass), PROP_LABEL, "label");
127
128 /**
129 * VisuDataAtomic::spin-filename:
130 *
131 * The path to the source filename.
132 *
133 * Since: 3.8
134 */
135 _properties[PROP_FILE] =
136 g_param_spec_string("spin-filename", "Spin filename", "source filename",
137 (gchar*)0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
138 /**
139 * VisuDataAtomic::spin-format:
140 *
141 * The format of the source filename, if known.
142 *
143 * Since: 3.8
144 */
145 _properties[PROP_FORMAT] =
146 g_param_spec_object("spin-format", "Spin format", "source format",
147 VISU_TYPE_DATA_LOADER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
148 g_object_class_install_properties(G_OBJECT_CLASS(klass), N_PROP, _properties);
149
150 _initSpinFormats();
151 }
visu_data_spin_init(VisuDataSpin * obj)152 static void visu_data_spin_init(VisuDataSpin *obj)
153 {
154 obj->priv = visu_data_spin_get_instance_private(obj);
155
156 /* Private data. */
157 obj->priv->file = (gchar*)0;
158 obj->priv->format = (VisuDataLoader*)0;
159 }
visu_data_spin_finalize(GObject * obj)160 static void visu_data_spin_finalize(GObject* obj)
161 {
162 VisuDataSpin *data;
163
164 data = VISU_DATA_SPIN(obj);
165
166 g_free(data->priv->file);
167
168 /* Chain up to the parent class */
169 G_OBJECT_CLASS(visu_data_spin_parent_class)->finalize(obj);
170 }
visu_data_spin_get_property(GObject * obj,guint property_id,GValue * value,GParamSpec * pspec)171 static void visu_data_spin_get_property(GObject* obj, guint property_id,
172 GValue *value, GParamSpec *pspec)
173 {
174 gchar *at, *sp;
175 VisuDataSpin *self = VISU_DATA_SPIN(obj);
176
177 switch (property_id)
178 {
179 case PROP_LABEL:
180 at = g_path_get_basename(visu_data_atomic_getFile(VISU_DATA_ATOMIC(self),
181 (VisuDataLoader**)0));
182 sp = g_path_get_basename(self->priv->file);
183 g_value_take_string(value, g_strdup_printf("%s \302\240\342\200\224 %s", at, sp));
184 g_free(at);
185 g_free(sp);
186 break;
187 case PROP_FILE:
188 g_value_set_string(value, self->priv->file);
189 break;
190 case PROP_FORMAT:
191 g_value_set_object(value, self->priv->format);
192 break;
193 default:
194 /* We don't have any other property... */
195 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
196 break;
197 }
198 }
visu_data_spin_set_property(GObject * obj,guint property_id,const GValue * value,GParamSpec * pspec)199 static void visu_data_spin_set_property(GObject* obj, guint property_id,
200 const GValue *value, GParamSpec *pspec)
201 {
202 VisuDataSpin *self = VISU_DATA_SPIN(obj);
203
204 switch (property_id)
205 {
206 case PROP_FILE:
207 self->priv->file = tool_path_normalize(g_value_get_string(value));
208 break;
209 case PROP_FORMAT:
210 self->priv->format = g_value_get_object(value);
211 break;
212 default:
213 /* We don't have any other property... */
214 G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, property_id, pspec);
215 break;
216 }
217 }
218
219 /**
220 * visu_data_spin_new:
221 * @atomic: a filename.
222 * @spin: a filename.
223 * @atomicFormat: (allow-none): a #VisuDataLoader format, if known.
224 * @spinFormat: (allow-none): a #VisuDataLoader format, if known.
225 *
226 * Creates a #VisuDataSpin object and set @atomic as its atomic file
227 * source and @file for the spin source.
228 *
229 * Since: 3.8
230 *
231 * Returns: a newly allocated #VisuDataSpin object.
232 **/
visu_data_spin_new(const gchar * atomic,const gchar * spin,VisuDataLoader * atomicFormat,VisuDataLoader * spinFormat)233 VisuDataSpin* visu_data_spin_new(const gchar *atomic, const gchar *spin,
234 VisuDataLoader *atomicFormat,
235 VisuDataLoader *spinFormat)
236 {
237 return g_object_new(VISU_TYPE_DATA_SPIN, "n-files", 2,
238 "atomic-filename", atomic, "spin-filename", spin,
239 "atomic-format", atomicFormat, "spin-format", spinFormat, NULL);
240 }
241
242 /**
243 * visu_data_spin_class_addLoader:
244 * @loader: (transfer full): a #VisuDataSpin object.
245 *
246 * Add @loader to the list of #VisuDataLoader to be used when
247 * visu_data_loadable_load() is called.
248 *
249 * Since: 3.8
250 **/
visu_data_spin_class_addLoader(VisuDataLoader * loader)251 void visu_data_spin_class_addLoader(VisuDataLoader *loader)
252 {
253 if (g_list_find(_spinFormats, loader))
254 return;
255
256 _spinFormats = g_list_prepend(_spinFormats, loader);
257 _spinFormats = g_list_sort(_spinFormats,
258 (GCompareFunc)visu_data_loader_comparePriority);
259 }
260
261 /**
262 * visu_data_spin_class_getLoaders:
263 *
264 * Returns a list of available #VisuDataLoader.
265 *
266 * Since: 3.8
267 *
268 * Returns: (transfer none) (element-type VisuDataLoader): a list of
269 * #VisuDataLoader owned by V_Sim.
270 **/
visu_data_spin_class_getLoaders(void)271 GList* visu_data_spin_class_getLoaders(void)
272 {
273 return _spinFormats;
274 }
275 /**
276 * visu_data_spin_class_getFileDescription:
277 *
278 * Returns a translated string describing what is files loaded by
279 * #VisuDataSpin objects.
280 *
281 * Since: 3.8
282 *
283 * Returns: a string owned by V_Sim.
284 **/
visu_data_spin_class_getFileDescription(void)285 const gchar* visu_data_spin_class_getFileDescription(void)
286 {
287 return _("Spin files");
288 }
289 /**
290 * visu_data_spin_class_finalize:
291 *
292 * Empty the list of known loaders.
293 *
294 * Since: 3.8
295 **/
visu_data_spin_class_finalize(void)296 void visu_data_spin_class_finalize(void)
297 {
298 g_list_free_full(_spinFormats, (GDestroyNotify)g_object_unref);
299 _spinFormats = (GList*)0;
300 }
301
visu_data_spin_getFilename(const VisuDataLoadable * self,guint fileType)302 static const gchar* visu_data_spin_getFilename(const VisuDataLoadable *self,
303 guint fileType)
304 {
305 g_return_val_if_fail(VISU_IS_DATA_SPIN(self) && fileType < 2, (const gchar*)0);
306
307 if (fileType == 1)
308 return visu_data_spin_getFile(VISU_DATA_SPIN(self), (VisuDataLoader**)0);
309 else
310 return visu_data_atomic_getFile(VISU_DATA_ATOMIC(self), (VisuDataLoader**)0);
311 }
312 /**
313 * visu_data_spin_getFile:
314 * @data: a #VisuDataSpin object.
315 * @format: (out caller-allocates): a location to store the format.
316 *
317 * Retrieve the spin filename. Optionally provides also the format of
318 * this file. If the file has been parsed this is the detected
319 * format. If not, this is the supposed format, as proposed by user.
320 *
321 * Since: 3.8
322 *
323 * Returns: a filename.
324 **/
visu_data_spin_getFile(VisuDataSpin * data,VisuDataLoader ** format)325 const gchar* visu_data_spin_getFile(VisuDataSpin *data, VisuDataLoader **format)
326 {
327 g_return_val_if_fail(VISU_IS_DATA_SPIN(data), (const gchar*)0);
328
329 if (format)
330 *format = data->priv->format;
331 return data->priv->file;
332 }
333
visu_data_spin_load(VisuDataLoadable * self,guint iSet,GCancellable * cancel,GError ** error)334 static gboolean visu_data_spin_load(VisuDataLoadable *self, guint iSet,
335 GCancellable *cancel, GError **error)
336 {
337 VisuDataSpin *data;
338 GList *lst;
339 VisuDataLoader *loader;
340
341 g_return_val_if_fail(VISU_IS_DATA_SPIN(self), FALSE);
342
343 if (!VISU_DATA_LOADABLE_CLASS(visu_data_spin_parent_class)->load(self, iSet,
344 cancel, error))
345 return FALSE;
346
347 data = VISU_DATA_SPIN(self);
348
349 if (!visu_data_loadable_checkFile(self, 1, error))
350 return FALSE;
351
352 for (lst = _spinFormats; lst; lst = g_list_next(lst))
353 {
354 loader = VISU_DATA_LOADER(lst->data);
355
356 /* Each load may set error even if the format is not recognise
357 and loadOK is FALSE, then we need to free the error. */
358 g_clear_error(error);
359
360 if (!data->priv->format || loader == data->priv->format)
361 {
362 DBG_fprintf(stderr,"Data Spin: testing '%s' with format: %s.\n",
363 data->priv->file, tool_file_format_getName(TOOL_FILE_FORMAT(loader)));
364 if (visu_data_loader_load(loader, self, 1, iSet, cancel, error))
365 return TRUE;
366 if (*error && (*error)->domain == G_FILE_ERROR)
367 return FALSE;
368 }
369 }
370 g_clear_error(error);
371 g_set_error(error, VISU_DATA_LOADABLE_ERROR, DATA_LOADABLE_ERROR_UNKNOWN,
372 _("Impossible to load '%s', unrecognised format.\n"), data->priv->file);
373 return FALSE;
374 }
375
initMaxModulus(VisuElement * ele _U_,GValue * val)376 static void initMaxModulus(VisuElement *ele _U_, GValue *val)
377 {
378 DBG_fprintf(stderr, " | init max modulus of val %p.\n", (gpointer)val);
379 g_value_init(val, G_TYPE_FLOAT);
380 g_value_set_float(val, -G_MAXFLOAT);
381 }
382
383 /**
384 * visu_data_spin_get:
385 * @dataObj: a #VisuDataSpin object.
386 *
387 * Retrieve the #VisuNodeValuesVector object stroing the spin
388 * components per #VisuNode.
389 *
390 * Since: 3.8
391 *
392 * Returns: (transfer none): the #VisuNodeValuesVector storing the spi
393 * components of @dataObj.
394 **/
visu_data_spin_get(const VisuDataSpin * dataObj)395 const VisuNodeValuesVector* visu_data_spin_get(const VisuDataSpin *dataObj)
396 {
397 return VISU_NODE_VALUES_VECTOR(visu_data_getNodeProperties(VISU_DATA(dataObj),
398 SPIN_PROP_ID));
399 }
400
401 /**
402 * visu_data_spin_setAt:
403 * @dataObj: a #VisuDataSpin object.
404 * @node: a #VisuNode object.
405 * @vals: (array fixed-size=3): a vector in cartesian coordinates.
406 *
407 * Store @vals as the spin representation for @node in @dataObj.
408 *
409 * Since: 3.8
410 **/
visu_data_spin_setAt(VisuDataSpin * dataObj,const VisuNode * node,const gfloat vals[3])411 void visu_data_spin_setAt(VisuDataSpin *dataObj,
412 const VisuNode *node, const gfloat vals[3])
413 {
414 GValue *val;
415 const gfloat* sph;
416
417 g_return_if_fail(VISU_IS_DATA_SPIN(dataObj));
418
419 if (!dataObj->priv->spin)
420 {
421 dataObj->priv->spin = visu_node_values_vector_new(VISU_NODE_ARRAY(dataObj),
422 SPIN_PROP_ID);
423 visu_data_addNodeProperties(VISU_DATA(dataObj),
424 VISU_NODE_VALUES(dataObj->priv->spin));
425 }
426 visu_node_values_vector_setAt(dataObj->priv->spin, node, vals);
427 sph = visu_node_values_vector_getAtSpherical(dataObj->priv->spin, node);
428 if (!dataObj->priv->maxModulus)
429 dataObj->priv->maxModulus = visu_node_array_setElementProperty
430 (VISU_NODE_ARRAY(dataObj), SPIN_MAX_MOD_ID, initMaxModulus);
431 val = &g_array_index(dataObj->priv->maxModulus, GValue, node->posElement);
432 g_value_set_float(val, MAX(sph[TOOL_MATRIX_SPHERICAL_MODULUS],
433 g_value_get_float(val)));
434 }
435 /**
436 * visu_data_spin_setAtSpherical:
437 * @dataObj: a #VisuDataSpin object.
438 * @node: a #VisuNode object.
439 * @vals: (array fixed-size=3): a vector in spherical coordinates.
440 *
441 * Store @vals as the spin representation for @node in @dataObj.
442 *
443 * Since: 3.8
444 **/
visu_data_spin_setAtSpherical(VisuDataSpin * dataObj,const VisuNode * node,const gfloat vals[3])445 void visu_data_spin_setAtSpherical(VisuDataSpin *dataObj, const VisuNode *node,
446 const gfloat vals[3])
447 {
448 GValue *val;
449
450 g_return_if_fail(VISU_IS_DATA_SPIN(dataObj));
451
452 if (!dataObj->priv->spin)
453 {
454 dataObj->priv->spin = visu_node_values_vector_new(VISU_NODE_ARRAY(dataObj),
455 SPIN_PROP_ID);
456 visu_data_addNodeProperties(VISU_DATA(dataObj),
457 VISU_NODE_VALUES(dataObj->priv->spin));
458 }
459 visu_node_values_vector_setAtSpherical(dataObj->priv->spin, node, vals);
460 if (!dataObj->priv->maxModulus)
461 dataObj->priv->maxModulus = visu_node_array_setElementProperty
462 (VISU_NODE_ARRAY(dataObj), SPIN_MAX_MOD_ID, initMaxModulus);
463 val = &g_array_index(dataObj->priv->maxModulus, GValue, node->posElement);
464 g_value_set_float(val, MAX(vals[TOOL_MATRIX_SPHERICAL_MODULUS],
465 g_value_get_float(val)));
466 }
467
468 /**
469 * visu_data_spin_getMaxModulus:
470 * @dataObj: a #VisuDataSpin object.
471 * @iElement: an integer.
472 *
473 * Inquires the max spin modulous from @dataObj for the given
474 * #VisuElement represented by @iElement.
475 *
476 * Since: 3.8
477 *
478 * Returns: a positive float.
479 **/
visu_data_spin_getMaxModulus(const VisuDataSpin * dataObj,guint iElement)480 gfloat visu_data_spin_getMaxModulus(const VisuDataSpin *dataObj, guint iElement)
481 {
482 GValue *val;
483
484 g_return_val_if_fail(VISU_IS_DATA_SPIN(dataObj), 1.f);
485
486 g_return_val_if_fail(dataObj->priv->maxModulus &&
487 iElement < dataObj->priv->maxModulus->len, 1.f);
488
489 val = &g_array_index(dataObj->priv->maxModulus, GValue, iElement);
490 return g_value_get_float(val);
491 }
492
493 /*****************************************************************************/
494 /* */
495 /*****************************************************************************/
496 /* The following are the methods responsible of dealing with the reading of files. */
497 /*****************************************************************************/
498 /* */
499 /*****************************************************************************/
500
501 /* This is the method associated to the reading of supported spin files. */
read_spin_file(VisuDataLoader * loader _U_,VisuDataLoadable * data,guint type,guint nSet _U_,GCancellable * cancel _U_,GError ** error)502 static gboolean read_spin_file(VisuDataLoader *loader _U_, VisuDataLoadable *data,
503 guint type, guint nSet _U_,
504 GCancellable *cancel _U_, GError **error)
505 {
506 char line[TOOL_MAX_LINE_LENGTH] = "\0";
507 float vals[3];
508 int itrash, iLine;
509 VisuNodeArrayIter iter;
510 FILE *readFrom;
511 gboolean readContinue;
512
513 g_return_val_if_fail(error && *error == (GError*)0, FALSE);
514
515 readFrom = fopen(visu_data_loadable_getFilename(data, type), "r");
516 if (!readFrom)
517 {
518 *error = g_error_new(VISU_DATA_LOADABLE_ERROR, DATA_LOADABLE_ERROR_FILE,
519 _("impossible to open this spin file.\n"));
520 return FALSE;
521 }
522 iLine = 1;
523
524 /* The first line is a commentry. */
525 if(!fgets(line, TOOL_MAX_LINE_LENGTH, readFrom) || feof(readFrom))
526 {
527 *error = g_error_new(VISU_DATA_LOADABLE_ERROR, DATA_LOADABLE_ERROR_FORMAT,
528 _("spin file should have one line at least.\n"));
529 fclose(readFrom);
530 return FALSE;
531 }
532 iLine += 1;
533
534 readContinue = TRUE;
535 visu_node_array_iter_new(VISU_NODE_ARRAY(data), &iter);
536 for(visu_node_array_iterStartNumber(VISU_NODE_ARRAY(data), &iter); iter.node;
537 visu_node_array_iterNextNodeNumber(VISU_NODE_ARRAY(data), &iter))
538 {
539 if (readContinue)
540 {
541 if(!fgets(line, TOOL_MAX_LINE_LENGTH, readFrom) || feof(readFrom))
542 readContinue = FALSE;
543 else
544 {
545 if(sscanf(line, "%d %f %f %f", &itrash, vals + TOOL_MATRIX_SPHERICAL_MODULUS,
546 vals + TOOL_MATRIX_SPHERICAL_THETA, vals + TOOL_MATRIX_SPHERICAL_PHI) != 4)
547 {
548 g_warning("line number #%d is invalid."
549 " Setting node parameters to default ones...", iLine);
550 vals[TOOL_MATRIX_SPHERICAL_THETA] = 0.f;
551 vals[TOOL_MATRIX_SPHERICAL_PHI] = 0.f;
552 vals[TOOL_MATRIX_SPHERICAL_MODULUS] = 0.f;
553 }
554 }
555 iLine += 1;
556 }
557 else
558 {
559 vals[TOOL_MATRIX_SPHERICAL_THETA] = 0.f;
560 vals[TOOL_MATRIX_SPHERICAL_PHI] = 0.f;
561 vals[TOOL_MATRIX_SPHERICAL_MODULUS] = 0.f;
562 }
563 visu_data_spin_setAtSpherical(VISU_DATA_SPIN(data), iter.node, vals);
564 }
565 fclose(readFrom);
566
567 return TRUE;
568 }
569
570 /* This is the method associated to the reading of binary spin files. */
read_binary_file(VisuDataLoader * loader _U_,VisuDataLoadable * data,guint type,guint nSet _U_,GCancellable * cancel _U_,GError ** error)571 static gboolean read_binary_file(VisuDataLoader *loader _U_, VisuDataLoadable *data,
572 guint type, guint nSet _U_,
573 GCancellable *cancel _U_, GError **error)
574 {
575 ToolFiles *readFrom;
576 gboolean valid;
577 ToolFortranEndianId endian;
578 guint nspins;
579 GArray *mods, *thetas, *phis;
580 int i;
581 float vals[3];
582 VisuNodeArrayIter iter;
583
584 g_return_val_if_fail(error && *error == (GError*)0, FALSE);
585
586 readFrom = tool_files_new();
587 if (!tool_files_fortran_open(readFrom, visu_data_loadable_getFilename(data, type), error))
588 return FALSE;
589
590 /* Try to find the endianness. */
591 if (!tool_files_fortran_testEndianness(readFrom, 4, &endian))
592 {
593 g_object_unref(readFrom);
594 return FALSE;
595 }
596
597 /* Try to the number of spins. */
598 if (!tool_files_fortran_readInteger(readFrom, (gint*)&nspins, endian, error))
599 {
600 g_object_unref(readFrom);
601 return FALSE;
602 }
603 if (!tool_files_fortran_checkFlag(readFrom, 4, endian, error))
604 {
605 g_object_unref(readFrom);
606 return FALSE;
607 }
608
609 /* From now on, we consider to a have valid spin file. */
610 visu_node_array_iter_new(VISU_NODE_ARRAY(data), &iter);
611 if (nspins != iter.nAllStoredNodes)
612 {
613 g_set_error(error, VISU_DATA_LOADABLE_ERROR, DATA_LOADABLE_ERROR_FORMAT,
614 _("number of spin differs from number of nodes.\n"));
615 g_object_unref(readFrom);
616 return TRUE;
617 }
618
619 /* Read module. */
620 valid = tool_files_fortran_readDoubleArray(readFrom, &mods,
621 nspins, endian, TRUE, error);
622 if (!valid)
623 {
624 g_object_unref(readFrom);
625 return TRUE;
626 }
627 /* Read theta. */
628 valid = tool_files_fortran_readDoubleArray(readFrom, &thetas,
629 nspins, endian, TRUE, error);
630 if (!valid)
631 {
632 g_array_unref(mods);
633 g_object_unref(readFrom);
634 return TRUE;
635 }
636 /* Read phi. */
637 valid = tool_files_fortran_readDoubleArray(readFrom, &phis,
638 nspins, endian, TRUE, error);
639 if (!valid)
640 {
641 g_array_unref(mods);
642 g_array_unref(thetas);
643 g_object_unref(readFrom);
644 return TRUE;
645 }
646 /* Close the file. */
647 g_object_unref(readFrom);
648
649 for(visu_node_array_iterStart(VISU_NODE_ARRAY(data), &iter), i = 0; iter.node;
650 visu_node_array_iterNext(VISU_NODE_ARRAY(data), &iter), i++)
651 {
652 vals[TOOL_MATRIX_SPHERICAL_MODULUS] = g_array_index(mods, double, i);
653 vals[TOOL_MATRIX_SPHERICAL_THETA] = g_array_index(thetas, double, i);
654 vals[TOOL_MATRIX_SPHERICAL_PHI] = g_array_index(phis, double, i);
655 visu_data_spin_setAtSpherical(VISU_DATA_SPIN(data), iter.node, vals);
656 }
657
658 g_array_unref(mods);
659 g_array_unref(thetas);
660 g_array_unref(phis);
661 return TRUE;
662 }
663