[contrib][haskell] Hkl.Xrd.Calibration
[hkl.git] / tests / hkl-geometry-t.c
blobe233fe0732a48cc45f71f3a05cfc8700e16880c2
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-2017 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>
22 #include "hkl.h"
23 #include <tap/basic.h>
24 #include <tap/float.h>
25 #include <tap/hkl-tap.h>
27 /* BEWARE THESE TESTS ARE DEALING WITH HKL INTERNALS WHICH EXPOSE A
28 * NON PUBLIC API WHICH ALLOW TO SHOOT YOURSELF IN YOUR FOOT */
30 #include "hkl/ccan/container_of/container_of.h"
31 #include "hkl-axis-private.h" /* temporary */
32 #include "hkl-geometry-private.h"
34 static void add_holder(void)
36 HklGeometry *g = NULL;
37 HklHolder *holder = NULL;
39 g = hkl_geometry_new(NULL, &hkl_geometry_operations_defaults);
40 is_int(0, darray_size(g->holders), __func__);
42 holder = hkl_geometry_add_holder(g);
43 hkl_holder_add_rotation(holder, "A", 1., 0., 0., &hkl_unit_angle_deg);
44 hkl_holder_add_rotation(holder, "B", 1., 0., 0., &hkl_unit_angle_deg);
45 hkl_holder_add_translation(holder, "T", 1., 0., 0., &hkl_unit_angle_deg);
46 is_int(1, darray_size(g->holders), __func__);
48 holder = hkl_geometry_add_holder(g);
49 hkl_holder_add_rotation(holder, "A", 1., 0., 0., &hkl_unit_angle_deg);
50 hkl_holder_add_rotation(holder, "C", 1., 0., 0., &hkl_unit_angle_deg);
51 hkl_holder_add_translation(holder, "T", 1., 0., 0., &hkl_unit_angle_deg);
52 is_int(2, darray_size(g->holders), __func__);
54 ok(holder == darray_item(g->holders, 1), __func__);
56 hkl_geometry_free(g);
59 static void get_axis(void)
61 int res = TRUE;
62 HklGeometry *g = NULL;
63 HklHolder *holder = NULL;
64 const HklParameter *axis0;
65 GError *error;
67 g = hkl_geometry_new(NULL, &hkl_geometry_operations_defaults);
69 holder = hkl_geometry_add_holder(g);
70 hkl_holder_add_rotation(holder, "A", 1., 0., 0., &hkl_unit_angle_deg);
71 hkl_holder_add_rotation(holder, "B", 1., 0., 0., &hkl_unit_angle_deg);
72 hkl_holder_add_translation(holder, "T", 1., 0., 0., &hkl_unit_length_mm);
74 holder = hkl_geometry_add_holder(g);
75 hkl_holder_add_rotation(holder, "A", 1., 0., 0., &hkl_unit_angle_deg);
76 hkl_holder_add_rotation(holder, "C", 1., 0., 0., &hkl_unit_angle_deg);
77 hkl_holder_add_translation(holder, "T", 1., 0., 0., &hkl_unit_length_mm);
79 /* check the private API */
80 res &= DIAG(0 == !hkl_geometry_get_axis_by_name(g, "A"));
81 res &= DIAG(0 == !hkl_geometry_get_axis_by_name(g, "B"));
82 res &= DIAG(0 == !hkl_geometry_get_axis_by_name(g, "C"));
83 res &= DIAG(0 == !hkl_geometry_get_axis_by_name(g, "T"));
84 res &= DIAG(1 == !hkl_geometry_get_axis_by_name(g, "DONOTEXIST"));
86 /* check the public API */
87 /* get */
88 res &= DIAG(NULL != hkl_geometry_axis_get(g, "A", NULL));
89 res &= DIAG(NULL == hkl_geometry_axis_get(g, "DONOTEXIST", NULL));
90 error = NULL;
91 res &= DIAG(NULL != hkl_geometry_axis_get(g, "A", &error));
92 res &= DIAG(error == NULL);
93 res &= DIAG(NULL != hkl_geometry_axis_get(g, "T", &error));
94 res &= DIAG(error == NULL);
95 res &= DIAG(NULL == hkl_geometry_axis_get(g, "DONOTEXIST", &error));
96 res &= DIAG(error != NULL);
97 g_clear_error(&error);
99 /* set */
100 axis0 = hkl_geometry_axis_get(g, "A", NULL);
101 res &= DIAG(TRUE == hkl_geometry_axis_set(g, "A", axis0, NULL));
102 res &= DIAG(FALSE == hkl_geometry_axis_set(g, "B", axis0, NULL));
103 res &= DIAG(FALSE == hkl_geometry_axis_set(g, "T", axis0, NULL));
105 error = NULL;
106 res &= DIAG(hkl_geometry_axis_set(g, "A", axis0, &error));
107 res &= DIAG(error == NULL);
109 res &= DIAG(FALSE == hkl_geometry_axis_set(g, "B", axis0, &error));
110 res &= DIAG(error != NULL);
111 g_clear_error(&error);
113 res &= DIAG(FALSE == hkl_geometry_axis_set(g, "T", axis0, &error));
114 res &= DIAG(error != NULL);
115 g_clear_error(&error);
117 ok(res, __func__);
119 hkl_geometry_free(g);
122 static void update(void)
124 int res = TRUE;
125 HklGeometry *g = NULL;
126 HklHolder *holder = NULL;
127 HklAxis *axis1;
128 HklQuaternion q_ref = {{1./sqrt(2), 1./sqrt(2), 0.0, 0.0 }};
130 g = hkl_geometry_new(NULL, &hkl_geometry_operations_defaults);
132 holder = hkl_geometry_add_holder(g);
133 hkl_holder_add_rotation(holder, "A", 1., 0., 0., &hkl_unit_angle_deg);
134 hkl_holder_add_rotation(holder, "B", 1., 0., 0., &hkl_unit_angle_deg);
135 hkl_holder_add_translation(holder, "T1", 1., 0., 0., &hkl_unit_length_mm);
137 holder = hkl_geometry_add_holder(g);
138 hkl_holder_add_rotation(holder, "A", 1., 0., 0., &hkl_unit_angle_deg);
139 hkl_holder_add_rotation(holder, "C", 1., 0., 0., &hkl_unit_angle_deg);
140 hkl_holder_add_translation(holder, "T2", 1., 0., 0., &hkl_unit_length_mm);
142 axis1 = container_of(hkl_geometry_get_axis_by_name(g, "B"), HklAxis, parameter);
143 res &= DIAG(hkl_parameter_value_set(&axis1->parameter, M_PI_2, HKL_UNIT_DEFAULT, NULL));
144 /* now axis1 is dirty */
145 ok(TRUE == axis1->parameter.changed, __func__);
147 hkl_geometry_update(g);
148 holder = darray_item(g->holders, 0);
149 is_quaternion(&q_ref, &holder->q, __func__);
150 /* now axis1 is clean */
151 res &= DIAG(FALSE == axis1->parameter.changed);
153 ok(res, __func__);
155 hkl_geometry_free(g);
158 static void set(void)
160 HklGeometry *g;
161 HklGeometry *g1;
162 HklGeometry *g2;
163 HklHolder *holder;
164 HklFactory *fake_factory;
166 g = hkl_geometry_new(NULL, &hkl_geometry_operations_defaults);
167 holder = hkl_geometry_add_holder(g);
168 hkl_holder_add_rotation(holder, "A", 1., 0., 0., &hkl_unit_angle_deg);
169 hkl_holder_add_rotation(holder, "B", 1., 0., 0., &hkl_unit_angle_deg);
170 hkl_holder_add_rotation(holder, "C", 1., 0., 0., &hkl_unit_angle_deg);
171 hkl_holder_add_translation(holder, "T", 1., 0., 0., &hkl_unit_length_mm);
173 g1 = hkl_geometry_new_copy(g);
175 /* it is required to use a fake factory, with the public API
176 * geometry contain always a real factory */
177 fake_factory = (HklFactory *)0x1;
178 g2 = hkl_geometry_new(fake_factory, &hkl_geometry_operations_defaults);
179 holder = hkl_geometry_add_holder(g);
180 hkl_holder_add_rotation(holder, "A", 1., 0., 0., &hkl_unit_angle_deg);
181 hkl_holder_add_rotation(holder, "B", 1., 0., 0., &hkl_unit_angle_deg);
183 ok(hkl_geometry_set(g, g1), __func__);
185 hkl_geometry_free(g2);
186 hkl_geometry_free(g1);
187 hkl_geometry_free(g);
190 static void axis_values_get_set(void)
192 unsigned int i;
193 HklGeometry *g;
194 HklHolder *holder;
195 static double set_1[] = {1, 1, 1, 1};
196 static double set_10[] = {10, 10, 10, 10};
197 double values[4];
198 GError *error;
200 g = hkl_geometry_new(NULL, &hkl_geometry_operations_defaults);
201 holder = hkl_geometry_add_holder(g);
202 hkl_holder_add_rotation(holder, "A", 1., 0., 0., &hkl_unit_angle_deg);
203 hkl_holder_add_rotation(holder, "B", 1., 0., 0., &hkl_unit_angle_deg);
204 hkl_holder_add_rotation(holder, "C", 1., 0., 0., &hkl_unit_angle_deg);
205 hkl_holder_add_translation(holder, "T", 1., 0., 0., &hkl_unit_length_mm);
207 /* check set DEFAULT unit */
208 error = NULL;
209 ok(TRUE == hkl_geometry_axis_values_set(g, set_1, ARRAY_SIZE(set_1), HKL_UNIT_DEFAULT, NULL), __func__);
210 ok(TRUE == hkl_geometry_axis_values_set(g, set_1, ARRAY_SIZE(set_1), HKL_UNIT_DEFAULT, &error), __func__);
211 ok(error == NULL, __func__);
212 for(i=0; i<ARRAY_SIZE(set_1); ++i)
213 is_double(set_1[i], hkl_parameter_value_get(darray_item(g->axes, i), HKL_UNIT_DEFAULT), HKL_EPSILON, __func__);
215 /* check get DEFAULT unit */
216 hkl_geometry_axis_values_get(g, values, ARRAY_SIZE(values), HKL_UNIT_DEFAULT);
217 for(i=0; i<ARRAY_SIZE(set_1); ++i)
218 is_double(set_1[i], values[i], HKL_EPSILON, __func__);
220 /* check set USER unit */
221 ok(TRUE == hkl_geometry_axis_values_set(g, set_10, ARRAY_SIZE(set_10), HKL_UNIT_USER, NULL), __func__);
222 ok(TRUE == hkl_geometry_axis_values_set(g, set_10, ARRAY_SIZE(set_10), HKL_UNIT_USER, &error), __func__);
223 ok(error == NULL, __func__);
225 /* check get USER unit */
226 hkl_geometry_axis_values_get(g, values, ARRAY_SIZE(values), HKL_UNIT_USER);
227 for(i=0; i<ARRAY_SIZE(set_10); ++i)
228 is_double(set_10[i], values[i], HKL_EPSILON, __func__);
230 hkl_geometry_free(g);
233 static void distance(void)
235 int res = TRUE;
236 HklGeometry *g1 = NULL;
237 HklGeometry *g2 = NULL;
238 HklHolder *holder = NULL;
240 g1 = hkl_geometry_new(NULL, &hkl_geometry_operations_defaults);
241 holder = hkl_geometry_add_holder(g1);
242 hkl_holder_add_rotation(holder, "A", 1., 0., 0., &hkl_unit_angle_deg);
243 hkl_holder_add_rotation(holder, "B", 1., 0., 0., &hkl_unit_angle_deg);
244 hkl_holder_add_rotation(holder, "C", 1., 0., 0., &hkl_unit_angle_deg);
245 hkl_holder_add_translation(holder, "T", 1., 0., 0., &hkl_unit_length_mm);
247 g2 = hkl_geometry_new_copy(g1);
249 res &= DIAG(hkl_geometry_set_values_v(g1, HKL_UNIT_DEFAULT, NULL, 0., 0., 0., 0.));
250 res &= DIAG(hkl_geometry_set_values_v(g2, HKL_UNIT_DEFAULT, NULL, 1., 1., 1., 1.));
251 is_double(4., hkl_geometry_distance(g1, g2), HKL_EPSILON, __func__);
253 ok(res, __func__);
255 hkl_geometry_free(g1);
256 hkl_geometry_free(g2);
259 static void is_valid(void)
261 int res = TRUE;
262 HklGeometry *geom = NULL;
263 HklHolder *holder = NULL;
265 geom = hkl_geometry_new(NULL, &hkl_geometry_operations_defaults);
266 holder = hkl_geometry_add_holder(geom);
267 hkl_holder_add_rotation(holder, "A", 1., 0., 0., &hkl_unit_angle_deg);
268 hkl_holder_add_rotation(holder, "B", 1., 0., 0., &hkl_unit_angle_deg);
269 hkl_holder_add_rotation(holder, "C", 1., 0., 0., &hkl_unit_angle_deg);
270 hkl_holder_add_translation(holder, "T", 1., 0., 0., &hkl_unit_length_mm);
272 res &= DIAG(hkl_geometry_set_values_v(geom, HKL_UNIT_DEFAULT, NULL, 0., 0., 0., 0.));
273 res &= DIAG(TRUE == hkl_geometry_is_valid(geom));
275 res &= DIAG(hkl_geometry_set_values_v(geom, HKL_UNIT_DEFAULT, NULL, -181. * HKL_DEGTORAD, 0., 0., 0.));
276 res &= DIAG(TRUE == hkl_geometry_is_valid(geom));
278 res &= DIAG(hkl_parameter_min_max_set(darray_item(geom->axes, 0),
279 -100 * HKL_DEGTORAD, 100 * HKL_DEGTORAD,
280 HKL_UNIT_DEFAULT, NULL));
281 res &= DIAG(FALSE == hkl_geometry_is_valid(geom));
283 ok(res, __func__);
285 hkl_geometry_free(geom);
288 static void wavelength(void)
290 HklGeometry *geom = NULL;
291 GError *error;
293 geom = hkl_geometry_new(NULL, &hkl_geometry_operations_defaults);
295 is_double(1.54, hkl_geometry_wavelength_get(geom, HKL_UNIT_DEFAULT), HKL_EPSILON, __func__);
297 ok(TRUE == hkl_geometry_wavelength_set(geom, 2, HKL_UNIT_DEFAULT, NULL), __func__);
298 is_double(2, hkl_geometry_wavelength_get(geom, HKL_UNIT_DEFAULT), HKL_EPSILON, __func__);
300 error = NULL;
301 ok(TRUE == hkl_geometry_wavelength_set(geom, 2, HKL_UNIT_DEFAULT, &error), __func__);
302 ok(error == NULL, __func__);
303 is_double(2, hkl_geometry_wavelength_get(geom, HKL_UNIT_DEFAULT), HKL_EPSILON, __func__);
305 hkl_geometry_free(geom);
308 static void xxx_rotation_get(void)
310 int res = TRUE;
311 size_t i, n;
312 HklFactory **factories;
313 HklDetector *detector = hkl_detector_factory_new(HKL_DETECTOR_TYPE_0D);
314 HklSample *sample = hkl_sample_new("test");
316 factories = hkl_factory_get_all(&n);
317 for(i=0; i<n && TRUE == res; i++){
318 HklGeometry *geometry = NULL;
319 HklQuaternion q_ref = {{1, 0, 0, 0}};
320 HklQuaternion qs;
321 HklQuaternion qd;
323 geometry = hkl_factory_create_new_geometry(factories[i]);
324 qs = hkl_geometry_sample_rotation_get(geometry, sample);
325 qd = hkl_geometry_detector_rotation_get(geometry, detector);
327 res &= DIAG(TRUE == hkl_quaternion_cmp(&q_ref, &qs));
328 res &= DIAG(TRUE == hkl_quaternion_cmp(&q_ref, &qd));
330 hkl_geometry_free(geometry);
332 ok(res, __func__);
334 hkl_detector_free(detector);
335 hkl_sample_free(sample);
338 static void list(void)
340 int i = 0;
341 int res = TRUE;
342 HklGeometry *g;
343 HklGeometryList *list;
344 const HklGeometryListItem *item;
345 HklHolder *holder;
346 static double values[] = {0. * HKL_DEGTORAD, 10 * HKL_DEGTORAD, 30 * HKL_DEGTORAD, 100 * HKL_DEGTORAD};
348 g = hkl_geometry_new(NULL, &hkl_geometry_operations_defaults);
349 holder = hkl_geometry_add_holder(g);
350 hkl_holder_add_rotation(holder, "A", 1., 0., 0., &hkl_unit_angle_deg);
351 hkl_holder_add_rotation(holder, "B", 1., 0., 0., &hkl_unit_angle_deg);
352 hkl_holder_add_rotation(holder, "C", 1., 0., 0., &hkl_unit_angle_deg);
353 hkl_holder_add_translation(holder, "T", 1., 0., 0., &hkl_unit_length_mm);
355 list = hkl_geometry_list_new();
357 res &= DIAG(hkl_geometry_set_values_v(g, HKL_UNIT_DEFAULT, NULL, values[0], 0., 0., 0.));
358 hkl_geometry_list_add(list, g);
359 is_int(1, hkl_geometry_list_n_items_get(list), __func__);
361 /* can not add two times the same geometry */
362 hkl_geometry_list_add(list, g);
363 is_int(1, hkl_geometry_list_n_items_get(list), __func__);
365 res &= DIAG(hkl_geometry_set_values_v(g, HKL_UNIT_DEFAULT, NULL, values[2], 0., 0., 0.));
366 hkl_geometry_list_add(list, g);
367 res &= DIAG(hkl_geometry_set_values_v(g, HKL_UNIT_DEFAULT, NULL, values[1], 0., 0., 0.));
368 hkl_geometry_list_add(list, g);
369 is_int(3, hkl_geometry_list_n_items_get(list), __func__);
371 res &= DIAG(hkl_geometry_set_values_v(g, HKL_UNIT_DEFAULT, NULL, values[0], 0., 0., 0.));
372 hkl_geometry_list_sort(list, g);
374 HKL_GEOMETRY_LIST_FOREACH(item, list){
375 is_double(values[i++],
376 hkl_parameter_value_get(darray_item(item->geometry->axes, 0), HKL_UNIT_DEFAULT),
377 HKL_EPSILON, __func__);
380 ok(res, __func__);
382 hkl_geometry_free(g);
383 hkl_geometry_list_free(list);
386 static void list_multiply_from_range(void)
388 int res = TRUE;
389 HklGeometry *g;
390 HklGeometryList *list;
391 HklHolder *holder;
392 HklParameter *axisA, *axisB, *axisC, *axisT;
394 g = hkl_geometry_new(NULL, &hkl_geometry_operations_defaults);
395 holder = hkl_geometry_add_holder(g);
396 hkl_holder_add_rotation(holder, "A", 1., 0., 0., &hkl_unit_angle_deg);
397 hkl_holder_add_rotation(holder, "B", 1., 0., 0., &hkl_unit_angle_deg);
398 hkl_holder_add_rotation(holder, "C", 1., 0., 0., &hkl_unit_angle_deg);
399 hkl_holder_add_translation(holder, "T", 1., 0., 0., &hkl_unit_length_mm);
401 axisA = hkl_geometry_get_axis_by_name(g, "A");
402 axisB = hkl_geometry_get_axis_by_name(g, "B");
403 axisC = hkl_geometry_get_axis_by_name(g, "C");
404 axisT = hkl_geometry_get_axis_by_name(g, "T");
406 res &= DIAG(hkl_parameter_min_max_set(axisA, -190, 190, HKL_UNIT_USER, NULL));
407 res &= DIAG(hkl_parameter_min_max_set(axisB, -190, 190, HKL_UNIT_USER, NULL));
408 res &= DIAG(hkl_parameter_min_max_set(axisC, -190, 190, HKL_UNIT_USER, NULL));
409 res &= DIAG(hkl_parameter_min_max_set(axisT, -190, 190., HKL_UNIT_USER, NULL));
411 list = hkl_geometry_list_new();
413 res &= DIAG(hkl_geometry_set_values_v(g, HKL_UNIT_DEFAULT, NULL,
414 185. * HKL_DEGTORAD, -185. * HKL_DEGTORAD, 190. * HKL_DEGTORAD, 100.));
415 hkl_geometry_list_add(list, g);
417 hkl_geometry_list_multiply_from_range(list);
419 res &= DIAG(8 == hkl_geometry_list_n_items_get(list));
421 ok(res, __func__);
423 hkl_geometry_free(g);
424 hkl_geometry_list_free(list);
427 static void list_remove_invalid(void)
429 int res = TRUE;
430 HklGeometry *g;
431 HklGeometryList *list;
432 HklHolder *holder;
433 HklParameter *axisA, *axisB, *axisC, *axisT;
435 g = hkl_geometry_new(NULL, &hkl_geometry_operations_defaults);
436 holder = hkl_geometry_add_holder(g);
437 hkl_holder_add_rotation(holder, "A", 1., 0., 0., &hkl_unit_angle_deg);
438 hkl_holder_add_rotation(holder, "B", 1., 0., 0., &hkl_unit_angle_deg);
439 hkl_holder_add_rotation(holder, "C", 1., 0., 0., &hkl_unit_angle_deg);
440 hkl_holder_add_translation(holder, "T", 1., 0., 0., &hkl_unit_length_mm);
442 axisA = hkl_geometry_get_axis_by_name(g, "A");
443 axisB = hkl_geometry_get_axis_by_name(g, "B");
444 axisC = hkl_geometry_get_axis_by_name(g, "C");
445 axisT = hkl_geometry_get_axis_by_name(g, "T");
447 res &= DIAG(hkl_parameter_min_max_set(axisA, -100, 180., HKL_UNIT_USER, NULL));
448 res &= DIAG(hkl_parameter_min_max_set(axisB, -100., 180., HKL_UNIT_USER, NULL));
449 res &= DIAG(hkl_parameter_min_max_set(axisC, -100., 180., HKL_UNIT_USER, NULL));
450 res &= DIAG(hkl_parameter_min_max_set(axisT, 0.0, 179., HKL_UNIT_USER, NULL));
452 list = hkl_geometry_list_new();
454 res &= DIAG(hkl_geometry_set_values_v(g, HKL_UNIT_DEFAULT, NULL,
455 185. * HKL_DEGTORAD,
456 -185. * HKL_DEGTORAD,
457 185. * HKL_DEGTORAD,
458 0.1));
459 hkl_geometry_list_add(list, g);
461 res &= DIAG(hkl_geometry_set_values_v(g, HKL_UNIT_DEFAULT, NULL,
462 -190. * HKL_DEGTORAD,
463 -190. * HKL_DEGTORAD,
464 -190. * HKL_DEGTORAD,
465 0.1));
466 hkl_geometry_list_add(list, g);
468 res &= DIAG(hkl_geometry_set_values_v(g, HKL_UNIT_DEFAULT, NULL,
469 180. * HKL_DEGTORAD,
470 180. * HKL_DEGTORAD,
471 180. * HKL_DEGTORAD,
472 0.1));
473 hkl_geometry_list_add(list, g);
475 is_int(3, hkl_geometry_list_n_items_get(list), __func__);
476 hkl_geometry_list_remove_invalid(list);
477 is_int(1, hkl_geometry_list_n_items_get(list), __func__);
479 ok(res, __func__);
481 hkl_geometry_free(g);
482 hkl_geometry_list_free(list);
485 int main(void)
487 plan(48);
489 add_holder();
490 get_axis();
491 update();
492 set();
493 axis_values_get_set();
494 distance();
495 is_valid();
496 wavelength();
497 xxx_rotation_get();
499 list();
500 list_multiply_from_range();
501 list_remove_invalid();
503 return 0;