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 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
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
);
300 * hkl_sample_new_copy: (skip)
307 HklSample
*hkl_sample_new_copy(const HklSample
*self
)
309 HklSample
*dup
= NULL
;
310 HklSampleReflection
*reflection
;
312 /* check parameters */
316 dup
= HKL_MALLOC(HklSample
);
318 dup
->name
= strdup(self
->name
);
319 dup
->lattice
= hkl_lattice_new_copy(self
->lattice
);
322 dup
->ux
= hkl_parameter_new_copy(self
->ux
);
323 dup
->uy
= hkl_parameter_new_copy(self
->uy
);
324 dup
->uz
= hkl_parameter_new_copy(self
->uz
);
326 /* copy the reflections */
327 list_head_init(&dup
->reflections
);
328 list_for_each(&self
->reflections
, reflection
, list
){
329 list_add_tail(&dup
->reflections
,
330 &hkl_sample_reflection_new_copy(reflection
)->list
);
337 * hkl_sample_free: (skip)
342 void hkl_sample_free(HklSample
*self
)
344 HklSampleReflection
*reflection
;
345 HklSampleReflection
*next
;
351 hkl_lattice_free(self
->lattice
);
352 hkl_parameter_free(self
->ux
);
353 hkl_parameter_free(self
->uy
);
354 hkl_parameter_free(self
->uz
);
355 list_for_each_safe(&self
->reflections
, reflection
, next
, list
){
356 list_del(&reflection
->list
);
357 hkl_sample_reflection_free(reflection
);
363 * hkl_sample_name_get:
364 * @self: the this ptr
366 * Return value: the name of the sample
368 const char *hkl_sample_name_get(const HklSample
*self
)
374 * hkl_sample_name_set:
375 * @self: the this ptr
376 * @name: the new name to set
378 * set the name of the sample
380 void hkl_sample_name_set(HklSample
*self
, const char *name
)
384 self
->name
= strdup(name
);
388 * hkl_sample_lattice_get:
389 * @self: the this ptr
391 * Return value: the lattice parameters of the sample.
393 const HklLattice
*hkl_sample_lattice_get(HklSample
*self
)
395 return self
->lattice
;
399 * hkl_sample_lattice_set:
400 * @self: the this ptr
401 * @lattice: the lattice to set
403 void hkl_sample_lattice_set(HklSample
*self
, const HklLattice
*lattice
)
405 hkl_lattice_lattice_set(self
->lattice
, lattice
);
406 hkl_sample_compute_UB(self
);
411 * @self: the this ptr
413 * Return value: the ux part of the U matrix.
415 const HklParameter
*hkl_sample_ux_get(const HklSample
*self
)
422 * @self: the this ptr
424 * Return value: the uy part of the U matrix.
426 const HklParameter
*hkl_sample_uy_get(const HklSample
*self
)
433 * @self: the this ptr
435 * Return value: the uz part of the U matrix.
437 const HklParameter
*hkl_sample_uz_get(const HklSample
*self
)
444 * @self: the this ptr
445 * @ux: the ux parameter to set
446 * @error: return location for a GError, or NULL
448 * set the ux part of the U matrix.
450 * Returns: TRUE on success, FALSE if an error occurred
452 int hkl_sample_ux_set(HklSample
*self
,
453 const HklParameter
*ux
,
456 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
458 if(!hkl_parameter_init_copy(self
->ux
, ux
, error
)){
459 g_assert (error
== NULL
|| *error
!= NULL
);
462 g_assert (error
== NULL
|| *error
== NULL
);
464 hkl_matrix_init_from_euler(&self
->U
,
465 hkl_parameter_value_get(self
->ux
, HKL_UNIT_DEFAULT
),
466 hkl_parameter_value_get(self
->uy
, HKL_UNIT_DEFAULT
),
467 hkl_parameter_value_get(self
->uz
, HKL_UNIT_DEFAULT
));
468 hkl_sample_compute_UB(self
);
475 * @self: the this ptr
476 * @uy: the uy parameter to set
477 * @error: return location for a GError, or NULL
479 * set the uy part of the U matrix.
481 * Returns: TRUE on success, FALSE if an error occurred
483 int hkl_sample_uy_set(HklSample
*self
, const HklParameter
*uy
,
486 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
488 if(!hkl_parameter_init_copy(self
->uy
, uy
, error
)){
489 g_assert (error
== NULL
|| *error
!= NULL
);
492 g_assert (error
== NULL
|| *error
== NULL
);
494 hkl_matrix_init_from_euler(&self
->U
,
495 hkl_parameter_value_get(self
->ux
, HKL_UNIT_DEFAULT
),
496 hkl_parameter_value_get(self
->uy
, HKL_UNIT_DEFAULT
),
497 hkl_parameter_value_get(self
->uz
, HKL_UNIT_DEFAULT
));
498 hkl_sample_compute_UB(self
);
503 * @self: the this ptr
504 * @uz: the uz parameter to set
505 * @error: return location for a GError, or NULL
507 * set the uz part of the U matrix.
509 * Returns: TRUE on success, FALSE if an error occurred
511 int hkl_sample_uz_set(HklSample
*self
, const HklParameter
*uz
,
514 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
516 if(!hkl_parameter_init_copy(self
->uz
, uz
, error
)){
517 g_assert (error
== NULL
|| *error
!= NULL
);
520 g_assert (error
== NULL
|| *error
== NULL
);
522 hkl_matrix_init_from_euler(&self
->U
,
523 hkl_parameter_value_get(self
->ux
, HKL_UNIT_DEFAULT
),
524 hkl_parameter_value_get(self
->uy
, HKL_UNIT_DEFAULT
),
525 hkl_parameter_value_get(self
->uz
, HKL_UNIT_DEFAULT
));
526 hkl_sample_compute_UB(self
);
531 * @self: the this ptr
533 * Return value: the U matrix of the sample
535 const HklMatrix
*hkl_sample_U_get(const HklSample
*self
)
540 void hkl_sample_U_set(HklSample
*self
, const HklMatrix
*U
)
544 hkl_matrix_matrix_set(&self
->U
, U
);
545 hkl_sample_compute_UB(self
);
546 hkl_matrix_to_euler(&self
->U
, &x
, &y
, &z
);
547 hkl_parameter_value_set(self
->ux
, x
, HKL_UNIT_DEFAULT
, NULL
);
548 hkl_parameter_value_set(self
->uy
, y
, HKL_UNIT_DEFAULT
, NULL
);
549 hkl_parameter_value_set(self
->uz
, z
, HKL_UNIT_DEFAULT
, NULL
);
554 * @self: the this ptr.
556 * Return value: get the UB matrix of the sample
558 const HklMatrix
*hkl_sample_UB_get(const HklSample
*self
)
565 * @self: the sample to modify
566 * @UB: the UB matrix to set
568 * Set the UB matrix using an external UB matrix. In fact you give
569 * the UB matrix but only the U matrix of the sample is affected by
570 * this operation. We keep the B matrix constant.
571 * U * B = UB -> U = UB * B^-1
573 int hkl_sample_UB_set(HklSample
*self
, const HklMatrix
*UB
,
576 struct set_UB_t params
= {
581 return minimize(self
, set_UB_fitness
, ¶ms
, error
);
585 * hkl_sample_first_reflection_get: (skip)
586 * @self: the this ptr
588 * Return value: the first HklSampleReflection of the sample.
590 HklSampleReflection
*hkl_sample_first_reflection_get(HklSample
*self
)
592 return list_top(&self
->reflections
, HklSampleReflection
, list
);
596 * hkl_sample_next_reflection_get: (skip)
597 * @self: the this ptr
598 * @reflection: the current reflection
600 * Return value: (allow-none): the next reflection or NULL if no more reflection
602 HklSampleReflection
*hkl_sample_next_reflection_get(HklSample
*self
,
603 HklSampleReflection
*reflection
)
605 return list_next(&self
->reflections
, reflection
, list
);
609 * hkl_sample_add_reflection: (skip)
610 * @self: the this ptr
611 * @reflection: The reflection to add
613 * add a reflection to the sample, if the reflection is already part
614 * of the sample reflection list, this method does nothing.
616 void hkl_sample_add_reflection(HklSample
*self
,
617 HklSampleReflection
*reflection
)
619 HklSampleReflection
*ref
;
621 list_for_each(&self
->reflections
, ref
, list
){
622 if (ref
== reflection
)
626 list_add_tail(&self
->reflections
, &reflection
->list
);
630 * hkl_sample_del_reflection:
631 * @self: the this ptr
632 * @reflection: the reflection to remove.
634 * remove an HklSampleRefelction from the reflections list.
636 void hkl_sample_del_reflection(HklSample
*self
,
637 HklSampleReflection
*reflection
)
639 list_del(&reflection
->list
);
640 hkl_sample_reflection_free(reflection
);
644 * hkl_sample_compute_UB_busing_levy:
645 * @self: the this ptr
646 * @r1: the first #HklsampleReflection
647 * @r2: the second #HklSampleReflection
649 * compute the UB matrix using the Busing and Levy method
652 * Returns: 0 or 1 if it succeed
654 int hkl_sample_compute_UB_busing_levy(HklSample
*self
,
655 const HklSampleReflection
*r1
,
656 const HklSampleReflection
*r2
,
660 if (!hkl_vector_is_colinear(&r1
->hkl
, &r2
->hkl
)) {
666 /* Compute matrix Tc from r1 and r2. */
669 hkl_lattice_get_B(self
->lattice
, &B
);
670 hkl_matrix_times_vector(&B
, &h1c
);
671 hkl_matrix_times_vector(&B
, &h2c
);
672 hkl_matrix_init_from_two_vector(&Tc
, &h1c
, &h2c
);
673 hkl_matrix_transpose(&Tc
);
676 hkl_matrix_init_from_two_vector(&self
->U
,
677 &r1
->_hkl
, &r2
->_hkl
);
678 hkl_matrix_times_matrix(&self
->U
, &Tc
);
679 hkl_sample_compute_UxUyUz(self
);
680 hkl_sample_compute_UB(self
);
689 * @self: the this ptr
693 * Returns: the fitness of the affined #HklSample
695 int hkl_sample_affine(HklSample
*self
, GError
**error
)
697 return minimize(self
, mono_crystal_fitness
, self
, error
);
701 * hkl_sample_get_reflection_mesured_angle:
702 * @self: the this ptr
703 * @r1: the first #HklSampleReflection
704 * @r2: the second #HklSampleReflection
706 * get the mesured angles between two #HklSampleReflection
708 * Returns: the mesured angle beetween them
710 double hkl_sample_get_reflection_mesured_angle(const HklSample
*self
,
711 const HklSampleReflection
*r1
,
712 const HklSampleReflection
*r2
)
714 return hkl_vector_angle(&r1
->_hkl
,
719 * hkl_sample_get_reflection_theoretical_angle:
720 * @self: the this ptr
721 * @r1: the first #HklSampleReflection
722 * @r2: the second #HklSampleReflection
724 * get the theoretical angles between two #HklSampleReflection
726 * Returns: the theoretical angle beetween them
728 double hkl_sample_get_reflection_theoretical_angle(const HklSample
*self
,
729 const HklSampleReflection
*r1
,
730 const HklSampleReflection
*r2
)
737 hkl_matrix_times_vector(&self
->UB
, &hkl1
);
738 hkl_matrix_times_vector(&self
->UB
, &hkl2
);
740 return hkl_vector_angle(&hkl1
, &hkl2
);
744 * hkl_sample_fprintf: (skip)
748 * print to a file a sample
750 void hkl_sample_fprintf(FILE *f
, const HklSample
*self
)
755 fprintf(f
, "\nSample name: \"%s\"", self
->name
);
757 fprintf(f
, "\nLattice parameters:");
759 hkl_parameter_fprintf(f
, self
->lattice
->a
);
761 hkl_parameter_fprintf(f
, self
->lattice
->b
);
763 hkl_parameter_fprintf(f
, self
->lattice
->c
);
765 hkl_parameter_fprintf(f
, self
->lattice
->alpha
);
767 hkl_parameter_fprintf(f
, self
->lattice
->beta
);
769 hkl_parameter_fprintf(f
, self
->lattice
->gamma
);
771 hkl_parameter_fprintf(f
, self
->ux
);
773 hkl_parameter_fprintf(f
, self
->uy
);
775 hkl_parameter_fprintf(f
, self
->uz
);
776 fprintf(f
, "\nUB:\n");
777 hkl_matrix_fprintf(f
, &self
->UB
);
779 if (!list_empty(&self
->reflections
)){
780 HklSampleReflection
*reflection
;
783 reflection
= list_top(&self
->reflections
, HklSampleReflection
, list
);
785 fprintf(f
, "Reflections:");
787 fprintf(f
, "%-10.6s %-10.6s %-10.6s", "h", "k", "l");
788 darray_foreach(axis
, reflection
->geometry
->axes
){
789 fprintf(f
, " %-10.6s", (*axis
)->name
);
792 list_for_each(&self
->reflections
, reflection
, list
){
793 fprintf(f
, "\n%-10.6f %-10.6f %-10.6f",
794 reflection
->hkl
.data
[0],
795 reflection
->hkl
.data
[1],
796 reflection
->hkl
.data
[2]);
797 darray_foreach(axis
, reflection
->geometry
->axes
){
798 fprintf(f
, " %-10.6f", hkl_parameter_value_get(*axis
, HKL_UNIT_USER
));
804 /***********************/
805 /* HklSampleReflection */
806 /***********************/
809 * hkl_sample_reflection_new:
820 HklSampleReflection
*hkl_sample_reflection_new(const HklGeometry
*geometry
,
821 const HklDetector
*detector
,
822 double h
, double k
, double l
,
825 HklSampleReflection
*self
;
827 if (!geometry
|| !detector
)
830 self
= HKL_MALLOC(HklSampleReflection
);
832 self
->geometry
= hkl_geometry_new_copy(geometry
);
833 self
->detector
= hkl_detector_new_copy(detector
);
834 self
->hkl
.data
[0] = h
;
835 self
->hkl
.data
[1] = k
;
836 self
->hkl
.data
[2] = l
;
839 hkl_sample_reflection_update(self
);
845 * hkl_sample_reflection_new_copy: (skip)
852 HklSampleReflection
*hkl_sample_reflection_new_copy(const HklSampleReflection
*self
)
854 HklSampleReflection
*dup
= NULL
;
856 dup
= HKL_MALLOC(HklSampleReflection
);
858 dup
->geometry
= hkl_geometry_new_copy(self
->geometry
);
859 dup
->detector
= hkl_detector_new_copy(self
->detector
);
860 dup
->hkl
= self
->hkl
;
861 dup
->_hkl
= self
->_hkl
;
862 dup
->flag
= self
->flag
;
868 * hkl_sample_reflection_free: (skip)
873 void hkl_sample_reflection_free(HklSampleReflection
*self
)
875 hkl_geometry_free(self
->geometry
);
876 hkl_detector_free(self
->detector
);
881 * hkl_sample_reflection_hkl_get:
882 * @self: the this ptr
883 * @h: (out caller-allocates): the h-coordinate of the #HklSampleReflection
884 * @k: (out caller-allocates): the k-coordinate of the #HklSampleReflection
885 * @l: (out caller-allocates): the l-coordinate of the #HklSampleReflection
887 * get the hkl coordinates of the #HklSampleReflection
889 void hkl_sample_reflection_hkl_get(const HklSampleReflection
*self
,
890 double *h
, double *k
, double *l
)
892 *h
= self
->hkl
.data
[0];
893 *k
= self
->hkl
.data
[1];
894 *l
= self
->hkl
.data
[2];
898 * hkl_sample_reflection_hkl_set:
899 * @self: the this ptr
900 * @h: the h-coordinate of the #HklSampleReflection
901 * @k: the k-coordinate of the #HklSampleReflection
902 * @l: the l-coordinate of the #HklSampleReflection
903 * @error: return location for a GError, or NULL
905 * set the hkl coordinates of the #HklSampleReflection
907 * Returns: TRUE on success, FALSE if an error occurred
909 int hkl_sample_reflection_hkl_set(HklSampleReflection
*self
,
910 double h
, double k
, double l
,
913 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
915 if((fabs(h
) + fabs(k
) + fabs(l
) < HKL_EPSILON
)){
917 HKL_SAMPLE_REFLECTION_ERROR
,
918 HKL_SAMPLE_REFLECTION_ERROR_HKL_SET
,
919 "it is not allow to set a null hkl reflection\n");
923 self
->hkl
.data
[0] = h
;
924 self
->hkl
.data
[1] = k
;
925 self
->hkl
.data
[2] = l
;
931 * hkl_sample_reflection_flag_get: (skip)
934 * get the flag of the reflection
936 int hkl_sample_reflection_flag_get(const HklSampleReflection
*self
)
942 * hkl_sample_reflection_flag_set: (skip)
946 * set the flag of the reglection
948 void hkl_sample_reflection_flag_set(HklSampleReflection
*self
, int flag
)
954 * hkl_sample_reflection_geometry_get: (skip)
957 * set the geometry of the reflection
959 const HklGeometry
*hkl_sample_reflection_geometry_get(HklSampleReflection
*self
)
961 return self
->geometry
;
965 * hkl_sample_reflection_geometry_set: (skip)
969 * set the geometry of the reflection
971 void hkl_sample_reflection_geometry_set(HklSampleReflection
*self
,
972 const HklGeometry
*geometry
)
975 if(self
->geometry
!= geometry
){
976 hkl_geometry_free(self
->geometry
);
977 self
->geometry
= hkl_geometry_new_copy(geometry
);
980 self
->geometry
= hkl_geometry_new_copy(geometry
);
982 hkl_sample_reflection_update(self
);