[contrib] use (*~~) and (/~~) instead of from/toAngles
[hkl.git] / hkl / hkl-pseudoaxis-private.h
blobe09ecd80d54bcfd3b940673f98c18b699f0325ec
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>
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 _HklPseudoAxis HklPseudoAxis;
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 /* HklPseudoAxis */
50 /*****************/
52 struct _HklPseudoAxis
54 HklParameter parameter;
55 HklEngine *engine;
59 #define HKL_PARAMETER_OPERATIONS_PSEUDOAXIS_DEFAULTS HKL_PARAMETER_OPERATIONS_DEFAULTS, \
60 .copy = hkl_parameter_copy_pseudo_axis_real, \
61 .free = hkl_parameter_free_pseudo_axis_real, \
62 .fprintf = hkl_parameter_fprintf_pseudo_axis_real
65 static inline HklParameter *hkl_parameter_copy_pseudo_axis_real(const HklParameter *self)
67 HklPseudoAxis *pseudo_axis = container_of(self, HklPseudoAxis, parameter);
68 HklPseudoAxis *dup = HKL_MALLOC(HklPseudoAxis);
70 *dup = *pseudo_axis;
72 return &dup->parameter;
76 static inline void hkl_parameter_free_pseudo_axis_real(HklParameter *self)
78 HklPseudoAxis *pseudo_axis = container_of(self, HklPseudoAxis, parameter);
80 free(pseudo_axis);
84 static inline void hkl_parameter_fprintf_pseudo_axis_real(FILE *f, const HklParameter *self)
86 HklPseudoAxis *pseudo_axis = container_of(self, HklPseudoAxis, parameter);
88 hkl_parameter_fprintf_real(f, self);
89 fprintf(f, " %p", pseudo_axis->engine);
93 static inline HklParameter *hkl_parameter_new_pseudo_axis(const HklParameter *parameter,
94 HklEngine *engine)
96 HklPseudoAxis *self;
97 static HklParameterOperations ops = {HKL_PARAMETER_OPERATIONS_PSEUDOAXIS_DEFAULTS};
99 self = HKL_MALLOC(HklPseudoAxis);
101 self->parameter = *parameter;
102 self->parameter.ops = &ops;
103 self->engine = engine;
105 return &self->parameter;
108 /***********/
109 /* HklMode */
110 /***********/
112 struct _HklModeInfo {
113 const char *name;
114 const darray_string axes_r;
115 const darray_string axes_w;
116 const darray(const HklParameter) parameters;
119 #define HKL_MODE_INFO(_name, _axes_r, _axes_w) .name=_name, .axes_r=DARRAY(_axes_r), .axes_w=DARRAY(_axes_w)
121 #define HKL_MODE_INFO_WITH_PARAMS(_name, _axes_r, _axes_w, _parameters) \
122 HKL_MODE_INFO(_name, _axes_r, _axes_w), .parameters=DARRAY(_parameters)
124 struct _HklModeOperations
126 unsigned long capabilities;
128 void (* free)(HklMode *self);
129 int (* initialized_get)(const HklMode *self);
130 int (* initialized_set)(HklMode *self,
131 HklEngine *engine,
132 HklGeometry *geometry,
133 HklDetector *detector,
134 HklSample *sample,
135 int initialized,
136 GError **error);
137 int (* get)(HklMode *self,
138 HklEngine *engine,
139 HklGeometry *geometry,
140 HklDetector *detector,
141 HklSample *sample,
142 GError **error);
143 int (* set)(HklMode *self,
144 HklEngine *engine,
145 HklGeometry *geometry,
146 HklDetector *detector,
147 HklSample *sample,
148 GError **error);
152 #define HKL_MODE_OPERATIONS_DEFAULTS .capabilities=HKL_ENGINE_CAPABILITIES_READABLE | HKL_ENGINE_CAPABILITIES_WRITABLE, \
153 .free=hkl_mode_free_real, \
154 .initialized_get=hkl_mode_initialized_get_real, \
155 .initialized_set=hkl_mode_initialized_set_real, \
156 .get=hkl_mode_get_real, \
157 .set=hkl_mode_set_real
160 struct _HklMode
162 const HklModeInfo *info;
163 const HklModeOperations *ops;
164 darray_parameter parameters;
165 darray_string parameters_names;
166 int initialized;
170 static inline void hkl_mode_free_real(HklMode *self)
172 HklParameter **parameter;
174 darray_foreach(parameter, self->parameters){
175 hkl_parameter_free(*parameter);
177 darray_free(self->parameters);
179 darray_free(self->parameters_names);
181 free(self);
185 static inline int hkl_mode_initialized_get_real(const HklMode *self)
187 return self->initialized;
191 static inline int hkl_mode_initialized_get(const HklMode *self)
193 return self->ops->initialized_get(self);
197 static inline int hkl_mode_initialized_set_real(HklMode *self,
198 HklEngine *engine,
199 HklGeometry *geometry,
200 HklDetector *detector,
201 HklSample *sample,
202 int initialized,
203 GError **error)
205 /* by default do nothing and no error */
206 return TRUE;
210 static inline int hkl_mode_initialized_set(HklMode *self,
211 HklEngine *engine,
212 HklGeometry *geometry,
213 HklDetector *detector,
214 HklSample *sample,
215 int initialized,
216 GError **error)
218 return self->ops->initialized_set(self,
219 engine, geometry, detector, sample,
220 initialized, error);
224 static inline int hkl_mode_get_real(HklMode *self,
225 HklEngine *engine,
226 HklGeometry *geometry,
227 HklDetector *detector,
228 HklSample *sample,
229 GError **error)
231 /* by default do nothing and no error */
232 return TRUE;
236 static inline int hkl_mode_set_real(HklMode *self,
237 HklEngine *engine,
238 HklGeometry *geometry,
239 HklDetector *detector,
240 HklSample *sample,
241 GError **error)
243 /* by default do nothing and no error */
244 return TRUE;
248 static inline int hkl_mode_init(HklMode *self,
249 const HklModeInfo *info,
250 const HklModeOperations *ops,
251 int initialized)
253 size_t i;
254 const HklParameter *parameter;
256 /* ensure part */
257 if (!self)
258 return FALSE;
260 self->info = info;
261 self->ops = ops;
263 /* parameters */
264 darray_init(self->parameters);
265 darray_init(self->parameters_names);
266 darray_foreach(parameter, self->info->parameters){
267 darray_append(self->parameters, hkl_parameter_new_copy(parameter));
268 darray_append(self->parameters_names, parameter->name);
271 self->initialized = initialized;
273 return TRUE;
277 static inline HklMode *hkl_mode_new(const HklModeInfo *info,
278 const HklModeOperations *op,
279 int initialized)
281 HklMode *self = NULL;
283 self = HKL_MALLOC(HklMode);
285 hkl_mode_init(self, info, op, initialized);
287 return self;
292 * hkl_mode_free: (skip)
293 * @self:
295 * delete an HklMode
297 static inline void hkl_mode_free(HklMode *self)
299 self->ops->free(self);
302 /*************/
303 /* HklEngine */
304 /*************/
307 struct _HklEngineInfo {
308 const char *name;
309 const darray(const HklPseudoAxis *) pseudo_axes;
313 struct _HklEngine
315 const HklEngineInfo *info;
316 const HklEngineOperations *ops;
317 HklGeometry *geometry;
318 HklDetector *detector;
319 HklSample *sample;
320 HklMode *mode; /* not owned */
321 HklEngineList *engines; /* not owned */
322 darray_parameter axes;
323 darray_parameter pseudo_axes;
324 darray_string pseudo_axis_names;
325 darray_mode modes;
326 darray_string mode_names;
330 struct _HklEngineList
332 _darray(HklEngine *);
333 HklGeometryList *geometries;
334 HklGeometry *geometry;
335 HklDetector *detector;
336 HklSample *sample;
340 #define HKL_ENGINE_ERROR hkl_engine_error_quark ()
343 static GQuark hkl_engine_error_quark (void)
345 return g_quark_from_static_string ("hkl-engine-error-quark");
349 typedef enum {
350 HKL_ENGINE_ERROR_PSEUDO_AXIS_VALUES_GET, /* can not get the engine pseudo axes values */
351 HKL_ENGINE_ERROR_PSEUDO_AXIS_VALUES_SET, /* can not set the engine pseudo axes values */
352 HKL_ENGINE_ERROR_PSEUDO_AXIS_SET, /* can not set the pseudo axis */
353 HKL_ENGINE_ERROR_INITIALIZE, /* can not initialize the engine */
354 HKL_ENGINE_ERROR_SET, /* can not set the engine */
355 HKL_ENGINE_ERROR_GET, /* can not get the engine */
356 HKL_ENGINE_ERROR_PARAMETER_GET, /* can not get the parameter */
357 HKL_ENGINE_ERROR_PARAMETER_SET, /* can not set the parameter */
358 HKL_ENGINE_ERROR_CURRENT_MODE_SET, /* can not select the mode */
359 } HklEngineError;
362 static inline void set_geometry_axes(HklEngine *engine, const double values[])
364 HklParameter **axis;
365 uint i = 0;
367 darray_foreach(axis, engine->axes){
368 hkl_parameter_value_set(*axis, values[i++], HKL_UNIT_DEFAULT, NULL);
370 hkl_geometry_update(engine->geometry);
374 static inline void hkl_engine_release(HklEngine *self)
376 HklMode **mode;
377 HklParameter **pseudo_axis;
379 if(self->geometry)
380 hkl_geometry_free(self->geometry);
382 if(self->detector)
383 hkl_detector_free(self->detector);
385 if(self->sample)
386 hkl_sample_free(self->sample);
388 /* release the mode added */
389 darray_foreach(mode, self->modes){
390 hkl_mode_free(*mode);
392 darray_free(self->modes);
394 darray_free(self->axes);
396 /* release the HklPseudoAxe memory */
397 darray_foreach(pseudo_axis, self->pseudo_axes){
398 hkl_parameter_free(*pseudo_axis);
400 darray_free(self->pseudo_axes);
402 darray_free(self->pseudo_axis_names);
404 darray_free(self->mode_names);
408 struct _HklEngineOperations
410 void (*free)(HklEngine *self);
414 #define HKL_ENGINE_OPERATIONS_DEFAULTS .free=hkl_engine_free_real
417 static inline void hkl_engine_free_real(HklEngine *self)
422 static inline void hkl_engine_free(HklEngine *self)
424 self->ops->free(self);
428 static inline void hkl_engine_init(HklEngine *self,
429 const HklEngineInfo *info,
430 const HklEngineOperations *ops)
432 self->info = info;
433 self->ops = ops;
434 darray_init(self->modes);
435 darray_init(self->pseudo_axes);
436 darray_init(self->pseudo_axis_names);
437 darray_init(self->mode_names);
438 self->geometry = NULL;
439 self->detector = NULL;
440 self->sample = NULL;
444 static inline void unregister_pseudo_axis(HklParameter *pseudo_axis)
446 hkl_parameter_free(pseudo_axis);
450 static inline HklParameter *register_pseudo_axis(HklEngine *self,
451 const HklParameter *pseudo_axis)
453 HklParameter *parameter;
455 parameter = hkl_parameter_new_pseudo_axis(pseudo_axis, self);
456 darray_append(self->pseudo_axes, parameter);
457 darray_append(self->pseudo_axis_names, parameter->name);
459 return parameter;
463 * hkl_engine_add_mode: (skip)
464 * @self:
465 * @mode: the mode to add
467 * add an HklMode to the self HklEngine
469 static inline void hkl_engine_add_mode(HklEngine *self,
470 HklMode *mode)
472 darray_append(self->modes, mode);
473 darray_append(self->mode_names, mode->info->name);
477 * hkl_engine_add_geometry: (skip)
478 * @self: the current PseudoAxeEngine
479 * @x: x A vector of double with the axes values to put in the geometry.
481 * This method try to be clever by allocating memory only if the
482 * current length of the geometries is not large enought. Then it just
483 * set the geometry axes and copy it to the right geometries. We do
484 * not gives the x len as it is equal to the self->axes_len.
487 static inline void hkl_engine_add_geometry(HklEngine *self,
488 double const x[])
490 HklParameter **axis;
491 uint i = 0;
493 /* copy the axes configuration into the engine->geometry */
494 darray_foreach(axis, self->axes){
495 hkl_parameter_value_set(*axis,
496 gsl_sf_angle_restrict_symm(x[i++]),
497 HKL_UNIT_DEFAULT,
498 NULL);
501 hkl_geometry_list_add(self->engines->geometries, self->geometry);
505 static inline void hkl_engine_prepare_internal(HklEngine *self)
507 uint i;
509 if(!self || !self->engines)
510 return;
512 /* set */
513 if(self->geometry)
514 hkl_geometry_free(self->geometry);
515 self->geometry = hkl_geometry_new_copy(self->engines->geometry);
517 if(self->detector)
518 hkl_detector_free(self->detector);
519 self->detector = hkl_detector_new_copy(self->engines->detector);
521 if(self->sample)
522 hkl_sample_free(self->sample);
523 self->sample = hkl_sample_new_copy(self->engines->sample);
525 /* fill the axes member from the function */
526 if(self->mode){
527 const char **axis_name;
529 darray_free(self->axes);
530 darray_init(self->axes);
531 darray_foreach(axis_name, self->mode->info->axes_w){
532 HklParameter *axis = hkl_geometry_get_axis_by_name(self->geometry,
533 *axis_name);
534 darray_append(self->axes, axis);
538 /* reset the geometries len */
539 hkl_geometry_list_reset(self->engines->geometries);
543 * hkl_engine_mode_set: (skip)
544 * @self: the HklEngine
545 * @name: the mode to select
547 * This method also populate the self->axes from the mode->axis_names.
548 * this is to speed the computation of the numerical axes.
550 static inline void hkl_engine_mode_set(HklEngine *self, HklMode *mode)
552 self->mode = mode;
553 hkl_engine_prepare_internal(self);
557 static inline int hkl_engine_get(HklEngine *self,
558 GError **error) HKL_ARG_NONNULL(1);
560 * hkl_engine_get: (skip)
561 * @self: The HklEngine
562 * @error: return location for a GError, or NULL
564 * get the values of the pseudo-axes from the real-axes values
566 * return value: TRUE if succeded or FALSE otherwise.
568 static inline int hkl_engine_get(HklEngine *self, GError **error)
570 hkl_error (error == NULL || *error == NULL);
572 if(!self->engines || !self->engines->geometry || !self->engines->detector
573 || !self->engines->sample || !self->mode || !self->mode->ops->get){
574 g_set_error(error,
575 HKL_ENGINE_ERROR,
576 HKL_ENGINE_ERROR_GET,
577 "Internal error");
578 return FALSE;
581 if (!self->mode->ops->get(self->mode,
582 self,
583 self->engines->geometry,
584 self->engines->detector,
585 self->engines->sample,
586 error)){
587 hkl_assert(error == NULL || *error != NULL);
588 return FALSE;
590 hkl_assert(error == NULL || *error == NULL);
592 return TRUE;
597 * hkl_engine_set: (skip)
598 * @self: the HklEngine
599 * @error: return location for a GError, or NULL
601 * use the HklPseudoaxisEngine values to compute the real axes values.
603 * return value: TRUE if succeded or FALSE otherwise.
605 static inline int hkl_engine_set(HklEngine *self, GError **error)
607 hkl_error (error == NULL || *error == NULL);
609 if(!self->geometry || !self->detector || !self->sample
610 || !self->mode || !self->mode->ops->set){
611 g_set_error(error,
612 HKL_ENGINE_ERROR,
613 HKL_ENGINE_ERROR_SET,
614 "Internal error");
615 return FALSE;
618 hkl_engine_prepare_internal(self);
620 if (!self->mode->ops->set(self->mode, self,
621 self->geometry,
622 self->detector,
623 self->sample,
624 error)){
625 hkl_assert(error == NULL || *error != NULL);
626 return FALSE;
628 hkl_assert(error == NULL || *error == NULL);
630 hkl_geometry_list_multiply(self->engines->geometries);
631 hkl_geometry_list_multiply_from_range(self->engines->geometries);
632 hkl_geometry_list_remove_invalid(self->engines->geometries);
633 hkl_geometry_list_sort(self->engines->geometries, self->engines->geometry);
635 if(self->engines->geometries->n_items == 0){
636 g_set_error(error,
637 HKL_ENGINE_ERROR,
638 HKL_ENGINE_ERROR_SET,
639 "no remaining solutions");
640 return FALSE;
643 return TRUE;
646 /* HklEngineList */
649 #define HKL_ENGINE_LIST_ERROR hkl_engine_list_error_quark ()
652 static GQuark hkl_engine_list_error_quark (void)
654 return g_quark_from_static_string ("hkl-engine-list-error-quark");
658 typedef enum {
659 HKL_ENGINE_LIST_ERROR_ENGINE_GET_BY_NAME, /* can not set this geometry */
660 HKL_ENGINE_LIST_ERROR_PSEUDO_AXIS_GET_BY_NAME, /* can not set this geometry */
661 } HklEngineListError;
665 * hkl_engine_list_new: (skip)
667 * default constructor
669 * Returns:
671 static inline HklEngineList *hkl_engine_list_new(void)
673 HklEngineList *self = NULL;
675 self = HKL_MALLOC(HklEngineList);
677 darray_init(*self);
679 self->geometries = hkl_geometry_list_new();
681 self->geometry = NULL;
682 self->detector = NULL;
683 self->sample = NULL;
685 return self;
690 * hkl_engine_list_new_copy: (skip)
691 * @self:
693 * dummy copy constructor for the binding
695 * Returns: (transfer none): NULL all the time the structure is non-copyable
697 static inline const HklEngineList *hkl_engine_list_new_copy(const HklEngineList *self)
699 return NULL;
704 * hkl_engine_list_add: (skip)
705 * @self: the engine list
706 * @engine: the engine to add
708 * add an #HklEngine to the #HklEngineList
710 * Returns: HKL_SUCCESS or HKL_FAIL
712 static inline int hkl_engine_list_add(HklEngineList *self,
713 HklEngine *engine)
715 if (!engine)
716 return FALSE;
718 /* set the engines to access the Geometries list. */
719 engine->engines = self;
721 darray_append(*self, engine);
723 return TRUE;
728 * hkl_engine_list_clear: (skip)
729 * @self: the engine list to clear
731 * remove all engine from the engine list
733 static inline void hkl_engine_list_clear(HklEngineList *self)
735 HklEngine **engine;
737 darray_foreach(engine, *self){
738 hkl_engine_free(*engine);
740 darray_free(*self);
744 G_END_DECLS
746 #endif /* __HKL_PSEUDOAXIS_PRIVATE_H__ */