Xmipp  v3.23.11-Nereus
lib_eul.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 * L I B _ E U L *
3 **********************************************************************
4 * Library is part of the Situs package URL: situs.biomachina.org *
5 * (c) Jochen Heyd, Valerio Mariani, Pablo Chacon, *
6 * and Willy Wriggers, 2001-2007 *
7 **********************************************************************
8 * *
9 * Euler angle - related routines. *
10 * *
11 **********************************************************************
12 * See legal statement for terms of distribution *
13 *********************************************************************/
14 
15 /*
16 
17 Euler angle order: (psi,theta,phi) <. (0,1,2)
18 Euler angle convention: Goldstein or "X-convention":
19 
20  A=BCD
21 
22 rotation components:
23 
24  | cos_psi sin_psi 0 |
25 B= | -sin_psi cos_psi 0 |
26  | 0 0 1 |
27 
28  | 1 0 0 |
29 C= | 0 cos_theta sin_theta |
30  | 0 -sin_theta cos_theta |
31 
32  | cos_phi sin_phi 0 |
33 D= | -sin_phi cos_phi 0 |
34  | 0 0 1 |
35 
36 
37 rotation matrix:
38 
39 |a_11 a_12 a_13|
40 A=|a_21 a_22 a_23|
41 |a_31 a_22 a_33|
42 
43 a_11 = cos_psi * cos_phi - cos_theta * sin_phi * sin_psi;
44 a_12 = cos_psi * sin_phi + cos_theta * cos_phi * sin_psi;
45 a_13 = sin_psi * sin_theta;
46 a_21 = -sin_psi * cos_phi- cos_theta * sin_phi * cos_psi;
47 a_22 = -sin_psi * sin_phi+ cos_theta * cos_phi * cos_psi;
48 a_23 =cos_psi * sin_theta;
49 a_31 =sin_theta * sin_phi;
50 a_32 = -sin_theta * cos_phi;
51 a_33 =cos_theta;
52 
53 See http://mathworld.wolfram.com/
54 */
55 
56 #include "situs.h"
57 #include "lib_eul.h"
58 #include "lib_err.h"
59 #include "lib_pwk.h"
60 #include "lib_vec.h"
61 
62 /*=====================================================================*/
63 /* writes range, step_size, and all angles to specified filename */
64 void write_eulers(char *eu_file, unsigned long eu_count, float *eu_store,
65  double eu_range[3][2], double delta)
66 {
67  FILE *out;
68  const char *program = "lib_eul";
69  unsigned i;
70 
71  if ((out = fopen(eu_file, "w")) == NULL) {
72  error_open_filename(15010, program, eu_file);
73  }
74 
75  for (i = 0; i < eu_count; i++)
76  fprintf(out, "%10.4f%10.4f%10.4f\n",
77  *(eu_store + 3 * i + 0) / ROT_CONV, *(eu_store + 3 * i + 1) / ROT_CONV, *(eu_store + 3 * i + 2) / ROT_CONV);
78  fclose(out);
79 }
80 
81 /*=====================================================================*/
82 /* reads Euler angles from in_file */
83 void read_eulers(char *in_file, unsigned long *eu_count, float **eu_store)
84 {
85  FILE *in;
86  unsigned long i;
87  double psi, theta, phi;
88  const char *program = "lib_eul";
89 
90  /* count number of Euler angle sets */
91 
92  if ((in = fopen(in_file, "r")) == NULL) {
93  error_open_filename(15020, program, in_file);
94  }
95  i = 0;
96  while (!feof(in)) {
97  if (fscanf(in, "%lf %lf %lf\n", &psi, &theta, &phi) != 3) break;
98  else i++;
99  }
100  fclose(in);
101 
102  /* allocate eu_store */
103  *eu_store = (float *) alloc_vect(i * 3, sizeof(float));
104  if ((in = fopen(in_file, "r")) == NULL) {
105  error_open_filename(15050, program, in_file);
106  }
107  i = 0;
108  while (!feof(in)) {
109  if (fscanf(in, "%lf %lf %lf\n", &psi, &theta, &phi) != 3) break;
110  else {
111  *(*eu_store + i * 3 + 0) = psi * ROT_CONV;
112  *(*eu_store + i * 3 + 1) = theta * ROT_CONV;
113  *(*eu_store + i * 3 + 2) = phi * ROT_CONV;
114  i++;
115  }
116  }
117  fclose(in);
118  *eu_count = i;
119  printf("lib_eul> %lu Euler angles read from file %s\n", i, in_file);
120 }
121 
122 /* remaps Euler angles using rot-matrix invariant transformations*/
123 /* and attempts to make angles fall in the intervalls: */
124 /* [psi_ref, psi_ref + 2*PI] */
125 /* [theta_ref, theta_ref + PI] */
126 /* [phi_ref, phi_ref + 2*PI] */
127 /* Note that this is strictly guaranteed only for*/
128 /* (psi_ref, theta_ref, phi_ref) == (0,0,0)*/
129 /* For non-zero reference we may have for small number of angles */
130 /* theta_ref + PI <= theta <= theta_ref + 2 * PI */
131 /*=====================================================================*/
132 void remap_eulers(double *psi_out, double *theta_out, double *phi_out,
133  double psi_in, double theta_in, double phi_in,
134  double psi_ref, double theta_ref, double phi_ref)
135 {
136  double curr_psi, curr_theta, curr_phi;
137  double new_psi, new_theta, new_phi;
138 
139  /* bring psi, theta, phi, within 2 PI of reference */
140  curr_psi = psi_in - psi_ref;
141  if (curr_psi >= 0) new_psi = fmod(curr_psi, 2 * PI) + psi_ref;
142  else new_psi = 2 * PI - fmod(-curr_psi, 2 * PI) + psi_ref;
143 
144  curr_theta = theta_in - theta_ref;
145  if (curr_theta >= 0) new_theta = fmod(curr_theta, 2 * PI) + theta_ref;
146  else new_theta = 2 * PI - fmod(-curr_theta, 2 * PI) + theta_ref;
147 
148  curr_phi = phi_in - phi_ref;
149  if (curr_phi >= 0) new_phi = fmod(curr_phi, 2 * PI) + phi_ref;
150  else new_phi = 2 * PI - fmod(-curr_phi, 2 * PI) + phi_ref;
151 
152  /* if theta is not within PI, we use invariant transformations */
153  /* and attempt to map to above intervals */
154  /* this works in most cases even if the reference is not zero*/
155  if (new_theta - theta_ref > PI) { /* theta overflow */
156  /* theta . 2 PI - theta */
157  if (new_theta >= 0) curr_theta = fmod(new_theta, 2 * PI);
158  else curr_theta = 2 * PI - fmod(-new_theta, 2 * PI);
159  new_theta -= 2 * curr_theta;
160 
161  /* remap to [0, 2 PI] interval */
162  curr_theta = new_theta - theta_ref;
163  if (curr_theta >= 0) new_theta = fmod(curr_theta, 2 * PI) + theta_ref;
164  else new_theta = 2 * PI - fmod(-curr_theta, 2 * PI) + theta_ref;
165 
166  /* we have flipped theta so we need to flip psi and phi as well */
167  /* to keep rot-matrix invariant */
168  /* psi . psi + PI */
169  if (new_psi - psi_ref > PI) new_psi -= PI;
170  else new_psi += PI;
171 
172  /* phi . phi + PI */
173  if (new_phi - phi_ref > PI) new_phi -= PI;
174  else new_phi += PI;
175  }
176 
177  *psi_out = new_psi;
178  *theta_out = new_theta;
179  *phi_out = new_phi;
180 }
181 
182 /* computes rotation matrix based on Euler angles psi, theta, phi in radians */
183 /*=====================================================================*/
184 void get_rot_matrix(double dump[3][3], double psi, double theta, double phi)
185 {
186  double sin_psi = sin(psi);
187  double cos_psi = cos(psi);
188  double sin_theta = sin(theta);
189  double cos_theta = cos(theta);
190  double sin_phi = sin(phi);
191  double cos_phi = cos(phi);
192 
193  /* use Goldstein convention */
194  dump[0][0] = cos_psi * cos_phi - cos_theta * sin_phi * sin_psi;
195  dump[0][1] = cos_psi * sin_phi + cos_theta * cos_phi * sin_psi;
196  dump[0][2] = sin_psi * sin_theta;
197  dump[1][0] = -sin_psi * cos_phi - cos_theta * sin_phi * cos_psi;
198  dump[1][1] = -sin_psi * sin_phi + cos_theta * cos_phi * cos_psi;
199  dump[1][2] = cos_psi * sin_theta;
200  dump[2][0] = sin_theta * sin_phi;
201  dump[2][1] = -sin_theta * cos_phi;
202  dump[2][2] = cos_theta;
203 }
204 
205 /* Spiral algorithm for Euler angle computation in specified range.*/
206 /* The idea behind the algorithm is that one can cut the globe with n*/
207 /* horizontal planes spaced 2/(n-1) units apart, forming n circles of*/
208 /* latitude on the sphere, each latitude containing one spiral point.*/
209 /* To obtain the kth spiral point, one proceeds upward from the*/
210 /* (k-1)st point (theta(k-1), psi(k-1)) along a great circle to the*/
211 /* next latitude and travels counterclockwise along it for a fixed */
212 /* distance to arrive at the kth point (theta(k), psi(k)). */
213 /* */
214 /* Refs: (1) E.B. Saff and A.B.J. Kuijlaars, Distributing Many */
215 /* Points on a Sphere, The Mathematical Intelligencer, */
216 /* 19(1), Winter (1997). */
217 /* (2) "Computational Geometry in C." Joseph O'Rourke*/
218 /*=====================================================================*/
219 void eu_spiral(double eu_range[3][2], double delta,
220  unsigned long *eu_count, float **eu_store)
221 {
222  unsigned long i, j;
223  int phi_steps, n, k;
224  double phi, phi_tmp, psi_old, psi_new, psi_tmp, theta, theta_tmp, h;
225  const char *program = "lib_eul";
226 
227  /* rough estimate of number of points on sphere that give a surface*/
228  /* density that is the squared linear density of angle increments*/
229  n = (int)ceil(360.0 * 360.0 / (delta * delta * PI));
230 
231  /* total nr. points = nr. of points on the sphere * phi increments */
232  phi_steps = (int)ceil((eu_range[2][1] - eu_range[2][0]) / delta);
233  if (phi_steps < 1) {
234  error_negative_euler(15080, program);
235  }
236 
237  /* count number of points on the (theta,psi) sphere */
238  j = 0;
239 
240  /* lower pole on (theta,psi) sphere, k=0 */
241  theta = PI;
242  psi_new = (eu_range[0][1] + eu_range[0][0]) * 0.5 * ROT_CONV;
243  remap_eulers(&psi_new, &theta, &phi_tmp, psi_new, theta, 0.0,
244  eu_range[0][0]*ROT_CONV, eu_range[1][0]*ROT_CONV, eu_range[2][0]*ROT_CONV);
245  if (eu_range[1][0]*ROT_CONV <= theta && eu_range[1][1]*ROT_CONV >= theta) j++;
246 
247 
248  /* intermediate sphere latitudes theta */
249  psi_old = 0; /* longitude */
250  for (k = 1; k < n - 1; k++) {
251  h = -1 + 2 * k / (n - 1.0); /* linear distance from pole */
252  theta = acos(h);
253  psi_new = psi_old + 3.6 / (sqrt((double)n * (1 - h * h)));
254  psi_old = psi_new;
255 
256  remap_eulers(&psi_new, &theta, &phi_tmp, psi_new, theta, 0.0,
257  eu_range[0][0]*ROT_CONV, eu_range[1][0]*ROT_CONV, eu_range[2][0]*ROT_CONV);
258 
259  if (eu_range[0][0]*ROT_CONV <= psi_new && eu_range[0][1]*ROT_CONV >= psi_new && eu_range[1][0]*ROT_CONV <= theta && eu_range[1][1]*ROT_CONV >= theta) j++;
260  }
261 
262  /* upper pole on (theta,psi) sphere, k=n-1 */
263  theta = 0.0;
264  psi_new = (eu_range[0][1] + eu_range[0][0]) * 0.5 * ROT_CONV;
265  remap_eulers(&psi_new, &theta, &phi_tmp, psi_new, theta, 0.0,
266  eu_range[0][0]*ROT_CONV, eu_range[1][0]*ROT_CONV, eu_range[2][0]*ROT_CONV);
267  if (eu_range[1][0]*ROT_CONV <= theta && eu_range[1][1]*ROT_CONV >= theta) j++;
268 
269  i = phi_steps * j;
270  *eu_count = i;
271  printf("lib_eul> Spiral Euler angle distribution, total number %lu (delta = %f deg.)\n", i, delta);
272 
273  /* allocate memory */
274 
275  *eu_store = (float *) alloc_vect(i * 3, sizeof(float));
276 
277  j = 0;
278  /* lower pole on (theta,psi) sphere, k=0 */
279  theta = PI;
280  psi_new = (eu_range[0][1] + eu_range[0][0]) * 0.5 * ROT_CONV;
281  remap_eulers(&psi_new, &theta, &phi_tmp, psi_new, theta, 0.0,
282  eu_range[0][0]*ROT_CONV, eu_range[1][0]*ROT_CONV, eu_range[2][0]*ROT_CONV);
283  if (eu_range[1][0]*ROT_CONV <= theta && eu_range[1][1]*ROT_CONV >= theta) {
284  for (phi = eu_range[2][0]; phi <= eu_range[2][1]; phi += delta) {
285  if (phi >= 360) break;
286  remap_eulers(&psi_tmp, &theta_tmp, &phi_tmp, psi_new, theta, phi * ROT_CONV,
287  0.0, 0.0, 0.0);
288  *(*eu_store + j + 0) = psi_tmp;
289  *(*eu_store + j + 1) = theta_tmp;
290  *(*eu_store + j + 2) = phi_tmp;
291  j += 3;
292  }
293  }
294 
295  /* intermediate sphere latitudes theta */
296  psi_old = 0; /* longitude */
297  for (k = 1; k < n - 1; k++) {
298  h = -1 + 2 * k / (n - 1.0); /* linear distance from pole */
299  theta = acos(h);
300  psi_new = psi_old + 3.6 / (sqrt((double)n * (1 - h * h)));
301  psi_old = psi_new;
302  remap_eulers(&psi_new, &theta, &phi_tmp, psi_new, theta, 0.0,
303  eu_range[0][0]*ROT_CONV, eu_range[1][0]*ROT_CONV, eu_range[2][0]*ROT_CONV);
304  if (eu_range[0][0]*ROT_CONV <= psi_new && eu_range[0][1]*ROT_CONV >= psi_new && eu_range[1][0]*ROT_CONV <= theta && eu_range[1][1]*ROT_CONV >= theta) {
305  for (phi = eu_range[2][0]; phi <= eu_range[2][1]; phi += delta) {
306  if (phi >= 360) break;
307  remap_eulers(&psi_tmp, &theta_tmp, &phi_tmp, psi_new, theta, phi * ROT_CONV,
308  0.0, 0.0, 0.0);
309  *(*eu_store + j + 0) = psi_tmp;
310  *(*eu_store + j + 1) = theta_tmp;
311  *(*eu_store + j + 2) = phi_tmp;
312  j += 3;
313  }
314  }
315  }
316 
317  /* upper pole on (theta,psi) sphere, k=n-1 */
318  theta = 0.0;
319  psi_new = (eu_range[0][1] + eu_range[0][0]) * 0.5 * ROT_CONV;
320  remap_eulers(&psi_new, &theta, &phi_tmp, psi_new, theta, 0.0,
321  eu_range[0][0]*ROT_CONV, eu_range[1][0]*ROT_CONV, eu_range[2][0]*ROT_CONV);
322  if (eu_range[1][0]*ROT_CONV <= theta && eu_range[1][1]*ROT_CONV >= theta) {
323  for (phi = eu_range[2][0]; phi <= eu_range[2][1]; phi += delta) {
324  if (phi >= 360) break;
325  remap_eulers(&psi_tmp, &theta_tmp, &phi_tmp, psi_new, theta, phi * ROT_CONV,
326  0.0, 0.0, 0.0);
327  *(*eu_store + j + 0) = psi_tmp;
328  *(*eu_store + j + 1) = theta_tmp;
329  *(*eu_store + j + 2) = phi_tmp;
330  j += 3;
331  }
332  }
333 }
334 
335 /* This subroutine generates a nondegenerate set of Euler angles */
336 /* in the specified scan range. The angles are first sampled with*/
337 /* equal spacing in psi, theta, phi. Finally, the distribution is*/
338 /* sparsed to reduce the density at the poles. */
339 /*=====================================================================*/
340 void eu_sparsed(double eu_range[3][2], double delta,
341  unsigned long *eu_count, float **eu_store)
342 {
343  double psi, psi_tmp, theta, theta_tmp, phi, phi_tmp;
344  char *degenerate;
345  int psi_steps, theta_steps, phi_steps;
346  int h;
347  unsigned long i, j, n, k;
348  unsigned long partial_count, curr_count;
349  float *curr_eulers;
350  const char *program = "lib_eul";
351  PDB *pdb1;
352  PDB *pdb2;
353  PDB *pdb3;
354 
355  psi_steps = (int)ceil((eu_range[0][1] - eu_range[0][0]) / delta);
356  theta_steps = (int)ceil((eu_range[1][1] - eu_range[1][0]) / delta);
357  phi_steps = (int)ceil((eu_range[2][1] - eu_range[2][0]) / delta);
358 
359  if (psi_steps < 1 || theta_steps < 1 || phi_steps < 1) {
360  error_negative_euler(15115, program);
361  }
362 
363  partial_count = (psi_steps + 1) * (theta_steps + 1);
364 
365  /* allocate memory */
366  curr_eulers = (float *) alloc_vect(partial_count * 3, sizeof(float));
367  degenerate = (char *) alloc_vect(partial_count, sizeof(char));
368  pdb1 = (PDB *) alloc_vect(1, sizeof(PDB));
369  pdb2 = (PDB *) alloc_vect(1, sizeof(PDB));
370  pdb3 = (PDB *) alloc_vect(1, sizeof(PDB));
371 
372  pdb1[0].x = 0.0;
373  pdb1[0].y = 0.0;
374  pdb1[0].z = 1.0;
375 
376  j = 0;
377  n = 0;
378  phi = 0;
379  for (psi = 0; (float)psi <= psi_steps * delta && (float)psi < 360 ; psi += delta) {
380  for (theta = 0; (float)theta <= theta_steps * delta && (float)theta < 360 ; theta += delta) {
381  remap_eulers(&psi_tmp, &theta_tmp, &phi_tmp,
382  (eu_range[0][0] + psi)*ROT_CONV,
383  (eu_range[1][0] + theta)*ROT_CONV,
384  (eu_range[2][0] + phi)*ROT_CONV,
385  0.0, 0.0, 0.0);
386  *(curr_eulers + j + 0) = psi_tmp;
387  *(curr_eulers + j + 1) = theta_tmp;
388  *(curr_eulers + j + 2) = phi_tmp;
389  n++;
390  j += 3;
391  }
392  }
393 
394  partial_count = n;
395 
396  printf("lib_eul> Euler angles, initial combinations of psi and phi angles %lu (delta = %f deg.)\n", partial_count, delta);
397 
398  for (j = 0; j < partial_count; j++) *(degenerate + j) = 0;
399 
400  k = 0;
401  printf("lib_eul> Searching for redundant orientations ");
402  for (j = 0; j < partial_count; j++) if (*(degenerate + j) == 0) {
403  if (fmod(j + 1, 1000) == 0.0)printf(".");
404  rot_euler(pdb1, pdb2, 1, *(curr_eulers + j * 3 + 0), *(curr_eulers + j * 3 + 1), *(curr_eulers + j * 3 + 2));
405  for (i = j + 1; i < partial_count; i++) if (*(degenerate + i) == 0) {
406  rot_euler(pdb1, pdb3, 1, *(curr_eulers + i * 3 + 0), *(curr_eulers + i * 3 + 1), *(curr_eulers + i * 3 + 2));
407  if ((pdb2[0].x - pdb3[0].x) * (pdb2[0].x - pdb3[0].x) + (pdb2[0].y - pdb3[0].y) * (pdb2[0].y - pdb3[0].y) +
408  (pdb2[0].z - pdb3[0].z) * (pdb2[0].z - pdb3[0].z) < ((2.0 * sin(0.7 * delta * ROT_CONV / 2.0)) * (2.0 * sin(0.7 * delta * ROT_CONV / 2.0)))) {
409  k++;
410  *(degenerate + i) = 1;
411  }
412  }
413  }
414 
415  printf("\n");
416  *eu_count = (partial_count - k) * (phi_steps + 1);
417  curr_count = (partial_count - k) * (phi_steps + 1);
418 
419  /* allocate memors */
420  *eu_store = (float *) alloc_vect(curr_count * phi_steps * 3, sizeof(float));
421  h = 0;
422  printf("lib_eul> Adding psi angle to reduced set...\n");
423  for (j = 0; j < partial_count; j++) {
424  if (*(degenerate + j) != 1) {
425  for (phi = 0; (float)phi <= phi_steps * delta && (float)phi < 360 ; phi += delta) {
426  *(*eu_store + h * 3 + 0) = *(curr_eulers + j * 3 + 0);
427  *(*eu_store + h * 3 + 1) = *(curr_eulers + j * 3 + 1);
428  *(*eu_store + h * 3 + 2) = phi * ROT_CONV;
429  h++;
430  }
431  }
432  }
433 
434  *eu_count = h;
435 
436  printf("lib_eul> Euler angles, final number %lu (delta = %f deg.)\n", *eu_count, delta);
437 
438  free_vect_and_zero_ptr((void**)&pdb1);
439  free_vect_and_zero_ptr((void**)&pdb2);
440  free_vect_and_zero_ptr((void**)&pdb3);
441  free_vect_and_zero_ptr((void**)&curr_eulers);
442  free_vect_and_zero_ptr((void**)&degenerate);
443 }
444 
445 /* returns cosine of deviation angle between two rotations */
446 /* as defined by Gabb et al., J. Mol. Biol. 272:106-120, 1997. */
447 /*=====================================================================*/
448 double deviation_cosine(double matrix1[3][3], double matrix2[3][3])
449 {
450  double trace;
451  int i, j;
452 
453  trace = 0;
454  for (i = 0; i < 3; ++i) for (j = 0; j < 3; ++j) trace += matrix1[i][j] * matrix2[i][j];
455  return (trace - 1.0) / 2.0;
456 }
457 
458 /* checks if two orientations are within 1 degree*/
459 /* this can be slow if one of the orientations remains the same in a loop*/
460 /*=====================================================================*/
461 char similar_eulers(double a1, double a2, double a3, double b1, double b2, double b3)
462 {
463 
464  double deviation_cosine;
465  double trace;
466  double matrix1[3][3], matrix2[3][3];
467  int i, j;
468 
469  get_rot_matrix(matrix2, a1, a2, a3);
470  get_rot_matrix(matrix1, b1, b2, b3);
471  trace = 0;
472  for (i = 0; i < 3; ++i) for (j = 0; j < 3; ++j) trace += matrix2[i][j] * matrix1[i][j];
473  deviation_cosine = (trace - 1.0) / 2.0;
474  if (deviation_cosine <= 0.9998477) return 0;
475  else return 1;
476 }
477 
478 /* This subroutine generates a nondegenerate set of Euler angles */
479 /* in the specified scan range. For the full sphere, the number */
480 /* of points is almost identical to the spiral method but without */
481 /* the helical slant and the weirdness at the poles. Angle */
482 /* generation for subintervals is far superior and even cases */
483 /* where the range can't be evenly devided by delta are handled */
484 /* gracefully. */
485 /* The method works by dividing the sphere into slices and */
486 /* determining how many psi angles need to be in a slice to re- */
487 /* produce the same spacing as on the equator. */
488 /*=====================================================================*/
489 void eu_proportional(double eu_range[3][2], double delta,
490  unsigned long *eu_count, float **eu_store)
491 {
492  double psi, theta, phi;
493  double psi_ang_dist, psi_real_dist;
494  double theta_real_dist, phi_real_dist;
495  double psi_steps, theta_steps, phi_steps;
496  double psi_range, theta_range, phi_range;
497  unsigned long u, j;
498  const char *program = "lib_eul";
499 
500  if ((eu_range[0][1] - eu_range[0][0]) / delta < -1 ||
501  (eu_range[1][1] - eu_range[1][0]) / delta < -1 ||
502  (eu_range[2][1] - eu_range[2][0]) / delta < -1) {
503  error_negative_euler(15115, program);
504  }
505 
506  psi_range = eu_range[0][1] - eu_range[0][0];
507  theta_range = eu_range[1][1] - eu_range[1][0];
508  phi_range = eu_range[2][1] - eu_range[2][0];
509 
510  /* Use rounding instead of CEIL to avoid rounding up at x.001 */
511 
512  phi_steps = rint((phi_range / delta) + 0.499);
513  phi_real_dist = phi_range / phi_steps;
514 
515  theta_steps = rint((theta_range / delta) + 0.499);
516  theta_real_dist = theta_range / theta_steps;
517 
518  /* Computes the number of angles that will be generated */
519 
520  u = 0;
521  for (phi = eu_range[2][0]; phi < 360.0 &&
522  phi <= eu_range[2][1]; phi += phi_real_dist) {
523  for (theta = eu_range[1][0]; theta <= 180.0 &&
524  theta <= eu_range[1][1]; theta += theta_real_dist) {
525  if (theta == 0.0 || theta == 180.0) {
526  psi_steps = 1;
527  } else {
528  psi_steps = rint(360.0 * cos((90.0 - theta) * ROT_CONV) / delta);
529  }
530  psi_ang_dist = 360.0 / psi_steps;
531  psi_real_dist = psi_range / (ceil(psi_range / psi_ang_dist));
532  for (psi = eu_range[0][0]; psi < 360.0 &&
533  psi <= eu_range[0][1]; psi += psi_real_dist) {
534  u++;
535  }
536  }
537  }
538 
539  *eu_count = u;
540 
541  /* allocate memory */
542  *eu_store = (float *) alloc_vect(*eu_count * 3, sizeof(float));
543 
544  j = 0;
545  for (phi = eu_range[2][0]; phi < 360.0 &&
546  phi <= eu_range[2][1]; phi += phi_real_dist) {
547  for (theta = eu_range[1][0]; theta <= 180.0 &&
548  theta <= eu_range[1][1]; theta += theta_real_dist) {
549  if (theta == 0.0 || theta == 180.0) {
550  psi_steps = 1;
551  } else {
552  psi_steps = rint(360.0 * cos((90.0 - theta) * ROT_CONV) / delta);
553  }
554  psi_ang_dist = 360.0 / psi_steps;
555  psi_real_dist = psi_range / (ceil(psi_range / psi_ang_dist));
556  for (psi = eu_range[0][0]; psi < 360.0 &&
557  psi <= eu_range[0][1]; psi += psi_real_dist) {
558 
559  *(*eu_store + j * 3 + 0) = (float)psi * ROT_CONV;
560  *(*eu_store + j * 3 + 1) = (float)theta * ROT_CONV;
561  *(*eu_store + j * 3 + 2) = (float)phi * ROT_CONV;
562 
563  j++;
564  }
565  }
566  }
567 
568  printf("lib_eul> Proportional Euler angles distribution, total number %lu (delta = %f deg.)\n", *eu_count, delta);
569 
570  return;
571 
572 }
573 
574 
575 
576 
577 
578 
579 
580 
581 
582 
583 
float y
Definition: situs.h:47
float z
Definition: situs.h:48
void rot_euler(PDB *pdb_original, PDB *pdb_rotate, unsigned num_atoms, double psi, double theta, double phi)
Definition: lib_pwk.cpp:98
void free_vect_and_zero_ptr(void **pvect)
Definition: lib_vec.cpp:83
void read_eulers(char *in_file, unsigned long *eu_count, float **eu_store)
Definition: lib_eul.cpp:83
void sqrt(Image< double > &op)
static double * y
void eu_spiral(double eu_range[3][2], double delta, unsigned long *eu_count, float **eu_store)
Definition: lib_eul.cpp:219
Definition: situs.h:43
double deviation_cosine(double matrix1[3][3], double matrix2[3][3])
Definition: lib_eul.cpp:448
doublereal * x
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
double theta
void error_open_filename(int error_number, const char *program, char *argv)
Definition: lib_err.cpp:67
void remap_eulers(double *psi_out, double *theta_out, double *phi_out, double psi_in, double theta_in, double phi_in, double psi_ref, double theta_ref, double phi_ref)
Definition: lib_eul.cpp:132
int in
float x
Definition: situs.h:46
double z
void error_negative_euler(int error_number, const char *program)
Definition: lib_err.cpp:243
void write_eulers(char *eu_file, unsigned long eu_count, float *eu_store, double eu_range[3][2], double delta)
Definition: lib_eul.cpp:64
#define ROT_CONV
Definition: situs.h:29
#define j
void get_rot_matrix(double dump[3][3], double psi, double theta, double phi)
Definition: lib_eul.cpp:184
double psi(const double x)
char similar_eulers(double a1, double a2, double a3, double b1, double b2, double b3)
Definition: lib_eul.cpp:461
void * alloc_vect(unsigned int n, size_t elem_size)
Definition: lib_vec.cpp:71
doublereal * u
fprintf(glob_prnt.io, "\)
#define PI
Definition: tools.h:43
void eu_sparsed(double eu_range[3][2], double delta, unsigned long *eu_count, float **eu_store)
Definition: lib_eul.cpp:340
int * n
void eu_proportional(double eu_range[3][2], double delta, unsigned long *eu_count, float **eu_store)
Definition: lib_eul.cpp:489
double * delta