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
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
;
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
,
71 HklGeometry
*geometry
,
72 HklDetector
*detector
,
76 int (* get
)(HklMode
*self
,
78 HklGeometry
*geometry
,
79 HklDetector
*detector
,
82 int (* set
)(HklMode
*self
,
84 HklGeometry
*geometry
,
85 HklDetector
*detector
,
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
101 const HklModeInfo
*info
;
102 const HklModeOperations
*ops
;
103 darray_parameter parameters
;
104 darray_string parameters_names
;
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
);
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
,
138 HklGeometry
*geometry
,
139 HklDetector
*detector
,
144 /* by default do nothing and no error */
149 static inline int hkl_mode_initialized_set(HklMode
*self
,
151 HklGeometry
*geometry
,
152 HklDetector
*detector
,
157 return self
->ops
->initialized_set(self
,
158 engine
, geometry
, detector
, sample
,
163 static inline int hkl_mode_get_real(HklMode
*self
,
165 HklGeometry
*geometry
,
166 HklDetector
*detector
,
170 /* by default do nothing and no error */
175 static inline int hkl_mode_set_real(HklMode
*self
,
177 HklGeometry
*geometry
,
178 HklDetector
*detector
,
182 /* by default do nothing and no error */
187 static inline int hkl_mode_init(HklMode
*self
,
188 const HklModeInfo
*info
,
189 const HklModeOperations
*ops
,
193 const HklParameter
*parameter
;
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
;
216 static inline HklMode
*hkl_mode_new(const HklModeInfo
*info
,
217 const HklModeOperations
*op
,
220 HklMode
*self
= NULL
;
222 self
= HKL_MALLOC(HklMode
);
224 hkl_mode_init(self
, info
, op
, initialized
);
231 * hkl_mode_free: (skip)
236 static inline void hkl_mode_free(HklMode
*self
)
238 self
->ops
->free(self
);
246 struct _HklEngineInfo
{
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)
258 const HklEngineInfo
*info
;
259 const HklEngineOperations
*ops
;
260 HklGeometry
*geometry
;
261 HklDetector
*detector
;
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
;
269 darray_string mode_names
;
273 struct _HklEngineList
275 _darray(HklEngine
*);
276 HklGeometryList
*geometries
;
277 HklGeometry
*geometry
;
278 HklDetector
*detector
;
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");
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 */
305 static inline void set_geometry_axes(HklEngine
*engine
, const double values
[])
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
)
320 HklParameter
**pseudo_axis
;
323 hkl_geometry_free(self
->geometry
);
326 hkl_detector_free(self
->detector
);
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
)
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
;
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
);
411 * hkl_engine_add_mode: (skip)
413 * @mode: the mode to add
415 * add an HklMode to the self HklEngine
417 static inline void hkl_engine_add_mode(HklEngine
*self
,
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
,
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
++]),
449 hkl_geometry_list_add(self
->engines
->geometries
, self
->geometry
);
453 static inline void hkl_engine_prepare_internal(HklEngine
*self
)
457 if(!self
|| !self
->engines
)
462 hkl_geometry_free(self
->geometry
);
463 self
->geometry
= hkl_geometry_new_copy(self
->engines
->geometry
);
466 hkl_detector_free(self
->detector
);
467 self
->detector
= hkl_detector_new_copy(self
->engines
->detector
);
470 hkl_sample_free(self
->sample
);
471 self
->sample
= hkl_sample_new_copy(self
->engines
->sample
);
473 /* fill the axes member from the function */
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
,
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
)
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
){
523 HKL_ENGINE_ERROR_GET
,
528 if (!self
->mode
->ops
->get(self
->mode
,
530 self
->engines
->geometry
,
531 self
->engines
->detector
,
532 self
->engines
->sample
,
534 hkl_assert(error
== NULL
|| *error
!= NULL
);
537 hkl_assert(error
== NULL
|| *error
== NULL
);
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
){
560 HKL_ENGINE_ERROR_SET
,
565 hkl_engine_prepare_internal(self
);
567 if (!self
->mode
->ops
->set(self
->mode
, self
,
572 hkl_assert(error
== NULL
|| *error
!= NULL
);
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){
585 HKL_ENGINE_ERROR_SET
,
586 "no remaining solutions");
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");
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
618 static inline HklEngineList
*hkl_engine_list_new(void)
620 HklEngineList
*self
= NULL
;
622 self
= HKL_MALLOC(HklEngineList
);
626 self
->geometries
= hkl_geometry_list_new();
628 self
->geometry
= NULL
;
629 self
->detector
= NULL
;
637 * hkl_engine_list_new_copy: (skip)
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
)
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
,
665 darray_append(*self
, engine
);
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
)
681 darray_foreach(engine
, *self
){
682 hkl_engine_free(*engine
);
690 #endif /* __HKL_PSEUDOAXIS_PRIVATE_H__ */