atomes 1.3.2
atomes: an atomic scale modeling tool box
Loading...
Searching...
No Matches
read_cif.c
Go to the documentation of this file.
1/* This file is part of the 'atomes' software
2
3'atomes' is free software: you can redistribute it and/or modify it under the terms
4of the GNU Affero General Public License as published by the Free Software Foundation,
5either version 3 of the License, or (at your option) any later version.
6
7'atomes' is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
8without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
9See the GNU General Public License for more details.
10
11You should have received a copy of the GNU Affero General Public License along with 'atomes'.
12If not, see <https://www.gnu.org/licenses/>
13
14Copyright (C) 2022-2026 by CNRS and University of Strasbourg */
15
21
22/*
23* This file: 'read_cif.c'
24*
25* Contains:
26*
27
28 - The functions to read CIF files
29
30*
31* List of functions:
32
33 int get_atom_wyckoff (gchar * line, int wid);
34 int cif_get_value (gchar * kroot, gchar * keyw, int lstart, int linec, gchar ** cif_word,
35 gboolean rec_val, gboolean all_ligne, gboolean total_num, gboolean record_position, int * line_position)
36 int cif_file_get_data_in_loop (int linec, int lid);
37 int cif_file_get_number_of_atoms (int linec, int lid, int nelem);
38 int get_loop_line_id (int lid);
39 int get_loop_line_for_key (int linec, int conf, gchar * key_a, gchar * key_b);
40 int cif_file_get_number_of_positions (int lid);
41 int get_space_group_from_hm (gchar * hmk);
42 int get_setting_from_hm (gchar * hmk, int end);
43 int group_info_from_hm_key (int spg, gchar * key_hm);
44 int cif_get_space_group (int linec);
45 int open_cif_configuration (int linec, int conf);
46 int open_cif_file (int linec);
47
48 float get_atom_coord (gchar * line, int mid);
49
50 gboolean get_missing_object_from_user ();
51 gboolean cif_file_get_atoms_data (int conf, int lin, int cid[8]);
52 gboolean cif_get_atomic_coordinates (int linec);
53 gboolean cif_get_symmetry_positions (int linec);
54 gboolean cif_get_cell_data (int linec, int conf);
55
56 gchar * get_cif_word (gchar * mot);
57 gchar * get_atom_label (gchar * line, int lid);
58 gchar * get_atom_disorder (gchar * line, int lid);
59 gchar * get_string_from_origin (space_group * spg);
60 gchar * cif_retrieve_value (int linec, int conf, gchar * key_a, gchar * key_b, gboolean all_ligne, gboolean in_loop, gboolean warning);
61
62 G_MODULE_EXPORT void set_cif_to_insert (GtkComboBox * box, gpointer data);
63 void file_get_to_line (int line_id);
64 void check_for_to_lab (int ato, gchar * stlab);
65
66*/
67
68#include "global.h"
69#include "bind.h"
70#include "interface.h"
71#include "project.h"
72#include "atom_edit.h"
73#include "cbuild_edit.h"
74#include "readers.h"
75#include <ctype.h>
76#ifdef OPENMP
77# include <omp.h>
78#endif
79
80extern int get_atom_id_from_periodic_table (atom_search * asearch);
81extern double get_z_from_periodic_table (gchar * lab);
82extern void get_origin (space_group * spg);
83extern void compute_lattice_properties (cell_info * cell, int box_id);
84extern int test_lattice (builder_edition * cbuilder, cell_info * cif_cell);
85extern int read_space_group (builder_edition * cbuilder, int spg);
86extern gchar * wnpos[3];
87extern void get_wyck_char (float val, int ax, int bx);
89extern distance distance_3d (cell_info * cell, int mdstep, atom * at, atom * bt);
90extern void sort (int dim, int * tab);
91
92extern gchar * tmp_pos;
93
94FILE * cifp;
95char * line_ptr;
96int * keylines = NULL;
100int * cif_lot = NULL;
101int * cif_nsps = NULL;
102
103gboolean cif_multiple = FALSE;
104
105gchar ** cif_strings = NULL;
106
107gchar * cif_coord_opts[40][2] = {{"b1", "Monoclinic unique axis b, cell choice 1, abc"}, // 0
108 {"b2", "Monoclinic unique axis b, cell choice 2, abc"}, // 1
109 {"b3", "Monoclinic unique axis b, cell choice 3, abc"}, // 2
110 {"-b1", "Monoclinic unique axis b, cell choice 1, c-ba"}, // 3
111 {"-b2", "Monoclinic unique axis b, cell choice 2, c-ba"}, // 4
112 {"-b3", "Monoclinic unique axis b, cell choice 3, c-ba"}, // 5
113 {"c1", "Monoclinic unique axis c, cell choice 1, abc"}, // 6
114 {"c2", "Monoclinic unique axis c, cell choice 2, abc"}, // 7
115 {"c3", "Monoclinic unique axis c, cell choice 3, abc"}, // 8
116 {"-c1", "Monoclinic unique axis c, cell choice 1, ba-c"}, // 9
117 {"-c2", "Monoclinic unique axis c, cell choice 2, ba-c"}, // 10
118 {"-c3", "Monoclinic unique axis c, cell choice 3, ba-c"}, // 11
119 {"a1", "Monoclinic unique axis a, cell choice 1, abc"}, // 12
120 {"a2", "Monoclinic unique axis a, cell choice 2, abc"}, // 13
121 {"a3", "Monoclinic unique axis a, cell choice 3, abc"}, // 14
122 {"-a1", "Monoclinic unique axis a, cell choice 1, -acb"}, // 15
123 {"-a2", "Monoclinic unique axis a, cell choice 2, -acb"}, // 16
124 {"-a3", "Monoclinic unique axis a, cell choice 3, -acb"}, // 17
125 {"abc", "Orthorhombic"}, // 18
126 {"ba-c", "Orthorhombic"}, // 10
127 {"cab", "Orthorhombic"}, // 20
128 {"-cba", "Orthorhombic"}, // 21
129 {"bca", "Orthorhombic"}, // 22
130 {"a-cb", "Orthorhombic"}, // 23
131 {"1abc", "Orthorhombic origin choice 1"}, // 24
132 {"1ba-c", "Orthorhombic origin choice 1"}, // 25
133 {"1cab", "Orthorhombic origin choice 1"}, // 26
134 {"1-cba", "Orthorhombic origin choice 1"}, // 27
135 {"1bca", "Orthorhombic origin choice 1"}, // 28
136 {"1a-cb", "rthorhombic origin choice 1"}, // 29
137 {"2abc", "Orthorhombic origin choice 2"}, // 30
138 {"2ba-c", "Orthorhombic origin choice 2"}, // 31
139 {"2cab", "Orthorhombic origin choice 2"}, // 32
140 {"2-cba", "Orthorhombic origin choice 2"}, // 33
141 {"2bca", "Orthorhombic origin choice 2"}, // 34
142 {"2a-cb", "Orthorhombic origin choice 2"}, // 35
143 {"1", "Tetragonal or cubic origin choice 1"}, // 36
144 {"2", "Tetragonal or cubic origin choice 2"}, // 37
145 {"h", "Trigonal using hexagonal axes"}, // 38
146 {"r", "Trigonal using rhombohedral axes "}}; // 39
147
148/*
149The following lines describe keywords used to declare atomic coordinates in the CIF file:
150
151 - NLKEYS : the number of keyword possibly used to start the line
152 - linekeys : the keyword possibly used to start the line
153
154 - CFKEYS : he number of keyword possibly used to describe coordinates
155 - frackeys : the keyword possibly used to describe fractional coordinates
156 - cartkeys : the keyword possibly used to describe Cartesian coordinates
157
158Note that this can change, so in all cases if required add more.
159*/
160#define NLKEYS 2
161gchar * linekeys[NLKEYS] = {"_atom_site", // Most common
162 "_chem_comp_atom"}; // RCSB database: https://www.rcsb.org/
163
164#define CFKEYS 3
165gchar * frackeys[CFKEYS-1][3] = {{"fract_x", "fract_y", "fract_z"}, // Most common
166 {"model_fract_x", "model_fract_y", "model_fract_z"}}; // mmCIF, RCSB database: https://www.rcsb.org/
167gchar * cartkeys[CFKEYS][3] = {{"cartn_x", "cartn_y", "cartn_z"}, // Most common
168 {"model_cartn_x", "model_cartn_y", "model_cartn_z"}, // mmCIF, RCSB database: https://www.rcsb.org/
169 {"pdbx_model_cartn_x_ideal", "pdbx_model_cartn_y_ideal", "pdbx_model_cartn_z_ideal"}}; // mmCIF, RCSB database: https://www.rcsb.org/
170
171// Coordinates identification buffers if multiple sets of Cartesian coordinates are found
172int cif_cnfcart = 0; // Number of formats of Cartesian coordinates, if multiple
173int ** cif_cnfkeys = NULL; // Associated keywords in linekeys and cartkeys
174gboolean * cif_cnftodo = NULL; // Was processed already or not
175int cif_cnfdone = 0; // Number of format(s) processed
176
177#ifdef G_OS_WIN32
178 typedef intptr_t ssize_t;
179
180 ssize_t getline(char **lineptr, size_t *n, FILE *stream)
181 {
182 size_t pos;
183 int c;
184
185 if (lineptr == NULL || stream == NULL || n == NULL)
186 {
187 errno = EINVAL;
188 return -1;
189 }
190
191 c = getc(stream);
192 if (c == EOF) return -1;
193
194 if (*lineptr == NULL)
195 {
196 *lineptr = malloc(128);
197 if (*lineptr == NULL) return -1;
198 *n = 128;
199 }
200
201 pos = 0;
202 while(c != EOF)
203 {
204 if (pos + 1 >= *n)
205 {
206 size_t new_size = *n + (*n >> 2);
207 if (new_size < 128)
208 {
209 new_size = 128;
210 }
211 char *new_ptr = realloc(*lineptr, new_size);
212 if (new_ptr == NULL) return -1;
213 *n = new_size;
214 *lineptr = new_ptr;
215 }
216
217 ((unsigned char *)(*lineptr))[pos ++] = c;
218 if (c == '\n') break;
219 c = getc(stream);
220 }
221
222 (*lineptr)[pos] = '\0';
223 return pos;
224 }
225#endif // G_OS_WIN_32
226
234gchar * get_cif_word (gchar * mot)
235{
236 gchar * word = substitute_string (mot, "\n", NULL);
237 word = substitute_string (word, "\r", NULL);
238 return word;
239}
240
249float get_atom_coord (gchar * line, int mid)
250{
251 gchar * co_line;
252 gchar * init = g_strdup_printf ("%s", line);
253 char * co_word = strtok_r (init, " ", & co_line);
254 int i;
255 for (i=0; i<mid-1; i++)
256 {
257 co_word = strtok_r (NULL, " ", & co_line);
258 }
259 double v = string_to_double ((gpointer)get_cif_word(co_word));
260 g_free (init);
261 return v;
262}
263
272gchar * get_atom_label (gchar * line, int lid)
273{
274 gchar * at_line;
275 gchar * init = g_strdup_printf ("%s", line);
276 char * at_word = strtok_r (init, " ", & at_line);
277 int i;
278 for (i=0; i<lid-1; i++) at_word = strtok_r (NULL, " ", & at_line);
279 gchar * str;
280 for (i=0; i<10; i++)
281 {
282 str = g_strdup_printf ("%d", i);
283 at_word = substitute_string (at_word, str, NULL);
284 g_free (str);
285 }
286 at_word = get_cif_word (at_word);
287 at_word = substitute_string (at_word, "-", NULL);
288 at_word = substitute_string (at_word, "+", NULL);
289 g_free (init);
290 return g_strdup_printf ("%c%c", at_word[0], tolower(at_word[1]));
291}
292
301int get_atom_wyckoff (gchar * line, int wid)
302{
303 gchar * wy_line;
304 gchar * init = g_strdup_printf ("%s", line);
305 char * wy_word = strtok_r (init, " ", & wy_line);
306 int i, j;
307 j = 0;
308 for (i=0; i<wid-1; i++) wy_word = strtok_r (NULL, " ", & wy_line);
309 for (i=0; i<this_reader -> lattice.sp_group -> numw; i++)
310 {
311 if (g_strcmp0(get_cif_word(wy_word), this_reader -> lattice.sp_group -> wyckoff[i].let) == 0)
312 {
313 j = i;
314 break;
315 }
316 }
317 g_free (init);
318 return j;
319}
320
329gchar * get_atom_disorder (gchar * line, int lid)
330{
331 gchar * at_line;
332 gchar * init = g_strdup_printf ("%s", line);
333 char * at_word = strtok_r (init, " ", & at_line);
334 int i;
335 for (i=0; i<lid-1; i++) at_word = strtok_r (NULL, " ", & at_line);
336 g_free (init);
337 return get_cif_word (at_word);
338}
339
340GtkWidget ** img_cif;
343
352G_MODULE_EXPORT void set_cif_to_insert (GtkComboBox * box, gpointer data)
353{
354 GValue val = {0, };
355 int i, j, k;
356 i = GPOINTER_TO_INT(data);
357 GtkTreeModel * cmodel = gtk_combo_box_get_model (box);
358 GtkTreeIter iter;
359 gchar * str;
360 gboolean done = TRUE;
361 if (gtk_combo_box_get_active_iter (box, & iter))
362 {
363 gtk_tree_model_get_value (cmodel, & iter, 0, & val);
364 str = g_strdup_printf ("%s", (char *)g_value_get_string (& val));
365 j = get_selected_object_id (FALSE, activep, str, cif_search);
367 if (j > 0)
368 {
369 gtk_tree_store_set (GTK_TREE_STORE(cmodel), & iter, 0, periodic_table_info[j].lab, -1);
370 }
371 cif_search -> todo[i] = (! j) ? 0 : 1;
372 if (! j) done = FALSE;
373 cif_search -> in_selection = 0;
374 for (k=0; k<this_reader -> object_to_insert; k++) cif_search -> in_selection += cif_search -> todo[k];
375 }
376 str = (done) ? g_strdup_printf (APPLY) : g_strdup_printf (DELETEB);
378 g_free (str);
379 if (! done) combo_set_active ((GtkWidget *)box, 0);
380}
381
388{
389 cif_search = allocate_atom_search (activep, REPLACE, 0, this_reader -> object_to_insert);
390 cif_object = NULL;
391 GtkWidget * info = dialogmodal (_("Error while reading CIF file"), GTK_WINDOW(atomes_main_window));
392 GtkWidget * vbox, * hbox;
393 gchar * str;
395 gchar * labpick = _("<b>To continue and build the crystal according to the information of the CIF file\n"
396 "it is required to provide a suitable value for each and every missing parameter(s).</b>"
397 "\n\nPlease select an atom type for the following object(s):");
398 add_box_child_start (GTK_ORIENTATION_VERTICAL, vbox, markup_label (labpick, 200, -1, 0.5, 0.5), FALSE, FALSE, 10);
399 img_cif = g_malloc0(this_reader -> object_to_insert*sizeof*img_cif);
400 GtkWidget * but;
401 GtkCellRenderer * renderer;
402 GtkTreeModel * model;
403 int i;
404 for (i=0; i<this_reader -> object_to_insert; i++)
405 {
406 hbox = create_hbox(0);
407 add_box_child_start (GTK_ORIENTATION_VERTICAL, vbox, hbox, FALSE, FALSE, 5);
408 str = g_strdup_printf (_("Type N°%d:\t<b>%s</b>"), i+1, this_reader -> label[i]);
409 add_box_child_start (GTK_ORIENTATION_HORIZONTAL, hbox, markup_label(str, 150, -1, 0.0, 0.5), FALSE, FALSE, 20);
410 g_free (str);
413 but = gtk_combo_box_new_with_model (model);
414 g_object_unref (model);
415 renderer = gtk_cell_renderer_combo_new ();
416 gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (but), renderer, TRUE);
417 gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (but), renderer, "text", 0, NULL);
418 combo_set_active (but, 0);
419 g_signal_connect (G_OBJECT(but), "changed", G_CALLBACK(set_cif_to_insert), GINT_TO_POINTER(i));
420 combo_set_markup (but);
421 add_box_child_start (GTK_ORIENTATION_HORIZONTAL, hbox, but, FALSE, FALSE, 0);
422 add_box_child_start (GTK_ORIENTATION_HORIZONTAL, hbox, img_cif[i], FALSE, FALSE, 30);
423 }
424
425 gchar * endpick = _("In case of a molecule: insert an extra type of atom and run a substitution afterwards.");
426 add_box_child_start (GTK_ORIENTATION_VERTICAL, vbox, markup_label (endpick, 200, -1, 0.5, 0.5), FALSE, FALSE, 10);
427 run_this_gtk_dialog (info, G_CALLBACK(run_destroy_dialog), NULL);
428 g_free (img_cif);
429 return (cif_search -> in_selection == this_reader -> object_to_insert) ? TRUE : FALSE;
430}
431
432#ifndef OPENMP
440void file_get_to_line (int line_id)
441{
442 int i;
443 tail = head;
444 for (i=0; i<line_id; i++) tail = tail -> next;
445}
446#endif
447
465int cif_get_value (gchar * kroot, gchar * keyw, int lstart, int lend, gchar ** cif_word,
466 gboolean rec_val, gboolean all_ligne, gboolean total_num, gboolean record_position, int * line_position)
467{
468 int res = 0;
469 int i;
470 size_t j, k, l, m;
471 gchar * str;
472 gchar * str_w, * str_a, * str_b;
473 gchar * mot;
474 gchar * saved_line;
475 gchar * the_line;
476 gchar * the_word;
477 j = strlen(kroot);
478 k = strlen(keyw);
479 l = j+k+1;
480
481#ifdef OPENMP
482 int numth = omp_get_max_threads ();
483 #pragma omp parallel for num_threads(numth) private(i,m,the_line,saved_line,the_word,mot,str_a,str_b,str_w) shared(j,k,l,this_reader,coord_line,cif_word,rec_val,all_ligne,kroot,keyw,total_num,record_position,line_position,res)
484 for (i=lstart; i<lend; i++)
485 {
486 the_line = NULL;
487 if (res && ! total_num) goto endi;
488 the_line = g_strdup_printf ("%s", coord_line[i]);
489 the_word = strtok_r (the_line, " ", & saved_line);
490 while (the_word)
491 {
492 str_w = get_cif_word (the_word);
493 str_w = g_ascii_strdown (str_w, strlen(str_w));
494 if (strlen(str_w) == l)
495 {
496 str_a = g_strdup_printf ("%c", str_w[0]);
497 for (m=1; m<j; m++) str_a = g_strdup_printf ("%s%c", str_a, str_w[m]);
498 str_b = g_strdup_printf ("%c", str_w[j+1]);
499 for (m=j+2; m<l; m++) str_b = g_strdup_printf ("%s%c", str_b, str_w[m]);
500 if (g_strcmp0(str_a, kroot) == 0 && g_strcmp0(str_b,keyw) == 0)
501 {
502 the_word = strtok_r (NULL, " ", & saved_line);
503 if (! the_word)
504 {
505 if (rec_val || all_ligne)
506 {
507 str = g_strdup_printf (_("Wrong file format: searching for <b>%s</b> - error at line <b>%d</b> !\n"), keyw, i+1);
508 add_reader_info (str, 0);
509 g_free (str);
510 g_free (str_w);
511 g_free (str_a);
512 g_free (str_b);
513 res = -1;
514 goto endi;
515 }
516 }
517 if (total_num)
518 {
519 #pragma omp critical
520 {
521 if (record_position)
522 {
523 line_position[res] = i + 1;
524 }
525 res ++;
526 if (this_reader -> steps && res == this_reader -> steps) total_num = FALSE;
527 }
528 }
529 else
530 {
531 res = i + 1;
532 }
533 if (all_ligne)
534 {
535 mot = g_strdup_printf ("%s", the_word);
536 the_word = strtok_r (NULL, " ", & saved_line);
537 while (the_word)
538 {
539 mot = g_strdup_printf ("%s%s", mot, the_word);
540 the_word = strtok_r (NULL, " ", & saved_line);
541 }
542 the_word = g_strdup_printf ("%s", mot);
543 g_free (mot);
544 }
545 if (the_word && rec_val)
546 {
547 * cif_word = get_cif_word (the_word);
548 }
549 g_free (str_w);
550 g_free (str_a);
551 g_free (str_b);
552 goto endi;
553 }
554 g_free (str_a);
555 g_free (str_b);
556 }
557 g_free (str_w);
558 the_word = strtok_r (NULL, " ", & saved_line);
559 }
560 endi:;
561 g_free (the_line);
562 }
563
564 if (res < 0) res = 0;
565#else
566 file_get_to_line (lstart);
567 res = 0;
568 i = lstart;
569 while (tail)
570 {
571 the_line = g_strdup_printf ("%s", tail -> line);
572 the_word = strtok_r (the_line, " ", & saved_line);
573 while (the_word)
574 {
575 str_w = get_cif_word (the_word);
576 str_w = g_ascii_strdown (str_w, strlen(str_w));
577 if (strlen(str_w) == l)
578 {
579 str_a = g_strdup_printf ("%c", str_w[0]);
580 for (m=1; m<j; m++) str_a = g_strdup_printf ("%s%c", str_a, str_w[m]);
581 str_b = g_strdup_printf ("%c", str_w[j+1]);
582 for (m=j+2; m<l; m++) str_b = g_strdup_printf ("%s%c", str_b, str_w[m]);
583 if (g_strcmp0(str_a, kroot) == 0 && g_strcmp0(str_b,keyw) == 0)
584 {
585 the_word = strtok_r (NULL, " ", & saved_line);
586 if (! the_word)
587 {
588 if (rec_val || all_ligne)
589 {
590 str = g_strdup_printf (_("Wrong file format: searching for <b>%s</b> - error at line <b>%d</b> !\n"), keyw, i+1);
591 add_reader_info (str, 0);
592 g_free (str);
593 g_free (str_w);
594 g_free (str_a);
595 g_free (str_b);
596 g_free (the_line);
597 return 0;
598 }
599 }
600
601 if (all_ligne)
602 {
603 mot = g_strdup_printf ("%s", the_word);
604 the_word = strtok_r (NULL, " ", & saved_line);
605 while (the_word)
606 {
607 mot = g_strdup_printf ("%s%s", mot, the_word);
608 the_word = strtok_r (NULL, " ", & saved_line);
609 }
610 the_word = g_strdup_printf ("%s", mot);
611 g_free (mot);
612 }
613 if (the_word && rec_val)
614 {
615 * cif_word = get_cif_word (the_word);
616 }
617 if (total_num)
618 {
619 if (record_position)
620 {
621 line_position[res] = i + 1;
622 }
623 res ++;
624 if (this_reader -> steps && res == this_reader -> steps)
625 {
626 g_free (str_a);
627 g_free (str_b);
628 g_free (str_w);
629 g_free (the_line);
630 return res;
631 }
632 }
633 else
634 {
635 g_free (str_a);
636 g_free (str_b);
637 g_free (str_w);
638 g_free (the_line);
639 return i + 1;
640 }
641 }
642 g_free (str_a);
643 g_free (str_b);
644 }
645 g_free (str_w);
646 the_word = strtok_r (NULL, " ", & saved_line);
647 }
648 g_free (the_line);
649 tail = tail -> next;
650 i ++;
651 }
652#endif
653 return res;
654}
655
664int cif_file_get_data_in_loop (int linec, int lid)
665{
666 gboolean res = FALSE;
667 int i = 0;
668 gchar * the_word;
669 gchar * the_line;
670 gchar * saved_line;
671#ifdef OPENMP
672 while (! res)
673 {
674 if (lid+i < linec)
675 {
676 the_line = g_strdup_printf ("%s", coord_line[lid+i]);
677 the_word = strtok_r (the_line, " ", & saved_line);
678 if (the_word[0] == '_')
679 {
680 i ++;
681 }
682 else
683 {
684 res = TRUE;
685 }
686 g_free (the_line);
687 }
688 else
689 {
690 res = TRUE;
691 }
692 }
693#else
694 file_get_to_line (lid);
695 while (! res)
696 {
697 if (tail)
698 {
699 the_line = g_strdup_printf ("%s", tail -> line);
700 the_word = strtok_r (the_line, " ", & saved_line);
701 if (the_word[0] == '_')
702 {
703 i ++;
704 tail = tail -> next;
705 }
706 else
707 {
708 res = TRUE;
709 }
710 g_free (the_line);
711 }
712 else
713 {
714 res = TRUE;
715 }
716 }
717#endif
718 return i;
719}
720
728int get_loop_line_id (int lid)
729{
730 int i;
731 gchar * the_word;
732 gchar * the_line;
733 gchar * saved_line;
734 gchar * str_w;
735#ifdef OPENMP
736 for (i=lid-1; i>-1; i--)
737 {
738 the_line = g_strdup_printf ("%s", coord_line[i]);
739 the_word = strtok_r (the_line, " ", & saved_line);
740 if (the_word)
741 {
742 str_w = g_ascii_strdown (the_word, strlen(the_word));
743 if (g_strcmp0 ("loop_", get_cif_word(str_w)) == 0)
744 {
745 g_free (str_w);
746 return i+1;
747 }
748 g_free (str_w);
749 }
750 }
751#else
752 file_get_to_line (lid);
753 i = lid;
754 while (tail)
755 {
756 the_line = g_strdup_printf ("%s", tail -> line);
757 the_word = strtok_r (the_line, " ", & saved_line);
758 if (the_word)
759 {
760 str_w = g_ascii_strdown (the_word, strlen(the_word));
761 if (g_strcmp0 ("loop_", get_cif_word(str_w)) == 0)
762 {
763 g_free (str_w);
764 return i+1;
765 }
766 g_free (str_w);
767 }
768 i --;
769 tail = tail -> prev;
770 }
771#endif
772 return 0;
773}
774
785int get_loop_line_for_key (int linec, int conf, gchar * key_a, gchar * key_b)
786{
787 int lli = 0;
788 int * line_numbers;
789 int steps;
790 if (this_reader -> steps > 1)
791 {
792 line_numbers = allocint (this_reader -> steps);
793 steps = cif_get_value (key_a, key_b, 0, linec, NULL, FALSE, FALSE, TRUE, TRUE, line_numbers);
794 if (steps)
795 {
796 if (steps != this_reader -> steps)
797 {
798 gchar * str = g_strdup_printf (_("<b>CIF get loop line</b>: something is wrong for keyword: %s_%s\n"
799 " -> keyword found= %d times\n"
800 " -> configurations in CIF file= %d !\n"), key_a, key_b, steps, this_reader -> steps);
801 add_reader_info (str, 0);
802 g_free (str);
803 g_free (line_numbers);
804 return 0;
805 }
806 sort (steps, line_numbers);
807 lli = line_numbers[conf];
808 g_free (line_numbers);
809 }
810 }
811 else
812 {
813 lli = cif_get_value (key_a, key_b, 0, linec, NULL, FALSE, FALSE, FALSE, FALSE, NULL);
814 }
815 return (lli) ? get_loop_line_id (lli) : 0;
816}
817
831gchar * cif_retrieve_value (int linec, int conf, gchar * key_a, gchar * key_b, gboolean all_ligne, gboolean in_loop, gboolean warning)
832{
833 gchar * str;
834 gchar * cif_value = NULL;
835 int loop_pos[2];
836 int * line_numbers;
837 int steps;
838 if (this_reader -> steps > 1)
839 {
840 line_numbers = allocint (this_reader -> steps);
841 // g_debug ("CIF:: retrieve:: linec= %d, conf= %d, key_a= %s, key_b= %s, this_reader -> steps= %d", linec, conf, key_a, key_b, this_reader -> steps);
842 steps = cif_get_value (key_a, key_b, 0, linec, NULL, FALSE, FALSE, TRUE, TRUE, line_numbers);
843 // g_debug ("CIF:: retrieve:: steps= %d", steps);
844 if (steps)
845 {
846 if (steps != this_reader -> steps)
847 {
848 str = g_strdup_printf (_("<b>CIF retrieved value</b>: keyword: %s_%s\n"
849 " -> keyword found= %d times\n"
850 " -> configurations in CIF file= %d !\n"), key_a, key_b, steps, this_reader -> steps);
851 add_reader_info (str, 0);
852 g_free (str);
853 str = NULL;
854 g_free (line_numbers);
855 line_numbers = NULL;
856 return NULL;
857 }
858 sort (steps, line_numbers);
859 if (in_loop)
860 {
861 // Considering that the loop has not more than a thousand keys
862 loop_pos[0] = get_loop_line_id (line_numbers[conf]);
863 loop_pos[1] = (loop_pos[0] + 1000) > linec ? linec : (loop_pos[0] + 1000);
864 }
865 else
866 {
867 loop_pos[0] = (! line_numbers[conf]) ? line_numbers[conf] : line_numbers[conf] - 1;
868 loop_pos[1] = (loop_pos[0] + 1000) > linec ? linec : (loop_pos[0] + 1000);
869 // loop_pos[1] = (conf == this_reader -> steps - 1) ? linec : line_numbers[conf + 1];
870 }
871 g_free (line_numbers);
872 line_numbers = NULL;
873 }
874 }
875 else
876 {
877 loop_pos[0] = 0;
878 loop_pos[1] = linec;
879 }
880 if (! cif_get_value (key_a, key_b, loop_pos[0], loop_pos[1], & cif_value, TRUE, all_ligne, FALSE, FALSE, NULL) && warning)
881 {
882#ifdef DEBUG
883 g_debug ("CIF:: retrieve:: keyword: %s_%s not found for conf %d between loop_pos[0]= %d and loop_pos[1]= %d\n", key_a, key_b, conf, loop_pos[0], loop_pos[1]);
884#endif
885 str = g_strdup_printf (_("<b>Key positions</b>: keyword: %s_%s\n"
886 " -> not found for conf %d between loop_pos[0]= %d and loop_pos[1]= %d\n"), key_a, key_b, conf, loop_pos[0], loop_pos[1]);
887 add_reader_info (str, 0);
888 g_free (str);
889 return NULL;
890 }
891 return cif_value;
892}
893
903int cif_file_get_number_of_atoms (int linec, int lid, int nelem)
904{
905 gboolean res = FALSE;
906 int i, j;
907 char init;
908 gchar * the_word;
909 gchar * the_line;
910 gchar * saved_line;
911 i = 0;
912#ifdef OPENMP
913 while (! res && (lid+i) < linec)
914 {
915 the_line = g_strdup_printf ("%s", coord_line[lid+i]);
916 the_word = strtok_r (the_line, " ", & saved_line);
917 j = 0;
918 while (the_word)
919 {
920 if (! j) init = the_word[0];
921 j ++;
922 the_word = strtok_r (NULL, " ", & saved_line);
923 }
924 if (j == nelem && init != '_')
925 {
926 i ++;
927 }
928 else
929 {
930 res = TRUE;
931 }
932 g_free (the_line);
933 }
934#else
935 file_get_to_line (lid);
936 while (! res && tail)
937 {
938 the_line = g_strdup_printf ("%s", tail -> line);
939 the_word = strtok_r (the_line, " ", & saved_line);
940 j = 0;
941 while (the_word)
942 {
943 if (j == 0) init = the_word[0];
944 j ++;
945 the_word = strtok_r (NULL, " ", & saved_line);
946 }
947 if (j == nelem && init != '_')
948 {
949 i ++;
950 }
951 else
952 {
953 res = TRUE;
954 }
955 g_free (the_line);
956 tail = tail -> next;
957 }
958#endif
959 return i;
960}
961
970void check_for_to_lab (int ato, gchar * stlab)
971{
972 int i, j;
973 j = -1;
974 // First is the label of 'ato' already listed
975 for (i=0; i<this_reader -> object_to_insert; i++)
976 {
977 if (g_strcmp0(this_reader -> label[i], stlab) == 0)
978 {
979 j = i;
980 break;
981 }
982 }
983 if (j < 0)
984 {
985 if (this_reader -> label)
986 {
987 this_reader -> label = g_realloc (this_reader -> label, (this_reader -> object_to_insert+1)*sizeof*this_reader -> label);
988 }
989 else
990 {
991 this_reader -> label = g_malloc0(1*sizeof*this_reader -> label);
992 }
993 this_reader -> label[this_reader -> object_to_insert] = g_strdup_printf ("%s", stlab);
994 this_reader -> object_to_insert ++;
995 j = this_reader -> object_to_insert-1;
996 }
997 if (this_reader -> object_list)
998 {
999 this_reader -> object_list = g_realloc (this_reader -> object_list, (this_reader -> atom_unlabelled+1)*sizeof*this_reader -> object_list);
1000 this_reader -> u_atom_list = g_realloc (this_reader -> u_atom_list, (this_reader -> atom_unlabelled+1)*sizeof*this_reader -> u_atom_list);
1001 }
1002 else
1003 {
1004 this_reader -> object_list = g_malloc0(1*sizeof*this_reader -> object_list);
1005 this_reader -> u_atom_list = g_malloc0(1*sizeof*this_reader -> u_atom_list);
1006 }
1007 this_reader -> object_list[this_reader -> atom_unlabelled] = j;
1008 this_reader -> u_atom_list[this_reader -> atom_unlabelled] = ato;
1009 this_reader -> atom_unlabelled ++;
1010}
1011
1021gboolean cif_file_get_atoms_data (int conf, int lin, int cid[9])
1022{
1023 int i, j;
1024 double v;
1025 gchar * str;
1026 gboolean done = TRUE;
1027 gchar * cline;
1028 int at_step = (active_project -> steps == 1) ? 0 : conf;
1029#ifdef OPENMP
1030 int numth = omp_get_max_threads ();
1031 #pragma omp parallel for num_threads(numth) private(i,j,v,cline,str) shared(this_reader,coord_line,at_step,done,lin,cid)
1032 for (i=0; i<this_reader -> natomes; i++)
1033 {
1034 cline = g_strdup_printf ("%s", coord_line[i+lin]);
1035 str = get_atom_label (cline, (cid[0]) ? cid[0] : cid[1]);
1036 v = get_z_from_periodic_table (str);
1037 #pragma omp critical
1038 {
1039 if (v)
1040 {
1041 check_for_species (v, i);
1042 }
1043 else
1044 {
1045 done = FALSE;
1046 check_for_to_lab (i, str);
1047 }
1048 }
1049 if (this_reader -> cartesian)
1050 {
1051 active_project -> atoms[at_step][i].x = get_atom_coord (cline, cid[2]);
1052 active_project -> atoms[at_step][i].y = get_atom_coord (cline, cid[3]);
1053 active_project -> atoms[at_step][i].z = get_atom_coord (cline, cid[4]);
1054 }
1055 else
1056 {
1057 for (j=0; j<3; j++) this_reader -> coord[i][j] = get_atom_coord (cline, cid[j+2]);
1058 }
1059 if (! this_reader -> cartesian)
1060 {
1061 this_reader -> wyckoff[i] = (cid[5]) ? get_atom_wyckoff (cline, cid[5]) : 0;
1062 this_reader -> occupancy[i] = (cid[6]) ? get_atom_coord (cline, cid[6]) : 1.0;
1063 this_reader -> multi[i] = (cid[7]) ? get_atom_coord (cline, cid[7]) : 0.0;
1064 this_reader -> disorder[i] = (cid[8]) ? (int) get_atom_coord (cline, cid[8]) : 0;
1065 }
1066 if (cline)
1067 {
1068 g_free (cline);
1069 cline = NULL;
1070 }
1071 if (str)
1072 {
1073 g_free (str);
1074 str = NULL;
1075 }
1076 }
1077#else
1078 file_get_to_line (lin);
1079 for (i=0; i<this_reader -> natomes; i++)
1080 {
1081 cline = g_strdup_printf ("%s", tail -> line);
1082 str = get_atom_label (cline, (cid[0]) ? cid[0] : cid[1]);
1083 v = get_z_from_periodic_table (str);
1084 if (v)
1085 {
1086 check_for_species (v, i);
1087 }
1088 else
1089 {
1090 done = FALSE;
1091 check_for_to_lab (i, str);
1092 }
1093 if (this_reader -> cartesian)
1094 {
1095 active_project -> atoms[at_step][i].x = get_atom_coord (cline, cid[2]);
1096 active_project -> atoms[at_step][i].y = get_atom_coord (cline, cid[3]);
1097 active_project -> atoms[at_step][i].z = get_atom_coord (cline, cid[4]);
1098 }
1099 else
1100 {
1101 for (j=0; j<3; j++) this_reader -> coord[i][j] = get_atom_coord (cline, cid[j+2]);
1102 }
1103 if (! this_reader -> cartesian)
1104 {
1105 this_reader -> wyckoff[i] = (cid[5]) ? get_atom_wyckoff (cline, cid[5]) : 0;
1106 this_reader -> occupancy[i] = (cid[6]) ? get_atom_coord (cline, cid[6]) : 1.0;
1107 this_reader -> multi[i] = (cid[7]) ? get_atom_coord (cline, cid[7]) : 0.0;
1108 this_reader -> disorder[i] = (cid[8]) ? get_atom_coord (cline, cid[8]) : 0;
1109 }
1110/* #ifdef DEBUG
1111 j = this_reader -> wyckoff[i];
1112 g_debug ("CIF:: At= %s, w_letter[%d]= %s, occ= %f, x= %f, y= %f, z= %f", this_reader -> label[i],
1113 j, this_reader -> lattice.sp_group -> wyckoff[j].let, this_reader -> occupancy[i],
1114 this_reader -> coord[i][0], this_reader -> coord[i][1], this_reader -> coord[i][2]);
1115#endif */
1116 tail = tail -> next;
1117 }
1118#endif
1119 if (! done)
1120 {
1121 done = (cif_search) ? TRUE : get_missing_object_from_user ();
1122 }
1123 return done;
1124}
1125
1134gboolean cif_get_atomic_coordinates (int linec, int conf)
1135{
1136 gchar * labkeys[2] = {"type_symbol", "label"};
1137 gchar * symkeys[4] = {"wyckoff_symbol", "occupancy", "symmetry_multiplicity", "disorder_group"};
1138 gchar * str = NULL;
1139 int cid[9];
1140 int loop_line;
1141 int loop_max;
1142 int i, j, k;
1143 int lid, fid;
1144 double u, v;
1145 int * tmp_nsps;
1146 double * tmp_z;
1147 if (cif_multiple)
1148 {
1149 if (this_reader -> cartesian)
1150 {
1151 if (! cif_cnftodo)
1152 {
1153 k = 0;
1154 for (i=0; i<NLKEYS; i++)
1155 {
1156 for (j=0; j<CFKEYS; j++)
1157 {
1158 if (get_loop_line_for_key (linec, conf, linekeys[i], cartkeys[j][0]))
1159 {
1160 lid = i;
1161 fid = j;
1162 k ++;
1163 }
1164 }
1165 }
1166 if (k > 1)
1167 {
1168 // Opening k models for the different sets of atomic coordinates
1169 add_reader_info (_("<b>Atomic coordinates</b>: different sets of coordinate(s) were found.\n"
1170 "<b>atomes</b> will open each set of coordinate(s) in a separate model."), 1);
1171 cif_cnfkeys = allocdint (k, 2);
1172 cif_cnftodo = allocbool (k);
1173 cif_cnfcart = k;
1174 k = 0;
1175 for (i=0; i<NLKEYS; i++)
1176 {
1177 for (j=0; j<CFKEYS; j++)
1178 {
1179 if (get_loop_line_for_key (linec, conf, linekeys[i], cartkeys[j][0]))
1180 {
1181 cif_cnfkeys[k][0] = i;
1182 cif_cnfkeys[k][1] = j;
1183 k ++;
1184 }
1185 }
1186 }
1187 lid = cif_cnfkeys[0][0];
1188 fid = cif_cnfkeys[0][1];
1189 cif_cnftodo[0] = TRUE;
1190 cif_cnfdone = 1;
1191 }
1192 }
1193 else
1194 {
1195 for (i=0; i<cif_cnfcart; i++)
1196 {
1197 if (! cif_cnftodo[i])
1198 {
1199 lid = cif_cnfkeys[i][0];
1200 fid = cif_cnfkeys[i][1];
1201 cif_cnftodo[i] = TRUE;
1202 cif_cnfdone ++;
1203 break;
1204 }
1205 }
1206 }
1207 loop_line = get_loop_line_for_key (linec, conf, linekeys[lid], cartkeys[fid][0]);
1208 }
1209 else
1210 {
1211 for (i=0; i<NLKEYS; i++)
1212 {
1213 for (j=0; j<CFKEYS-1; j++)
1214 {
1215 loop_line = get_loop_line_for_key (linec, conf, linekeys[i], frackeys[j][0]);
1216 if (loop_line)
1217 {
1218 lid = i;
1219 fid = j;
1220 break;
1221 }
1222 }
1223 if (loop_line) break;
1224 }
1225 if (! loop_line) return FALSE;
1226 }
1227 }
1228 else
1229 {
1230 if (this_reader -> cartesian)
1231 {
1232 if (! cif_cnftodo)
1233 {
1234 k = 0;
1235 for (i=0; i<NLKEYS; i++)
1236 {
1237 for (j=0; j<CFKEYS; j++)
1238 {
1239 if (get_loop_line_for_key (linec, conf, linekeys[i], cartkeys[j][0]))
1240 {
1241 lid = i;
1242 fid = j;
1243 k ++;
1244 }
1245 }
1246 }
1247 if (k > 1)
1248 {
1249 // Opening k models for the different sets of atomic coordinates
1250 add_reader_info (_("<b>Atomic coordinates</b>: different sets of coordinate(s) were found.\n"
1251 "<b>atomes</b> will open each set of coordinate(s) in a separate model."), 1);
1252 cif_cnfkeys = allocdint (k, 2);
1253 cif_cnftodo = allocbool (k);
1254 cif_cnfcart = k;
1255 k = 0;
1256 for (i=0; i<NLKEYS; i++)
1257 {
1258 for (j=0; j<CFKEYS; j++)
1259 {
1260 if (get_loop_line_for_key (linec, conf, linekeys[i], cartkeys[j][0]))
1261 {
1262 cif_cnfkeys[k][0] = i;
1263 cif_cnfkeys[k][1] = j;
1264 k ++;
1265 }
1266 }
1267 }
1268 lid = cif_cnfkeys[0][0];
1269 fid = cif_cnfkeys[0][1];
1270 cif_cnftodo[0] = TRUE;
1271 cif_cnfdone = 1;
1272 }
1273 }
1274 else
1275 {
1276 for (i=1; i<cif_cnfcart; i++)
1277 {
1278 if (! cif_cnftodo[i])
1279 {
1280 lid = cif_cnfkeys[i][0];
1281 fid = cif_cnfkeys[i][1];
1282 cif_cnftodo[i] = TRUE;
1283 cif_cnfdone ++;
1284 break;
1285 }
1286 }
1287 }
1288 loop_line = get_loop_line_for_key (linec, conf, linekeys[lid], cartkeys[fid][0]);
1289 }
1290 else
1291 {
1292 for (i=0; i<NLKEYS; i++)
1293 {
1294 for (j=0; j<CFKEYS-1; j++)
1295 {
1296 loop_line = get_loop_line_for_key (linec, 0, linekeys[i], frackeys[j][0]);
1297 if (loop_line)
1298 {
1299 lid = i;
1300 fid = j;
1301 break;
1302 }
1303 }
1304 if (loop_line) break;
1305 }
1306 if (! loop_line) return FALSE;
1307 }
1308 }
1309 loop_max = (loop_line + 1000 > linec) ? linec : loop_line + 1000;
1310 i = 0;
1311 for (j=0; j<2; j++)
1312 {
1313 cid[j] = cif_get_value (linekeys[lid], labkeys[j], loop_line, loop_max, NULL, FALSE, FALSE, FALSE, FALSE, NULL);
1314 if (cid[j])
1315 {
1316 i ++;
1317 cid[j] -= loop_line;
1318 }
1319 }
1320 if (! i)
1321 {
1322 add_reader_info (_("<b>Atomic coordinates</b>: impossible to find atomic label(s) ..."), 0);
1323 return FALSE;
1324 }
1325 for (i=0; i<3; i++)
1326 {
1327 cid[i+2] = cif_get_value (linekeys[lid], (this_reader -> cartesian) ? cartkeys[fid][i] : frackeys[fid][i], loop_line, loop_max, NULL, FALSE, FALSE, FALSE, FALSE, NULL);
1328 if (cid[i+2])
1329 {
1330 cid[i+2] -= loop_line;
1331 }
1332 else
1333 {
1334 str = g_strdup_printf (_("<b>Atomic coordinates</b>: impossible to find '%s' ..."), (this_reader -> cartesian) ? cartkeys[fid][i] : frackeys[fid][i]);
1335 add_reader_info (str, 1);
1336 g_free (str);
1337 this_reader -> cartesian = FALSE;
1338 }
1339 }
1340 if (! this_reader -> cartesian)
1341 {
1342 for (i=0; i<4; i++)
1343 {
1344 cid[i+5] = cif_get_value (linekeys[lid], symkeys[i], loop_line, loop_max, NULL, FALSE, FALSE, FALSE, FALSE, NULL);
1345 if (cid[i+5])
1346 {
1347 cid[i+5] -= loop_line;
1348 if (i == 1 && this_reader -> rounding < 0)
1349 {
1350 this_reader -> rounding = iask (_("Please select how to handle occupancy"), _("Select how to handle occupancy"), 5, atomes_main_window);
1351 if (this_reader -> rounding < 0 || this_reader -> rounding > 2) this_reader -> rounding = 2;
1353 {
1354 str = g_strdup_printf (_("Occupancy %s\n\t%s\n"), cif_occ[this_reader -> rounding], cif_sites[cif_use_symmetry_positions]);
1355 add_reader_info (str, 1);
1356 g_free (str);
1357 }
1358 }
1359 }
1360 }
1361 }
1362 i = cif_file_get_data_in_loop (linec, loop_line);
1363 this_reader -> natomes = cif_file_get_number_of_atoms (linec, loop_line+i, i);
1364 if (! this_reader -> natomes) return FALSE;
1365
1366 if (conf && active_project -> steps > 1 && this_reader -> natomes != cif_atoms)
1367 {
1368 // Not the same number of atoms between each configuration
1369 str = g_strdup_printf (_("<b>Atomic coordinates</b>: the number of atom(s) changes !\n"
1370 " - configuration N°%d\t :: atoms= %d\n"
1371 " - initialization \t\t :: atoms= %d\n"), conf, this_reader -> natomes, cif_atoms);
1372 add_reader_info (str, 0);
1373 g_free (str);
1374 return FALSE;
1375 }
1376 if (this_reader -> cartesian)
1377 {
1378 if (! conf)
1379 {
1380 active_project -> natomes = this_reader -> natomes;
1382 }
1383 }
1384 else
1385 {
1386 this_reader -> coord = allocddouble (this_reader -> natomes*this_reader -> steps, 3);
1387 }
1388
1389 if (! this_reader -> cartesian)
1390 {
1391 this_reader -> lot = allocint (this_reader -> natomes);
1392 this_reader -> wyckoff = allocint (this_reader -> natomes);
1393 this_reader -> occupancy = allocdouble (this_reader -> natomes);
1394 this_reader -> multi = allocint (this_reader -> natomes);
1395 this_reader -> disorder = allocint (this_reader -> natomes);
1396 }
1397 this_reader -> z = allocdouble (1);
1398 this_reader -> nsps = allocint (1);
1399
1400 if (! cif_file_get_atoms_data (conf, loop_line+i, cid)) return FALSE;
1401 if (active_project -> steps > 1)
1402 {
1403 tmp_nsps = duplicate_int (this_reader -> nspec, this_reader -> nsps);
1404 tmp_z = duplicate_double (this_reader -> nspec, this_reader -> z);
1405 for (i=1; i<this_reader -> nspec; i++)
1406 {
1407 v = tmp_z[i];
1408 j = tmp_nsps[i];
1409 for (k=i-1; k>-1; k--)
1410 {
1411 if (tmp_z[k] <= v) break;
1412 tmp_z[k+1] = tmp_z[k];
1413 tmp_nsps[k+1] = tmp_nsps[k];
1414 }
1415 tmp_z[k+1] = v;
1416 tmp_nsps[k+1] = j;
1417 }
1418 g_free (tmp_z);
1419 if (! conf)
1420 {
1421 cif_atoms = this_reader -> natomes;
1422 cif_nspec = this_reader -> nspec;
1423 cif_nsps = duplicate_int (this_reader -> nspec, tmp_nsps);
1424 }
1425 }
1426 if (conf && active_project -> steps > 1)
1427 {
1428 if (this_reader -> nspec != cif_nspec)
1429 {
1430 // Not the same number of chemical species between each configuration
1431 str = g_strdup_printf (_("<b>Atomic coordinates</b>: the number of chemical species changes !\n"
1432 " - configuration N°%d\t :: species= %d\n"
1433 " - initialization \t\t :: species= %d\n"), conf, this_reader -> nspec, cif_nspec);
1434 add_reader_info (str, 0);
1435 g_free (str);
1436 return FALSE;
1437 }
1438 for (i=0; i<this_reader -> nspec; i++)
1439 {
1440 if (tmp_nsps[i] != cif_nsps[i])
1441 {
1442 // Not the same number of atom(s) by chemical species between each configuration
1443 str = g_strdup_printf (_("<b>Atomic coordinates</b>: the number of atom(s) for species %d changes !\n"
1444 " - configuration N°%d\t :: atom(s)= %d\n"
1445 " - initialization \t\t :: atom(s)= %d\n"), conf, i+1, this_reader -> nsps[i], cif_nsps[i]);
1446 add_reader_info (str, 0);
1447 g_free (str);
1448 return FALSE;
1449 }
1450 }
1451 g_free (tmp_nsps);
1452 }
1453 if (! this_reader -> cartesian && cif_use_symmetry_positions)
1454 {
1455 // Testing site multiplicity, to ensure that occupancy is not > 1.0
1456 for (i=0; i<this_reader -> natomes; i++)
1457 {
1458 v = this_reader -> occupancy[i];
1459 for (j=0; j<this_reader -> natomes; j++)
1460 {
1461 if (j != i)
1462 {
1463 if (this_reader -> coord[i][0] == this_reader -> coord[j][0]
1464 && this_reader -> coord[i][1] == this_reader -> coord[j][1]
1465 && this_reader -> coord[i][2] == this_reader -> coord[j][2])
1466 {
1467 v += this_reader -> occupancy[j];
1468 if (v > 1.00001)
1469 {
1470 add_reader_info (_("<b>Atomic coordinates</b>: a site has an occupancy > 1.0 !\n"), 0);
1471 return FALSE;
1472 }
1473 }
1474 }
1475 }
1476 }
1477 }
1478 if (! this_reader -> cartesian && this_reader -> chemical)
1479 {
1480 // Testing the different number of occupancies
1481 double * test_occ = allocdouble (1);
1482 int * num_occ = allocint (1);
1483 int * test_order = allocint (1);
1484 int * num_order = allocint (1);
1485 gboolean new_occ, new_order;
1486 int occupancies = 1;
1487 int disorders = 1;
1488 u = v = test_occ[0] = this_reader -> occupancy[0];
1489 test_order[0] = this_reader -> disorder[0];
1490 num_occ[0] = num_order[0] = 1;
1491 for (i=1; i<this_reader -> natomes; i++)
1492 {
1493 new_occ = new_order = TRUE;
1494 for (j=0; j<occupancies; j++)
1495 {
1496 if (test_occ[j] == this_reader -> occupancy[i])
1497 {
1498 num_occ[j] ++;
1499 new_occ = FALSE;
1500 break;
1501 }
1502 }
1503 if (new_occ)
1504 {
1505 test_occ = g_realloc (test_occ, (occupancies+1)*sizeof*test_occ);
1506 test_occ[occupancies] = this_reader -> occupancy[i];
1507 u = min (u, test_occ[occupancies]);
1508 v = max (v, test_occ[occupancies]);
1509 num_occ = g_realloc (num_occ, (occupancies+1)*sizeof*num_occ);
1510 num_occ[occupancies] = 1;
1511 occupancies ++;
1512 }
1513 for (j=0; j<disorders; j++)
1514 {
1515 if (test_order[j] == this_reader -> disorder[i])
1516 {
1517 num_order[j] ++;
1518 new_order = FALSE;
1519 break;
1520 }
1521 }
1522 if (new_order)
1523 {
1524 test_order = g_realloc (test_order, (disorders+1)*sizeof*test_order);
1525 test_order[disorders] = this_reader -> disorder[i];
1526 num_order = g_realloc (num_order, (disorders+1)*sizeof*num_order);
1527 num_order[disorders] = 1;
1528 disorders ++;
1529 }
1530 }
1531 if (this_reader -> natomes%occupancies == 0 || this_reader -> natomes%disorders == 0)
1532 {
1533 // Atoms can be separated based on site occupancy or site disorder
1534 // We can consider this as a chemical reaction or trajectory
1535 // As many lattices near by as occupancies or disorders
1536 new_occ = TRUE;
1537 for (i=0; i<occupancies; i++)
1538 {
1539 if (num_occ[i] != this_reader -> natomes/occupancies)
1540 {
1541 new_occ = FALSE;
1542 break;
1543 }
1544 }
1545 // if (new_occ) add_reader_info (_("CIF file is compatible with a chemical reaction: \n\t Reactants can be separated using occupancy\n"), 1);
1546 // g_debug ("min= %f, max= %f, max/min= %f", u, v, v/u);
1547 new_order = TRUE;
1548 for (i=0; i<disorders; i++)
1549 {
1550 if (num_order[i] != this_reader -> natomes/disorders)
1551 {
1552 new_order = FALSE;
1553 break;
1554 }
1555 }
1556 // if (new_order) add_reader_info (_("CIF file is compatible with a chemical reaction: \n\t Reactants can be separated using disorder site\n"), 1);
1557 }
1558 }
1559 return TRUE;
1560}
1561
1570{
1571 gboolean res = FALSE;
1572 gchar * saved_line;
1573 gchar * the_line;
1574 gchar * the_word;
1575 int i = 0;
1576 while (! res)
1577 {
1578#ifdef OPENMP
1579 the_line = g_strdup_printf ("%s", coord_line[lid+i]);
1580#else
1581 file_get_to_line (lid+i);
1582 the_line = g_strdup_printf ("%s", tail -> line);
1583#endif
1584 the_word = strtok_r (the_line, " ", & saved_line);
1585 if (the_word[0] == '_' || g_strcmp0(the_word, "loop_") == 0)
1586 {
1587 res = TRUE;
1588 break;
1589 }
1590 else
1591 {
1592 i ++;
1593 }
1594 }
1595 if (i)
1596 {
1597 this_reader -> sym_pos = g_malloc0(i*sizeof*this_reader -> sym_pos);
1598 int j, k;
1599 gchar * str;
1600 gchar * k_word;
1601 gchar * sym_pos_line;
1602 for (j=0; j<i; j++)
1603 {
1604 this_reader -> sym_pos[j] = g_malloc0(3*sizeof*this_reader -> sym_pos[j]);
1605#ifdef OPENMP
1606 sym_pos_line = g_strdup_printf ("%s", coord_line[lid+j]);
1607#else
1608 file_get_to_line (lid+j);
1609 sym_pos_line = g_strdup_printf ("%s", tail -> line);
1610#endif
1611 the_line = g_strdup_printf ("%s", sym_pos_line);
1612 the_word = strtok_r (the_line, " ", & saved_line);
1613 k_word = g_strdup_printf ("%s", the_word);
1614 str = g_strdup_printf ("%d", j+1);
1615 if (g_strcmp0(k_word, str) == 0)
1616 {
1617 g_free (the_line);
1618 the_line = NULL;
1619 for (k=strlen(k_word); k<strlen(sym_pos_line); k++)
1620 {
1621 if (! this_line)
1622 {
1623 the_line = g_strdup_printf ("%c", sym_pos_line[k]);
1624 }
1625 else
1626 {
1627 the_line = g_strdup_printf ("%s%c", the_line, sym_pos_line[k]);
1628 }
1629 }
1630 }
1631 else
1632 {
1633 the_line = g_strdup_printf ("%s", sym_pos_line);
1634 }
1635 g_free (k_word);
1636 g_free (str);
1637 g_free (sym_pos_line);
1638 the_line = substitute_string (the_line, " ", NULL);
1639 the_line = substitute_string (the_line, "'", NULL);
1640 the_line = substitute_string (the_line, ",", " ");
1641 the_word = strtok_r (the_line, " ", & saved_line);
1642 for (k=0; k<3; k++)
1643 {
1644 this_reader -> sym_pos[j][k] = g_strdup_printf ("%s", the_word);
1645 the_word = strtok_r (NULL, " ", & saved_line);
1646 }
1647#ifdef DEBUG
1648 g_debug ("SYM_POS:: pos= %d, x= %s, y= %s, z= %s", j+1, this_reader -> sym_pos[j][0], this_reader -> sym_pos[j][1], this_reader -> sym_pos[j][2]);
1649#endif // DEBUG
1650 }
1651 }
1652 return i;
1653}
1654
1663gboolean cif_get_symmetry_positions (int linec, int conf)
1664{
1665 gchar * pos_key[2]={"_symmetry_equiv_pos_as", "_space_group_symop_operation"};
1666 int loop_line;
1667 int line_id;
1668 int i;
1669 for (i=0; i<2; i++)
1670 {
1671 loop_line = get_loop_line_for_key (linec, conf, pos_key[i], "xyz");
1672 if (loop_line)
1673 {
1674 line_id = cif_get_value (pos_key[i], "xyz", loop_line, linec, NULL, FALSE, FALSE, FALSE, FALSE, NULL);
1675 break;
1676 }
1677 }
1678 if (! loop_line) return FALSE;
1679 // Read lines after the instruction, as many positions as line until _ or loop
1680 this_reader -> num_sym_pos = cif_file_get_number_of_positions (line_id);
1681 return TRUE;
1682}
1683
1692{
1693 int i;
1694 gchar * str;
1695 gchar * hm = replace_markup (hmk, "S", NULL);
1696 for (i=0; i<230; i++)
1697 {
1698 str = substitute_string (hmsymbols[i], " ", NULL);
1699 if (g_strcmp0(str, hm) == 0)
1700 {
1701 g_free (str);
1702 g_free (hm);
1703 return i+1;
1704 }
1705 g_free (str);
1706 str = substitute_string (groups[i], "<sub>", NULL);
1707 str = substitute_string (str, "</sub>", NULL);
1708 if (g_strcmp0(str, hm) == 0)
1709 {
1710 g_free (str);
1711 g_free (hm);
1712 return i+1;
1713 }
1714 g_free (str);
1715 }
1716 // Cross checking for erroneus writting in the CIF file
1717 // ie. Fm3m in place of Fm-3m
1718 for (i=0; i<230; i++)
1719 {
1720 str = substitute_string (groups[i], "<sub>", NULL);
1721 str = substitute_string (str, "</sub>", NULL);
1722 if (g_strrstr(str, "-"))
1723 {
1724 str = substitute_string (str, "-", NULL);
1725 if (g_strcmp0(str, hm) == 0)
1726 {
1727 g_free (str);
1728 g_free (hm);
1729 return i+1;
1730 }
1731 }
1732 g_free (str);
1733 }
1734 g_free (hm);
1735 return 0;
1736}
1737
1746{
1747 gchar * str = NULL;
1748 if (wnpos[1])
1749 {
1750 g_free (wnpos[1]);
1751 wnpos[1] = NULL;
1752 }
1753
1754 get_wyck_char (spg -> coord_origin.m01, 1, 0);
1755 get_wyck_char (spg -> coord_origin.m11, 1, 1);
1756 get_wyck_char (spg -> coord_origin.m21, 1, 2);
1757
1758 if (wnpos[1])
1759 {
1760 str = g_strdup_printf ("%s", wnpos[1]);
1761 g_free (wnpos[1]);
1762 wnpos[1] = NULL;
1763 }
1764 return str;
1765}
1766
1775int get_setting_from_hm (gchar * hmk, int end)
1776{
1777 int i, j;
1778 gchar * str;
1779 if (this_reader -> lattice.sp_group)
1780 {
1781 i = this_reader -> lattice.sp_group -> nums;
1782 for (j=0; j<i; j++)
1783 {
1784 str = replace_markup (this_reader -> lattice.sp_group -> settings[j].name, "s", "/");
1785 str = substitute_string (str, "_", NULL);
1786 if (end < 0)
1787 {
1788 if (g_strcmp0(str, hmk) == 0)
1789 {
1790 g_free (str);
1791 return j;
1792 }
1793 }
1794 else
1795 {
1796 if (g_strcmp0(str, hmk) == 0 && this_reader -> lattice.sp_group -> settings[j].origin == end+1)
1797 {
1798 g_free (str);
1799 return j;
1800 }
1801 }
1802 g_free (str);
1803 }
1804 if (this_reader -> lattice.sp_group -> id > 2 && this_reader -> lattice.sp_group -> id < 16)
1805 {
1806 // This is a way around the way this familly of SG is often written,
1807 // using incomplete or inexact hmk keyword, ex: P21/a instead of P121/a1
1808 for (j=0; j<i; j++)
1809 {
1810 str = replace_markup (this_reader -> lattice.sp_group -> settings[j].name, "s", "/");
1811 str = substitute_string (str, "_", NULL);
1812 str = substitute_string (str, "12", "2");
1813 str = substitute_string (str, "/a1", "/a");
1814 str = substitute_string (str, "/b1", "/b");
1815 str = substitute_string (str, "/c1", "/c");
1816 str = substitute_string (str, "/m1", "/m");
1817 str = substitute_string (str, "/n1", "/n");
1818 if (end < 0)
1819 {
1820 if (g_strcmp0(str, hmk) == 0)
1821 {
1822 g_free (str);
1823 str = g_strdup_printf (_("<b>Space group</b>: CIF file information could be inaccurate !\n"
1824 " CIF file space group: <b>%s</b>, CIF file H-M symbol: <b>%s</b>\n"),
1825 groups[this_reader -> lattice.sp_group -> id-1], hmk);
1826 add_reader_info (str, 1);
1827 g_free (str);
1828 return j;
1829 }
1830 }
1831 else
1832 {
1833 if (g_strcmp0(str, hmk) == 0 && this_reader -> lattice.sp_group -> settings[j].origin == end+1)
1834 {
1835 g_free (str);
1836 str = g_strdup_printf (_("<b>Space group</b>: CIF file information could be inaccurate !\n"
1837 " CIF file space group: <b>%s</b>, CIF file H-M symbol: <b>%s</b>\n"),
1838 groups[this_reader -> lattice.sp_group -> id-1], hmk);
1839 add_reader_info (str, 1);
1840 g_free (str);
1841 return j;
1842 }
1843 }
1844 g_free (str);
1845 }
1846 }
1847 return -1;
1848 }
1849 else
1850 {
1851 return -1;
1852 }
1853}
1854
1863int group_info_from_hm_key (int spg, gchar * key_hm)
1864{
1865 int i, j;
1866 gchar * str;
1867 gchar * exts[2] = {"h", "r"};
1868 gchar * orig[2] = {"1", "2"};
1869 gchar * key = NULL;
1870 gchar * hmk = NULL;
1871 gchar * hma, * hmb;
1872 gchar * hmkey = substitute_string (key_hm, "'", NULL);
1873 //hmkey = substitute_string (hmkey, "/", "s");
1874 this_reader -> setting = -1;
1875 if (strstr(hmkey,":"))
1876 {
1877 key = g_strdup_printf ("%s", hmkey);
1878 hmk = g_strdup_printf ("%s", strtok (key, ":"));
1879 hma = g_strdup_printf ("%s:", hmk);
1880 hmb = replace_markup (hmkey, hma, NULL);
1881 i = strlen(hmb);
1882 hmb = g_ascii_strdown (hmb, i);
1883 for (i=0; i<2; i++)
1884 {
1885 if (g_strcmp0(hmb, exts[i]) == 0)
1886 {
1887 this_reader -> setting = i;
1888 break;
1889 }
1890 }
1891 g_free (hma);
1892 g_free (key);
1893 if (this_reader -> setting < 0)
1894 {
1895 for (i=0; i<2; i++)
1896 {
1897 if (g_strcmp0(hmb, orig[i]) == 0)
1898 {
1899 j = get_space_group_from_hm (hmk);
1900 this_reader -> setting = (spg) ? get_setting_from_hm (hmk, i) : 0;
1901 if (! j && this_reader -> setting < 0)
1902 {
1903 this_reader -> setting = 0;
1904 str = g_strdup_printf (_("<b>Space group</b>: CIF file information could be inaccurate !\n"
1905 " CIF file space group: <b>%s</b>, CIF file H-M symbol: <b>%s</b>\n"),
1906 groups[this_reader -> lattice.sp_group -> id-1], key_hm);
1907 add_reader_info (str, 1);
1908 g_free (str);
1909 }
1910 if (this_reader -> setting < 0) this_reader -> setting = 0;
1911 g_free (hmk);
1912 g_free (hmb);
1913 return j;
1914 }
1915 }
1916 }
1917 g_free (hmb);
1918 }
1919 else
1920 {
1921 hmk = g_strdup_printf ("%s", hmkey);
1922 }
1923 j = get_space_group_from_hm (hmk);
1924 this_reader -> setting = (spg || j) ? get_setting_from_hm (hmk, -1) : 0;
1925 g_free (hmk);
1926 if (! j && this_reader -> setting < 0)
1927 {
1928 str = g_strdup_printf (_("<b>Space group</b>: CIF file information could be inaccurate !\n"
1929 " CIF file space group: <b>%s</b>, CIF file H-M symbol: <b>%s</b>\n"),
1930 groups[this_reader -> lattice.sp_group -> id-1], key_hm);
1931 add_reader_info (str, 1);
1932 g_free (str);
1933 }
1934 if (this_reader -> setting < 0) this_reader -> setting = 0;
1935 return (spg) ? (j) ? j : spg : j;
1936}
1937
1946gboolean cif_get_cell_data (int linec, int conf)
1947{
1948 gchar * cellkeys[3] = {"length_a", "length_b", "length_c"};
1949 gchar * cellangs[3] = {"angle_alpha", "angle_beta", "angle_gamma",};
1950 int i, j;
1951 gchar * str = NULL;
1952 if (! conf || (conf && active_project -> steps == 1))
1953 {
1954 this_reader -> lattice.box = g_malloc0(active_project -> steps*sizeof*this_reader -> lattice.box);
1955 }
1956 i = (conf && active_project -> steps == 1) ? 0 : conf;
1957 for (j=0; j<3; j++)
1958 {
1959 str = cif_retrieve_value (linec, conf, "_cell", cellkeys[j], TRUE, TRUE, TRUE);
1960 if (! str)
1961 {
1962 str = g_strdup_printf (_("<b>Lattice parameters</b>: impossible to retrieve the '%s' parameter !\n"), box_prop[0][j]);
1963 add_reader_info (str, 0);
1964 g_free (str);
1965 return FALSE;
1966 }
1967 this_reader -> lattice.box[i].param[0][j] = string_to_double ((gpointer)str);
1968 if (i)
1969 {
1970 if (this_reader -> lattice.box[i].param[0][j] != this_reader -> lattice.box[i-1].param[0][j]) active_cell -> npt = TRUE;
1971 }
1972#ifdef DEBUG
1973 g_debug ("CIF:: box[%d][%d]= %f", i, j, this_reader -> lattice.box[i].param[0][j]);
1974#endif
1975 g_free (str);
1976 str = cif_retrieve_value (linec, conf, "_cell", cellangs[j], TRUE, TRUE, TRUE);
1977 if (! str)
1978 {
1979 str = g_strdup_printf (_("<b>Lattice parameters</b>: impossible to retrieve the '%s' parameter !\n"), box_prop[1][j]);
1980 add_reader_info (str, 0);
1981 g_free (str);
1982 return FALSE;
1983 }
1984 this_reader -> lattice.box[i].param[1][j] = string_to_double ((gpointer)str);
1985 g_free (str);
1986 if (i)
1987 {
1988 if (this_reader -> lattice.box[i].param[1][j] != this_reader -> lattice.box[i-1].param[1][j]) active_cell -> npt = TRUE;
1989 }
1990#ifdef DEBUG
1991 g_debug ("CIF:: angle[%d][%d]= %f", i, j, this_reader -> lattice.box[i].param[1][j]);
1992#endif
1993 }
1994 this_reader -> lattice.ltype = 0;
1996 for (i=0; i<3; i++) this_reader -> lattice.cextra[i] = 1;
1997 return TRUE;
1998}
1999
2008int cif_get_space_group (int linec, int conf)
2009{
2010 gchar * symkey[2] = {"int_tables_number", "group_it_number"};
2011 gchar * str = NULL;
2012 int spg = 0;
2013 int i, j, k, l;
2014
2015 for (i=0; i<2; i++)
2016 {
2017 str = cif_retrieve_value (linec, conf, "_symmetry", symkey[i], TRUE, FALSE, FALSE);
2018 if (str)
2019 {
2020 spg = (int)string_to_double ((gpointer)str);
2021 break;
2022 }
2023 }
2024 if (! spg)
2025 {
2026 str = cif_retrieve_value (linec, conf, "_space_group", "it_number", TRUE, FALSE, FALSE);
2027 if (str)
2028 {
2029 spg = (int)string_to_double ((gpointer)str);
2030 }
2031 }
2032 gchar * hmkey = NULL;
2033
2034 hmkey = cif_retrieve_value (linec, conf, "_symmetry", "space_group_name_h-m", TRUE, FALSE, FALSE);
2035 if (! hmkey)
2036 {
2037 hmkey = cif_retrieve_value (linec, conf, "_symmetry", "name_h-m_alt", TRUE, FALSE, FALSE);
2038 }
2039 if (! hmkey && ! spg)
2040 {
2041 add_reader_info (_("<b>Space group</b>: no space group and no H-M symbol found !\n"), 1);
2042 return FALSE;
2043 }
2044#ifdef DEBUG
2045 if (spg) g_debug ("CIF:: Space group:: N°= %d, name= %s", spg, groups[spg-1]);
2046 if (hmkey) g_debug ("CIF:: H-M symbol:: %s", hmkey);
2047#endif
2048 if (spg)
2049 {
2050 if (! read_space_group (NULL, spg-1)) return FALSE;
2051 }
2052 if (hmkey)
2053 {
2054 i = group_info_from_hm_key (spg, hmkey);
2055 if (! spg && ! i)
2056 {
2057 add_reader_info (_("<b>Space group</b>: no space group found, unknown H-M symbol !\n"), 1);
2058#ifdef DEBUG
2059 g_debug ("CIF:: No space group found, unknown H-M symbol !");
2060#endif
2061 }
2062 else if (spg && ! i)
2063 {
2064 str = g_strdup_printf (_("<b>Space group</b>: space group and H-M symbol do not match !\n"
2065 " CIF file space group: <b>%s</b>, CIF file H-M symbol: <b>%s</b>\n"), groups[spg-1], hmkey);
2066 add_reader_info (str, 1);
2067 g_free (str);
2068#ifdef DEBUG
2069 g_debug ("CIF:: Space group and H-M symbol do not match:: spg= %d, hm= %d", spg, i);
2070#endif
2071 }
2072 else if (i && ! spg)
2073 {
2074 spg = i;
2075 }
2076 if (! this_reader -> lattice.sp_group)
2077 {
2078 if (! read_space_group (NULL, spg-1)) return FALSE;
2079 }
2080 }
2081 gchar * lat;
2082 int res = spg;
2083 if (spg > 1)
2084 {
2085 str = cif_retrieve_value (linec, conf, "_space_group", "it_coordinate_system_code", TRUE, FALSE, FALSE);
2086 if (str)
2087 {
2088 str = substitute_string (str, "'", NULL);
2089 for (i=0; i<40; i++)
2090 {
2091 if (g_strcmp0(str, cif_coord_opts[i][0]) == 0)
2092 {
2093 if (i < 18)
2094 {
2095 if (spg < 3 || spg > 15)
2096 {
2097 res = 0;
2098 break;
2099 }
2100 if (str[0] == '-')
2101 {
2102 k = (int) string_to_double ((gpointer)g_strdup_printf ("%c", str[2]));
2103 str = g_strdup_printf ("%c%c", str[0], str[1]);
2104 }
2105 else
2106 {
2107 k = (int) string_to_double ((gpointer)g_strdup_printf ("%c", str[1]));
2108 str = g_strdup_printf ("%c", str[0]);
2109 }
2110 l = 0;
2111 for (j=0; j< this_reader -> lattice.sp_group -> nums; j++)
2112 {
2113 this_reader -> lattice.sp_group -> sid = j;
2114 get_origin (this_reader -> lattice.sp_group);
2115 lat = get_string_from_origin (this_reader -> lattice.sp_group);
2116 if (g_strcmp0(lat, str) == 0) l ++;
2117 if (l == k)
2118 {
2119 if (j < this_reader -> setting) add_reader_info (_("<b>Space group</b>: ambiguous space group setting !\n"), 1);
2120 this_reader -> setting = j;
2121 break;
2122 }
2123 }
2124 }
2125 else if (i < 36)
2126 {
2127 if (spg < 16 || spg > 74)
2128 {
2129 res = 0;
2130 break;
2131 }
2132 k = 0;
2133 if (str[0] == '1' || str[0]=='2')
2134 {
2135 k = (int) string_to_double ((gpointer)g_strdup_printf ("%c", str[0]));
2136 str = replace_markup (str, g_strdup_printf("%d", k), NULL);
2137 }
2138 l = 0;
2139 for (j=0; j< this_reader -> lattice.sp_group -> nums; j++)
2140 {
2141 lat = g_strdup_printf ("%s%s%s",
2142 this_reader -> lattice.sp_group -> settings[j].pos[0],
2143 this_reader -> lattice.sp_group -> settings[j].pos[1],
2144 this_reader -> lattice.sp_group -> settings[j].pos[2]);
2145 if (g_strcmp0(lat, str) == 0)
2146 {
2147 if (j < this_reader -> setting || this_reader -> lattice.sp_group -> settings[j].origin != k)
2148 {
2149 add_reader_info (_("<b>Space group</b>: ambiguous space group setting !\n"), 1);
2150 }
2151 this_reader -> setting = j;
2152 l = 1;
2153 break;
2154 }
2155 }
2156 if (! l) add_reader_info (_("<b>Space group</b>: ambiguous space group setting !\n"), 1);
2157 }
2158 else if (i < 38)
2159 {
2160 if (spg < 75 || (spg > 142 && spg < 195))
2161 {
2162 res = 0;
2163 break;
2164 }
2165 j = i - 36;
2166 if (j < this_reader -> setting) add_reader_info (_("<b>Space group</b>: ambiguous space group setting !\n"), 1);
2167 this_reader -> setting = j;
2168 }
2169 else
2170 {
2171 if (spg < 143 || spg > 165)
2172 {
2173 res = 0;
2174 break;
2175 }
2176 j = i - 38;
2177 if (j < this_reader -> setting) add_reader_info (_("<b>Space group</b>: ambiguous space group setting !\n"), 1);
2178 this_reader -> setting = j;
2179 }
2180 }
2181 }
2182 g_free (str);
2183 }
2184
2185 if (spg > 142 && spg < 168)
2186 {
2187 // Trigonal space group
2188 gboolean correct_this = FALSE;
2189 box_info * box = (conf && active_project -> steps == 1) ? & this_reader -> lattice.box[0] : & this_reader -> lattice.box[conf];
2190 switch (this_reader -> setting)
2191 {
2192 case 0:
2193 if (box -> param[0][0] == box -> param[0][1] && box -> param[0][0] == box -> param[0][2])
2194 {
2195 if (box -> param[1][0] == box -> param[1][1] && box -> param[1][0] == box -> param[1][2])
2196 {
2197 correct_this = TRUE;
2198 }
2199 }
2200 break;
2201 case 1:
2202 if (box -> param[0][0] == box -> param[0][1] && box -> param[0][0] != box -> param[0][2])
2203 {
2204 if (box -> param[1][0] == box -> param[1][1] && box -> param[1][0] == 90.0 && box -> param[1][2] == 120.0)
2205 {
2206 correct_this = TRUE;
2207 }
2208 }
2209 break;
2210 }
2211 if (correct_this)
2212 {
2213 gchar * setc[2] = {i18n("hexagonal"), i18n("rhombohedral")};
2214 str = g_strdup_printf (_("<b>Space group</b>: found trigonal space group N°%d-%s, <b>%s</b> setting\n"
2215 "but the lattice parameters were found in <b>%s</b> format ...\n"
2216 "\t ... the space group setting was modified accordingly !\n"),
2217 spg, groups[spg-1], _(setc[this_reader -> setting]), _(setc[! this_reader -> setting]));
2218 add_reader_info (str, 1);
2219 g_free (str);
2220 this_reader -> setting = ! this_reader -> setting;
2221 }
2222 }
2223
2224 // Test space group vs. box parameters:
2225 this_reader -> lattice.sp_group -> sid = this_reader -> setting;
2226 if (! test_lattice (NULL, & this_reader -> lattice))
2227 {
2228 str = g_strdup_printf (_("<b>Space group</b> and <b>lattice parameters</b> are not compatible !\n"
2229 "\nCheck a, b, c, and &#x3B1;, &#x3B2;, &#x263;, with the type of crystal system.\n"));
2230 add_reader_info (str, 0);
2231 g_free (str);
2232 res = -1;
2233 }
2234 }
2235 this_reader -> lattice.sp_group -> sid = this_reader -> setting;
2236 get_origin (this_reader -> lattice.sp_group);
2237 return res;
2238}
2239
2248int open_cif_configuration (int linec, int conf)
2249{
2250 int res;
2251 int i, j, k, l, m, n;
2252 int cid;
2253
2254 if (! this_reader -> cartesian && ! conf)
2255 {
2256 for (i=0; i<2; i++)
2257 {
2258 for (j=0; j<2; j++)
2259 {
2260 k = cif_get_value (linekeys[i], cartkeys[j][0], 0, linec, NULL, FALSE, FALSE, TRUE, FALSE, NULL);
2261 if (k)
2262 {
2263 this_reader -> cartesian = TRUE;
2264 break;
2265 }
2266 }
2267 if (this_reader -> cartesian) break;
2268 }
2269 }
2270
2271 if (! this_reader -> cartesian)
2272 {
2273 if (cif_get_cell_data (linec, conf))
2274 {
2275 i = cif_get_space_group (linec, conf);
2276 if (conf && active_project -> steps > 1 && i != saved_group)
2277 {
2278#ifdef DEBUG
2279 g_debug ("CIF:: SP group changes between configuration:: conf= %d, saved_group= %d, new_group= %d", conf, saved_group, i);
2280#endif
2281 add_reader_info (_("Space group changes between configurations !\n"), 0);
2282 return 3;
2283 }
2284 else if (i > 0)
2285 {
2286 saved_group = i;
2287#ifdef DEBUG
2288 g_debug ("CIF:: SP setting:: %d, name= %s", this_reader -> setting+1, this_reader -> lattice.sp_group -> settings[this_reader -> setting].name);
2289#endif
2290 if (this_reader -> lattice.sp_group) get_origin (this_reader -> lattice.sp_group);
2291 }
2292 else if (i == 0)
2293 {
2294 // No space group found
2295#ifdef DEBUG
2296 g_debug ("CIF:: Impossible to retrieve space group information !");
2297#endif
2298 }
2299 else if (cif_multiple && ! this_reader -> cartesian)
2300 {
2301 // Error in space group
2302 return 3;
2303 }
2304 }
2305 else
2306 {
2307 // Coordinates are fractional and no cell data is provided
2308 return 3;
2309 }
2310 }
2311 else
2312 {
2313 // No symmetry data for Cartesian CIF file
2315 }
2316 // Reading positions
2317 if (cif_get_symmetry_positions (linec, conf))
2318 {
2319 if (! cif_use_symmetry_positions && this_reader -> num_sym_pos)
2320 {
2321 add_reader_info (_("Symmetry position(s) in CIF file\n"), 1);
2322 }
2323 }
2324 if (cif_use_symmetry_positions && ! this_reader -> num_sym_pos)
2325 {
2326 add_reader_info (_("No symmetry position(s) in CIF file\n"), 0);
2327 return 3;
2328 }
2329 if (cif_get_atomic_coordinates (linec, conf))
2330 {
2331 cid = (conf && active_project -> steps == 1) ? 0 : conf;
2332 if (! this_reader -> cartesian)
2333 {
2334 for (i=0; i<3; i++)
2335 {
2336 for (j=0; j<3; j++)
2337 {
2338 if (i < 2)
2339 {
2340 active_cell -> box[cid].param[i][j] = this_reader -> lattice.box[cid].param[i][j];
2341 }
2342 active_cell -> box[cid].vect[i][j] = this_reader -> lattice.box[cid].vect[i][j];
2343 }
2344 }
2345 active_cell -> ltype = 1;
2346 active_cell -> pbc = TRUE;
2347 active_cell -> has_a_box = TRUE;
2348 if (this_reader -> lattice.sp_group)
2349 {
2350 active_cell -> crystal = TRUE;
2351 active_cell -> sp_group = duplicate_space_group (this_reader -> lattice.sp_group);
2352 }
2353 }
2354 res = 0;
2356 {
2357 gchar * str = g_strdup_printf (_("<b>Building crystal using symmetry positions: </b> \n"
2358 " 1) evaluate candidate atomic positions using data in CIF file: \n"
2359 " - symmetry positions\n"
2360 " - atomic coordinates + occupancy\n"
2361 " 2) fill each candidate position using the associated occupancy: \n"
2362 " - occupancy %s\n"
2363 " - %s\n"), cif_occ[this_reader -> rounding], cif_sites[1]);
2364 add_reader_info (str, 1);
2365 g_free (str);
2366 this_reader -> cartesian = TRUE;
2368 double spgpos[3][4];
2369 int max_pos = this_reader -> num_sym_pos * this_reader -> natomes;
2370 gboolean dist_message = FALSE;
2371 gboolean low_occ = FALSE;
2372 gboolean save_it;
2373 vec3_t f_pos, c_pos;
2374 gboolean * save_pos = allocbool (max_pos);
2375 mat4_t pos_mat;
2376 atom at, bt;
2377 distance dist;
2378 double u;
2379 vec3_t * all_pos = g_malloc0(max_pos*sizeof*all_pos);
2380 int * all_origin = allocint (max_pos);
2381 int * cif_pos = allocint (this_reader -> natomes);
2382 double ** cryst_pos = allocddouble (this_reader -> natomes, 3);
2383 double ** occ_pos = g_malloc0(sizeof*occ_pos);
2384 int ** lot_pos = g_malloc0(sizeof*lot_pos);
2385
2386 double * list_occ = allocdouble (this_reader -> natomes);
2387 double val;
2388 int vbl;
2389 int * list_pos = allocint (this_reader -> natomes);
2390 for (i=0; i<this_reader -> natomes; i++)
2391 {
2392 list_pos[i] = i;
2393 list_occ[i] = this_reader -> occupancy[i];
2394 }
2395 for (i=1; i<this_reader -> natomes; i++)
2396 {
2397 val = list_occ[i];
2398 vbl = list_pos[i];
2399 for (j=i-1; j>-1; j--)
2400 {
2401 if (list_occ[j] >= val) break;
2402 list_occ[j+1] = list_occ[j];
2403 list_pos[j+1] = list_pos[j];
2404 }
2405 list_occ[j+1] = val;
2406 list_pos[j+1] = vbl;
2407 }
2408 int num_pos = 0;
2409 int pos_max = 0;
2410 // The following might be modified for reaction CIF:
2411 // - this_reader -> coord[i] and this_readaer -> coord[j] are not necessarily equal
2412 // - both the disorder group and the occupancy matters in place of the coordinates
2413 for (i=0; i<2; i++)
2414 {
2415 for (j=0; j<this_reader -> natomes; j++)
2416 {
2417 k = list_pos[j];
2418 if (! j)
2419 {
2420 num_pos = 0;
2421 for (l=0; l<3; l++) cryst_pos[num_pos][l] = this_reader -> coord[k][l];
2422 cif_pos[num_pos] = 1;
2423 if (i)
2424 {
2425 occ_pos[num_pos][0] = this_reader -> occupancy[k];
2426 lot_pos[num_pos][0] = this_reader -> lot[k];
2427 }
2428 num_pos ++;
2429 pos_max = 1;
2430 }
2431 else
2432 {
2433 save_it = TRUE;
2434 for (l=0; l<num_pos; l++)
2435 {
2436 if (this_reader -> coord[k][0] == cryst_pos[l][0]
2437 && this_reader -> coord[k][1] == cryst_pos[l][1]
2438 && this_reader -> coord[k][2] == cryst_pos[l][2])
2439 {
2440 save_it = FALSE;
2441 break;
2442 }
2443 }
2444 if (save_it)
2445 {
2446 for (l=0; l<3; l++) cryst_pos[num_pos][l] = this_reader -> coord[k][l];
2447 cif_pos[num_pos] = 1;
2448 if (i)
2449 {
2450 occ_pos[num_pos][0] = this_reader -> occupancy[k];
2451 lot_pos[num_pos][0] = this_reader -> lot[k];
2452 }
2453 num_pos ++;
2454 }
2455 else
2456 {
2457 if (i)
2458 {
2459 occ_pos[l][cif_pos[l]] = this_reader -> occupancy[k];
2460 lot_pos[l][cif_pos[l]] = this_reader -> lot[k];
2461 }
2462 cif_pos[l] ++;
2463 pos_max = max (pos_max, cif_pos[l]);
2464 }
2465 }
2466 }
2467 if (! i)
2468 {
2469 occ_pos = allocddouble (num_pos, pos_max);
2470 lot_pos = allocdint (num_pos, pos_max);
2471 }
2472 }
2473 g_free (list_occ);
2474 g_free (list_pos);
2475 for (i=0; i<num_pos; i++)
2476 {
2477 u = 0;
2478 for (j=0; j<cif_pos[i]; j++)
2479 {
2480 u += occ_pos[i][j];
2481 }
2482 if (u < 1.0)
2483 {
2484 low_occ = TRUE;
2485 break;
2486 }
2487 }
2488 int * all_id = allocint (num_pos);
2489 l = m = 0;
2490 for (i=0; i<this_reader -> num_sym_pos; i++)
2491 {
2492 for (j=0; j<3; j++)
2493 {
2494 tmp_pos = g_strdup_printf ("%s", this_reader -> sym_pos[i][j]);
2495 for (k=0; k<3; k++)
2496 {
2497 spgpos[j][k] = get_val_from_wyckoff (vect_comp[k], this_reader -> sym_pos[i][j]);
2498 }
2499 if (tmp_pos)
2500 {
2501 spgpos[j][3] = get_value_from_pos (tmp_pos);
2502 g_free (tmp_pos);
2503 tmp_pos = NULL;
2504 }
2505 else
2506 {
2507 spgpos[j][3] = 0.0;
2508 }
2509 }
2510 pos_mat = mat4 (spgpos[0][0], spgpos[0][1], spgpos[0][2], spgpos[0][3],
2511 spgpos[1][0], spgpos[1][1], spgpos[1][2], spgpos[1][3],
2512 spgpos[2][0], spgpos[2][1], spgpos[2][2], spgpos[2][3],
2513 0.0, 0.0, 0.0, 1.0);
2514 for (j=0; j<num_pos; j++)
2515 {
2516 f_pos = vec3 (cryst_pos[j][0], cryst_pos[j][1], cryst_pos[j][2]);
2517 f_pos = m4_mul_coord (pos_mat, f_pos);
2518 c_pos = m4_mul_coord (this_reader -> lattice.box[cid].frac_to_cart, f_pos);
2519 all_pos[l].x = c_pos.x;
2520 all_pos[l].y = c_pos.y;
2521 all_pos[l].z = c_pos.z;
2522 all_origin[l] = j;
2523 save_it = TRUE;
2524 if (l)
2525 {
2526 at.x = all_pos[l].x;
2527 at.y = all_pos[l].y;
2528 at.z = all_pos[l].z;
2529 for (k=0; k<l; k++)
2530 {
2531 bt.x = all_pos[k].x;
2532 bt.y = all_pos[k].y;
2533 bt.z = all_pos[k].z;
2534 dist = distance_3d (active_cell, 0, & at, & bt);
2535 if (dist.length < 0.1)
2536 {
2537 dist_message = TRUE;
2538 save_it = FALSE;
2539 break;
2540 }
2541 }
2542 }
2543 save_pos[l] = save_it;
2544 l ++;
2545 if (save_it)
2546 {
2547 all_id[j] ++;
2548 m ++;
2549 }
2550 }
2551 }
2552 double prob;
2553 gboolean pick_it;
2554 gboolean ** taken_pos = g_malloc0(num_pos*sizeof*taken_pos);
2555 int ** site_lot = g_malloc0(num_pos*sizeof*site_lot);
2556 clock_t CPU_time;
2557 int tot_pos = 0;
2558 for (i=0; i<num_pos; i++)
2559 {
2560 taken_pos[i] = allocbool(all_id[i]);
2561 site_lot[i] = allocint (all_id[i]);
2562 for (j=0; j<cif_pos[i]; j++)
2563 {
2564 u = occ_pos[i][j]*all_id[i];
2565 if (u < 1.0 && tot_pos < all_id[i]) u = 1.0;
2566 k = lot_pos[i][j];
2567 l = 0;
2568 // Warning for occupancy closest integer value to u:
2569 // - (int)u ?
2570 // - nearbyint (u) : closest integer value ?
2571 while (l < occupancy(u, this_reader -> rounding))
2572 {
2573 CPU_time = clock ();
2574 m = (CPU_time - (j+17)*all_id[i]);
2575 prob = random3_(& m);
2576 m = round (prob * (all_id[i]-1));
2577 pick_it = ! taken_pos[i][m];
2578 if (pick_it)
2579 {
2580 site_lot[i][m] = k;
2581 taken_pos[i][m] = TRUE;
2582 l ++;
2583 tot_pos ++;
2584 }
2585 }
2586 }
2587 }
2588 crystal_data * cryst = allocate_crystal_data (tot_pos, this_reader -> nspec + this_reader -> object_to_insert);
2589 i = 0;
2590 int * cryst_lot = allocint (cryst -> objects);
2591 int * from_origin = allocint (num_pos);
2592 for (j=0; j<max_pos; j++)
2593 {
2594 if (save_pos[j])
2595 {
2596 k = all_origin[j];
2597 l = from_origin[k];
2598 if (taken_pos[k][l])
2599 {
2600 cryst -> coord[i] = g_malloc0(sizeof*cryst -> coord[i]);
2601 cryst -> coord[i][0].x = all_pos[j].x;
2602 cryst -> coord[i][0].y = all_pos[j].y;
2603 cryst -> coord[i][0].z = all_pos[j].z;
2604 cryst -> pos_by_object[i] = 1;
2605 cryst_lot[i] = site_lot[k][l];
2606 if (cryst_lot[i] < 0)
2607 {
2608 cryst -> at_by_object[i] = get_atomic_object_by_origin (cif_object, - cryst_lot[i] - 1, 0) -> atoms;
2609 }
2610 else
2611 {
2612 cryst -> at_by_object[i] = 1;
2613 }
2614 i ++;
2615 }
2616 from_origin[k] ++;
2617 }
2618 }
2619 g_free (site_lot);
2620 g_free (all_origin);
2621 g_free (from_origin);
2622 g_free (all_pos);
2623 g_free (save_pos);
2624 g_free (taken_pos);
2625 g_free (all_id);
2626 i = 0;
2627 for (j=0; j<cryst -> objects; j++)
2628 {
2629 i += cryst -> at_by_object[j] * cryst -> pos_by_object[j];
2630 }
2631 if (! conf || active_project -> steps == 1)
2632 {
2633 active_project -> natomes = i;
2635 }
2636 atomic_object * c_obj;
2637 int * spec_num = allocint (120);
2638 i = 0;
2639 for (j=0; j<cryst -> objects; j++)
2640 {
2641 if (cryst_lot[j] < 0)
2642 {
2643 k = - cryst_lot[j] - 1;
2645 for (l=0; l<c_obj -> atoms; l++)
2646 {
2647 m = c_obj -> at_list[l].sp;
2648 n = c_obj -> old_z[m];
2649 spec_num[n] ++;
2650 active_project -> atoms[cid][i].sp = n;
2651 active_project -> atoms[cid][i].x = cryst -> coord[j][0].x + c_obj -> at_list[l].x;
2652 active_project -> atoms[cid][i].y = cryst -> coord[j][0].y + c_obj -> at_list[l].y;
2653 active_project -> atoms[cid][i].z = cryst -> coord[j][0].z + c_obj -> at_list[l].z;
2654 i ++;
2655 }
2656 }
2657 else
2658 {
2659 k = (int)this_reader -> z[cryst_lot[j]];
2660 spec_num[k] ++;
2661 active_project -> atoms[cid][i].sp = k;
2662 active_project -> atoms[cid][i].x = cryst -> coord[j][0].x;
2663 active_project -> atoms[cid][i].y = cryst -> coord[j][0].y;
2664 active_project -> atoms[cid][i].z = cryst -> coord[j][0].z;
2665 i ++;
2666 }
2667 }
2668 g_free (this_reader -> nsps);
2669 int * tmp_nsps = allocint (120);
2670 int * tmp_spid = allocint (120);
2671 i = 0;
2672 for (j=0; j<120; j++)
2673 {
2674 if (spec_num[j])
2675 {
2676 tmp_nsps[i] = spec_num[j];
2677 tmp_spid[j] = i;
2678 i++;
2679 }
2680 }
2681 this_reader -> nspec = i;
2682 this_reader -> nsps = allocint (i);
2683 for (i=0; i<this_reader -> nspec; i++) this_reader -> nsps[i] = tmp_nsps[i];
2684 g_free (tmp_nsps);
2685 g_free (this_reader -> z);
2686 this_reader -> z = allocdouble (i);
2687 i = 0;
2688 for (j=0; j<120; j++)
2689 {
2690 if (spec_num[j])
2691 {
2692 this_reader -> z[i] = (double)j;
2693 i ++;
2694 }
2695 }
2696 for (i=0; i<active_project -> natomes; i++)
2697 {
2698 j = active_project -> atoms[cid][i].sp;
2699 k = tmp_spid[j];
2700 active_project -> atoms[cid][i].sp = k;
2701 }
2702 g_free (tmp_spid);
2703 if (low_occ)
2704 {
2705 add_reader_info (_("The crystal will be created however some objects might be missing,\n"
2706 "Occupancy is too low compared to the number of site(s) per cell.\n\n"
2707 "<b>To build a crystal matching the defined occupancy</b>:\n"
2708 "\t <b>1)</b> If you are trying to read a CIF file, use the crystal builder instead.\n"
2709 "\t <b>2)</b> Modify the occupancy set-up to 'Completely random'.\n"
2710 "\t <b>3)</b> Increase the number of unit cells up to get rid of this message.\n\n"), 1);
2711 }
2712 if (dist_message)
2713 {
2714 add_reader_info (_("Object(s) at equivalent positions have been removed\n"
2715 "to ensure the consistency of the model\n"
2716 "when using <b>P</b>eriodic <b>B</b>oundary <b>C</b>onditions\n "), 1);
2717 }
2718 }
2719 }
2720 else
2721 {
2722 // No coordinates found
2723#ifdef DEBUG
2724 g_debug ("CIF:: Impossible to retrieve atomic coordinates !");
2725#endif
2726 res = 2;
2727 }
2728 return res;
2729}
2730
2738int open_cif_file (int linec)
2739{
2740 gchar * str = NULL;
2741 int cif_action = 0;
2742 int cif_step = 1;
2743 int cif_site;
2744 int cif_occup = 0;
2745 int lid;
2746 int i, j;
2747
2748 cif_multiple = TRUE;
2749 // Determine the number of configuration(s) by checking the presence
2750 // of the instruction used to declare atomic coordinates
2751 for (i=0; i<NLKEYS; i++)
2752 {
2753 for (j=0; j<CFKEYS-1; j++)
2754 {
2755 this_reader -> steps = cif_get_value (linekeys[i], frackeys[j][0], 0, linec, NULL, FALSE, FALSE, TRUE, FALSE, NULL);
2756 if (this_reader -> steps)
2757 {
2758 lid = i;
2759 break;
2760 }
2761 }
2762 if (this_reader -> steps) break;
2763 }
2764 if (! this_reader -> steps)
2765 {
2766 for (i=0; i<NLKEYS; i++)
2767 {
2768 for (j=0; j<CFKEYS; j++)
2769 {
2770 this_reader -> steps = cif_get_value (linekeys[i], cartkeys[j][0], 0, linec, NULL, FALSE, FALSE, TRUE, FALSE, NULL);
2771 if (this_reader -> steps)
2772 {
2773 lid = i;
2774 this_reader -> cartesian = TRUE;
2775 break;
2776 }
2777 }
2778 if (this_reader -> steps) break;
2779 }
2780 }
2781 else
2782 {
2783 // How to treat occupancy
2784 cif_occup = cif_get_value (linekeys[lid], _("occupancy"), 0, linec, NULL, FALSE, FALSE, TRUE, FALSE, NULL);
2785 if (cif_occup)
2786 {
2787 this_reader -> rounding = iask (_("Please select how to handle occupancy"), _("Select how to handle occupancy"), 5, atomes_main_window);
2788 if (this_reader -> rounding < 0 || this_reader -> rounding > 2) this_reader -> rounding = 2;
2790 {
2791 str = g_strdup_printf (_("Occupancy %s\n\t%s\n"), cif_occ[this_reader -> rounding], cif_sites[cif_use_symmetry_positions]);
2792 add_reader_info (str, 1);
2793 g_free (str);
2794 }
2795 }
2796 }
2797
2798 if (this_reader -> steps > 1)
2799 {
2800 str = g_strdup_printf (_("It seems the CIF file contains <b>%d</b> distinct configurations\n"), this_reader -> steps);
2801 add_reader_info (str, 1);
2802 g_free (str);
2804 {
2805 str = g_strdup_printf (_("Impossible to use symmetry positions with multiple configurations\n"));
2806 add_reader_info (str, 1);
2807 g_free (str);
2808 }
2809 }
2810
2811 if (this_reader -> steps > 1 && ! cif_use_symmetry_positions)
2812 {
2813 cif_site = cif_get_value (linekeys[lid], "disorder_group", 0, linec, NULL, FALSE, FALSE, TRUE, FALSE, NULL);
2814 if (cif_occup == this_reader -> steps && cif_occup == cif_site)
2815 {
2816 add_reader_info (_("This CIF file could be describing a trajectory or a chemical reaction.\n"), 1);
2817 // This is where to ask what to do !
2818 // Read like a chemical reaction: read one configuration sort coordinates by occupancy
2819 // Read all as trajectory CIF file: forget about using occupancy to sort coordinates
2820 // - possible if the number of atom(s) by configuration remains constant
2821 // Read only a selected configuration and:
2822 // - read as normal CIF file, forget about using occupancy to sort coordinates
2823 // Because what follow will depend on this choice
2824 /* cif_action = iask ("Please select how to process the data in the CIF file", "Select how to process data", 3, atomes_main_window);
2825 this_reader -> chemical = ! cif_action;
2826 cif_action = (cif_action == 1) ? 0 : 1; */
2827 cif_action = iask (_("Please select how to process the data in the CIF file"), _("Select how to process data"), 4, atomes_main_window);
2828 }
2829 else
2830 {
2831 add_reader_info (_("This CIF file could be describing a trajectory.\n"), 1);
2832 cif_action = iask (_("Please select how to process the data in the CIF file"), _("Select how to process data"), 4, atomes_main_window);
2833 }
2834 }
2835 else
2836 {
2837 cif_action = 1;
2838 }
2839
2840 if (cif_action && this_reader -> steps > 1)
2841 {
2842 // We need to select the step to work on
2843 str = g_strdup_printf (_("Select the configuration <i>c</i>, <i>c</i> &#x2208; [1-%d]"), this_reader -> steps);
2844 cif_step = 0;
2845 while (! cif_step)
2846 {
2847 cif_step = iask (_("Please select the configuration to work on"), str, 0, atomes_main_window);
2848 if (cif_step < 1 || cif_step > this_reader -> steps) cif_step = 0;
2849 }
2850 g_free (str);
2851 }
2852 if (cif_action)
2853 {
2854 active_project -> steps = 1;
2855 if (this_reader -> steps > 1)
2856 {
2857 str = g_strdup_printf (_("Working on configuration N°%d\n"), cif_step);
2858 add_reader_info (str, 1);
2859 g_free (str);
2860 }
2861 }
2862
2863 if (cif_action)
2864 {
2865 return open_cif_configuration (linec, cif_step - 1);
2866 }
2867 else
2868 {
2869 active_project -> steps = this_reader -> steps;
2870 g_free (active_cell -> box);
2871 active_cell -> box = g_malloc0(this_reader -> steps*sizeof*active_cell -> box);
2872 // For each configuration open it:
2873 i = 0;
2874 for (j=0; j<active_project -> steps; j++)
2875 {
2876 this_reader -> nspec = 0;
2877 if (this_reader -> nsps)
2878 {
2879 g_free (this_reader -> nsps);
2880 this_reader -> nsps = NULL;
2881 }
2882 i = open_cif_configuration (linec, j);
2883 if (i) return i;
2884 }
2885 return 0;
2886 }
2887}
atom_search * allocate_atom_search(int proj, int action, int searchid, int tsize)
allocate atom search data structure
Definition atom_edit.c:393
Function declarations for the mode edition window.
GtkTreeModel * replace_combo_tree(gboolean insert, int proj)
replace combo box in the tree view
Definition w_search.c:2612
int get_selected_object_id(gboolean visible, int p, gchar *str, atom_search *asearch)
get the id of the object selected (in contextual menu, or in combo box)
Definition w_search.c:2378
gchar * mot[2][2]
void to_insert_in_project(int stat, int orig, project *this_proj, atom_search *asearch, gboolean visible)
to insert object in project
atomic_object * get_atomic_object_by_origin(atomic_object *first, int oid, int aid)
get insert object from a list by id
Definition w_search.c:474
atomic_object * cif_object
Definition read_cif.c:342
Binding to the Fortran90 subroutines.
double random3_(int *)
gchar * substitute_string(gchar *init, gchar *o_motif, gchar *n_motif)
substitute all patterns in string
Definition w_library.c:378
double get_val_from_wyckoff(gchar *pos, gchar *wval)
get point value from wyckoff position
int occupancy(double occ, int cif_occ)
handle occupancy integer rouding
gchar * tmp_pos
crystal_data * allocate_crystal_data(int objects, int species)
allocate crystal data pointer
int test_lattice(builder_edition *cbuilder, cell_info *cif_cell)
test lattice parameters
double get_value_from_pos(gchar *pos)
get position double value from string description
int read_space_group(builder_edition *cbuilder, int spg)
read space group N°spg data from file
Function declarations for the crystal builder.
gchar * groups[230]
Definition cbuild_sg.c:43
void allocatoms(project *this_proj)
allocate project data
Definition open_p.c:177
gchar * hmsymbols[230]
Definition cbuild_sg.c:274
gchar * replace_markup(char *init, char *key, char *rep)
replace pattern in string
Definition w_library.c:343
gchar * wnpos[3]
Definition cbuild_info.c:74
gchar * param[2]
double ax
Definition curve.c:71
double dist
Definition d_measures.c:73
int atoms[NUM_STYLES][2]
float val
Definition dlp_init.c:117
int * duplicate_int(int num, int *old_val)
copy a list of int
Definition global.c:548
int multi
Definition dlp_init.c:121
char * box_prop[2][3]
Definition edit_menu.c:74
int ** allocdint(int xal, int yal)
allocate an int ** pointer
Definition global.c:318
double * duplicate_double(int num, double *old_val)
copy a list of double
Definition global.c:596
GtkWidget * atomes_main_window
Definition global.c:208
int activep
Definition global.c:162
gboolean * allocbool(int val)
allocate a gboolean * pointer
Definition global.c:242
double ** allocddouble(int xal, int yal)
allocate a double ** pointer
Definition global.c:463
double * allocdouble(int val)
allocate a double * pointer
Definition global.c:447
int * allocint(int val)
allocate an int * pointer
Definition global.c:302
#define i18n(String)
Definition global.c:80
gboolean cif_use_symmetry_positions
Definition global.c:193
double string_to_double(gpointer string)
convert string to double
Definition global.c:612
Global variable declarations Global convenience function declarations Global data structure defin...
void run_this_gtk_dialog(GtkWidget *dial, GCallback handler, gpointer data)
run a GTK (3 and 4) basic GtkDialog
Definition gtk-misc.c:533
GtkWidget * dialogmodal(gchar *str, GtkWindow *parent)
Create a new dialog modal window.
Definition gtk-misc.c:552
cell_info * active_cell
Definition project.c:50
void combo_set_markup(GtkWidget *combo)
use pango markup in combo widget
Definition gtk-misc.c:970
element_data periodic_table_info[]
Definition w_library.c:71
void combo_set_active(GtkWidget *combo, int pos)
set the active item's position
Definition gtk-misc.c:958
GtkWidget * stock_image(const gchar *stock_id)
create a GtkImage for the Gtk database
Definition gtk-misc.c:1451
#define APPLY
Definition global.h:237
GtkWidget * dialog_get_content_area(GtkWidget *widg)
prepare GtkWidget to insert content in a GtkDialog window
Definition gtk-misc.c:861
GtkWidget * markup_label(gchar *text, int dimx, int dimy, float ax, float ay)
create a GtkLabel with pango markup
Definition gtk-misc.c:1672
void add_box_child_start(int orientation, GtkWidget *widg, GtkWidget *child, gboolean expand, gboolean fill, int padding)
Add a GtkWidget in a GtkBox at the initial position.
Definition gtk-misc.c:340
#define DELETEB
Definition global.h:239
GtkWidget * create_hbox(int spacing)
create a GtkBox with horizontal orientation
Definition gtk-misc.c:849
G_MODULE_EXPORT void run_destroy_dialog(GtkDialog *dialog, gint response_id, gpointer data)
to destroy a GtkDialog when the dialog emit the closing signal
Definition gtk-misc.c:2272
#define min(a, b)
Definition global.h:94
void set_image_from_icon_name(GtkWidget *widg, gchar *icon)
set a image from a stock icon name
Definition gtk-misc.c:2030
project * active_project
Definition project.c:47
#define max(a, b)
Definition global.h:93
@ REPLACE
Definition glview.h:234
int objects[3]
Definition selection.c:212
int iask(char *question, char *lab, int id, GtkWidget *win)
enter an integer value - prepare the dialog
Definition interface.c:620
gchar * cif_occ[3]
Definition interface.c:542
gchar * cif_sites[2]
Definition interface.c:545
Messaging function declarations.
char * vect_comp[3]
Definition edit_menu.c:78
integer(kind=c_int) function lattice(totl, lid, vectors, vmod, angles, lat, cfrac, apbc)
Definition lattice.F90:162
double z
Definition ogl_draw.c:63
Function declarations for reading atomes project file Function declarations for saving atomes proje...
void check_for_species(double v, int ato)
Fill the species for each atom and the associated data.
Definition read_coord.c:221
int cif_atoms
Definition read_cif.c:98
gchar * get_atom_disorder(gchar *line, int lid)
read atom disorder group from CIF file
Definition read_cif.c:329
gboolean cif_get_atomic_coordinates(int linec, int conf)
Definition read_cif.c:1134
void file_get_to_line(int line_id)
reach line in CIF file
Definition read_cif.c:440
int * keylines
Definition read_cif.c:96
gchar * get_string_from_origin(space_group *spg)
get the space group origin from its name
Definition read_cif.c:1745
gboolean cif_multiple
Definition read_cif.c:103
gboolean * cif_cnftodo
Definition read_cif.c:174
int cif_file_get_number_of_positions(int lid)
get the number of symmetry positions
Definition read_cif.c:1569
G_MODULE_EXPORT void set_cif_to_insert(GtkComboBox *box, gpointer data)
change the object to insert at an empty cif position
Definition read_cif.c:352
int cif_get_space_group(int linec, int conf)
get the space group from the CIF file
Definition read_cif.c:2008
int * cif_nsps
Definition read_cif.c:101
double get_z_from_periodic_table(gchar *lab)
get Z from atom label
Definition w_library.c:308
gboolean cif_file_get_atoms_data(int conf, int lin, int cid[9])
Definition read_cif.c:1021
void compute_lattice_properties(cell_info *cell, int box_id)
compute lattice parameters following cell description
gchar * cartkeys[CFKEYS][3]
Definition read_cif.c:167
#define NLKEYS
Definition read_cif.c:160
void check_for_to_lab(int ato, gchar *stlab)
check atom label
Definition read_cif.c:970
GtkWidget ** img_cif
Definition read_cif.c:340
int saved_group
Definition read_cif.c:97
int get_atom_wyckoff(gchar *line, int wid)
read Wyckoff position from CIF file
Definition read_cif.c:301
int * cif_lot
Definition read_cif.c:100
gchar * frackeys[CFKEYS-1][3]
Definition read_cif.c:165
space_group * duplicate_space_group(space_group *spg)
duplicate space ground information
int group_info_from_hm_key(int spg, gchar *key_hm)
get the space group information using the HM key from the CIF file
Definition read_cif.c:1863
gboolean cif_get_symmetry_positions(int linec, int conf)
read the symmetry positions from the CIF file
Definition read_cif.c:1663
gboolean cif_get_cell_data(int linec, int conf)
get the cell data from the CIF file
Definition read_cif.c:1946
int cif_cnfdone
Definition read_cif.c:175
int read_space_group(builder_edition *cbuilder, int spg)
read space group N°spg data from file
gchar * linekeys[NLKEYS]
Definition read_cif.c:161
int cif_file_get_data_in_loop(int linec, int lid)
get the number of "_" motifs in a line
Definition read_cif.c:664
void get_wyck_char(float val, int ax, int bx)
convert wyckoff value to string
int get_loop_line_id(int lid)
reach a line in the CIF file
Definition read_cif.c:728
float get_atom_coord(gchar *line, int mid)
read atom coordinates from CIF file
Definition read_cif.c:249
int cif_file_get_number_of_atoms(int linec, int lid, int nelem)
get the number of atom(s) in a CIF file
Definition read_cif.c:903
int cif_cnfcart
Definition read_cif.c:172
int cif_get_value(gchar *kroot, gchar *keyw, int lstart, int lend, gchar **cif_word, gboolean rec_val, gboolean all_ligne, gboolean total_num, gboolean record_position, int *line_position)
read pattern in CIF file
Definition read_cif.c:465
FILE * cifp
Definition read_cif.c:94
gboolean get_missing_object_from_user()
get missing atomic number in CIF file from the user
Definition read_cif.c:387
char * line_ptr
Definition read_cif.c:95
int get_setting_from_hm(gchar *hmk, int end)
Getting the space group parameters using the HM Key.
Definition read_cif.c:1775
int get_loop_line_for_key(int linec, int conf, gchar *key_a, gchar *key_b)
search a string
Definition read_cif.c:785
int ** cif_cnfkeys
Definition read_cif.c:173
void get_origin(space_group *spg)
get space group origin matrices
int open_cif_file(int linec)
open CIF file
Definition read_cif.c:2738
gchar * cif_coord_opts[40][2]
Definition read_cif.c:107
gchar * get_atom_label(gchar *line, int lid)
read atom label from CIF file
Definition read_cif.c:272
int get_atom_id_from_periodic_table(atom_search *asearch)
get atom Z from selection in the periodic table
Definition w_periodic.c:672
gchar * cif_retrieve_value(int linec, int conf, gchar *key_a, gchar *key_b, gboolean all_ligne, gboolean in_loop, gboolean warning)
retrieve a field value as string in the CIF file
Definition read_cif.c:831
int open_cif_configuration(int linec, int conf)
Definition read_cif.c:2248
int test_lattice(builder_edition *cbuilder, cell_info *cif_cell)
test lattice parameters
int get_space_group_from_hm(gchar *hmk)
retrieve space group using the HM Key
Definition read_cif.c:1691
atom_search * cif_search
Definition read_cif.c:341
gchar ** cif_strings
Definition read_cif.c:105
int cif_nspec
Definition read_cif.c:99
void sort(int dim, int *tab)
sort, nim to max, a table by integer value
Definition glview.c:402
gchar * get_cif_word(gchar *mot)
get string from CIF file, EOL can be ugly
Definition read_cif.c:234
#define CFKEYS
Definition read_cif.c:164
distance distance_3d(cell_info *cell, int mdstep, atom *at, atom *bt)
distance between atom a and b in 3D
Definition ogl_utils.c:81
line_node * head
Definition read_coord.c:78
gchar ** coord_line
Definition read_coord.c:75
coord_file * this_reader
Definition read_coord.c:74
line_node * tail
Definition read_coord.c:79
void add_reader_info(gchar *info, int mid)
append information message to the reader information
Definition read_coord.c:89
gchar * this_line
Definition read_coord.c:76
Functions declaration to read atomic coordinates.
Definition global.h:968
double z
Definition global.h:974
double y
Definition global.h:973
double x
Definition global.h:972
Definition glwin.h:350
double * z
Definition cbuild_edit.h:42
float y
Definition math_3d.h:130
float x
Definition math_3d.h:130
float z
Definition math_3d.h:130
GtkWidget * res[2]
Definition w_encode.c:342
GtkWidget * hbox
Definition workspace.c:71
GtkWidget * vbox
Definition workspace.c:72
GtkWidget * lab
Definition workspace.c:73