upgrading copyright year from 2015 to 2016
[hkl.git] / hkl / hkl-pseudoaxis-private.h
blob42cc5f5cf3b7326413735e168573d459350f9237
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 #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/array_size/array_size.h"
36 #include "hkl/ccan/darray/darray.h" // for darray_foreach, etc
38 G_BEGIN_DECLS
40 typedef struct _HklModeOperations HklModeOperations;
41 typedef struct _HklModeInfo HklModeInfo;
42 typedef struct _HklMode HklMode;
43 typedef struct _HklEngineInfo HklEngineInfo;
44 typedef struct _HklEngineOperations HklEngineOperations;
46 typedef darray(HklMode *) darray_mode;
48 /***********/
49 /* HklMode */
50 /***********/
52 struct _HklModeInfo {
53 const char *name;
54 const darray_string axes_r;
55 const darray_string axes_w;
56 const darray(const HklParameter) parameters;
59 #define HKL_MODE_INFO_RO(_name, _axes) .name=_name, .axes_r=DARRAY(_axes)
60 #define HKL_MODE_INFO(_name, _axes_r, _axes_w) HKL_MODE_INFO_RO((_name), (_axes_r)), .axes_w=DARRAY((_axes_w))
62 #define HKL_MODE_INFO_RO_WITH_PARAMS(_name, _axes, _parameters) HKL_MODE_INFO_RO((_name), (_axes)), .parameters=DARRAY(_parameters)
63 #define HKL_MODE_INFO_WITH_PARAMS(_name, _axes_r, _axes_w, _parameters) \
64 HKL_MODE_INFO(_name, _axes_r, _axes_w), .parameters=DARRAY(_parameters)
66 struct _HklModeOperations
68 unsigned long capabilities;
70 void (* free)(HklMode *self);
71 int (* initialized_get)(const HklMode *self);
72 int (* initialized_set)(HklMode *self,
73 HklEngine *engine,
74 HklGeometry *geometry,
75 HklDetector *detector,
76 HklSample *sample,
77 int initialized,
78 GError **error);
79 int (* get)(HklMode *self,
80 HklEngine *engine,
81 HklGeometry *geometry,
82 HklDetector *detector,
83 HklSample *sample,
84 GError **error);
85 int (* set)(HklMode *self,
86 HklEngine *engine,
87 HklGeometry *geometry,
88 HklDetector *detector,
89 HklSample *sample,
90 GError **error);
94 #define HKL_MODE_OPERATIONS_DEFAULTS .capabilities=HKL_ENGINE_CAPABILITIES_READABLE | HKL_ENGINE_CAPABILITIES_WRITABLE, \
95 .free=hkl_mode_free_real, \
96 .initialized_get=hkl_mode_initialized_get_real, \
97 .initialized_set=hkl_mode_initialized_set_real, \
98 .get=hkl_mode_get_real, \
99 .set=hkl_mode_set_real
102 struct _HklMode
104 const HklModeInfo *info;
105 const HklModeOperations *ops;
106 darray_parameter parameters;
107 darray_string parameters_names;
108 int initialized;
112 static inline void hkl_mode_free_real(HklMode *self)
114 HklParameter **parameter;
116 darray_foreach(parameter, self->parameters){
117 hkl_parameter_free(*parameter);
119 darray_free(self->parameters);
121 darray_free(self->parameters_names);
123 free(self);
127 static inline int hkl_mode_initialized_get_real(const HklMode *self)
129 return self->initialized;
133 static inline int hkl_mode_initialized_get(const HklMode *self)
135 return self->ops->initialized_get(self);
139 static inline int hkl_mode_initialized_set_real(HklMode *self,
140 HklEngine *engine,
141 HklGeometry *geometry,
142 HklDetector *detector,
143 HklSample *sample,
144 int initialized,
145 GError **error)
147 /* by default do nothing and no error */
148 return TRUE;
152 static inline int hkl_mode_initialized_set(HklMode *self,
153 HklEngine *engine,
154 HklGeometry *geometry,
155 HklDetector *detector,
156 HklSample *sample,
157 int initialized,
158 GError **error)
160 return self->ops->initialized_set(self,
161 engine, geometry, detector, sample,
162 initialized, error);
166 static inline int hkl_mode_get_real(HklMode *self,
167 HklEngine *engine,
168 HklGeometry *geometry,
169 HklDetector *detector,
170 HklSample *sample,
171 GError **error)
173 /* by default do nothing and no error */
174 return FALSE;
178 static inline int hkl_mode_set_real(HklMode *self,
179 HklEngine *engine,
180 HklGeometry *geometry,
181 HklDetector *detector,
182 HklSample *sample,
183 GError **error)
185 /* by default do nothing and no error */
186 return FALSE;
190 static inline int hkl_mode_init(HklMode *self,
191 const HklModeInfo *info,
192 const HklModeOperations *ops,
193 int initialized)
195 const HklParameter *parameter;
197 /* ensure part */
198 if (!self)
199 return FALSE;
201 self->info = info;
202 self->ops = ops;
204 /* parameters */
205 darray_init(self->parameters);
206 darray_init(self->parameters_names);
207 darray_foreach(parameter, self->info->parameters){
208 darray_append(self->parameters, hkl_parameter_new_copy(parameter));
209 darray_append(self->parameters_names, parameter->name);
212 self->initialized = initialized;
214 return TRUE;
218 static inline HklMode *hkl_mode_new(const HklModeInfo *info,
219 const HklModeOperations *op,
220 int initialized)
222 HklMode *self = NULL;
224 self = HKL_MALLOC(HklMode);
226 hkl_mode_init(self, info, op, initialized);
228 return self;
233 * hkl_mode_free: (skip)
234 * @self:
236 * delete an HklMode
238 static inline void hkl_mode_free(HklMode *self)
240 self->ops->free(self);
243 /*************/
244 /* HklEngine */
245 /*************/
248 struct _HklEngineInfo {
249 const char *name;
250 const darray(const HklParameter *) pseudo_axes;
251 unsigned int dependencies;
254 #define HKL_ENGINE_INFO(_name, _pseudo_axes, _dependencies) .name = (_name), \
255 .pseudo_axes = DARRAY(_pseudo_axes), \
256 .dependencies = (_dependencies)
258 struct _HklEngine
260 const HklEngineInfo *info;
261 const HklEngineOperations *ops;
262 HklGeometry *geometry;
263 HklDetector *detector;
264 HklSample *sample;
265 HklMode *mode; /* not owned */
266 HklEngineList *engines; /* not owned */
267 darray_parameter axes;
268 darray_parameter pseudo_axes;
269 darray_string pseudo_axis_names;
270 darray_mode modes;
271 darray_string mode_names;
275 struct _HklEngineList
277 _darray(HklEngine *);
278 HklGeometryList *geometries;
279 HklGeometry *geometry;
280 HklDetector *detector;
281 HklSample *sample;
282 darray_parameter pseudo_axes;
286 #define HKL_ENGINE_ERROR hkl_engine_error_quark ()
289 static GQuark hkl_engine_error_quark (void)
291 return g_quark_from_static_string ("hkl-engine-error-quark");
295 typedef enum {
296 HKL_ENGINE_ERROR_PSEUDO_AXIS_VALUES_GET, /* can not get the engine pseudo axes values */
297 HKL_ENGINE_ERROR_PSEUDO_AXIS_VALUES_SET, /* can not set the engine pseudo axes values */
298 HKL_ENGINE_ERROR_PSEUDO_AXIS_SET, /* can not set the pseudo axis */
299 HKL_ENGINE_ERROR_INITIALIZE, /* can not initialize the engine */
300 HKL_ENGINE_ERROR_SET, /* can not set the engine */
301 HKL_ENGINE_ERROR_GET, /* can not get the engine */
302 HKL_ENGINE_ERROR_PARAMETER_GET, /* can not get the parameter */
303 HKL_ENGINE_ERROR_PARAMETER_SET, /* can not set the parameter */
304 HKL_ENGINE_ERROR_CURRENT_MODE_SET, /* can not select the mode */
305 } HklEngineError;
308 static inline void set_geometry_axes(HklEngine *engine, const double values[])
310 HklParameter **axis;
311 uint i = 0;
313 darray_foreach(axis, engine->axes){
314 hkl_parameter_value_set(*axis, values[i++], HKL_UNIT_DEFAULT, NULL);
316 hkl_geometry_update(engine->geometry);
320 static inline void hkl_engine_release(HklEngine *self)
322 HklMode **mode;
324 if(self->geometry)
325 hkl_geometry_free(self->geometry);
327 if(self->detector)
328 hkl_detector_free(self->detector);
330 if(self->sample)
331 hkl_sample_free(self->sample);
333 /* release the mode added */
334 darray_foreach(mode, self->modes){
335 hkl_mode_free(*mode);
337 darray_free(self->modes);
339 darray_free(self->axes);
340 darray_free(self->pseudo_axes);
341 darray_free(self->pseudo_axis_names);
342 darray_free(self->mode_names);
346 struct _HklEngineOperations
348 void (*free)(HklEngine *self);
352 #define HKL_ENGINE_OPERATIONS_DEFAULTS .free=hkl_engine_free_real
355 static inline void hkl_engine_free_real(HklEngine *self)
360 static inline void hkl_engine_free(HklEngine *self)
362 self->ops->free(self);
366 static inline void hkl_engine_init(HklEngine *self,
367 const HklEngineInfo *info,
368 const HklEngineOperations *ops,
369 HklEngineList *engines)
371 self->info = info;
372 self->ops = ops;
373 darray_init(self->modes);
374 darray_init(self->pseudo_axes);
375 darray_init(self->pseudo_axis_names);
376 darray_init(self->mode_names);
377 self->geometry = NULL;
378 self->detector = NULL;
379 self->sample = NULL;
380 self->engines = engines;
382 darray_append(*engines, self);
386 static inline HklParameter *register_mode_parameter(HklMode *mode, unsigned int index)
388 return darray_item(mode->parameters, index);
391 static inline HklParameter *register_pseudo_axis(HklEngine *self,
392 HklEngineList *engines,
393 const HklParameter *pseudo_axis)
395 HklParameter **param;
396 HklParameter *parameter;
398 /* try to find an already existing pseudo axis in the list. */
399 darray_foreach(param, engines->pseudo_axes){
400 if(!strcmp(pseudo_axis->name, (*param)->name)){
401 parameter = *param;
402 goto out;
406 parameter = hkl_parameter_new_copy(pseudo_axis);
407 darray_append(engines->pseudo_axes, parameter);
408 out:
409 darray_append(self->pseudo_axes, parameter);
410 darray_append(self->pseudo_axis_names, parameter->name);
412 return parameter;
416 * hkl_engine_add_mode: (skip)
417 * @self:
418 * @mode: the mode to add
420 * add an HklMode to the self HklEngine
422 static inline void hkl_engine_add_mode(HklEngine *self,
423 HklMode *mode)
425 darray_append(self->modes, mode);
426 darray_append(self->mode_names, mode->info->name);
430 * hkl_engine_add_geometry: (skip)
431 * @self: the current PseudoAxeEngine
432 * @x: x A vector of double with the axes values to put in the geometry.
434 * This method try to be clever by allocating memory only if the
435 * current length of the geometries is not large enought. Then it just
436 * set the geometry axes and copy it to the right geometries. We do
437 * not gives the x len as it is equal to the self->axes_len.
440 static inline void hkl_engine_add_geometry(HklEngine *self,
441 double const x[])
443 HklParameter **axis;
444 uint i = 0;
446 /* copy the axes configuration into the engine->geometry */
447 darray_foreach(axis, self->axes){
448 hkl_parameter_value_set(*axis,
449 gsl_sf_angle_restrict_symm(x[i++]),
450 HKL_UNIT_DEFAULT,
451 NULL);
454 hkl_geometry_list_add(self->engines->geometries, self->geometry);
458 static inline void hkl_engine_prepare_internal(HklEngine *self)
460 if(!self || !self->engines)
461 return;
463 /* set */
464 if(self->geometry)
465 hkl_geometry_free(self->geometry);
466 self->geometry = hkl_geometry_new_copy(self->engines->geometry);
468 if(self->detector)
469 hkl_detector_free(self->detector);
470 self->detector = hkl_detector_new_copy(self->engines->detector);
472 if(self->sample)
473 hkl_sample_free(self->sample);
474 self->sample = hkl_sample_new_copy(self->engines->sample);
476 /* fill the axes member from the function */
477 if(self->mode){
478 const char **axis_name;
480 darray_free(self->axes);
481 darray_init(self->axes);
482 darray_foreach(axis_name, self->mode->info->axes_w){
483 HklParameter *axis = hkl_geometry_get_axis_by_name(self->geometry,
484 *axis_name);
485 darray_append(self->axes, axis);
489 /* reset the geometries len */
490 hkl_geometry_list_reset(self->engines->geometries);
494 * hkl_engine_mode_set: (skip)
495 * @self: the HklEngine
496 * @name: the mode to select
498 * This method also populate the self->axes from the mode->axis_names.
499 * this is to speed the computation of the numerical axes.
501 static inline void hkl_engine_mode_set(HklEngine *self, HklMode *mode)
503 self->mode = mode;
507 static inline int hkl_engine_get(HklEngine *self,
508 GError **error) HKL_ARG_NONNULL(1);
510 * hkl_engine_get: (skip)
511 * @self: The HklEngine
512 * @error: return location for a GError, or NULL
514 * get the values of the pseudo-axes from the real-axes values
516 * return value: TRUE if succeded or FALSE otherwise.
518 static inline int hkl_engine_get(HklEngine *self, GError **error)
520 hkl_error (error == NULL || *error == NULL);
522 if(!self->engines || !self->engines->geometry || !self->engines->detector
523 || !self->engines->sample || !self->mode || !self->mode->ops->get){
524 g_set_error(error,
525 HKL_ENGINE_ERROR,
526 HKL_ENGINE_ERROR_GET,
527 "Internal error");
528 return FALSE;
531 if (!self->mode->ops->get(self->mode,
532 self,
533 self->engines->geometry,
534 self->engines->detector,
535 self->engines->sample,
536 error)){
537 hkl_assert(error == NULL || *error != NULL);
538 return FALSE;
540 hkl_assert(error == NULL || *error == NULL);
542 return TRUE;
547 * hkl_engine_set: (skip)
548 * @self: the HklEngine
549 * @error: return location for a GError, or NULL
551 * use the HklPseudoaxisEngine values to compute the real axes values.
553 * return value: TRUE if succeded or FALSE otherwise.
555 static inline int hkl_engine_set(HklEngine *self, GError **error)
557 hkl_error (error == NULL || *error == NULL);
559 if(!self->geometry || !self->detector || !self->sample
560 || !self->mode || !self->mode->ops->set){
561 g_set_error(error,
562 HKL_ENGINE_ERROR,
563 HKL_ENGINE_ERROR_SET,
564 "Internal error");
565 return FALSE;
568 hkl_engine_prepare_internal(self);
570 if (!self->mode->ops->set(self->mode, self,
571 self->geometry,
572 self->detector,
573 self->sample,
574 error)){
575 hkl_assert(error == NULL || *error != NULL);
576 return FALSE;
578 hkl_assert(error == NULL || *error == NULL);
580 hkl_geometry_list_multiply(self->engines->geometries);
581 hkl_geometry_list_multiply_from_range(self->engines->geometries);
582 hkl_geometry_list_remove_invalid(self->engines->geometries);
583 hkl_geometry_list_sort(self->engines->geometries, self->engines->geometry);
585 if(self->engines->geometries->n_items == 0){
586 g_set_error(error,
587 HKL_ENGINE_ERROR,
588 HKL_ENGINE_ERROR_SET,
589 "no remaining solutions");
590 return FALSE;
593 return TRUE;
596 /* HklEngineList */
599 #define HKL_ENGINE_LIST_ERROR hkl_engine_list_error_quark ()
602 static inline GQuark hkl_engine_list_error_quark (void)
604 return g_quark_from_static_string ("hkl-engine-list-error-quark");
608 typedef enum {
609 HKL_ENGINE_LIST_ERROR_ENGINE_GET_BY_NAME, /* can not set this geometry */
610 HKL_ENGINE_LIST_ERROR_PSEUDO_AXIS_GET_BY_NAME, /* can not set this geometry */
611 } HklEngineListError;
615 * hkl_engine_list_new: (skip)
617 * default constructor
619 * Returns:
621 static inline HklEngineList *hkl_engine_list_new(void)
623 HklEngineList *self = NULL;
625 self = HKL_MALLOC(HklEngineList);
627 darray_init(*self);
629 self->geometries = hkl_geometry_list_new();
631 self->geometry = NULL;
632 self->detector = NULL;
633 self->sample = NULL;
635 darray_init(self->pseudo_axes);
637 return self;
642 * hkl_engine_list_new_copy: (skip)
643 * @self:
645 * dummy copy constructor for the binding
647 * Returns: (transfer none): NULL all the time the structure is non-copyable
649 static inline const HklEngineList *hkl_engine_list_new_copy(const HklEngineList *self)
651 return NULL;
655 * hkl_engine_list_clear: (skip)
656 * @self: the engine list to clear
658 * remove all engine from the engine list
660 static inline void hkl_engine_list_clear(HklEngineList *self)
662 HklEngine **engine;
663 HklParameter **parameter;
665 darray_foreach(engine, *self){
666 hkl_engine_free(*engine);
668 darray_free(*self);
670 darray_foreach(parameter, self->pseudo_axes){
671 hkl_parameter_free(*parameter);
673 darray_free(self->pseudo_axes);
677 G_END_DECLS
679 #endif /* __HKL_PSEUDOAXIS_PRIVATE_H__ */