[hkl] set the engines in the hkl_engine_init method.
[hkl.git] / hkl / hkl-pseudoaxis-private.h
blob9bb7c64c387bec4db77d14478b0e278d54860f0d
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-2015 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 #ifndef __HKL_PSEUDOAXIS_PRIVATE_H__
23 #define __HKL_PSEUDOAXIS_PRIVATE_H__
25 #include <gsl/gsl_sf_trig.h> // for gsl_sf_angle_restrict_symm
26 #include <stddef.h> // for size_t
27 #include <stdlib.h> // for free
28 #include <string.h> // for NULL
29 #include <sys/types.h> // for uint
30 #include "hkl-detector-private.h"
31 #include "hkl-geometry-private.h" // for hkl_geometry_update, etc
32 #include "hkl-macros-private.h" // for HKL_MALLOC
33 #include "hkl-parameter-private.h" // for hkl_parameter_list_free, etc
34 #include "hkl.h" // for HklEngine, HklMode, etc
35 #include "hkl/ccan/darray/darray.h" // for darray_foreach, etc
37 G_BEGIN_DECLS
39 typedef struct _HklModeOperations HklModeOperations;
40 typedef struct _HklModeInfo HklModeInfo;
41 typedef struct _HklMode HklMode;
42 typedef struct _HklEngineInfo HklEngineInfo;
43 typedef struct _HklEngineOperations HklEngineOperations;
45 typedef darray(HklMode *) darray_mode;
47 /***********/
48 /* HklMode */
49 /***********/
51 struct _HklModeInfo {
52 const char *name;
53 const darray_string axes_r;
54 const darray_string axes_w;
55 const darray(const HklParameter) parameters;
58 #define HKL_MODE_INFO(_name, _axes_r, _axes_w) .name=_name, .axes_r=DARRAY(_axes_r), .axes_w=DARRAY(_axes_w)
60 #define HKL_MODE_INFO_WITH_PARAMS(_name, _axes_r, _axes_w, _parameters) \
61 HKL_MODE_INFO(_name, _axes_r, _axes_w), .parameters=DARRAY(_parameters)
63 struct _HklModeOperations
65 unsigned long capabilities;
67 void (* free)(HklMode *self);
68 int (* initialized_get)(const HklMode *self);
69 int (* initialized_set)(HklMode *self,
70 HklEngine *engine,
71 HklGeometry *geometry,
72 HklDetector *detector,
73 HklSample *sample,
74 int initialized,
75 GError **error);
76 int (* get)(HklMode *self,
77 HklEngine *engine,
78 HklGeometry *geometry,
79 HklDetector *detector,
80 HklSample *sample,
81 GError **error);
82 int (* set)(HklMode *self,
83 HklEngine *engine,
84 HklGeometry *geometry,
85 HklDetector *detector,
86 HklSample *sample,
87 GError **error);
91 #define HKL_MODE_OPERATIONS_DEFAULTS .capabilities=HKL_ENGINE_CAPABILITIES_READABLE | HKL_ENGINE_CAPABILITIES_WRITABLE, \
92 .free=hkl_mode_free_real, \
93 .initialized_get=hkl_mode_initialized_get_real, \
94 .initialized_set=hkl_mode_initialized_set_real, \
95 .get=hkl_mode_get_real, \
96 .set=hkl_mode_set_real
99 struct _HklMode
101 const HklModeInfo *info;
102 const HklModeOperations *ops;
103 darray_parameter parameters;
104 darray_string parameters_names;
105 int initialized;
109 static inline void hkl_mode_free_real(HklMode *self)
111 HklParameter **parameter;
113 darray_foreach(parameter, self->parameters){
114 hkl_parameter_free(*parameter);
116 darray_free(self->parameters);
118 darray_free(self->parameters_names);
120 free(self);
124 static inline int hkl_mode_initialized_get_real(const HklMode *self)
126 return self->initialized;
130 static inline int hkl_mode_initialized_get(const HklMode *self)
132 return self->ops->initialized_get(self);
136 static inline int hkl_mode_initialized_set_real(HklMode *self,
137 HklEngine *engine,
138 HklGeometry *geometry,
139 HklDetector *detector,
140 HklSample *sample,
141 int initialized,
142 GError **error)
144 /* by default do nothing and no error */
145 return TRUE;
149 static inline int hkl_mode_initialized_set(HklMode *self,
150 HklEngine *engine,
151 HklGeometry *geometry,
152 HklDetector *detector,
153 HklSample *sample,
154 int initialized,
155 GError **error)
157 return self->ops->initialized_set(self,
158 engine, geometry, detector, sample,
159 initialized, error);
163 static inline int hkl_mode_get_real(HklMode *self,
164 HklEngine *engine,
165 HklGeometry *geometry,
166 HklDetector *detector,
167 HklSample *sample,
168 GError **error)
170 /* by default do nothing and no error */
171 return TRUE;
175 static inline int hkl_mode_set_real(HklMode *self,
176 HklEngine *engine,
177 HklGeometry *geometry,
178 HklDetector *detector,
179 HklSample *sample,
180 GError **error)
182 /* by default do nothing and no error */
183 return TRUE;
187 static inline int hkl_mode_init(HklMode *self,
188 const HklModeInfo *info,
189 const HklModeOperations *ops,
190 int initialized)
192 size_t i;
193 const HklParameter *parameter;
195 /* ensure part */
196 if (!self)
197 return FALSE;
199 self->info = info;
200 self->ops = ops;
202 /* parameters */
203 darray_init(self->parameters);
204 darray_init(self->parameters_names);
205 darray_foreach(parameter, self->info->parameters){
206 darray_append(self->parameters, hkl_parameter_new_copy(parameter));
207 darray_append(self->parameters_names, parameter->name);
210 self->initialized = initialized;
212 return TRUE;
216 static inline HklMode *hkl_mode_new(const HklModeInfo *info,
217 const HklModeOperations *op,
218 int initialized)
220 HklMode *self = NULL;
222 self = HKL_MALLOC(HklMode);
224 hkl_mode_init(self, info, op, initialized);
226 return self;
231 * hkl_mode_free: (skip)
232 * @self:
234 * delete an HklMode
236 static inline void hkl_mode_free(HklMode *self)
238 self->ops->free(self);
241 /*************/
242 /* HklEngine */
243 /*************/
246 struct _HklEngineInfo {
247 const char *name;
248 const darray(const HklParameter *) pseudo_axes;
249 unsigned int dependencies;
252 #define HKL_ENGINE_INFO(_name, _pseudo_axes, _dependencies) .name = (_name), \
253 .pseudo_axes = DARRAY(_pseudo_axes), \
254 .dependencies = (_dependencies)
256 struct _HklEngine
258 const HklEngineInfo *info;
259 const HklEngineOperations *ops;
260 HklGeometry *geometry;
261 HklDetector *detector;
262 HklSample *sample;
263 HklMode *mode; /* not owned */
264 HklEngineList *engines; /* not owned */
265 darray_parameter axes;
266 darray_parameter pseudo_axes;
267 darray_string pseudo_axis_names;
268 darray_mode modes;
269 darray_string mode_names;
273 struct _HklEngineList
275 _darray(HklEngine *);
276 HklGeometryList *geometries;
277 HklGeometry *geometry;
278 HklDetector *detector;
279 HklSample *sample;
283 #define HKL_ENGINE_ERROR hkl_engine_error_quark ()
286 static GQuark hkl_engine_error_quark (void)
288 return g_quark_from_static_string ("hkl-engine-error-quark");
292 typedef enum {
293 HKL_ENGINE_ERROR_PSEUDO_AXIS_VALUES_GET, /* can not get the engine pseudo axes values */
294 HKL_ENGINE_ERROR_PSEUDO_AXIS_VALUES_SET, /* can not set the engine pseudo axes values */
295 HKL_ENGINE_ERROR_PSEUDO_AXIS_SET, /* can not set the pseudo axis */
296 HKL_ENGINE_ERROR_INITIALIZE, /* can not initialize the engine */
297 HKL_ENGINE_ERROR_SET, /* can not set the engine */
298 HKL_ENGINE_ERROR_GET, /* can not get the engine */
299 HKL_ENGINE_ERROR_PARAMETER_GET, /* can not get the parameter */
300 HKL_ENGINE_ERROR_PARAMETER_SET, /* can not set the parameter */
301 HKL_ENGINE_ERROR_CURRENT_MODE_SET, /* can not select the mode */
302 } HklEngineError;
305 static inline void set_geometry_axes(HklEngine *engine, const double values[])
307 HklParameter **axis;
308 uint i = 0;
310 darray_foreach(axis, engine->axes){
311 hkl_parameter_value_set(*axis, values[i++], HKL_UNIT_DEFAULT, NULL);
313 hkl_geometry_update(engine->geometry);
317 static inline void hkl_engine_release(HklEngine *self)
319 HklMode **mode;
320 HklParameter **pseudo_axis;
322 if(self->geometry)
323 hkl_geometry_free(self->geometry);
325 if(self->detector)
326 hkl_detector_free(self->detector);
328 if(self->sample)
329 hkl_sample_free(self->sample);
331 /* release the mode added */
332 darray_foreach(mode, self->modes){
333 hkl_mode_free(*mode);
335 darray_free(self->modes);
337 darray_free(self->axes);
339 /* release the HklPseudoAxe memory */
340 darray_foreach(pseudo_axis, self->pseudo_axes){
341 hkl_parameter_free(*pseudo_axis);
343 darray_free(self->pseudo_axes);
345 darray_free(self->pseudo_axis_names);
347 darray_free(self->mode_names);
351 struct _HklEngineOperations
353 void (*free)(HklEngine *self);
357 #define HKL_ENGINE_OPERATIONS_DEFAULTS .free=hkl_engine_free_real
360 static inline void hkl_engine_free_real(HklEngine *self)
365 static inline void hkl_engine_free(HklEngine *self)
367 self->ops->free(self);
371 static inline void hkl_engine_init(HklEngine *self,
372 const HklEngineInfo *info,
373 const HklEngineOperations *ops,
374 HklEngineList *engines)
376 self->info = info;
377 self->ops = ops;
378 darray_init(self->modes);
379 darray_init(self->pseudo_axes);
380 darray_init(self->pseudo_axis_names);
381 darray_init(self->mode_names);
382 self->geometry = NULL;
383 self->detector = NULL;
384 self->sample = NULL;
385 self->engines = engines;
389 static inline void unregister_pseudo_axis(HklParameter *pseudo_axis)
391 hkl_parameter_free(pseudo_axis);
395 static inline HklParameter *register_pseudo_axis(HklEngine *self,
396 HklEngineList *engines,
397 const HklParameter *pseudo_axis)
399 HklParameter *parameter;
401 /* TODO find an already existing pseudo axis in the list */
403 parameter = hkl_parameter_new_copy(pseudo_axis);
404 darray_append(self->pseudo_axes, parameter);
405 darray_append(self->pseudo_axis_names, parameter->name);
407 return parameter;
411 * hkl_engine_add_mode: (skip)
412 * @self:
413 * @mode: the mode to add
415 * add an HklMode to the self HklEngine
417 static inline void hkl_engine_add_mode(HklEngine *self,
418 HklMode *mode)
420 darray_append(self->modes, mode);
421 darray_append(self->mode_names, mode->info->name);
425 * hkl_engine_add_geometry: (skip)
426 * @self: the current PseudoAxeEngine
427 * @x: x A vector of double with the axes values to put in the geometry.
429 * This method try to be clever by allocating memory only if the
430 * current length of the geometries is not large enought. Then it just
431 * set the geometry axes and copy it to the right geometries. We do
432 * not gives the x len as it is equal to the self->axes_len.
435 static inline void hkl_engine_add_geometry(HklEngine *self,
436 double const x[])
438 HklParameter **axis;
439 uint i = 0;
441 /* copy the axes configuration into the engine->geometry */
442 darray_foreach(axis, self->axes){
443 hkl_parameter_value_set(*axis,
444 gsl_sf_angle_restrict_symm(x[i++]),
445 HKL_UNIT_DEFAULT,
446 NULL);
449 hkl_geometry_list_add(self->engines->geometries, self->geometry);
453 static inline void hkl_engine_prepare_internal(HklEngine *self)
455 uint i;
457 if(!self || !self->engines)
458 return;
460 /* set */
461 if(self->geometry)
462 hkl_geometry_free(self->geometry);
463 self->geometry = hkl_geometry_new_copy(self->engines->geometry);
465 if(self->detector)
466 hkl_detector_free(self->detector);
467 self->detector = hkl_detector_new_copy(self->engines->detector);
469 if(self->sample)
470 hkl_sample_free(self->sample);
471 self->sample = hkl_sample_new_copy(self->engines->sample);
473 /* fill the axes member from the function */
474 if(self->mode){
475 const char **axis_name;
477 darray_free(self->axes);
478 darray_init(self->axes);
479 darray_foreach(axis_name, self->mode->info->axes_w){
480 HklParameter *axis = hkl_geometry_get_axis_by_name(self->geometry,
481 *axis_name);
482 darray_append(self->axes, axis);
486 /* reset the geometries len */
487 hkl_geometry_list_reset(self->engines->geometries);
491 * hkl_engine_mode_set: (skip)
492 * @self: the HklEngine
493 * @name: the mode to select
495 * This method also populate the self->axes from the mode->axis_names.
496 * this is to speed the computation of the numerical axes.
498 static inline void hkl_engine_mode_set(HklEngine *self, HklMode *mode)
500 self->mode = mode;
504 static inline int hkl_engine_get(HklEngine *self,
505 GError **error) HKL_ARG_NONNULL(1);
507 * hkl_engine_get: (skip)
508 * @self: The HklEngine
509 * @error: return location for a GError, or NULL
511 * get the values of the pseudo-axes from the real-axes values
513 * return value: TRUE if succeded or FALSE otherwise.
515 static inline int hkl_engine_get(HklEngine *self, GError **error)
517 hkl_error (error == NULL || *error == NULL);
519 if(!self->engines || !self->engines->geometry || !self->engines->detector
520 || !self->engines->sample || !self->mode || !self->mode->ops->get){
521 g_set_error(error,
522 HKL_ENGINE_ERROR,
523 HKL_ENGINE_ERROR_GET,
524 "Internal error");
525 return FALSE;
528 if (!self->mode->ops->get(self->mode,
529 self,
530 self->engines->geometry,
531 self->engines->detector,
532 self->engines->sample,
533 error)){
534 hkl_assert(error == NULL || *error != NULL);
535 return FALSE;
537 hkl_assert(error == NULL || *error == NULL);
539 return TRUE;
544 * hkl_engine_set: (skip)
545 * @self: the HklEngine
546 * @error: return location for a GError, or NULL
548 * use the HklPseudoaxisEngine values to compute the real axes values.
550 * return value: TRUE if succeded or FALSE otherwise.
552 static inline int hkl_engine_set(HklEngine *self, GError **error)
554 hkl_error (error == NULL || *error == NULL);
556 if(!self->geometry || !self->detector || !self->sample
557 || !self->mode || !self->mode->ops->set){
558 g_set_error(error,
559 HKL_ENGINE_ERROR,
560 HKL_ENGINE_ERROR_SET,
561 "Internal error");
562 return FALSE;
565 hkl_engine_prepare_internal(self);
567 if (!self->mode->ops->set(self->mode, self,
568 self->geometry,
569 self->detector,
570 self->sample,
571 error)){
572 hkl_assert(error == NULL || *error != NULL);
573 return FALSE;
575 hkl_assert(error == NULL || *error == NULL);
577 hkl_geometry_list_multiply(self->engines->geometries);
578 hkl_geometry_list_multiply_from_range(self->engines->geometries);
579 hkl_geometry_list_remove_invalid(self->engines->geometries);
580 hkl_geometry_list_sort(self->engines->geometries, self->engines->geometry);
582 if(self->engines->geometries->n_items == 0){
583 g_set_error(error,
584 HKL_ENGINE_ERROR,
585 HKL_ENGINE_ERROR_SET,
586 "no remaining solutions");
587 return FALSE;
590 return TRUE;
593 /* HklEngineList */
596 #define HKL_ENGINE_LIST_ERROR hkl_engine_list_error_quark ()
599 static GQuark hkl_engine_list_error_quark (void)
601 return g_quark_from_static_string ("hkl-engine-list-error-quark");
605 typedef enum {
606 HKL_ENGINE_LIST_ERROR_ENGINE_GET_BY_NAME, /* can not set this geometry */
607 HKL_ENGINE_LIST_ERROR_PSEUDO_AXIS_GET_BY_NAME, /* can not set this geometry */
608 } HklEngineListError;
612 * hkl_engine_list_new: (skip)
614 * default constructor
616 * Returns:
618 static inline HklEngineList *hkl_engine_list_new(void)
620 HklEngineList *self = NULL;
622 self = HKL_MALLOC(HklEngineList);
624 darray_init(*self);
626 self->geometries = hkl_geometry_list_new();
628 self->geometry = NULL;
629 self->detector = NULL;
630 self->sample = NULL;
632 return self;
637 * hkl_engine_list_new_copy: (skip)
638 * @self:
640 * dummy copy constructor for the binding
642 * Returns: (transfer none): NULL all the time the structure is non-copyable
644 static inline const HklEngineList *hkl_engine_list_new_copy(const HklEngineList *self)
646 return NULL;
651 * hkl_engine_list_add: (skip)
652 * @self: the engine list
653 * @engine: the engine to add
655 * add an #HklEngine to the #HklEngineList
657 * Returns: HKL_SUCCESS or HKL_FAIL
659 static inline int hkl_engine_list_add(HklEngineList *self,
660 HklEngine *engine)
662 if (!engine)
663 return FALSE;
665 darray_append(*self, engine);
667 return TRUE;
672 * hkl_engine_list_clear: (skip)
673 * @self: the engine list to clear
675 * remove all engine from the engine list
677 static inline void hkl_engine_list_clear(HklEngineList *self)
679 HklEngine **engine;
681 darray_foreach(engine, *self){
682 hkl_engine_free(*engine);
684 darray_free(*self);
688 G_END_DECLS
690 #endif /* __HKL_PSEUDOAXIS_PRIVATE_H__ */