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-2017 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
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
;
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
,
74 HklGeometry
*geometry
,
75 HklDetector
*detector
,
79 int (* get
)(HklMode
*self
,
81 HklGeometry
*geometry
,
82 HklDetector
*detector
,
85 int (* set
)(HklMode
*self
,
87 HklGeometry
*geometry
,
88 HklDetector
*detector
,
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
104 const HklModeInfo
*info
;
105 const HklModeOperations
*ops
;
106 darray_parameter parameters
;
107 darray_string parameters_names
;
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
);
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(UNUSED HklMode
*self
,
140 UNUSED HklEngine
*engine
,
141 UNUSED HklGeometry
*geometry
,
142 UNUSED HklDetector
*detector
,
143 UNUSED HklSample
*sample
,
144 UNUSED
int initialized
,
145 UNUSED GError
**error
)
147 /* by default do nothing and no error */
152 static inline int hkl_mode_initialized_set(HklMode
*self
,
154 HklGeometry
*geometry
,
155 HklDetector
*detector
,
160 return self
->ops
->initialized_set(self
,
161 engine
, geometry
, detector
, sample
,
166 static inline int hkl_mode_get_real(UNUSED HklMode
*self
,
167 UNUSED HklEngine
*engine
,
168 UNUSED HklGeometry
*geometry
,
169 UNUSED HklDetector
*detector
,
170 UNUSED HklSample
*sample
,
171 UNUSED GError
**error
)
173 /* by default do nothing and no error */
178 static inline int hkl_mode_set_real(UNUSED HklMode
*self
,
179 UNUSED HklEngine
*engine
,
180 UNUSED HklGeometry
*geometry
,
181 UNUSED HklDetector
*detector
,
182 UNUSED HklSample
*sample
,
183 UNUSED GError
**error
)
185 /* by default do nothing and no error */
190 static inline int hkl_mode_init(HklMode
*self
,
191 const HklModeInfo
*info
,
192 const HklModeOperations
*ops
,
195 const HklParameter
*parameter
;
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
;
218 static inline HklMode
*hkl_mode_new(const HklModeInfo
*info
,
219 const HklModeOperations
*op
,
222 HklMode
*self
= NULL
;
224 self
= HKL_MALLOC(HklMode
);
226 hkl_mode_init(self
, info
, op
, initialized
);
233 * hkl_mode_free: (skip)
238 static inline void hkl_mode_free(HklMode
*self
)
240 self
->ops
->free(self
);
248 struct _HklEngineInfo
{
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)
260 const HklEngineInfo
*info
;
261 const HklEngineOperations
*ops
;
262 HklGeometry
*geometry
;
263 HklDetector
*detector
;
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
;
271 darray_string mode_names
;
275 struct _HklEngineList
277 _darray(HklEngine
*);
278 HklGeometryList
*geometries
;
279 HklGeometry
*geometry
;
280 HklDetector
*detector
;
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");
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 */
308 static inline void set_geometry_axes(HklEngine
*engine
, const double values
[])
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
)
325 hkl_geometry_free(self
->geometry
);
328 hkl_detector_free(self
->detector
);
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(UNUSED 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
)
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
;
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
)){
406 parameter
= hkl_parameter_new_copy(pseudo_axis
);
407 darray_append(engines
->pseudo_axes
, parameter
);
409 darray_append(self
->pseudo_axes
, parameter
);
410 darray_append(self
->pseudo_axis_names
, parameter
->name
);
416 * hkl_engine_add_mode: (skip)
418 * @mode: the mode to add
420 * add an HklMode to the self HklEngine
422 static inline void hkl_engine_add_mode(HklEngine
*self
,
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
,
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
++]),
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
)
465 hkl_geometry_free(self
->geometry
);
466 self
->geometry
= hkl_geometry_new_copy(self
->engines
->geometry
);
469 hkl_detector_free(self
->detector
);
470 self
->detector
= hkl_detector_new_copy(self
->engines
->detector
);
473 hkl_sample_free(self
->sample
);
474 self
->sample
= hkl_sample_new_copy(self
->engines
->sample
);
476 /* fill the axes member from the function */
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
,
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
)
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
){
526 HKL_ENGINE_ERROR_GET
,
531 if (!self
->mode
->ops
->get(self
->mode
,
533 self
->engines
->geometry
,
534 self
->engines
->detector
,
535 self
->engines
->sample
,
537 hkl_assert(error
== NULL
|| *error
!= NULL
);
540 hkl_assert(error
== NULL
|| *error
== NULL
);
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
){
563 HKL_ENGINE_ERROR_SET
,
568 hkl_engine_prepare_internal(self
);
570 if (!self
->mode
->ops
->set(self
->mode
, self
,
575 hkl_assert(error
== NULL
|| *error
!= NULL
);
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){
588 HKL_ENGINE_ERROR_SET
,
589 "no remaining solutions");
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");
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
621 static inline HklEngineList
*hkl_engine_list_new(void)
623 HklEngineList
*self
= NULL
;
625 self
= HKL_MALLOC(HklEngineList
);
629 self
->geometries
= hkl_geometry_list_new();
631 self
->geometry
= NULL
;
632 self
->detector
= NULL
;
635 darray_init(self
->pseudo_axes
);
642 * hkl_engine_list_new_copy: (skip)
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(UNUSED
const HklEngineList
*self
)
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
)
663 HklParameter
**parameter
;
665 darray_foreach(engine
, *self
){
666 hkl_engine_free(*engine
);
670 darray_foreach(parameter
, self
->pseudo_axes
){
671 hkl_parameter_free(*parameter
);
673 darray_free(self
->pseudo_axes
);
679 #endif /* __HKL_PSEUDOAXIS_PRIVATE_H__ */