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
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
;
54 HklParameter parameter
;
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
);
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
);
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
,
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
;
112 struct _HklModeInfo
{
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
,
132 HklGeometry
*geometry
,
133 HklDetector
*detector
,
137 int (* get
)(HklMode
*self
,
139 HklGeometry
*geometry
,
140 HklDetector
*detector
,
143 int (* set
)(HklMode
*self
,
145 HklGeometry
*geometry
,
146 HklDetector
*detector
,
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
162 const HklModeInfo
*info
;
163 const HklModeOperations
*ops
;
164 darray_parameter parameters
;
165 darray_string parameters_names
;
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
);
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
,
199 HklGeometry
*geometry
,
200 HklDetector
*detector
,
205 /* by default do nothing and no error */
210 static inline int hkl_mode_initialized_set(HklMode
*self
,
212 HklGeometry
*geometry
,
213 HklDetector
*detector
,
218 return self
->ops
->initialized_set(self
,
219 engine
, geometry
, detector
, sample
,
224 static inline int hkl_mode_get_real(HklMode
*self
,
226 HklGeometry
*geometry
,
227 HklDetector
*detector
,
231 /* by default do nothing and no error */
236 static inline int hkl_mode_set_real(HklMode
*self
,
238 HklGeometry
*geometry
,
239 HklDetector
*detector
,
243 /* by default do nothing and no error */
248 static inline int hkl_mode_init(HklMode
*self
,
249 const HklModeInfo
*info
,
250 const HklModeOperations
*ops
,
254 const HklParameter
*parameter
;
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
;
277 static inline HklMode
*hkl_mode_new(const HklModeInfo
*info
,
278 const HklModeOperations
*op
,
281 HklMode
*self
= NULL
;
283 self
= HKL_MALLOC(HklMode
);
285 hkl_mode_init(self
, info
, op
, initialized
);
292 * hkl_mode_free: (skip)
297 static inline void hkl_mode_free(HklMode
*self
)
299 self
->ops
->free(self
);
307 struct _HklEngineInfo
{
309 const darray(const HklPseudoAxis
*) pseudo_axes
;
315 const HklEngineInfo
*info
;
316 const HklEngineOperations
*ops
;
317 HklGeometry
*geometry
;
318 HklDetector
*detector
;
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
;
326 darray_string mode_names
;
330 struct _HklEngineList
332 _darray(HklEngine
*);
333 HklGeometryList
*geometries
;
334 HklGeometry
*geometry
;
335 HklDetector
*detector
;
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");
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 */
362 static inline void set_geometry_axes(HklEngine
*engine
, const double values
[])
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
)
377 HklParameter
**pseudo_axis
;
380 hkl_geometry_free(self
->geometry
);
383 hkl_detector_free(self
->detector
);
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
)
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
;
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
);
463 * hkl_engine_add_mode: (skip)
465 * @mode: the mode to add
467 * add an HklMode to the self HklEngine
469 static inline void hkl_engine_add_mode(HklEngine
*self
,
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
,
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
++]),
501 hkl_geometry_list_add(self
->engines
->geometries
, self
->geometry
);
505 static inline void hkl_engine_prepare_internal(HklEngine
*self
)
509 if(!self
|| !self
->engines
)
514 hkl_geometry_free(self
->geometry
);
515 self
->geometry
= hkl_geometry_new_copy(self
->engines
->geometry
);
518 hkl_detector_free(self
->detector
);
519 self
->detector
= hkl_detector_new_copy(self
->engines
->detector
);
522 hkl_sample_free(self
->sample
);
523 self
->sample
= hkl_sample_new_copy(self
->engines
->sample
);
525 /* fill the axes member from the function */
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
,
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
)
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
){
576 HKL_ENGINE_ERROR_GET
,
581 if (!self
->mode
->ops
->get(self
->mode
,
583 self
->engines
->geometry
,
584 self
->engines
->detector
,
585 self
->engines
->sample
,
587 hkl_assert(error
== NULL
|| *error
!= NULL
);
590 hkl_assert(error
== NULL
|| *error
== NULL
);
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
){
613 HKL_ENGINE_ERROR_SET
,
618 hkl_engine_prepare_internal(self
);
620 if (!self
->mode
->ops
->set(self
->mode
, self
,
625 hkl_assert(error
== NULL
|| *error
!= NULL
);
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){
638 HKL_ENGINE_ERROR_SET
,
639 "no remaining solutions");
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");
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
671 static inline HklEngineList
*hkl_engine_list_new(void)
673 HklEngineList
*self
= NULL
;
675 self
= HKL_MALLOC(HklEngineList
);
679 self
->geometries
= hkl_geometry_list_new();
681 self
->geometry
= NULL
;
682 self
->detector
= NULL
;
690 * hkl_engine_list_new_copy: (skip)
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
)
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
,
718 /* set the engines to access the Geometries list. */
719 engine
->engines
= self
;
721 darray_append(*self
, engine
);
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
)
737 darray_foreach(engine
, *self
){
738 hkl_engine_free(*engine
);
746 #endif /* __HKL_PSEUDOAXIS_PRIVATE_H__ */