* small documentation improvement.
[hkl.git] / src / hkl-pseudoaxis.c
blob38920ef68f93e1aae099c19877404099fcc4e819
1 #include <string.h>
2 #include <gsl/gsl_sf_trig.h>
3 #include <hkl/hkl-pseudoaxis.h>
5 /*****************************/
6 /* HklPseudoAxisEngineGetSet */
7 /*****************************/
9 HklPseudoAxisEngineGetSet *hkl_pseudo_axis_engine_get_set_new(
10 char const *name,
11 HklPseudoAxisEngineGetterFunc get,
12 HklPseudoAxisEngineSetterFunc set,
13 size_t n, ...)
15 HklPseudoAxisEngineGetSet *self = NULL;
16 va_list ap;
17 size_t i;
18 size_t len;
20 self = calloc(1, sizeof(*self));
21 if (!self)
22 die("Can not allocate memory for an HklPseudoAxisEngineGetSet");
24 self->name = name;
25 self->get = get;
26 self->set = set;
28 va_start(ap, n);
29 /* parameters */
30 if (n) {
31 self->parameters = calloc(n, sizeof(HklParameter));
32 self->parameters_len = n;
33 for(i=0; i<n; ++i)
34 self->parameters[i] = *va_arg(ap, HklParameter*);
37 /* axes */
38 len = va_arg(ap, size_t);
39 self->axes_names = calloc(len, sizeof(char const *));
40 self->axes_names_len = len;
41 for(i=0; i<len; ++i)
42 self->axes_names[i] = va_arg(ap, char const *);
43 va_end(ap);
45 return self;
49 void hkl_pseudo_axis_engine_get_set_free(HklPseudoAxisEngineGetSet *self)
51 if(self->parameters_len) {
52 self->parameters_len = 0;
53 free(self->parameters);
54 self->parameters = NULL;
57 if(self->axes_names_len) {
58 self->axes_names_len = 0;
59 free(self->axes_names);
60 self->axes_names = NULL;
62 free(self);
65 /*******************/
66 /* pseudoAxeEngine */
67 /*******************/
69 HklPseudoAxisEngine *hkl_pseudoAxisEngine_new(char const *name,
70 size_t n, ...)
72 va_list ap;
73 size_t i;
75 HklPseudoAxisEngine *self = NULL;
77 self = calloc(1, sizeof(*self));
78 if (!self)
79 die("Can not allocate memory for an HklPseudoAxisEngine");
81 self->name = name;
83 // create the pseudoAxes
84 self->pseudoAxes = malloc(n * sizeof(HklPseudoAxis));
85 self->pseudoAxes_len = n;
86 va_start(ap, n);
87 for(i=0; i<n; ++i) {
88 self->pseudoAxes[i].name = va_arg(ap, const char*);
89 self->pseudoAxes[i].engine = self;
91 va_end(ap);
93 return self;
96 void hkl_pseudoAxisEngine_free(HklPseudoAxisEngine *self)
98 size_t i;
100 if (self->geometry)
101 hkl_geometry_free(self->geometry);
102 /* release the axes memory */
103 if (self->axes_len) {
104 free(self->axes);
105 self->axes = NULL;
106 self->axes_len = 0;
108 /* release the getset added */
109 if (self->getsets_len) {
110 for(i=0; i<self->getsets_len; ++i)
111 hkl_pseudo_axis_engine_get_set_free(self->getsets[i]);
112 self->getsets_len = 0;
113 free(self->getsets);
114 self->getsets = NULL;
116 /* release the HklPseudoAxe memory */
117 if (self->pseudoAxes_len) {
118 free(self->pseudoAxes);
119 self->pseudoAxes = NULL;
120 self->pseudoAxes_len = 0;
122 /* release the geometries allocated during calculations */
123 if (self->geometries_alloc) {
124 for(i=0; i<self->geometries_alloc; ++i)
125 hkl_geometry_free(self->geometries[i]);
126 free(self->geometries);
127 self->geometries = NULL;
128 self->geometries_alloc = self->geometries_len = 0;
130 free(self);
133 void hkl_pseudoAxisEngine_add_get_set(HklPseudoAxisEngine *self,
134 HklPseudoAxisEngineGetSet *getset)
136 size_t n = self->getsets_len++;
137 self->getsets = realloc(self->getsets,
138 self->getsets_len*sizeof(HklPseudoAxisEngineGetSet*));
139 self->getsets[n] = getset;
142 /**
143 * @brief this method Add a geometry to the geometries
145 * @param self The current PseudoAxeEngine
146 * @param x A vector of double with the axes values to put in the geometry.
148 * This method try to be clever by allocating memory only if the current
149 * length of the geometries is not large enought. Then it just set the
150 * geometry axes and copy it to the right geometries. We do not gives the
151 * x len as it is equal to the self->axes_len.
153 void hkl_pseudoAxisEngine_add_geometry(HklPseudoAxisEngine *self,
154 double const x[])
156 size_t i;
157 HklGeometry *geometry;
159 // first check if we can get an old geometry.
160 if (self->geometries_len == self->geometries_alloc) {
161 self->geometries_alloc = alloc_nr(self->geometries_alloc);
162 self->geometries = realloc(self->geometries,
163 self->geometries_alloc * sizeof(HklGeometry*));
164 for(i=self->geometries_len; i<self->geometries_alloc; i++)
165 self->geometries[i] = hkl_geometry_new_copy(self->geometry);
168 /* copy the axes configuration into the engine->geometry */
169 for(i=0; i<self->axes_len; ++i)
170 self->axes[i]->config.value = x[i];
172 /* put the axes configuration from engine->geometry -> geometry */
173 geometry = self->geometries[self->geometries_len++];
174 hkl_geometry_init_geometry(geometry, self->geometry);
177 void hkl_pseudoAxisEngine_select_get_set(HklPseudoAxisEngine *self,
178 size_t idx)
180 self->getset = self->getsets[idx];
183 /**
184 * @brief update the geometry, detector and sample internals.
186 * @param self The current PseudoAxeEngine
187 * @param geometry the geometry to initialize the self->geometry
188 * @param detector idem for the geometry
189 * @param sample idem for the sample
191 * This method also populate the self->axes from the getset->axes_names.
192 * this is to speed the computation of the numerical axes. this method is
193 * usually only use with numerical pseudoAxes.
195 void hkl_pseudoAxeEngine_prepare_internal(HklPseudoAxisEngine *self,
196 HklGeometry *geometry, HklDetector *detector,
197 HklSample *sample)
199 size_t i;
201 /* set */
202 if(self->geometry)
203 hkl_geometry_init_geometry(self->geometry, geometry);
204 else
205 self->geometry = hkl_geometry_new_copy(geometry);
206 self->detector = detector;
207 self->sample = sample;
209 // fill the axes member from the function
210 if (self->axes_len)
211 free(self->axes), self->axes = NULL, self->axes_len = 0;
212 self->axes_len = self->getset->axes_names_len;
213 self->axes = malloc(self->axes_len * sizeof(HklAxis *));
214 for(i=0; i<self->axes_len; ++i)
215 self->axes[i] = hkl_geometry_get_axis_by_name(self->geometry,
216 self->getset->axes_names[i]);
218 // reset the geometries len
219 self->geometries_len = 0;
222 int hkl_pseudoAxisEngine_setter(HklPseudoAxisEngine *self,
223 HklGeometry *geom, HklDetector *det, HklSample *sample)
225 return self->getset->set(self, geom, det, sample);
228 void hkl_pseudoAxisEngine_getter(HklPseudoAxisEngine *self,
229 HklGeometry *geom, HklDetector *det, HklSample *sample)
231 self->getset->get(self, geom, det, sample);
234 void hkl_pseudoAxisEngine_fprintf(HklPseudoAxisEngine *self, FILE *f)
236 size_t i, j;
237 double value;
239 fprintf(f, "\nPseudoAxesEngine : \"%s\"", self->name);
241 /* getset */
242 if (self->getset) {
243 fprintf(f, " %s", self->getset->name);
245 for(i=0; i<self->getset->parameters_len; ++i)
246 fprintf(f, " \"%s\" = %g",
247 self->getset->parameters[i].name,
248 self->getset->parameters[i].value);
251 /* the pseudoAxes part */
252 fprintf(f, "\n ");
253 for(i=0; i<self->pseudoAxes_len; ++i)
254 fprintf(f, " \"%s\" : %f", self->pseudoAxes[i].name, self->pseudoAxes[i].config.value);
256 /* axes names */
257 if (self->geometry) {
258 fprintf(f, "\n ");
259 for(i=0; i<self->geometry->axes_len; ++i)
260 fprintf(f, "%9s", self->geometry->axes[i]->name);
262 /* geometries */
263 fprintf(f, "\n");
264 for(i=0; i<self->geometries_len; ++i) {
265 fprintf(f, "%d :", i);
266 for(j=0; j<self->geometry->axes_len; ++j) {
267 value = self->geometries[i]->axes[j]->config.value;
268 //value = gsl_sf_angle_restrict_symm(value);
269 fprintf(f, " % 9.6g", value * HKL_RADTODEG);
271 fprintf(f, "\n");
273 } else
274 fprintf(stdout, "\n");