1 /* This file is part of the hkl library.
3 * The hkl library is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * The hkl library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with the hkl library. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright (C) 2003-2014 Synchrotron SOLEIL
17 * L'Orme des Merisiers Saint-Aubin
18 * BP 48 91192 GIF-sur-YVETTE CEDEX
20 * Authors: Picca Frédéric-Emmanuel <picca@synchrotron-soleil.fr>
24 #define _XOPEN_SOURCE 500
25 #include <gsl/gsl_errno.h> // for gsl_set_error_handler, etc
26 #include <gsl/gsl_multimin.h> // for gsl_multimin_function, etc
27 #include <gsl/gsl_nan.h> // for GSL_NAN
28 #include <gsl/gsl_vector_double.h> // for gsl_vector_get, etc
29 #include <math.h> // for M_PI, fabs
30 #include <stddef.h> // for size_t
31 #include <stdio.h> // for fprintf, FILE
32 #include <stdlib.h> // for free
33 #include <string.h> // for NULL, strdup
34 #include "hkl-detector-private.h" // for hkl_detector_new_copy, etc
35 #include "hkl-geometry-private.h" // for _HklGeometry, etc
36 #include "hkl-lattice-private.h" // for _HklLattice, etc
37 #include "hkl-macros-private.h" // for HKL_MALLOC
38 #include "hkl-matrix-private.h" // for hkl_matrix_init_from_euler, etc
39 #include "hkl-parameter-private.h" // for hkl_parameter_fprintf, etc
40 #include "hkl-quaternion-private.h" // for hkl_quaternion_conjugate, etc
41 #include "hkl-sample-private.h" // for _HklSample, etc
42 #include "hkl-source-private.h" // for hkl_source_compute_ki
43 #include "hkl-unit-private.h" // for hkl_unit_angle_deg, etc
44 #include "hkl-vector-private.h" // for HklVector, hkl_vector_angle, etc
45 #include "hkl.h" // for HklSample, etc
46 #include "hkl/ccan/darray/darray.h" // for darray_foreach, darray_item
47 #include "hkl/ccan/list/list.h" // for list_head, list_add_tail, etc
51 static void hkl_sample_reflection_update(HklSampleReflection
*self
)
59 /* compute the _hkl using only the axes of the geometry */
60 /* first Q from angles */
61 hkl_source_compute_ki(&self
->geometry
->source
, &ki
);
63 hkl_vector_rotated_quaternion(&self
->_hkl
,
64 &darray_item(self
->geometry
->holders
, self
->detector
->idx
)->q
);
65 hkl_vector_minus_vector(&self
->_hkl
, &ki
);
67 q
= darray_item(self
->geometry
->holders
, 0)->q
;
68 hkl_quaternion_conjugate(&q
);
69 hkl_vector_rotated_quaternion(&self
->_hkl
, &q
);
72 static void hkl_sample_compute_UxUyUz(HklSample
*self
)
78 hkl_matrix_to_euler(&self
->U
, &ux
, &uy
, &uz
);
79 hkl_parameter_value_set(self
->ux
, ux
, HKL_UNIT_DEFAULT
, NULL
);
80 hkl_parameter_value_set(self
->uy
, uy
, HKL_UNIT_DEFAULT
, NULL
);
81 hkl_parameter_value_set(self
->uz
, uz
, HKL_UNIT_DEFAULT
, NULL
);
84 static int hkl_sample_compute_UB(HklSample
*self
)
88 if (!hkl_lattice_get_B(self
->lattice
, &B
))
92 hkl_matrix_times_matrix(&self
->UB
, &B
);
98 * this structure is used by the minimization gsl algorithm.
99 * in the set_UB method
107 static double set_UB_fitness(const gsl_vector
*x
, void *params
)
114 struct set_UB_t
*parameters
= params
;
115 HklSample
*sample
= parameters
->sample
;
116 const HklMatrix
*UB
= parameters
->UB
;
118 euler_x
= gsl_vector_get(x
, 0);
119 euler_y
= gsl_vector_get(x
, 1);
120 euler_z
= gsl_vector_get(x
, 2);
122 hkl_parameter_value_set(sample
->ux
, euler_x
, HKL_UNIT_DEFAULT
, NULL
);
123 hkl_parameter_value_set(sample
->uy
, euler_y
, HKL_UNIT_DEFAULT
, NULL
);
124 hkl_parameter_value_set(sample
->uz
, euler_z
, HKL_UNIT_DEFAULT
, NULL
);
125 hkl_parameter_value_set(sample
->lattice
->a
, gsl_vector_get(x
, 3), HKL_UNIT_DEFAULT
, NULL
);
126 hkl_parameter_value_set(sample
->lattice
->b
, gsl_vector_get(x
, 4), HKL_UNIT_DEFAULT
, NULL
);
127 hkl_parameter_value_set(sample
->lattice
->c
, gsl_vector_get(x
, 5), HKL_UNIT_DEFAULT
, NULL
);
128 hkl_parameter_value_set(sample
->lattice
->alpha
, gsl_vector_get(x
, 6), HKL_UNIT_DEFAULT
, NULL
);
129 hkl_parameter_value_set(sample
->lattice
->beta
, gsl_vector_get(x
, 7), HKL_UNIT_DEFAULT
, NULL
);
130 hkl_parameter_value_set(sample
->lattice
->gamma
, gsl_vector_get(x
, 8), HKL_UNIT_DEFAULT
, NULL
);
132 hkl_matrix_init_from_euler(&sample
->U
, euler_x
, euler_y
, euler_z
);
133 if (!hkl_sample_compute_UB(sample
))
139 double tmp
= UB
->data
[i
][j
] - sample
->UB
.data
[i
][j
];
140 fitness
+= tmp
* tmp
;
145 static double mono_crystal_fitness(const gsl_vector
*x
, void *params
)
152 HklSample
*sample
= params
;
153 HklSampleReflection
*reflection
;
155 euler_x
= gsl_vector_get(x
, 0);
156 euler_y
= gsl_vector_get(x
, 1);
157 euler_z
= gsl_vector_get(x
, 2);
159 hkl_parameter_value_set(sample
->ux
, euler_x
, HKL_UNIT_DEFAULT
, NULL
);
160 hkl_parameter_value_set(sample
->uy
, euler_y
, HKL_UNIT_DEFAULT
, NULL
);
161 hkl_parameter_value_set(sample
->uz
, euler_z
, HKL_UNIT_DEFAULT
, NULL
);
162 hkl_parameter_value_set(sample
->lattice
->a
, gsl_vector_get(x
, 3), HKL_UNIT_DEFAULT
, NULL
);
163 hkl_parameter_value_set(sample
->lattice
->b
, gsl_vector_get(x
, 4), HKL_UNIT_DEFAULT
, NULL
);
164 hkl_parameter_value_set(sample
->lattice
->c
, gsl_vector_get(x
, 5), HKL_UNIT_DEFAULT
, NULL
);
165 hkl_parameter_value_set(sample
->lattice
->alpha
, gsl_vector_get(x
, 6), HKL_UNIT_DEFAULT
, NULL
);
166 hkl_parameter_value_set(sample
->lattice
->beta
, gsl_vector_get(x
, 7), HKL_UNIT_DEFAULT
, NULL
);
167 hkl_parameter_value_set(sample
->lattice
->gamma
, gsl_vector_get(x
, 8), HKL_UNIT_DEFAULT
, NULL
);
168 hkl_matrix_init_from_euler(&sample
->U
, euler_x
, euler_y
, euler_z
);
169 if (!hkl_sample_compute_UB(sample
))
173 list_for_each(&sample
->reflections
, reflection
, list
){
174 if(reflection
->flag
){
177 UBh
= reflection
->hkl
;
178 hkl_matrix_times_vector(&sample
->UB
, &UBh
);
181 double tmp
= UBh
.data
[j
] - reflection
->_hkl
.data
[j
];
182 fitness
+= tmp
* tmp
;
189 static int minimize(HklSample
*sample
,
190 double (* f
) (const gsl_vector
* x
, void * params
),
191 void *params
, GError
**error
)
193 gsl_multimin_fminimizer_type
const *T
= gsl_multimin_fminimizer_nmsimplex
;
194 gsl_multimin_fminimizer
*s
= NULL
;
196 gsl_multimin_function minex_func
;
201 hkl_error (error
== NULL
|| *error
== NULL
);
204 x
= gsl_vector_alloc (9);
205 gsl_vector_set (x
, 0, hkl_parameter_value_get(sample
->ux
, HKL_UNIT_DEFAULT
));
206 gsl_vector_set (x
, 1, hkl_parameter_value_get(sample
->uy
, HKL_UNIT_DEFAULT
));
207 gsl_vector_set (x
, 2, hkl_parameter_value_get(sample
->uz
, HKL_UNIT_DEFAULT
));
208 gsl_vector_set (x
, 3, hkl_parameter_value_get(sample
->lattice
->a
, HKL_UNIT_DEFAULT
));
209 gsl_vector_set (x
, 4, hkl_parameter_value_get(sample
->lattice
->b
, HKL_UNIT_DEFAULT
));
210 gsl_vector_set (x
, 5, hkl_parameter_value_get(sample
->lattice
->c
, HKL_UNIT_DEFAULT
));
211 gsl_vector_set (x
, 6, hkl_parameter_value_get(sample
->lattice
->alpha
, HKL_UNIT_DEFAULT
));
212 gsl_vector_set (x
, 7, hkl_parameter_value_get(sample
->lattice
->beta
, HKL_UNIT_DEFAULT
));
213 gsl_vector_set (x
, 8, hkl_parameter_value_get(sample
->lattice
->gamma
, HKL_UNIT_DEFAULT
));
215 /* Set initial step sizes to 1 */
216 ss
= gsl_vector_alloc (9);
217 gsl_vector_set (ss
, 0, sample
->ux
->fit
);
218 gsl_vector_set (ss
, 1, sample
->uy
->fit
);
219 gsl_vector_set (ss
, 2, sample
->uz
->fit
);
220 gsl_vector_set (ss
, 3, sample
->lattice
->a
->fit
);
221 gsl_vector_set (ss
, 4, sample
->lattice
->b
->fit
);
222 gsl_vector_set (ss
, 5, sample
->lattice
->c
->fit
);
223 gsl_vector_set (ss
, 6, sample
->lattice
->alpha
->fit
);
224 gsl_vector_set (ss
, 7, sample
->lattice
->beta
->fit
);
225 gsl_vector_set (ss
, 8, sample
->lattice
->gamma
->fit
);
227 /* Initialize method and iterate */
230 minex_func
.params
= params
;
231 s
= gsl_multimin_fminimizer_alloc (T
, 9);
232 gsl_set_error_handler_off();
233 gsl_multimin_fminimizer_set (s
, &minex_func
, x
, ss
);
236 status
= gsl_multimin_fminimizer_iterate(s
);
239 size
= gsl_multimin_fminimizer_size (s
);
240 status
= gsl_multimin_test_size (size
, HKL_EPSILON
/ 2.);
241 } while (status
== GSL_CONTINUE
&& iter
< 10000);
244 gsl_multimin_fminimizer_free(s
);
245 gsl_set_error_handler (NULL
);
247 if (status
== GSL_CONTINUE
)
265 HklSample
* hkl_sample_new(const char *name
)
267 HklSample
*self
= NULL
;
269 /* check parameters */
273 self
= HKL_MALLOC(HklSample
);
275 self
->name
= strdup(name
);
276 self
->lattice
= hkl_lattice_new_default();
277 hkl_matrix_init(&self
->U
,1, 0, 0, 0, 1, 0, 0, 0, 1);
278 hkl_matrix_init(&self
->UB
,1, 0, 0, 0, 1, 0, 0, 0, 1);
280 self
->ux
= hkl_parameter_new("ux", -M_PI
, 0., M_PI
,
283 &hkl_unit_angle_deg
);
284 self
->uy
= hkl_parameter_new("uy", -M_PI
, 0., M_PI
,
287 &hkl_unit_angle_deg
);
288 self
->uz
= hkl_parameter_new("uz", -M_PI
, 0., M_PI
,
291 &hkl_unit_angle_deg
);
293 hkl_sample_compute_UB(self
);
294 list_head_init(&self
->reflections
);
295 self
->n_reflections
= 0;
301 * hkl_sample_new_copy: (skip)
308 HklSample
*hkl_sample_new_copy(const HklSample
*self
)
310 HklSample
*dup
= NULL
;
311 HklSampleReflection
*reflection
;
313 /* check parameters */
317 dup
= HKL_MALLOC(HklSample
);
319 dup
->name
= strdup(self
->name
);
320 dup
->lattice
= hkl_lattice_new_copy(self
->lattice
);
323 dup
->ux
= hkl_parameter_new_copy(self
->ux
);
324 dup
->uy
= hkl_parameter_new_copy(self
->uy
);
325 dup
->uz
= hkl_parameter_new_copy(self
->uz
);
327 /* copy the reflections */
328 list_head_init(&dup
->reflections
);
329 list_for_each(&self
->reflections
, reflection
, list
){
330 list_add_tail(&dup
->reflections
,
331 &hkl_sample_reflection_new_copy(reflection
)->list
);
333 dup
->n_reflections
= self
->n_reflections
;
339 * hkl_sample_free: (skip)
344 void hkl_sample_free(HklSample
*self
)
346 HklSampleReflection
*reflection
;
347 HklSampleReflection
*next
;
353 hkl_lattice_free(self
->lattice
);
354 hkl_parameter_free(self
->ux
);
355 hkl_parameter_free(self
->uy
);
356 hkl_parameter_free(self
->uz
);
357 list_for_each_safe(&self
->reflections
, reflection
, next
, list
){
358 list_del(&reflection
->list
);
359 hkl_sample_reflection_free(reflection
);
365 * hkl_sample_name_get:
366 * @self: the this ptr
368 * Return value: the name of the sample
370 const char *hkl_sample_name_get(const HklSample
*self
)
376 * hkl_sample_name_set:
377 * @self: the this ptr
378 * @name: the new name to set
380 * set the name of the sample
382 void hkl_sample_name_set(HklSample
*self
, const char *name
)
386 self
->name
= strdup(name
);
390 * hkl_sample_lattice_get:
391 * @self: the this ptr
393 * Return value: the lattice parameters of the sample.
395 const HklLattice
*hkl_sample_lattice_get(HklSample
*self
)
397 return self
->lattice
;
401 * hkl_sample_lattice_set:
402 * @self: the this ptr
403 * @lattice: the lattice to set
405 void hkl_sample_lattice_set(HklSample
*self
, const HklLattice
*lattice
)
407 hkl_lattice_lattice_set(self
->lattice
, lattice
);
408 hkl_sample_compute_UB(self
);
413 * @self: the this ptr
415 * Return value: the ux part of the U matrix.
417 const HklParameter
*hkl_sample_ux_get(const HklSample
*self
)
424 * @self: the this ptr
426 * Return value: the uy part of the U matrix.
428 const HklParameter
*hkl_sample_uy_get(const HklSample
*self
)
435 * @self: the this ptr
437 * Return value: the uz part of the U matrix.
439 const HklParameter
*hkl_sample_uz_get(const HklSample
*self
)
446 * @self: the this ptr
447 * @ux: the ux parameter to set
448 * @error: return location for a GError, or NULL
450 * set the ux part of the U matrix.
452 * Returns: TRUE on success, FALSE if an error occurred
454 int hkl_sample_ux_set(HklSample
*self
,
455 const HklParameter
*ux
,
458 hkl_error (error
== NULL
|| *error
== NULL
);
460 if(!hkl_parameter_init_copy(self
->ux
, ux
, error
)){
461 g_assert (error
== NULL
|| *error
!= NULL
);
464 g_assert (error
== NULL
|| *error
== NULL
);
466 hkl_matrix_init_from_euler(&self
->U
,
467 hkl_parameter_value_get(self
->ux
, HKL_UNIT_DEFAULT
),
468 hkl_parameter_value_get(self
->uy
, HKL_UNIT_DEFAULT
),
469 hkl_parameter_value_get(self
->uz
, HKL_UNIT_DEFAULT
));
470 hkl_sample_compute_UB(self
);
477 * @self: the this ptr
478 * @uy: the uy parameter to set
479 * @error: return location for a GError, or NULL
481 * set the uy part of the U matrix.
483 * Returns: TRUE on success, FALSE if an error occurred
485 int hkl_sample_uy_set(HklSample
*self
, const HklParameter
*uy
,
488 hkl_error (error
== NULL
|| *error
== NULL
);
490 if(!hkl_parameter_init_copy(self
->uy
, uy
, error
)){
491 g_assert (error
== NULL
|| *error
!= NULL
);
494 g_assert (error
== NULL
|| *error
== NULL
);
496 hkl_matrix_init_from_euler(&self
->U
,
497 hkl_parameter_value_get(self
->ux
, HKL_UNIT_DEFAULT
),
498 hkl_parameter_value_get(self
->uy
, HKL_UNIT_DEFAULT
),
499 hkl_parameter_value_get(self
->uz
, HKL_UNIT_DEFAULT
));
500 hkl_sample_compute_UB(self
);
505 * @self: the this ptr
506 * @uz: the uz parameter to set
507 * @error: return location for a GError, or NULL
509 * set the uz part of the U matrix.
511 * Returns: TRUE on success, FALSE if an error occurred
513 int hkl_sample_uz_set(HklSample
*self
, const HklParameter
*uz
,
516 hkl_error (error
== NULL
|| *error
== NULL
);
518 if(!hkl_parameter_init_copy(self
->uz
, uz
, error
)){
519 g_assert (error
== NULL
|| *error
!= NULL
);
522 g_assert (error
== NULL
|| *error
== NULL
);
524 hkl_matrix_init_from_euler(&self
->U
,
525 hkl_parameter_value_get(self
->ux
, HKL_UNIT_DEFAULT
),
526 hkl_parameter_value_get(self
->uy
, HKL_UNIT_DEFAULT
),
527 hkl_parameter_value_get(self
->uz
, HKL_UNIT_DEFAULT
));
528 hkl_sample_compute_UB(self
);
533 * @self: the this ptr
535 * Return value: the U matrix of the sample
537 const HklMatrix
*hkl_sample_U_get(const HklSample
*self
)
542 void hkl_sample_U_set(HklSample
*self
, const HklMatrix
*U
)
546 hkl_matrix_matrix_set(&self
->U
, U
);
547 hkl_sample_compute_UB(self
);
548 hkl_matrix_to_euler(&self
->U
, &x
, &y
, &z
);
549 hkl_parameter_value_set(self
->ux
, x
, HKL_UNIT_DEFAULT
, NULL
);
550 hkl_parameter_value_set(self
->uy
, y
, HKL_UNIT_DEFAULT
, NULL
);
551 hkl_parameter_value_set(self
->uz
, z
, HKL_UNIT_DEFAULT
, NULL
);
556 * @self: the this ptr.
558 * Return value: get the UB matrix of the sample
560 const HklMatrix
*hkl_sample_UB_get(const HklSample
*self
)
567 * @self: the sample to modify
568 * @UB: the UB matrix to set
570 * Set the UB matrix using an external UB matrix. In fact you give
571 * the UB matrix but only the U matrix of the sample is affected by
572 * this operation. We keep the B matrix constant.
573 * U * B = UB -> U = UB * B^-1
575 int hkl_sample_UB_set(HklSample
*self
, const HklMatrix
*UB
,
578 struct set_UB_t params
= {
583 return minimize(self
, set_UB_fitness
, ¶ms
, error
);
587 * hkl_sample_n_reflections_get: (skip)
588 * @self: the this ptr
590 * return the number of reflections of the sample
594 size_t hkl_sample_n_reflections_get(const HklSample
*self
)
596 return self
->n_reflections
;
600 * hkl_sample_reflections_first_get: (skip)
601 * @self: the this ptr
603 * Return value: the first HklSampleReflection of the sample.
605 HklSampleReflection
*hkl_sample_reflections_first_get(HklSample
*self
)
607 return list_top(&self
->reflections
, HklSampleReflection
, list
);
611 * hkl_sample_reflections_next_get: (skip)
612 * @self: the this ptr
613 * @reflection: the current reflection
615 * Return value: (allow-none): the next reflection or NULL if no more reflection
617 HklSampleReflection
*hkl_sample_reflections_next_get(HklSample
*self
,
618 HklSampleReflection
*reflection
)
620 return list_next(&self
->reflections
, reflection
, list
);
624 * hkl_sample_add_reflection: (skip)
625 * @self: the this ptr
626 * @reflection: The reflection to add
628 * add a reflection to the sample, if the reflection is already part
629 * of the sample reflection list, this method does nothing.
631 void hkl_sample_add_reflection(HklSample
*self
,
632 HklSampleReflection
*reflection
)
634 HklSampleReflection
*ref
;
636 list_for_each(&self
->reflections
, ref
, list
){
637 if (ref
== reflection
)
641 list_add_tail(&self
->reflections
, &reflection
->list
);
642 self
->n_reflections
++;
646 * hkl_sample_del_reflection:
647 * @self: the this ptr
648 * @reflection: the reflection to remove.
650 * remove an HklSampleRefelction from the reflections list.
652 void hkl_sample_del_reflection(HklSample
*self
,
653 HklSampleReflection
*reflection
)
655 list_del(&reflection
->list
);
656 hkl_sample_reflection_free(reflection
);
657 self
->n_reflections
--;
661 * hkl_sample_compute_UB_busing_levy:
662 * @self: the this ptr
663 * @r1: the first #HklsampleReflection
664 * @r2: the second #HklSampleReflection
666 * compute the UB matrix using the Busing and Levy method
669 * Returns: 0 or 1 if it succeed
671 int hkl_sample_compute_UB_busing_levy(HklSample
*self
,
672 const HklSampleReflection
*r1
,
673 const HklSampleReflection
*r2
,
677 if (!hkl_vector_is_colinear(&r1
->hkl
, &r2
->hkl
)) {
683 /* Compute matrix Tc from r1 and r2. */
686 hkl_lattice_get_B(self
->lattice
, &B
);
687 hkl_matrix_times_vector(&B
, &h1c
);
688 hkl_matrix_times_vector(&B
, &h2c
);
689 hkl_matrix_init_from_two_vector(&Tc
, &h1c
, &h2c
);
690 hkl_matrix_transpose(&Tc
);
693 hkl_matrix_init_from_two_vector(&self
->U
,
694 &r1
->_hkl
, &r2
->_hkl
);
695 hkl_matrix_times_matrix(&self
->U
, &Tc
);
696 hkl_sample_compute_UxUyUz(self
);
697 hkl_sample_compute_UB(self
);
706 * @self: the this ptr
710 * Returns: the fitness of the affined #HklSample
712 int hkl_sample_affine(HklSample
*self
, GError
**error
)
714 return minimize(self
, mono_crystal_fitness
, self
, error
);
718 * hkl_sample_get_reflection_mesured_angle:
719 * @self: the this ptr
720 * @r1: the first #HklSampleReflection
721 * @r2: the second #HklSampleReflection
723 * get the mesured angles between two #HklSampleReflection
725 * Returns: the mesured angle beetween them
727 double hkl_sample_get_reflection_mesured_angle(const HklSample
*self
,
728 const HklSampleReflection
*r1
,
729 const HklSampleReflection
*r2
)
731 return hkl_vector_angle(&r1
->_hkl
,
736 * hkl_sample_get_reflection_theoretical_angle:
737 * @self: the this ptr
738 * @r1: the first #HklSampleReflection
739 * @r2: the second #HklSampleReflection
741 * get the theoretical angles between two #HklSampleReflection
743 * Returns: the theoretical angle beetween them
745 double hkl_sample_get_reflection_theoretical_angle(const HklSample
*self
,
746 const HklSampleReflection
*r1
,
747 const HklSampleReflection
*r2
)
754 hkl_matrix_times_vector(&self
->UB
, &hkl1
);
755 hkl_matrix_times_vector(&self
->UB
, &hkl2
);
757 return hkl_vector_angle(&hkl1
, &hkl2
);
761 * hkl_sample_fprintf: (skip)
765 * print to a file a sample
767 void hkl_sample_fprintf(FILE *f
, const HklSample
*self
)
772 fprintf(f
, "\nSample name: \"%s\"", self
->name
);
774 fprintf(f
, "\nLattice parameters:");
776 hkl_parameter_fprintf(f
, self
->lattice
->a
);
778 hkl_parameter_fprintf(f
, self
->lattice
->b
);
780 hkl_parameter_fprintf(f
, self
->lattice
->c
);
782 hkl_parameter_fprintf(f
, self
->lattice
->alpha
);
784 hkl_parameter_fprintf(f
, self
->lattice
->beta
);
786 hkl_parameter_fprintf(f
, self
->lattice
->gamma
);
788 hkl_parameter_fprintf(f
, self
->ux
);
790 hkl_parameter_fprintf(f
, self
->uy
);
792 hkl_parameter_fprintf(f
, self
->uz
);
793 fprintf(f
, "\nUB:\n");
794 hkl_matrix_fprintf(f
, &self
->UB
);
796 if (!list_empty(&self
->reflections
)){
797 HklSampleReflection
*reflection
;
800 reflection
= list_top(&self
->reflections
, HklSampleReflection
, list
);
802 fprintf(f
, "Reflections:");
804 fprintf(f
, "%-10.6s %-10.6s %-10.6s", "h", "k", "l");
805 darray_foreach(axis
, reflection
->geometry
->axes
){
806 fprintf(f
, " %-10.6s", (*axis
)->name
);
809 list_for_each(&self
->reflections
, reflection
, list
){
810 fprintf(f
, "\n%-10.6f %-10.6f %-10.6f",
811 reflection
->hkl
.data
[0],
812 reflection
->hkl
.data
[1],
813 reflection
->hkl
.data
[2]);
814 darray_foreach(axis
, reflection
->geometry
->axes
){
815 fprintf(f
, " %-10.6f", hkl_parameter_value_get(*axis
, HKL_UNIT_USER
));
821 /***********************/
822 /* HklSampleReflection */
823 /***********************/
826 * hkl_sample_reflection_new:
837 HklSampleReflection
*hkl_sample_reflection_new(const HklGeometry
*geometry
,
838 const HklDetector
*detector
,
839 double h
, double k
, double l
,
842 HklSampleReflection
*self
;
844 if (!geometry
|| !detector
)
847 self
= HKL_MALLOC(HklSampleReflection
);
849 self
->geometry
= hkl_geometry_new_copy(geometry
);
850 self
->detector
= hkl_detector_new_copy(detector
);
851 self
->hkl
.data
[0] = h
;
852 self
->hkl
.data
[1] = k
;
853 self
->hkl
.data
[2] = l
;
856 hkl_sample_reflection_update(self
);
862 * hkl_sample_reflection_new_copy: (skip)
869 HklSampleReflection
*hkl_sample_reflection_new_copy(const HklSampleReflection
*self
)
871 HklSampleReflection
*dup
= NULL
;
873 dup
= HKL_MALLOC(HklSampleReflection
);
875 dup
->geometry
= hkl_geometry_new_copy(self
->geometry
);
876 dup
->detector
= hkl_detector_new_copy(self
->detector
);
877 dup
->hkl
= self
->hkl
;
878 dup
->_hkl
= self
->_hkl
;
879 dup
->flag
= self
->flag
;
885 * hkl_sample_reflection_free: (skip)
890 void hkl_sample_reflection_free(HklSampleReflection
*self
)
892 hkl_geometry_free(self
->geometry
);
893 hkl_detector_free(self
->detector
);
898 * hkl_sample_reflection_hkl_get:
899 * @self: the this ptr
900 * @h: (out caller-allocates): the h-coordinate of the #HklSampleReflection
901 * @k: (out caller-allocates): the k-coordinate of the #HklSampleReflection
902 * @l: (out caller-allocates): the l-coordinate of the #HklSampleReflection
904 * get the hkl coordinates of the #HklSampleReflection
906 void hkl_sample_reflection_hkl_get(const HklSampleReflection
*self
,
907 double *h
, double *k
, double *l
)
909 *h
= self
->hkl
.data
[0];
910 *k
= self
->hkl
.data
[1];
911 *l
= self
->hkl
.data
[2];
915 * hkl_sample_reflection_hkl_set:
916 * @self: the this ptr
917 * @h: the h-coordinate of the #HklSampleReflection
918 * @k: the k-coordinate of the #HklSampleReflection
919 * @l: the l-coordinate of the #HklSampleReflection
920 * @error: return location for a GError, or NULL
922 * set the hkl coordinates of the #HklSampleReflection
924 * Returns: TRUE on success, FALSE if an error occurred
926 int hkl_sample_reflection_hkl_set(HklSampleReflection
*self
,
927 double h
, double k
, double l
,
930 hkl_error (error
== NULL
|| *error
== NULL
);
932 if((fabs(h
) + fabs(k
) + fabs(l
) < HKL_EPSILON
)){
934 HKL_SAMPLE_REFLECTION_ERROR
,
935 HKL_SAMPLE_REFLECTION_ERROR_HKL_SET
,
936 "it is not allow to set a null hkl reflection\n");
940 self
->hkl
.data
[0] = h
;
941 self
->hkl
.data
[1] = k
;
942 self
->hkl
.data
[2] = l
;
948 * hkl_sample_reflection_flag_get: (skip)
951 * get the flag of the reflection
953 int hkl_sample_reflection_flag_get(const HklSampleReflection
*self
)
959 * hkl_sample_reflection_flag_set: (skip)
963 * set the flag of the reglection
965 void hkl_sample_reflection_flag_set(HklSampleReflection
*self
, int flag
)
971 * hkl_sample_reflection_geometry_get: (skip)
974 * set the geometry of the reflection
976 const HklGeometry
*hkl_sample_reflection_geometry_get(HklSampleReflection
*self
)
978 return self
->geometry
;
982 * hkl_sample_reflection_geometry_set: (skip)
986 * set the geometry of the reflection
988 void hkl_sample_reflection_geometry_set(HklSampleReflection
*self
,
989 const HklGeometry
*geometry
)
992 if(self
->geometry
!= geometry
){
993 hkl_geometry_free(self
->geometry
);
994 self
->geometry
= hkl_geometry_new_copy(geometry
);
997 self
->geometry
= hkl_geometry_new_copy(geometry
);
999 hkl_sample_reflection_update(self
);