[hkl] add hkl_geometry_[sample/detector]_rotation_get
[hkl.git] / tests / hkl-pseudoaxis-t.c
bloba85128817d13be4426afe9724e2144c5e926f133
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-2016 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 <alloca.h>
23 #include <string.h>
24 #include "hkl.h"
25 #include <tap/basic.h>
26 #include <tap/hkl-tap.h>
28 #define DEBUG
31 typedef int (* test_func) (HklEngine *engine, HklEngineList *engine_list, unsigned int n);
33 static int __test(unsigned int nb_iter, test_func f, int foreach_mode)
35 HklFactory **factories;
36 size_t i, j, n;
37 HklGeometry *geometry = NULL;
38 HklDetector *detector = hkl_detector_factory_new(HKL_DETECTOR_TYPE_0D);
39 HklSample *sample = hkl_sample_new("test");
40 HklEngineList *engines;
41 int res = TRUE;
42 const char **mode;
44 factories = hkl_factory_get_all(&n);
45 for(i=0; i<n && TRUE == res; i++){
46 HklEngine **engine;
48 geometry = hkl_factory_create_new_geometry(factories[i]);
49 engines = hkl_factory_create_new_engine_list(factories[i]);
50 hkl_engine_list_init(engines, geometry, detector, sample);
51 darray_foreach(engine, *hkl_engine_list_engines_get(engines)){
52 const darray_string *modes = hkl_engine_modes_names_get(*engine);
53 if (foreach_mode){
54 darray_foreach(mode, *modes){
55 res &= DIAG(hkl_engine_current_mode_set(*engine, *mode, NULL));
56 for(j=0; j<nb_iter; ++j){
57 res &= DIAG(f(*engine, engines, nb_iter));
58 if(!res){
59 diag("failed at factory: \"%s\" engine: \"%s\" mode: \"%s\"",
60 hkl_geometry_name_get(geometry),
61 hkl_engine_name_get(*engine), *mode);
62 break;
65 if(!res)
66 break;
68 }else{
69 for(j=0; j<nb_iter; ++j){
70 res &= DIAG(f(*engine, engines, nb_iter));
71 if(!res)
72 break;
75 if(!res)
76 break;
78 hkl_geometry_free(geometry);
79 hkl_engine_list_free(engines);
81 hkl_detector_free(detector);
82 hkl_sample_free(sample);
84 return res;
87 #define TEST_FOREACH_ENGINE(_nb_iter, _f) __test(_nb_iter, _f, 0)
88 #define TEST_FOREACH_MODE(_nb_iter, _f) __test(_nb_iter, _f, 1)
90 static void factories(void)
92 int res = TRUE;
93 size_t i, n;
94 HklEngineList *engines;
95 HklFactory **factories;
97 factories = hkl_factory_get_all(&n);
98 for(i=0;i<n; i++){
99 engines = hkl_factory_create_new_engine_list(factories[i]);
100 hkl_engine_list_free(engines);
103 ok(res == TRUE, "factories");
106 static int _get(HklEngine *engine, HklEngineList *engine_list, UNUSED unsigned int n)
108 uint i;
109 GError *error;
110 int res = TRUE;
111 HklGeometry *geometry = hkl_engine_list_geometry_get(engine_list);
112 const darray_string *pseudo_axes = hkl_engine_pseudo_axis_names_get(engine);
113 const size_t n_pseudo_axes = darray_size(*pseudo_axes);
114 double targets[n_pseudo_axes];
115 double currents[n_pseudo_axes];
117 /* randomize the geometry */
118 hkl_geometry_randomize(geometry);
120 /* randomize the pseudoAxes values */
121 hkl_tap_engine_pseudo_axes_randomize(engine,
122 targets, n_pseudo_axes,
123 HKL_UNIT_DEFAULT);
125 /* randomize the parameters */
126 hkl_tap_engine_parameters_randomize(engine);
128 /* pseudo -> geometry */
129 if(HKL_ENGINE_CAPABILITIES_INITIALIZABLE & hkl_engine_capabilities_get(engine))
130 res &= DIAG(hkl_engine_initialized_set(engine, TRUE, NULL));
131 res &= DIAG(hkl_engine_pseudo_axis_values_get(engine, currents, n_pseudo_axes,
132 HKL_UNIT_DEFAULT, NULL));
134 /* idem with error management */
135 error = NULL;
136 res &= DIAG(hkl_engine_pseudo_axis_values_get(engine, currents, n_pseudo_axes,
137 HKL_UNIT_DEFAULT, &error));
138 res &= DIAG(NULL == error);
139 for(i=0; i<n_pseudo_axes; ++i)
140 res &= DIAG(targets[i] != currents[i]); /* TODO this test is almost true, need a real check */
142 return res;
145 static void get()
147 ok(TRUE == TEST_FOREACH_MODE(1, _get), __func__);
150 static int _set(HklEngine *engine, HklEngineList *engine_list, UNUSED unsigned int n)
152 GError *error = NULL;
153 int unreachable = 0;
154 int res = TRUE;
155 HklGeometry *geometry = hkl_engine_list_geometry_get(engine_list);
156 const darray_string *pseudo_axes = hkl_engine_pseudo_axis_names_get(engine);
157 const size_t n_pseudo_axes = darray_size(*pseudo_axes);
158 double targets[n_pseudo_axes];
159 double currents[n_pseudo_axes];
161 /* randomize the geometry */
162 hkl_geometry_randomize(geometry);
164 /* for now skip the eulerians check */
165 if(!strcmp(hkl_engine_current_mode_get(engine), "eulerians"))
166 return TRUE;
168 size_t j;
169 HklGeometryList *solutions;
171 /* randomize the pseudoAxes values */
172 hkl_tap_engine_pseudo_axes_randomize(engine,
173 targets, n_pseudo_axes,
174 HKL_UNIT_DEFAULT);
176 /* randomize the parameters */
177 hkl_tap_engine_parameters_randomize(engine);
179 /* pseudo -> geometry */
180 res &= DIAG(hkl_engine_initialized_set(engine, TRUE, &error));
182 /* geometry -> pseudo */
183 solutions = hkl_engine_pseudo_axis_values_set(engine,
184 targets, n_pseudo_axes,
185 HKL_UNIT_DEFAULT, &error);
186 if(solutions) {
187 const HklGeometryListItem *item;
189 HKL_GEOMETRY_LIST_FOREACH(item, solutions){
190 hkl_geometry_set(geometry,
191 hkl_geometry_list_item_geometry_get(item));
193 res &= DIAG(hkl_engine_pseudo_axis_values_get(engine, currents, n_pseudo_axes, HKL_UNIT_DEFAULT, &error));
194 for(j=0; j<n_pseudo_axes; ++j)
195 res &= DIAG(fabs(targets[j] - currents[j]) < HKL_EPSILON);
197 hkl_geometry_list_free(solutions);
198 }else{
199 res &= DIAG(error != NULL);
200 g_clear_error(&error);
201 unreachable++;
203 #if 0
204 fprintf(stderr, " unreachable : %d/%d", unreachable, i);
205 if(!res){
206 fprintf(stderr, " ko");
207 /* print the hkl internals if the test failed */
208 fprintf(stderr, "\n expected : ");
209 for(uint j=0; j<n_pseudo_axes; ++j)
210 fprintf(stderr, " %f", targets[j]);
211 fprintf(stderr, " obtained : ");
212 for(uint j=0; j<n_pseudo_axes; ++j)
213 fprintf(stderr, " %f", currents[j]);
214 hkl_engine_fprintf(stderr, engine);
215 exit(0);
216 }else{
217 fprintf(stderr, " ok");
219 #endif
221 return res;
225 static void set(int nb_iter)
227 ok(TRUE == TEST_FOREACH_MODE(nb_iter, _set), __func__);
231 static int _pseudo_axis_get(HklEngine *engine, UNUSED HklEngineList *engine_list, UNUSED unsigned int n)
233 static const char *bad = "_bad_name_";
234 const darray_string *pseudo_axis_names = hkl_engine_pseudo_axis_names_get(engine);
235 const char **pseudo_axis_name;
236 const HklParameter *pseudo_axis;
237 int res = TRUE;
238 GError *error;
240 darray_foreach(pseudo_axis_name, *pseudo_axis_names){
241 pseudo_axis = hkl_engine_pseudo_axis_get(engine, *pseudo_axis_name, NULL);
242 res &= DIAG(NULL != pseudo_axis);
244 error = NULL;
245 pseudo_axis = hkl_engine_pseudo_axis_get(engine, *pseudo_axis_name, &error);
246 res &= DIAG(NULL != pseudo_axis);
247 res &= DIAG(NULL == error);
250 /* error */
251 pseudo_axis = hkl_engine_pseudo_axis_get(engine, bad, NULL);
252 res &= DIAG(NULL == pseudo_axis);
254 error = NULL;
255 pseudo_axis = hkl_engine_pseudo_axis_get(engine, bad, &error);
256 res &= DIAG(NULL == pseudo_axis);
257 res &= DIAG(error != NULL);
258 g_clear_error(&error);
260 return res;
263 static void pseudo_axis_get(void)
265 ok(TRUE == TEST_FOREACH_ENGINE(1, _pseudo_axis_get), __func__);
268 static int _capabilities(HklEngine *engine, UNUSED HklEngineList *engine_list, UNUSED unsigned int n)
270 int res = TRUE;
271 const unsigned long capabilities = hkl_engine_capabilities_get(engine);
273 /* all motors must have the read capabilities */
274 res &= DIAG((capabilities & HKL_ENGINE_CAPABILITIES_READABLE) != 0);
276 /* all engines except the readonly (incidence, emergence) are writable */
277 if(strcmp("incidence", hkl_engine_name_get(engine))
278 && strcmp("emergence", hkl_engine_name_get(engine)))
279 res &= DIAG((capabilities & HKL_ENGINE_CAPABILITIES_WRITABLE) != 0);
281 /* all psi engines must be initialisable */
282 if(!strcmp("psi", hkl_engine_name_get(engine)))
283 res &= DIAG((capabilities & HKL_ENGINE_CAPABILITIES_INITIALIZABLE) != 0);
285 return res;
288 static void capabilities(void)
290 ok(TRUE == TEST_FOREACH_MODE(1, _capabilities), __func__);
293 static int _initialized(HklEngine *engine, UNUSED HklEngineList *engine_list, UNUSED unsigned int n)
295 int res = TRUE;
296 GError *error = NULL;
297 const unsigned long capabilities = hkl_engine_capabilities_get(engine);
299 if(HKL_ENGINE_CAPABILITIES_INITIALIZABLE & capabilities){
300 int tmp;
302 res &= DIAG(TRUE == hkl_engine_initialized_set(engine, FALSE, NULL));
303 res &= DIAG(FALSE == hkl_engine_initialized_get(engine));
304 tmp = hkl_engine_initialized_set(engine, TRUE, NULL);
305 res &= DIAG(tmp == hkl_engine_initialized_get(engine));
307 res &= DIAG(TRUE == hkl_engine_initialized_set(engine, FALSE, &error));
308 res &= DIAG(FALSE == hkl_engine_initialized_get(engine));
309 res &= DIAG(NULL == error);
310 tmp = hkl_engine_initialized_set(engine, TRUE, &error);
311 res &= DIAG(tmp == hkl_engine_initialized_get(engine));
312 if(tmp)
313 res &= DIAG(NULL == error);
314 else{
315 res &= DIAG(NULL != error);
316 g_clear_error(&error);
318 }else{
319 /* non-initializable engine should not produce an error */
320 res &= DIAG(TRUE == hkl_engine_initialized_get(engine));
321 res &= DIAG(TRUE == hkl_engine_initialized_set(engine, TRUE, NULL));
322 res &= DIAG(TRUE == hkl_engine_initialized_get(engine));
323 res &= DIAG(TRUE == hkl_engine_initialized_set(engine, FALSE, NULL));
324 res &= DIAG(TRUE == hkl_engine_initialized_get(engine));
326 res &= DIAG(TRUE == hkl_engine_initialized_set(engine, TRUE, &error));
327 res &= DIAG(TRUE == hkl_engine_initialized_get(engine));
328 res &= DIAG(NULL == error);
329 res &= DIAG(TRUE == hkl_engine_initialized_set(engine, FALSE, &error));
330 res &= DIAG(TRUE == hkl_engine_initialized_get(engine));
331 res &= DIAG(NULL == error);
334 return res;
337 static void initialized(void)
339 ok(TRUE == TEST_FOREACH_MODE(1, _initialized), __func__);
342 HKLAPI int hkl_engine_initialized_set(HklEngine *self, int initialized,
343 GError **error) HKL_ARG_NONNULL(1) HKL_WARN_UNUSED_RESULT;
345 static int _modes(HklEngine *engine, UNUSED HklEngineList *engine_list, UNUSED unsigned int n)
347 static const char *bad = "__bad_mode_name__";
348 int res = TRUE;
349 int ok;
350 const darray_string *modes;
351 const char **mode;
352 const char *current_mode;
353 GError *error = NULL;
355 modes = hkl_engine_modes_names_get(engine);
357 /* check that the current mode is available in the mode list. */
358 current_mode = hkl_engine_current_mode_get(engine);
359 ok = FALSE;
360 darray_foreach(mode, *modes){
361 if(!strcmp(current_mode, *mode))
362 ok = TRUE;
364 res &= DIAG(TRUE == ok);
366 /* check that all modes can be set */
367 darray_foreach(mode, *modes){
368 res &= DIAG(TRUE == hkl_engine_current_mode_set(engine, *mode, NULL));
370 res &= DIAG(TRUE == hkl_engine_current_mode_set(engine, *mode, &error));
371 res &= DIAG(NULL == error);
374 /* check for bad mode name */
375 res &= DIAG(FALSE == hkl_engine_current_mode_set(engine, bad, NULL));
377 res &= DIAG(FALSE == hkl_engine_current_mode_set(engine, bad, &error));
378 res &= DIAG(NULL != error);
379 g_clear_error(&error);
381 return res;
384 static void modes(void)
386 ok(TRUE == TEST_FOREACH_ENGINE(1, _modes), __func__);
389 static int _check_axes(const darray_string *axes, const darray_string *refs)
391 int ko = TRUE;
392 const char **axis;
393 const char **ref;
395 darray_foreach(axis, *axes){
396 darray_foreach(ref, *refs){
397 if(!strcmp(*axis, *ref))
398 ko = FALSE;
400 if(ko)
401 break;
402 ko = TRUE;
404 return ko;
407 static int _axis_names(HklEngine *engine, HklEngineList *engine_list, UNUSED unsigned int n)
409 int res = TRUE;
410 HklGeometry *geometry;
411 const darray_string *all_axes;
412 const darray_string *axes_r;
413 const darray_string *axes_w;
415 geometry = hkl_engine_list_geometry_get(engine_list);
416 all_axes = hkl_geometry_axis_names_get(geometry);
418 /* check consistency of the engines, all axes should be in the
419 * list of the geometry axes */
420 axes_r = hkl_engine_axis_names_get(engine,
421 HKL_ENGINE_AXIS_NAMES_GET_READ);
423 axes_w = hkl_engine_axis_names_get(engine,
424 HKL_ENGINE_AXIS_NAMES_GET_WRITE);
426 res &= DIAG(axes_r != NULL);
427 res &= DIAG(axes_w != NULL);
428 res &= DIAG(_check_axes(axes_r, all_axes));
429 res &= DIAG(_check_axes(axes_w, all_axes));
431 return res;
434 static void axis_names(void)
436 ok(TRUE == TEST_FOREACH_MODE(1, _axis_names), __func__);
440 static int _parameters(HklEngine *engine, UNUSED HklEngineList *engine_list, UNUSED unsigned int n)
442 static const char *bad = "__bad_parameter_name__";
443 int res = TRUE;
444 GError *error = NULL;
445 const char **parameter;
446 const darray_string *parameters = hkl_engine_parameters_names_get(engine);
447 const HklParameter *param;
448 int n_values = darray_size(*parameters);
449 double values[n_values];
451 /* can not get a bad parameter */
452 param = hkl_engine_parameter_get(engine, bad, NULL);
453 res &= DIAG(NULL == param);
455 param = hkl_engine_parameter_get(engine, bad, &error);
456 res &= DIAG(NULL == param);
457 res &= DIAG(NULL != error);
458 g_clear_error(&error);
460 /* it is possible to get and set all the parameters */
461 darray_foreach(parameter, *parameters){
462 /* get */
463 param = hkl_engine_parameter_get(engine, *parameter, NULL);
464 res &= DIAG(NULL != param);
466 param = hkl_engine_parameter_get(engine, *parameter, &error);
467 res &= DIAG(NULL != param);
468 res &= DIAG(NULL == error);
470 /* set */
471 res &= DIAG(TRUE == hkl_engine_parameter_set(engine, *parameter, param, NULL));
472 res &= DIAG(TRUE == hkl_engine_parameter_set(engine, *parameter, param, &error));
473 res &= DIAG(NULL == error);
475 res &= DIAG(FALSE == hkl_engine_parameter_set(engine, bad, param, &error));
476 res &= DIAG(NULL != error);
477 g_clear_error(&error);
480 hkl_engine_parameters_values_get(engine, values, n_values, HKL_UNIT_USER);
482 res &= DIAG(TRUE == hkl_engine_parameters_values_set(engine, values, n_values, HKL_UNIT_DEFAULT, NULL));
483 res &= DIAG(TRUE == hkl_engine_parameters_values_set(engine, values, n_values, HKL_UNIT_DEFAULT, &error));
484 res &= DIAG(NULL == error);
486 res &= DIAG(TRUE == hkl_engine_parameters_values_set(engine, values, n_values, HKL_UNIT_USER, NULL));
487 res &= DIAG(TRUE == hkl_engine_parameters_values_set(engine, values, n_values, HKL_UNIT_USER, &error));
488 res &= DIAG(NULL == error);
490 return res;
493 static void parameters(void)
495 ok(TRUE == TEST_FOREACH_MODE(1, _parameters), __func__);
498 static int _depends(HklEngine *engine, UNUSED HklEngineList *engine_list, UNUSED unsigned int n)
500 int res = TRUE;
501 const char *name = hkl_engine_name_get(engine);
502 const unsigned int depends = hkl_engine_dependencies_get(engine);
504 if(!strcmp("hkl", name))
505 res &= DIAG((depends & (HKL_ENGINE_DEPENDENCIES_AXES | HKL_ENGINE_DEPENDENCIES_ENERGY | HKL_ENGINE_DEPENDENCIES_SAMPLE)) != 0);
506 if(!strcmp("eulerians", hkl_engine_name_get(engine))){
507 res &= DIAG((depends & HKL_ENGINE_DEPENDENCIES_AXES) != 0);
508 res &= DIAG((depends & HKL_ENGINE_DEPENDENCIES_ENERGY) == 0);
509 res &= DIAG((depends & HKL_ENGINE_DEPENDENCIES_SAMPLE) == 0);
511 if(!strcmp("q", name)){
512 res &= DIAG((depends &(HKL_ENGINE_DEPENDENCIES_AXES | HKL_ENGINE_DEPENDENCIES_ENERGY)) != 0);
513 res &= DIAG((depends & HKL_ENGINE_DEPENDENCIES_SAMPLE) == 0);
515 if(!strcmp("q2", name)){
516 res &= DIAG((depends &(HKL_ENGINE_DEPENDENCIES_AXES | HKL_ENGINE_DEPENDENCIES_ENERGY)) != 0);
517 res &= DIAG((depends & HKL_ENGINE_DEPENDENCIES_SAMPLE) == 0);
519 if(!strcmp("qper_qpar", name)){
520 res &= DIAG((depends & (HKL_ENGINE_DEPENDENCIES_AXES | HKL_ENGINE_DEPENDENCIES_ENERGY)) != 0);
521 res &= DIAG((depends & HKL_ENGINE_DEPENDENCIES_SAMPLE) == 0);
523 if(!strcmp("psi", name))
524 res &= DIAG((depends & (HKL_ENGINE_DEPENDENCIES_AXES | HKL_ENGINE_DEPENDENCIES_ENERGY | HKL_ENGINE_DEPENDENCIES_SAMPLE)) != 0);
526 return res;
529 static void depends(void)
531 ok(TRUE == TEST_FOREACH_ENGINE(1, _depends), __func__);
534 int main(int argc, char** argv)
536 double n;
538 plan(10);
540 if (argc > 1)
541 n = atoi(argv[1]);
542 else
543 n = 10;
545 factories();
546 get();
547 set(n);
548 pseudo_axis_get();
549 capabilities();
550 initialized();
551 modes();
552 axis_names();
553 parameters();
554 depends();
556 return 0;