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-2023 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>
26 # define CGLM_DEFINE_PRINTS
27 # define CGLM_PRINT_PRECISION 7
33 #include "ccan/array_size/array_size.h"
34 #include "hkl-binoculars-private.h"
35 #include "hkl-matrix-private.h"
36 #include "hkl-quaternion-private.h"
37 #include "hkl-sample-private.h"
38 #include "hkl-vector-private.h"
40 /* mark the masked pixels with this value */
41 #define MASKED PTRDIFF_MAX
46 static inline ptrdiff_t min(ptrdiff_t x
, ptrdiff_t y
)
48 return y
^ ((x
^ y
) & -(x
< y
));
51 static inline ptrdiff_t max(ptrdiff_t x
, ptrdiff_t y
)
53 return x
^ ((x
^ y
) & -(x
< y
));
64 struct _HklBinocularsAxisLimits
70 void hkl_binoculars_axis_limits_free(HklBinocularsAxisLimits
*self
)
75 HklBinocularsAxisLimits
*hkl_binoculars_axis_limits_new(const ptrdiff_t *imin
,
76 const ptrdiff_t *imax
)
78 HklBinocularsAxisLimits
*self
= g_new(HklBinocularsAxisLimits
, 1);
81 self
->imin
= NoLimit();
83 self
->imin
= Limit(*imin
);
87 self
->imax
= NoLimit();
89 self
->imax
= Limit(*imax
);
97 static inline double axis_min(const HklBinocularsAxis
*self
)
99 return self
->imin
* self
->resolution
;
102 static inline double axis_max(const HklBinocularsAxis
*self
)
104 return self
->imax
* self
->resolution
;
107 static inline void hkl_binoculars_axis_init(HklBinocularsAxis
*self
,
116 self
->resolution
= resolution
;
121 static inline int hkl_binoculars_axis_cmp(const HklBinocularsAxis
*self
,
122 const HklBinocularsAxis
*other
)
126 res
|= strcmp(self
->name
, other
->name
);
127 res
|= self
->index
!= other
->index
;
128 res
|= self
->resolution
!= other
->resolution
;
129 res
|= self
->imin
!= other
->imin
;
130 res
|= self
->imax
!= other
->imax
;
135 double *hkl_binoculars_axis_array(const HklBinocularsAxis
*self
)
137 double *arr
= g_new0(double, 6);
139 arr
[0] = self
->index
;
140 arr
[1] = axis_min(self
);
141 arr
[2] = axis_max(self
);
142 arr
[3] = self
->resolution
;
149 /* check if *self contains *other */
150 static inline int hkl_binoculars_axis_contains_axis(const HklBinocularsAxis
*self
,
151 const HklBinocularsAxis
*other
)
153 return self
->imin
<= other
->imin
&& self
->imax
>= other
->imax
;
156 static inline void hkl_binoculars_axis_merge(HklBinocularsAxis
*self
, const HklBinocularsAxis
*other
)
158 self
->imin
= min(self
->imin
, other
->imin
);
159 self
->imax
= max(self
->imax
, other
->imax
);
162 void hkl_binoculars_axis_fprintf(FILE *f
, const HklBinocularsAxis
*self
)
164 fprintf(f
, "%s : %ld min: %f(%ld) max: %f(%ld) res: %f size: %ld",
165 self
->name
, self
->index
,
166 axis_min(self
), self
->imin
,
167 axis_max(self
), self
->imax
,
168 self
->resolution
, axis_size(self
));
174 static inline void merge_axes(darray_axis
*axes
,
175 const darray_axis
*others
)
179 for(i
=0; i
<darray_size(*axes
); ++i
)
180 hkl_binoculars_axis_merge(&darray_item(*axes
, i
),
181 &darray_item(*others
, i
));
184 static inline int does_not_include(const darray_axis
*axes
,
185 const darray_axis
*others
)
190 if (darray_size(*axes
) == darray_size(*others
)){
191 for(i
=0; i
<darray_size(*axes
); ++i
){
192 if (0 == hkl_binoculars_axis_contains_axis(&darray_item(*axes
, i
),
193 &darray_item(*others
, i
))){
208 static inline void hkl_binoculars_space_item_fprintf(FILE *f
, const HklBinocularsSpaceItem
*self
)
210 fprintf(f
, "item->indexes(%p) v: %ld %ld %ld, intensity: %d", &self
->indexes_0
[0],
211 self
->indexes_0
[0], self
->indexes_0
[1], self
->indexes_0
[2], self
->intensity
);
214 static inline int space_is_empty(const HklBinocularsSpace
*space
)
216 return 0 == darray_size(space
->items
);
219 static inline void space_update_axes(HklBinocularsSpace
*space
,
222 const double resolutions
[])
225 HklBinocularsSpaceItem
*item
;
226 HklBinocularsSpaceItem minimum
;
227 HklBinocularsSpaceItem maximum
;
229 if (space_is_empty(space
))
232 minimum
= maximum
= darray_item(space
->items
, 0);
234 for(i
=0; i
<darray_size(space
->axes
); ++i
){
235 darray_foreach(item
, space
->items
){
236 minimum
.indexes_0
[i
] = min(minimum
.indexes_0
[i
], item
->indexes_0
[i
]);
237 maximum
.indexes_0
[i
] = max(maximum
.indexes_0
[i
], item
->indexes_0
[i
]);
241 for(i
=0; i
<darray_size(space
->axes
); ++i
){
242 HklBinocularsAxis
*axis
= &darray_item(space
->axes
, i
);
243 hkl_binoculars_axis_init(axis
, names
[i
], i
,
244 minimum
.indexes_0
[i
], maximum
.indexes_0
[i
],
249 static inline int item_in_the_limits(const HklBinocularsSpaceItem
*item
,
250 const HklBinocularsAxisLimits
**limits
,
256 for(size_t i
=0; i
<n_limits
; ++i
){
257 ptrdiff_t v
= item
->indexes_0
[i
];
259 match(limits
[i
]->imin
){
263 if (v
< *imin
) res
= FALSE
;
268 match(limits
[i
]->imax
){
272 if(v
> *imax
) res
= FALSE
;
282 HklBinocularsSpace
*hkl_binoculars_space_new(size_t max_items
, size_t n_axes
)
284 HklBinocularsSpace
*self
= g_new(HklBinocularsSpace
, 1);
286 self
->max_items
= max_items
;
287 darray_init(self
->items
);
288 darray_resize(self
->items
, max_items
);
289 darray_init(self
->axes
);
290 darray_resize(self
->axes
, n_axes
);
295 void hkl_binoculars_space_free(HklBinocularsSpace
*self
)
297 darray_free(self
->axes
);
298 darray_free(self
->items
);
302 void hkl_binoculars_space_fprintf(FILE *f
, const HklBinocularsSpace
*self
)
305 HklBinocularsAxis
*axis
;
307 fprintf(f
, "\nHklBinocularsSpace: %p", self
);
308 fprintf(f
, "\nn_indexes_0: %ld", darray_size(self
->items
));
309 if(space_is_empty(self
)){
310 fprintf(f
, "\nempty");
312 fprintf(f
, "\nn_axes: %ld", darray_size(self
->axes
));
313 darray_foreach(axis
, self
->axes
){
315 hkl_binoculars_axis_fprintf(f
, axis
);
318 masked
= self
->max_items
- darray_size(self
->items
);
319 fprintf(f
, "\nmasked pixels: %ld (%f%%)", masked
, (double)masked
/ self
->max_items
* 100);
325 #define HKL_BINOCULARS_SPACE_ANGLES_IMPL(image_t) \
326 HKL_BINOCULARS_SPACE_ANGLES_DECL(image_t) \
329 const char * names[] = {"delta_lab", "gamma_lab", "tth"}; \
330 double delta0, gamma0, tth; \
332 assert(ARRAY_SIZE(names) == darray_size(space->axes)); \
333 assert(ARRAY_SIZE(names) == n_resolutions); \
334 assert(n_pixels == space->max_items); \
336 darray_size(space->items) = 0; \
338 const double *p_x = &pixels_coordinates[0 * n_pixels]; \
339 const double *p_y = &pixels_coordinates[1 * n_pixels]; \
340 const double *p_z = &pixels_coordinates[2 * n_pixels]; \
342 HklDetector *detector = hkl_detector_factory_new(HKL_DETECTOR_TYPE_0D); \
343 const HklQuaternion q = hkl_geometry_detector_rotation_get(geometry, detector); \
345 for(i=0;i<n_pixels;++i){ \
346 if(NULL == masked || 0 == masked[i]){ \
347 HklBinocularsSpaceItem item; \
348 HklVector v = {{p_x[i], p_y[i], p_z[i]}}; \
350 hkl_vector_rotated_quaternion(&v, &q); \
351 delta0 = atan2(v.data[2], v.data[0]); \
352 gamma0 = M_PI_2 - atan2(sqrt(v.data[2] * v.data[2] + v.data[0] * v.data[0]), v.data[1]); \
353 tth = acos(v.data[0]); \
355 v.data[0] = delta0 / M_PI * 180.0; \
356 v.data[1] = gamma0 / M_PI * 180.0; \
357 v.data[2] = tth / M_PI * 180.0; \
359 for(j=0; j<ARRAY_SIZE(names); ++j){ \
360 item.indexes_0[j] = rint(v.data[j] / resolutions[j]); \
362 item.intensity = rint((double)image[i] * weight); \
365 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
366 darray_append(space->items, item); \
370 space_update_axes(space, names, n_pixels, resolutions); \
372 hkl_detector_free(detector); \
375 HKL_BINOCULARS_SPACE_ANGLES_IMPL(int32_t);
376 HKL_BINOCULARS_SPACE_ANGLES_IMPL(uint16_t);
377 HKL_BINOCULARS_SPACE_ANGLES_IMPL(uint32_t);
381 static const char **axis_name_from_subprojection(HklBinocularsQCustomSubProjectionEnum subprojection
,
382 HklBinocularsSpace
*space
,
387 switch(subprojection
){
388 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_QX_QY_QZ
:
389 case HKL_BINOCULARS_QCUSTOM_NUM_SUBPROJECTIONS
:
391 static const char *names_qx_qy_qz
[] = {"qx", "qy", "qz"};
392 assert(ARRAY_SIZE(names_qx_qy_qz
) == darray_size(space
->axes
));
393 assert(ARRAY_SIZE(names_qx_qy_qz
) == n_resolutions
);
394 names
= names_qx_qy_qz
;
397 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_TTH_TIMESTAMP
:
399 static const char *names_q_tth_timestamp
[] = {"q", "tth", "timestamp"};
400 assert(ARRAY_SIZE(names_q_tth_timestamp
) == darray_size(space
->axes
));
401 assert(ARRAY_SIZE(names_q_tth_timestamp
) == n_resolutions
);
402 names
= names_q_tth_timestamp
;
405 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_TIMESTAMP
:
407 static const char *names_q_timestamp
[] = {"q", "timestamp"};
408 assert(ARRAY_SIZE(names_q_timestamp
) <= darray_size(space
->axes
));
409 assert(ARRAY_SIZE(names_q_timestamp
) <= n_resolutions
);
410 names
= names_q_timestamp
;
413 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_QPAR_QPER_TIMESTAMP
:
415 static const char *names_qpar_qper_timestamp
[] = {"qpar", "qper", "timestamp"};
416 assert(ARRAY_SIZE(names_qpar_qper_timestamp
) == darray_size(space
->axes
));
417 assert(ARRAY_SIZE(names_qpar_qper_timestamp
) == n_resolutions
);
418 names
= names_qpar_qper_timestamp
;
421 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_QPAR_QPER
:
423 static const char *names_qpar_qper
[] = {"qpar", "qper"};
424 assert(ARRAY_SIZE(names_qpar_qper
) <= darray_size(space
->axes
));
425 assert(ARRAY_SIZE(names_qpar_qper
) <= n_resolutions
);
426 names
= names_qpar_qper
;
429 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_PHI_QX
:
431 static const char *names_q_phi_qx
[] = {"q", "phi", "qx"};
432 assert(ARRAY_SIZE(names_q_phi_qx
) == darray_size(space
->axes
));
433 assert(ARRAY_SIZE(names_q_phi_qx
) == n_resolutions
);
434 names
= names_q_phi_qx
;
437 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_PHI_QY
:
439 static const char *names_q_phi_qy
[] = {"q", "phi", "qy"};
440 assert(ARRAY_SIZE(names_q_phi_qy
) == darray_size(space
->axes
));
441 assert(ARRAY_SIZE(names_q_phi_qy
) == n_resolutions
);
442 names
= names_q_phi_qy
;
445 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_PHI_QZ
:
447 static const char *names_q_phi_qz
[] = {"q", "phi", "qz"};
448 assert(ARRAY_SIZE(names_q_phi_qz
) == darray_size(space
->axes
));
449 assert(ARRAY_SIZE(names_q_phi_qz
) == n_resolutions
);
450 names
= names_q_phi_qz
;
453 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_STEREO
:
455 static const char *names_q_stereo
[] = {"q", "xp", "yp"};
456 assert(ARRAY_SIZE(names_q_stereo
) == darray_size(space
->axes
));
457 assert(ARRAY_SIZE(names_q_stereo
) == n_resolutions
);
458 names
= names_q_stereo
;
461 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_DELTALAB_GAMMALAB_SAMPLEAXIS
:
463 static const char *names_deltalab_gammalab_sampleaxis
[] = {"deltalab", "gammalab", "sampleaxis"};
464 assert(ARRAY_SIZE(names_deltalab_gammalab_sampleaxis
) == darray_size(space
->axes
));
465 assert(ARRAY_SIZE(names_deltalab_gammalab_sampleaxis
) == n_resolutions
);
466 names
= names_deltalab_gammalab_sampleaxis
;
469 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_X_Y_Z
:
471 static const char *names_x_y_z
[] = {"x", "y", "z"};
472 assert(ARRAY_SIZE(names_x_y_z
) == darray_size(space
->axes
));
473 assert(ARRAY_SIZE(names_x_y_z
) == n_resolutions
);
477 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Y_Z_TIMESTAMP
:
479 static const char *names_y_z_timestamp
[] = {"y", "z", "timestamp"};
480 assert(ARRAY_SIZE(names_y_z_timestamp
) == darray_size(space
->axes
));
481 assert(ARRAY_SIZE(names_y_z_timestamp
) == n_resolutions
);
482 names
= names_y_z_timestamp
;
485 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_QPAR_QPER
:
487 static const char *names_q_qpar_qper
[] = {"q", "qpar", "qper"};
488 assert(ARRAY_SIZE(names_q_qpar_qper
) == darray_size(space
->axes
));
489 assert(ARRAY_SIZE(names_q_qpar_qper
) == n_resolutions
);
490 names
= names_q_qpar_qper
;
493 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_QPARS_QPER_TIMESTAMP
:
495 static const char *names_qpars_qper_timestamp
[] = {"qpars", "qper", "timestamp"};
496 assert(ARRAY_SIZE(names_qpars_qper_timestamp
) == darray_size(space
->axes
));
497 assert(ARRAY_SIZE(names_qpars_qper_timestamp
) == n_resolutions
);
498 names
= names_qpars_qper_timestamp
;
501 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_QPAR_QPER_SAMPLEAXIS
:
503 static const char *names_qpar_qper_sampleaxis
[] = {"qpar", "qper", "sample axis"};
504 assert(ARRAY_SIZE(names_qpar_qper_sampleaxis
) == darray_size(space
->axes
));
505 assert(ARRAY_SIZE(names_qpar_qper_sampleaxis
) == n_resolutions
);
506 names
= names_qpar_qper_sampleaxis
;
509 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_SAMPLEAXIS_TTH
:
511 static const char *names_q_sampleaxis_tth
[] = {"q", "sample axis", "tth"};
512 assert(ARRAY_SIZE(names_q_sampleaxis_tth
) == darray_size(space
->axes
));
513 assert(ARRAY_SIZE(names_q_sampleaxis_tth
) == n_resolutions
);
514 names
= names_q_sampleaxis_tth
;
517 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_SAMPLEAXIS_TIMESTAMP
:
519 static const char *names_q_sampleaxis_timestamp
[] = {"q", "sample axis", "timestamp"};
520 assert(ARRAY_SIZE(names_q_sampleaxis_timestamp
) == darray_size(space
->axes
));
521 assert(ARRAY_SIZE(names_q_sampleaxis_timestamp
) == n_resolutions
);
522 names
= names_q_sampleaxis_timestamp
;
525 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_QX_QY_TIMESTAMP
:
527 static const char *names_
[] = {"qx", "qy", "timestamp"};
528 assert(ARRAY_SIZE(names_
) == darray_size(space
->axes
));
529 assert(ARRAY_SIZE(names_
) == n_resolutions
);
533 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_QX_QZ_TIMESTAMP
:
535 static const char *names_
[] = {"qx", "qz", "timestamp"};
536 assert(ARRAY_SIZE(names_
) == darray_size(space
->axes
));
537 assert(ARRAY_SIZE(names_
) == n_resolutions
);
541 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_QY_QZ_TIMESTAMP
:
543 static const char *names_
[] = {"qy", "qz", "timestamp"};
544 assert(ARRAY_SIZE(names_
) == darray_size(space
->axes
));
545 assert(ARRAY_SIZE(names_
) == n_resolutions
);
551 static const char *names_qx_qy_qz
[] = {"qx", "qy", "qz"};
552 assert(ARRAY_SIZE(names_qx_qy_qz
) == darray_size(space
->axes
));
553 assert(ARRAY_SIZE(names_qx_qy_qz
) == n_resolutions
);
554 names
= names_qx_qy_qz
;
561 static inline int not_masked(const uint8_t *masked
, size_t idx
)
563 return NULL
== masked
|| 0 == masked
[idx
];
566 static inline double polarisation(vec3s kf
, double weight
, int do_polarisation
)
568 if (do_polarisation
){
569 CGLM_ALIGN_MAT vec3s epsilon
= {{0, 1, 0}};
570 float p
= glms_vec3_dot(epsilon
, kf
) / glms_vec3_norm2(kf
);
571 weight
= weight
/ (1 - p
*p
);
576 #define HKL_BINOCULARS_SPACE_QCUSTOM_IMPL(image_t) \
577 HKL_BINOCULARS_SPACE_QCUSTOM_DECL(image_t) \
580 HklBinocularsSpaceItem item; \
582 const char **names = axis_name_from_subprojection(subprojection, space, n_resolutions); \
583 assert(n_pixels == space->max_items); \
585 const double *q_x = &pixels_coordinates[0 * n_pixels]; \
586 const double *q_y = &pixels_coordinates[1 * n_pixels]; \
587 const double *q_z = &pixels_coordinates[2 * n_pixels]; \
589 HklSample *sample = hkl_sample_new("test"); \
590 HklDetector *detector = hkl_detector_factory_new(HKL_DETECTOR_TYPE_0D); \
591 HklHolder *holder_d = hkl_geometry_detector_holder_get(geometry, detector); \
592 CGLM_ALIGN_MAT mat4s m_holder_d = hkl_binoculars_holder_transformation_get(holder_d); \
593 const HklVector ki_v = hkl_geometry_ki_get(geometry); \
594 CGLM_ALIGN_MAT vec3s ki = {{ki_v.data[0], ki_v.data[1], ki_v.data[2]}}; \
595 float k = glms_vec3_norm(ki); \
596 HklHolder *holder_s = hkl_geometry_sample_holder_get(geometry,sample); \
597 CGLM_ALIGN_MAT mat4s m_holder_s = hkl_binoculars_holder_transformation_get(holder_s); \
600 case HKL_BINOCULARS_SURFACE_ORIENTATION_VERTICAL: \
602 CGLM_ALIGN_MAT vec3s axis = GLMS_XUP; \
603 CGLM_ALIGN_MAT mat4s m_q_ub = glms_rotate_make(-M_PI_2, axis); \
605 m_holder_s = glms_mat4_mul(m_holder_s, m_q_ub); \
608 case HKL_BINOCULARS_SURFACE_ORIENTATION_HORIZONTAL: \
609 case HKL_BINOCULARS_SURFACE_ORIENTATION_NUM_ORIENTATION: \
613 CGLM_ALIGN_MAT vec3s euler_xyz = {{uqx, uqy, uqz}}; \
614 m_holder_s = glms_mat4_mul(m_holder_s, glms_euler_xyz(euler_xyz)); \
616 m_holder_s = glms_mat4_inv(m_holder_s); \
618 darray_size(space->items) = 0; \
620 glms_mat4_print(m_holder_s, stdout); \
621 glms_mat4_print(m_holder_d, stdout); \
623 switch(subprojection){ \
624 case HKL_BINOCULARS_QCUSTOM_NUM_SUBPROJECTIONS: \
625 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_QX_QY_QZ: \
627 for(i=0;i<n_pixels;++i){ \
628 if(not_masked(masked, i)){ \
629 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
631 v = glms_mat4_mulv3(m_holder_d, v, 1); \
632 v = glms_vec3_scale_as(v, k); \
633 correction = polarisation(v, weight, do_polarisation_correction); \
634 v = glms_vec3_sub(v, ki); \
635 v = glms_mat4_mulv3(m_holder_s, v, 0); \
637 item.indexes_0[0] = rint(v.raw[0] / resolutions[0]); \
638 item.indexes_0[1] = rint(v.raw[1] / resolutions[1]); \
639 item.indexes_0[2] = rint(v.raw[2] / resolutions[2]); \
640 item.intensity = rint((double)image[i] * correction); \
642 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
643 darray_append(space->items, item); \
648 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_TTH_TIMESTAMP: \
650 for(i=0;i<n_pixels;++i){ \
651 if(not_masked(masked, i)){ \
652 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
654 v = glms_mat4_mulv3(m_holder_d, v, 1); \
655 v = glms_vec3_scale_as(v, k); \
656 correction = polarisation(v, weight, do_polarisation_correction); \
657 v = glms_vec3_sub(v , ki); \
658 v = glms_mat4_mulv3(m_holder_s, v, 0); \
660 item.indexes_0[0] = rint(glms_vec3_norm(v) / resolutions[0]); \
661 item.indexes_0[1] = rint(asin(glms_vec3_norm(v) / 2 / k) * 2 / M_PI * 180 / resolutions[1]); \
662 item.indexes_0[2] = rint(timestamp / resolutions[2]); \
663 item.intensity = rint((double)image[i] * correction); \
665 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
666 darray_append(space->items, item); \
671 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_TIMESTAMP: \
673 for(i=0;i<n_pixels;++i){ \
674 if(not_masked(masked, i)){ \
675 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
677 v = glms_mat4_mulv3(m_holder_d, v, 1); \
678 v = glms_vec3_scale_as(v, k); \
679 correction = polarisation(v, weight, do_polarisation_correction); \
680 v = glms_vec3_sub(v , ki); \
681 v = glms_mat4_mulv3(m_holder_s, v, 0); \
683 item.indexes_0[0] = rint(glms_vec3_norm(v) / resolutions[0]); \
684 item.indexes_0[1] = rint(timestamp / resolutions[1]); \
685 item.indexes_0[2] = REMOVED; \
686 item.intensity = rint((double)image[i] * correction); \
688 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
689 darray_append(space->items, item); \
694 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_QPAR_QPER_TIMESTAMP: \
696 for(i=0;i<n_pixels;++i){ \
697 if(not_masked(masked, i)){ \
698 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
700 v = glms_mat4_mulv3(m_holder_d, v, 1); \
701 v = glms_vec3_scale_as(v, k); \
702 correction = polarisation(v, weight, do_polarisation_correction); \
703 v = glms_vec3_sub(v , ki); \
704 v = glms_mat4_mulv3(m_holder_s, v, 0); \
706 item.indexes_0[0] = rint(sqrt(v.raw[0] * v.raw[0] + v.raw[1] * v.raw[1]) / resolutions[0]); \
707 item.indexes_0[1] = rint(v.raw[2] / resolutions[1]); \
708 item.indexes_0[2] = rint(timestamp / resolutions[2]); \
709 item.intensity = rint((double)image[i] * correction); \
711 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
712 darray_append(space->items, item); \
717 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_QPAR_QPER: \
719 for(i=0;i<n_pixels;++i){ \
720 if(not_masked(masked, i)){ \
721 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
723 v = glms_mat4_mulv3(m_holder_d, v, 1); \
724 v = glms_vec3_scale_as(v, k); \
725 correction = polarisation(v, weight, do_polarisation_correction); \
726 v = glms_vec3_sub(v , ki); \
727 v = glms_mat4_mulv3(m_holder_s, v, 0); \
729 item.indexes_0[0] = rint(sqrt(v.raw[0] * v.raw[0] + v.raw[1] * v.raw[1]) / resolutions[0]); \
730 item.indexes_0[1] = rint(v.raw[2] / resolutions[1]); \
731 item.indexes_0[2] = REMOVED; \
732 item.intensity = rint((double)image[i] * correction); \
734 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
735 darray_append(space->items, item); \
740 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_PHI_QX: \
742 for(i=0;i<n_pixels;++i){ \
743 if(not_masked(masked, i)){ \
744 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
746 v = glms_mat4_mulv3(m_holder_d, v, 1); \
747 v = glms_vec3_scale_as(v, k); \
748 correction = polarisation(v, weight, do_polarisation_correction); \
749 v = glms_vec3_sub(v , ki); \
750 v = glms_mat4_mulv3(m_holder_s, v, 0); \
752 item.indexes_0[0] = rint(glms_vec3_norm(v) / resolutions[0]); \
753 item.indexes_0[1] = rint((atan2(v.raw[2], -v.raw[1])) / M_PI * 180 / resolutions[1]); \
754 item.indexes_0[2] = rint(v.raw[0] / resolutions[2]); \
755 item.intensity = rint((double)image[i] * correction); \
757 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
758 darray_append(space->items, item); \
763 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_PHI_QY: \
765 for(i=0;i<n_pixels;++i){ \
766 if(not_masked(masked, i)){ \
767 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
769 v = glms_mat4_mulv3(m_holder_d, v, 1); \
770 v = glms_vec3_scale_as(v, k); \
771 correction = polarisation(v, weight, do_polarisation_correction); \
772 v = glms_vec3_sub(v , ki); \
773 v = glms_mat4_mulv3(m_holder_s, v, 0); \
775 item.indexes_0[0] = rint(glms_vec3_norm(v) / resolutions[0]); \
776 item.indexes_0[1] = rint((atan2(v.raw[2], v.raw[0])) / M_PI * 180 / resolutions[1]); \
777 item.indexes_0[2] = rint(v.raw[1] / resolutions[2]); \
778 item.intensity = rint((double)image[i] * correction); \
780 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
781 darray_append(space->items, item); \
786 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_PHI_QZ: \
788 for(i=0;i<n_pixels;++i){ \
789 if(not_masked(masked, i)){ \
790 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
792 v = glms_mat4_mulv3(m_holder_d, v, 1); \
793 v = glms_vec3_scale_as(v, k); \
794 correction = polarisation(v, weight, do_polarisation_correction); \
795 v = glms_vec3_sub(v , ki); \
796 v = glms_mat4_mulv3(m_holder_s, v, 0); \
798 item.indexes_0[0] = rint(glms_vec3_norm(v) / resolutions[0]); \
799 item.indexes_0[1] = rint((atan2(v.raw[0], v.raw[1])) / M_PI * 180 / resolutions[1]); \
800 item.indexes_0[2] = rint(v.raw[2] / resolutions[2]); \
801 item.intensity = rint((double)image[i] * correction); \
803 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
804 darray_append(space->items, item); \
809 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_STEREO: \
811 for(i=0;i<n_pixels;++i){ \
812 if(not_masked(masked, i)){ \
813 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
815 v = glms_mat4_mulv3(m_holder_d, v, 1); \
816 v = glms_vec3_scale_as(v, k); \
817 correction = polarisation(v, weight, do_polarisation_correction); \
818 v = glms_vec3_sub(v , ki); \
819 v = glms_mat4_mulv3(m_holder_s, v, 0); \
821 item.indexes_0[0] = rint(glms_vec3_norm(v) / resolutions[0]); \
822 double ratio = v.raw[2] + item.indexes_0[0]; \
823 item.indexes_0[1] = rint(v.raw[0] / ratio / resolutions[1]); \
824 item.indexes_0[2] = rint(v.raw[1] / ratio / resolutions[2]); \
825 item.intensity = rint((double)image[i] * correction); \
827 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
828 darray_append(space->items, item); \
833 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_DELTALAB_GAMMALAB_SAMPLEAXIS: \
835 const HklParameter *p = hkl_geometry_axis_get(geometry, sample_axis, NULL); \
837 int axis = rint(hkl_parameter_value_get(p, HKL_UNIT_USER) / resolutions[2]); \
839 for(i=0;i<n_pixels;++i){ \
840 if(not_masked(masked, i)){ \
841 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
843 v = glms_mat4_mulv3(m_holder_d, v, 1); \
844 correction = polarisation(v, weight, do_polarisation_correction); \
846 item.indexes_0[0] = rint(atan2(v.raw[2], sqrt(v.raw[0] * v.raw[0] + v.raw[1] * v.raw[1])) / M_PI * 180 / resolutions[0]); \
847 item.indexes_0[1] = rint(atan2(v.raw[1], v.raw[0]) / M_PI * 180 / resolutions[1]); \
848 item.indexes_0[2] = axis; \
849 item.intensity = rint((double)image[i] * correction); \
851 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
852 darray_append(space->items, item); \
858 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_X_Y_Z: \
860 for(i=0;i<n_pixels;++i){ \
861 if(not_masked(masked, i)){ \
862 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
864 glms_vec3_print(v, stdout); \
865 v = glms_mat4_mulv3(m_holder_d, v, 1); \
866 correction = polarisation(v, weight, do_polarisation_correction); \
867 glms_mat4_print(m_holder_d, stdout); \
868 glms_vec3_print(v, stdout); \
870 item.indexes_0[0] = rint(v.raw[0] / resolutions[0]); \
871 item.indexes_0[1] = rint(v.raw[1] / resolutions[1]); \
872 item.indexes_0[2] = rint(v.raw[2] / resolutions[2]); \
873 item.intensity = rint((double)image[i] * correction); \
875 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
876 darray_append(space->items, item); \
881 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Y_Z_TIMESTAMP: \
883 for(i=0;i<n_pixels;++i){ \
884 if(not_masked(masked, i)){ \
885 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
887 v = glms_mat4_mulv3(m_holder_d, v, 1); \
888 correction = polarisation(v, weight, do_polarisation_correction); \
890 item.indexes_0[0] = rint(v.raw[1] / resolutions[0]); \
891 item.indexes_0[1] = rint(v.raw[2] / resolutions[1]); \
892 item.indexes_0[2] = rint(timestamp / resolutions[2]); \
893 item.intensity = rint((double)image[i] * correction); \
895 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
896 darray_append(space->items, item); \
901 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_QPAR_QPER: \
903 for(i=0;i<n_pixels;++i){ \
904 if(not_masked(masked, i)){ \
905 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
907 v = glms_mat4_mulv3(m_holder_d, v, 1); \
908 v = glms_vec3_scale_as(v, k); \
909 correction = polarisation(v, weight, do_polarisation_correction); \
910 v = glms_vec3_sub(v , ki); \
911 v = glms_mat4_mulv3(m_holder_s, v, 0); \
913 item.indexes_0[0] = rint(glms_vec3_norm(v) / resolutions[0]); \
914 item.indexes_0[1] = rint(sqrt(v.raw[0] * v.raw[0] + v.raw[1] * v.raw[1]) / resolutions[1]); \
915 item.indexes_0[2] = rint(v.raw[2] / resolutions[2]); \
916 item.intensity = rint((double)image[i] * correction); \
918 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
919 darray_append(space->items, item); \
924 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_QPARS_QPER_TIMESTAMP: \
926 for(i=0;i<n_pixels;++i){ \
927 if(not_masked(masked, i)){ \
928 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
930 v = glms_mat4_mulv3(m_holder_d, v, 1); \
931 v = glms_vec3_scale_as(v, k); \
932 correction = polarisation(v, weight, do_polarisation_correction); \
933 v = glms_vec3_sub(v , ki); \
934 v = glms_mat4_mulv3(m_holder_s, v, 0); \
936 item.indexes_0[0] = rint(sqrt(v.raw[0] * v.raw[0] + v.raw[1] * v.raw[1]) / resolutions[0]); \
937 item.indexes_0[1] = rint(v.raw[2] / resolutions[1]); \
938 item.indexes_0[2] = rint(timestamp / resolutions[2]); \
939 item.intensity = rint((double)image[i] * correction); \
941 if(v.raw[1] != 0.0){ \
942 if(signbit(v.raw[1]) != 0){ \
943 item.indexes_0[0] = -item.indexes_0[0]; \
946 if(signbit(v.raw[0]) != 0){ \
947 item.indexes_0[0] = -item.indexes_0[0]; \
950 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
951 darray_append(space->items, item); \
956 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_QPAR_QPER_SAMPLEAXIS: \
958 const HklParameter *p = hkl_geometry_axis_get(geometry, sample_axis, NULL); \
960 int axis = rint(hkl_parameter_value_get(p, HKL_UNIT_USER) / resolutions[2]); \
962 for(i=0;i<n_pixels;++i){ \
963 if(not_masked(masked, i)){ \
964 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
966 v = glms_mat4_mulv3(m_holder_d, v, 1); \
967 v = glms_vec3_scale_as(v, k); \
968 correction = polarisation(v, weight, do_polarisation_correction); \
969 v = glms_vec3_sub(v , ki); \
970 v = glms_mat4_mulv3(m_holder_s, v, 0); \
972 item.indexes_0[0] = rint(sqrt(v.raw[0] * v.raw[0] + v.raw[1] * v.raw[1]) / resolutions[0]); \
973 item.indexes_0[1] = rint(v.raw[2] / resolutions[1]); \
974 item.indexes_0[2] = axis; \
975 item.intensity = rint((double)image[i] * correction); \
977 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
978 darray_append(space->items, item); \
984 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_SAMPLEAXIS_TTH: \
986 const HklParameter *p = hkl_geometry_axis_get(geometry, sample_axis, NULL); \
988 int axis = rint(hkl_parameter_value_get(p, HKL_UNIT_USER) / resolutions[1]); \
990 for(i=0;i<n_pixels;++i){ \
991 if(not_masked(masked, i)){ \
992 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
994 v = glms_mat4_mulv3(m_holder_d, v, 1); \
995 v = glms_vec3_scale_as(v, k); \
996 correction = polarisation(v, weight, do_polarisation_correction); \
997 v = glms_vec3_sub(v , ki); \
998 v = glms_mat4_mulv3(m_holder_s, v, 0); \
1000 item.indexes_0[0] = rint(glms_vec3_norm(v) / resolutions[0]); \
1001 item.indexes_0[1] = axis; \
1002 item.indexes_0[2] = rint(asin(glms_vec3_norm(v) / 2 / k) * 2 / M_PI * 180 / resolutions[2]); \
1003 item.intensity = rint((double)image[i] * correction); \
1005 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
1006 darray_append(space->items, item); \
1012 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_Q_SAMPLEAXIS_TIMESTAMP: \
1014 const HklParameter *p = hkl_geometry_axis_get(geometry, sample_axis, NULL); \
1016 int axis = rint(hkl_parameter_value_get(p, HKL_UNIT_USER) / resolutions[1]); \
1018 for(i=0;i<n_pixels;++i){ \
1019 if(not_masked(masked, i)){ \
1020 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
1022 v = glms_mat4_mulv3(m_holder_d, v, 1); \
1023 v = glms_vec3_scale_as(v, k); \
1024 correction = polarisation(v, weight, do_polarisation_correction); \
1025 v = glms_vec3_sub(v , ki); \
1026 v = glms_mat4_mulv3(m_holder_s, v, 0); \
1028 item.indexes_0[0] = rint(glms_vec3_norm(v) / resolutions[0]); \
1029 item.indexes_0[1] = axis; \
1030 item.indexes_0[2] = rint(timestamp / resolutions[2]); \
1031 item.intensity = rint((double)image[i] * correction); \
1033 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
1034 darray_append(space->items, item); \
1040 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_QX_QY_TIMESTAMP: \
1042 for(i=0;i<n_pixels;++i){ \
1043 if(not_masked(masked, i)){ \
1044 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
1046 v = glms_mat4_mulv3(m_holder_d, v, 1); \
1047 v = glms_vec3_scale_as(v, k); \
1048 correction = polarisation(v, weight, do_polarisation_correction); \
1049 v = glms_vec3_sub(v, ki); \
1050 v = glms_mat4_mulv3(m_holder_s, v, 0); \
1052 item.indexes_0[0] = rint(v.raw[0] / resolutions[0]); \
1053 item.indexes_0[1] = rint(v.raw[1] / resolutions[1]); \
1054 item.indexes_0[2] = rint(timestamp / resolutions[2]); \
1055 item.intensity = rint((double)image[i] * correction); \
1057 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
1058 darray_append(space->items, item); \
1063 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_QX_QZ_TIMESTAMP: \
1065 for(i=0;i<n_pixels;++i){ \
1066 if(not_masked(masked, i)){ \
1067 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
1069 v = glms_mat4_mulv3(m_holder_d, v, 1); \
1070 v = glms_vec3_scale_as(v, k); \
1071 correction = polarisation(v, weight, do_polarisation_correction); \
1072 v = glms_vec3_sub(v, ki); \
1073 v = glms_mat4_mulv3(m_holder_s, v, 0); \
1075 item.indexes_0[0] = rint(v.raw[0] / resolutions[0]); \
1076 item.indexes_0[1] = rint(v.raw[2] / resolutions[1]); \
1077 item.indexes_0[2] = rint(timestamp / resolutions[2]); \
1078 item.intensity = rint((double)image[i] * correction); \
1080 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
1081 darray_append(space->items, item); \
1086 case HKL_BINOCULARS_QCUSTOM_SUB_PROJECTION_QY_QZ_TIMESTAMP: \
1088 for(i=0;i<n_pixels;++i){ \
1089 if(not_masked(masked, i)){ \
1090 CGLM_ALIGN_MAT vec3s v = {{q_x[i], q_y[i], q_z[i]}}; \
1092 v = glms_mat4_mulv3(m_holder_d, v, 1); \
1093 v = glms_vec3_scale_as(v, k); \
1094 correction = polarisation(v, weight, do_polarisation_correction); \
1095 v = glms_vec3_sub(v, ki); \
1096 v = glms_mat4_mulv3(m_holder_s, v, 0); \
1098 item.indexes_0[0] = rint(v.raw[1] / resolutions[0]); \
1099 item.indexes_0[1] = rint(v.raw[2] / resolutions[1]); \
1100 item.indexes_0[2] = rint(timestamp / resolutions[2]); \
1101 item.intensity = rint((double)image[i] * correction); \
1103 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
1104 darray_append(space->items, item); \
1110 space_update_axes(space, names, n_pixels, resolutions); \
1111 hkl_detector_free(detector); \
1112 hkl_sample_free(sample); \
1115 HKL_BINOCULARS_SPACE_QCUSTOM_IMPL(int32_t);
1116 HKL_BINOCULARS_SPACE_QCUSTOM_IMPL(uint16_t);
1117 HKL_BINOCULARS_SPACE_QCUSTOM_IMPL(uint32_t);
1121 #define HKL_BINOCULARS_SPACE_HKL_IMPL(image_t) \
1122 HKL_BINOCULARS_SPACE_HKL_DECL(image_t) \
1125 double correction; \
1126 const char * names[] = {"H", "K", "L"}; \
1127 HklBinocularsSpaceItem item; \
1129 assert(ARRAY_SIZE(names) == darray_size(space->axes)); \
1130 assert(ARRAY_SIZE(names) == n_resolutions); \
1131 assert(n_pixels == space->max_items); \
1133 const double *h = &pixels_coordinates[0 * n_pixels]; \
1134 const double *k = &pixels_coordinates[1 * n_pixels]; \
1135 const double *l = &pixels_coordinates[2 * n_pixels]; \
1137 HklDetector *detector = hkl_detector_factory_new(HKL_DETECTOR_TYPE_0D); \
1138 HklHolder *holder_d = hkl_geometry_detector_holder_get(geometry, detector); \
1139 CGLM_ALIGN_MAT mat4s m_holder_d = hkl_binoculars_holder_transformation_get(holder_d); \
1140 const HklVector ki_v = hkl_geometry_ki_get(geometry); \
1141 CGLM_ALIGN_MAT vec3s ki = {{ki_v.data[0], ki_v.data[1], ki_v.data[2]}}; \
1142 float K = glms_vec3_norm(ki); \
1143 HklHolder *holder_s = hkl_geometry_sample_holder_get(geometry,sample); \
1144 CGLM_ALIGN_MAT mat4s m_holder_s = hkl_binoculars_holder_transformation_get(holder_s); \
1146 const HklMatrix *UB = hkl_sample_UB_get(sample); \
1147 CGLM_ALIGN_MAT mat4s ub = {{{UB->data[0][0], UB->data[1][0], UB->data[2][0], 0}, \
1148 {UB->data[0][1], UB->data[1][1], UB->data[2][1], 0}, \
1149 {UB->data[0][2], UB->data[1][2], UB->data[2][2], 0}, \
1151 glms_mat4_print(ub, stdout); \
1152 m_holder_s = glms_mat4_mul(m_holder_s, ub); \
1153 glms_mat4_print(m_holder_s, stdout); \
1154 m_holder_s = glms_mat4_inv(m_holder_s); \
1156 darray_size(space->items) = 0; \
1158 glms_mat4_print(m_holder_s, stdout); \
1159 glms_mat4_print(m_holder_d, stdout); \
1161 for(i=0;i<n_pixels;++i){ \
1162 if(not_masked(masked, i)){ \
1163 CGLM_ALIGN_MAT vec3s v = {{h[i], k[i], l[i]}}; \
1165 v = glms_mat4_mulv3(m_holder_d, v, 1); \
1166 v = glms_vec3_scale_as(v, K); \
1167 correction = polarisation(v, weight, do_polarisation_correction); \
1168 v = glms_vec3_sub(v, ki); \
1169 v = glms_mat4_mulv3(m_holder_s, v, 0); \
1171 item.indexes_0[0] = rint(v.raw[0] / resolutions[0]); \
1172 item.indexes_0[1] = rint(v.raw[1] / resolutions[1]); \
1173 item.indexes_0[2] = rint(v.raw[2] / resolutions[2]); \
1174 item.intensity = rint((double)image[i] * correction); \
1176 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
1177 darray_append(space->items, item); \
1181 space_update_axes(space, names, n_pixels, resolutions); \
1183 hkl_detector_free(detector); \
1186 HKL_BINOCULARS_SPACE_HKL_IMPL(int32_t);
1187 HKL_BINOCULARS_SPACE_HKL_IMPL(uint16_t);
1188 HKL_BINOCULARS_SPACE_HKL_IMPL(uint32_t);
1192 #define HKL_BINOCULARS_SPACE_TEST_IMPL(image_t) \
1193 HKL_BINOCULARS_SPACE_TEST_DECL(image_t) \
1196 const char * names[] = {"H", "K", "L"}; \
1197 double correction; \
1198 HklBinocularsSpaceItem item; \
1200 assert(ARRAY_SIZE(names) == darray_size(space->axes)); \
1201 assert(ARRAY_SIZE(names) == n_resolutions); \
1202 assert(n_pixels == space->max_items); \
1204 const double *h = &pixels_coordinates[0 * n_pixels]; \
1205 const double *k = &pixels_coordinates[1 * n_pixels]; \
1206 const double *l = &pixels_coordinates[2 * n_pixels]; \
1208 HklDetector *detector = hkl_detector_factory_new(HKL_DETECTOR_TYPE_0D); \
1209 HklHolder *holder_d = hkl_geometry_detector_holder_get(geometry, detector); \
1210 CGLM_ALIGN_MAT mat4s m_holder_d = hkl_binoculars_holder_transformation_get(holder_d); \
1211 const HklVector ki_v = hkl_geometry_ki_get(geometry); \
1212 CGLM_ALIGN_MAT vec3s ki = {{ki_v.data[0], ki_v.data[1], ki_v.data[2]}}; \
1213 float K = glms_vec3_norm(ki); \
1214 HklHolder *holder_s = hkl_geometry_sample_holder_get(geometry,sample); \
1215 CGLM_ALIGN_MAT mat4s m_holder_s = hkl_binoculars_holder_transformation_get(holder_s); \
1217 const HklMatrix *UB = hkl_sample_UB_get(sample); \
1218 CGLM_ALIGN_MAT mat4s ub = {{{UB->data[0][0], UB->data[1][0], UB->data[2][0], 0}, \
1219 {UB->data[0][1], UB->data[1][1], UB->data[2][1], 0}, \
1220 {UB->data[0][2], UB->data[1][2], UB->data[2][2], 0}, \
1222 glms_mat4_print(ub, stdout); \
1223 m_holder_s = glms_mat4_mul(m_holder_s, ub); \
1224 glms_mat4_print(m_holder_s, stdout); \
1225 m_holder_s = glms_mat4_inv(m_holder_s); \
1227 darray_size(space->items) = 0; \
1229 glms_mat4_print(m_holder_s, stdout); \
1230 glms_mat4_print(m_holder_d, stdout); \
1232 for(i=0;i<n_pixels;++i){ \
1233 if(not_masked(masked, i)){ \
1234 CGLM_ALIGN_MAT vec3s v = {{h[i], k[i], l[i]}}; \
1236 v = glms_mat4_mulv3(m_holder_d, v, 1); \
1237 v = glms_vec3_scale_as(v, K); \
1238 correction = polarisation(v, weight, do_polarisation_correction); \
1239 v = glms_vec3_sub(v, ki); \
1240 v = glms_mat4_mulv3(m_holder_s, v, 0); \
1242 item.indexes_0[0] = rint(v.raw[0] / resolutions[0]); \
1243 item.indexes_0[1] = rint(v.raw[1] / resolutions[1]); \
1244 item.indexes_0[2] = rint(v.raw[2] / resolutions[2]); \
1245 item.intensity = rint((double)image[i] * correction); \
1247 if(TRUE == item_in_the_limits(&item, limits, n_limits)) \
1248 darray_append(space->items, item); \
1252 space_update_axes(space, names, n_pixels, resolutions); \
1254 hkl_detector_free(detector); \
1257 HKL_BINOCULARS_SPACE_TEST_IMPL(int32_t);
1258 HKL_BINOCULARS_SPACE_TEST_IMPL(uint16_t);
1259 HKL_BINOCULARS_SPACE_TEST_IMPL(uint32_t);
1264 /* this method compute the linear coordinates of the first element in
1265 * the absolute coordinates of the bin */
1266 static inline ptrdiff_t compute_offset0(const darray_axis
*axes
)
1270 ptrdiff_t offset
= 0;
1271 size_t n_axes
= darray_size(*axes
);
1273 for(i
=0; i
<n_axes
; ++i
){
1274 const HklBinocularsAxis
*axis
= &darray_item(*axes
, n_axes
-1-i
);
1275 offset
+= len
* axis
->imin
;
1276 len
*= axis_size(axis
);
1281 static inline HklBinocularsCube
*empty_cube_from_axes(const darray_axis
*axes
)
1283 HklBinocularsCube
*self
= NULL
;
1285 if (0 != darray_size(*axes
)){
1286 HklBinocularsAxis
*axis
;
1288 self
= g_new0(HklBinocularsCube
, 1);
1289 darray_foreach(axis
, *axes
){
1290 darray_append(self
->axes
, *axis
);
1292 self
->offset0
= compute_offset0(&self
->axes
);
1293 self
->photons
= NULL
;
1294 self
->contributions
= NULL
;
1300 static inline size_t cube_size(const HklBinocularsCube
*self
)
1303 HklBinocularsAxis
*axis
;
1305 darray_foreach(axis
, self
->axes
){
1306 n
*= axis_size(axis
);
1312 static inline size_t malloc_cube(HklBinocularsCube
*self
)
1314 size_t n
= cube_size(self
);
1316 self
->photons
= malloc(n
* sizeof(*self
->photons
));
1317 self
->contributions
= malloc(n
* sizeof(*self
->contributions
));
1322 static inline size_t calloc_cube(HklBinocularsCube
*self
)
1324 size_t n
= cube_size(self
);
1326 self
->photons
= calloc(n
, sizeof(*self
->photons
));
1327 self
->contributions
= calloc(n
, sizeof(*self
->contributions
));
1332 /* Using this method the Cube has already the right dimensions, we
1333 * just add the Space data into it. */
1334 static inline void add_non_empty_space(HklBinocularsCube
*cube
,
1335 const HklBinocularsSpace
*space
)
1338 size_t n_axes
= darray_size(cube
->axes
);
1339 ptrdiff_t lens
[n_axes
];
1340 HklBinocularsSpaceItem
*item
;
1342 assert(n_axes
== darray_size(space
->axes
));
1344 /* compute the lens */
1347 for(i
=1; i
<n_axes
; ++i
){
1348 lens
[i
] = lens
[i
- 1] * axis_size(&darray_item(cube
->axes
, n_axes
- i
));
1351 darray_foreach(item
, space
->items
){
1352 ptrdiff_t w
= -cube
->offset0
;
1354 for(i
=0; i
<n_axes
; ++i
){
1355 w
+= lens
[i
] * item
->indexes_0
[n_axes
- 1 - i
];
1356 /* fprintf(stdout, " %ld %ld", lens[i], item->indexes_0[n_axes - 1 - i]); */
1359 /* fprintf(stdout, " w: %ld %ld\n", w, cube_size(cube)); */
1360 cube
->photons
[w
] += item
->intensity
;
1361 cube
->contributions
[w
] += 1;
1365 static inline int cube_is_empty(const HklBinocularsCube
*self
)
1367 return 0 == darray_size(self
->axes
);
1370 HklBinocularsCube
*hkl_binoculars_cube_new_empty(void)
1372 HklBinocularsCube
*self
= g_new(HklBinocularsCube
, 1);
1374 darray_init(self
->axes
);
1376 self
->photons
= NULL
;
1377 self
->contributions
= NULL
;
1382 void hkl_binoculars_cube_free(HklBinocularsCube
*self
)
1384 free(self
->contributions
);
1385 free(self
->photons
);
1386 darray_free(self
->axes
);
1390 unsigned int hkl_binoculars_cube_cmp(const HklBinocularsCube
*self
, const HklBinocularsCube
*other
)
1393 unsigned int res
= 0;
1395 res
|= darray_size(self
->axes
) != darray_size(other
->axes
);
1396 res
|= self
->offset0
!= other
->offset0
;
1397 for(i
=0; i
<darray_size(self
->axes
); ++i
){
1398 res
|= hkl_binoculars_axis_cmp(&darray_item(self
->axes
, i
),
1399 &darray_item(other
->axes
, i
));
1402 /* for(i=0; i<cube_size(self); ++i){ */
1403 /* res |= self->photons[i] != other->photons[i]; */
1404 /* res |= self->contributions[i] != other->contributions[i]; */
1406 /* fprintf(stdout, "\nphotons: %d %u %u ", i, self->photons[i], other->photons[i]); */
1407 /* fprintf(stdout, "\ncontributions: %d %u %u", i, self->contributions[i], other->contributions[i]); */
1413 fprintf(stdout
, "cube: self\n");
1414 hkl_binoculars_cube_fprintf(stdout
, self
);
1415 fprintf(stdout
, "cube: other\n");
1416 hkl_binoculars_cube_fprintf(stdout
, other
);
1422 void hkl_binoculars_cube_fprintf(FILE *f
, const HklBinocularsCube
*self
)
1424 HklBinocularsAxis
*axis
;
1426 fprintf(f
, "HklBinocularsCube: %p", self
);
1428 fprintf(f
, "\nn_axes: %ld", darray_size(self
->axes
));
1429 darray_foreach(axis
, self
->axes
){
1431 hkl_binoculars_axis_fprintf(f
, axis
);
1433 fprintf(f
, "\nphotons: %p", self
->photons
);
1434 fprintf(f
, "\ncontributions: %p", self
->contributions
);
1437 void hkl_binoculars_cube_dims(const HklBinocularsCube
*self
, size_t ndims
, size_t *dims
)
1439 HklBinocularsAxis
*axis
;
1441 assert(ndims
== darray_size(self
->axes
));
1443 darray_foreach(axis
, self
->axes
){
1444 *(dims
++) = axis_size(axis
);
1448 static inline size_t find_first_non_empty_space_index(size_t n_spaces
,
1449 const HklBinocularsSpace
*const *spaces
)
1453 for(i
=0; i
<n_spaces
; ++i
)
1454 if(!space_is_empty(spaces
[i
]))
1460 HklBinocularsCube
*hkl_binoculars_cube_new(size_t n_spaces
,
1461 const HklBinocularsSpace
*const *spaces
)
1464 HklBinocularsCube
*self
= NULL
;
1466 i0
= find_first_non_empty_space_index(n_spaces
, spaces
);
1469 self
= empty_cube_from_axes(&spaces
[i0
]->axes
);
1472 /* compute the final cube dimensions and the index offset */
1473 for(i
=i0
; i
<n_spaces
; ++i
){
1474 const HklBinocularsSpace
*space
= spaces
[i
];
1476 if(space_is_empty(space
))
1479 merge_axes(&self
->axes
, &space
->axes
);
1481 self
->offset0
= compute_offset0(&self
->axes
);
1483 /* allocated the final cube photons and contributions */
1486 /* add all the spaces */
1487 for(i
=i0
; i
<n_spaces
; ++i
){
1488 const HklBinocularsSpace
*space
= spaces
[i
];
1490 if(space_is_empty(space
))
1493 add_non_empty_space(self
, space
);
1501 HklBinocularsCube
*hkl_binoculars_cube_new_empty_from_cube(const HklBinocularsCube
*cube
)
1503 HklBinocularsCube
*self
= empty_cube_from_axes(&cube
->axes
);
1507 self
= hkl_binoculars_cube_new_empty();
1514 HklBinocularsCube
*hkl_binoculars_cube_new_from_space(const HklBinocularsSpace
*space
)
1516 HklBinocularsCube
*self
= NULL
;
1518 if(space_is_empty(space
)){
1519 self
= hkl_binoculars_cube_new_empty();
1521 self
= empty_cube_from_axes(&space
->axes
);
1525 add_non_empty_space(self
, space
);
1532 HklBinocularsCube
*hkl_binoculars_cube_new_copy(const HklBinocularsCube
*src
)
1535 HklBinocularsCube
*self
= empty_cube_from_axes(&src
->axes
);
1538 /* allocate the final cube */
1539 n
= malloc_cube(self
);
1543 memcpy(self
->photons
, src
->photons
, n
* sizeof(*self
->photons
));
1544 if(self
->contributions
)
1545 memcpy(self
->contributions
, src
->contributions
, n
* sizeof(*self
->contributions
));
1551 static inline void cube_add_cube_2(HklBinocularsCube
*self
,
1552 const HklBinocularsCube
*other
)
1555 size_t i_offset
, j_offset
;
1557 size_t stride_i
= 1;
1558 size_t stride_j
= stride_i
* axis_size(&darray_item(self
->axes
, 1));
1560 /* fill the values of other */
1561 size_t stride_i_other
= 1;
1562 size_t stride_j_other
= stride_i_other
* axis_size(&darray_item(other
->axes
, 1));
1564 i_offset
= darray_item(other
->axes
, 1).imin
- darray_item(self
->axes
, 1).imin
;
1565 j_offset
= darray_item(other
->axes
, 0).imin
- darray_item(self
->axes
, 0).imin
;
1567 for(j
=0; j
<axis_size(&darray_item(other
->axes
, 0)); ++j
){
1568 for(i
=0; i
<axis_size(&darray_item(other
->axes
, 1)); ++i
){
1569 size_t w
= (i
+ i_offset
) * stride_i
+ (j
+ j_offset
) * stride_j
;
1570 size_t w1
= i
* stride_i_other
+ j
* stride_j_other
;
1572 self
->photons
[w
] += other
->photons
[w1
];
1573 self
->contributions
[w
] += other
->contributions
[w1
];
1578 static inline void cube_add_cube_3(HklBinocularsCube
*self
,
1579 const HklBinocularsCube
*other
)
1582 size_t i_offset
, j_offset
, k_offset
;
1584 size_t stride_i
= 1;
1585 size_t stride_j
= stride_i
* axis_size(&darray_item(self
->axes
, 2));
1586 size_t stride_k
= stride_j
* axis_size(&darray_item(self
->axes
, 1));
1588 /* fill the values of other */
1589 size_t stride_i_other
= 1;
1590 size_t stride_j_other
= stride_i_other
* axis_size(&darray_item(other
->axes
, 2));
1591 size_t stride_k_other
= stride_j_other
* axis_size(&darray_item(other
->axes
, 1));
1593 i_offset
= darray_item(other
->axes
, 2).imin
- darray_item(self
->axes
, 2).imin
;
1594 j_offset
= darray_item(other
->axes
, 1).imin
- darray_item(self
->axes
, 1).imin
;
1595 k_offset
= darray_item(other
->axes
, 0).imin
- darray_item(self
->axes
, 0).imin
;
1597 for(k
=0; k
<axis_size(&darray_item(other
->axes
, 0)); ++k
){
1598 for(j
=0; j
<axis_size(&darray_item(other
->axes
, 1)); ++j
){
1599 for(i
=0; i
<axis_size(&darray_item(other
->axes
, 2)); ++i
){
1600 size_t w
= (i
+ i_offset
) * stride_i
+ (j
+ j_offset
) * stride_j
+ (k
+ k_offset
) * stride_k
;
1601 size_t w1
= i
* stride_i_other
+ j
* stride_j_other
+ k
* stride_k_other
;
1603 self
->photons
[w
] += other
->photons
[w1
];
1604 self
->contributions
[w
] += other
->contributions
[w1
];
1610 static inline void cube_add_cube(HklBinocularsCube
*self
,
1611 const HklBinocularsCube
*other
)
1613 assert(darray_size(self
->axes
) == darray_size(other
->axes
));
1615 switch(darray_size(self
->axes
)){
1616 case 2: cube_add_cube_2(self
, other
);
1618 case 3: cube_add_cube_3(self
, other
);
1624 static inline void compute_strides(const darray_axis
*axes
, size_t strides
[], size_t n_strides
)
1629 for(i
=1; i
<n_strides
; ++i
)
1630 strides
[i
] = strides
[i
-1] * axis_size(&darray_item(*axes
, n_strides
- i
+ 1));
1633 HklBinocularsCube
*hkl_binoculars_cube_new_merge(const HklBinocularsCube
*cube1
,
1634 const HklBinocularsCube
*cube2
)
1636 HklBinocularsCube
*self
= empty_cube_from_axes(&cube1
->axes
);
1638 merge_axes(&self
->axes
, &cube2
->axes
);
1641 cube_add_cube(self
, cube1
);
1642 cube_add_cube(self
, cube2
);
1647 static inline void switch_content(HklBinocularsCube
*self
,
1648 HklBinocularsCube
*other
)
1655 self
->axes
= other
->axes
;
1658 offset0
= self
->offset0
;
1659 self
->offset0
= other
->offset0
;
1660 other
->offset0
= offset0
;
1662 ptr
= self
->photons
;
1663 self
->photons
= other
->photons
;
1664 other
->photons
= ptr
;
1666 ptr
= self
->contributions
;
1667 self
->contributions
= other
->contributions
;
1668 other
->contributions
= ptr
;
1671 void hkl_binoculars_cube_add_space(HklBinocularsCube
*self
,
1672 const HklBinocularsSpace
*space
)
1675 fprintf(stdout
, "\nENTERING hkl_binoculars_cube_add_space:\n");
1676 hkl_binoculars_cube_fprintf(stdout
, self
);
1677 hkl_binoculars_space_fprintf(stdout
, space
);
1679 /* check the compatibility of the cube and the space. */
1680 if (1 != space_is_empty(space
)){
1681 if (does_not_include(&self
->axes
, &space
->axes
)){
1683 fprintf(stdout
, "\nthe Cube does not contain the space, so create a new cube.");
1685 if(0 != darray_size(self
->axes
)){ /* self cube is not empty */
1686 HklBinocularsCube
*cube
= empty_cube_from_axes(&self
->axes
);
1688 merge_axes(&cube
->axes
, &space
->axes
); /* circonscript */
1689 cube
->offset0
= compute_offset0(&cube
->axes
);
1691 cube_add_cube(cube
, self
);
1692 switch_content(self
, cube
);
1693 hkl_binoculars_cube_free(cube
);
1695 } else { /* self cube is empty */
1696 HklBinocularsCube
*cube
= empty_cube_from_axes(&space
->axes
);
1698 cube
->offset0
= compute_offset0(&cube
->axes
);
1700 switch_content(self
, cube
);
1701 hkl_binoculars_cube_free(cube
);
1705 add_non_empty_space(self
, space
);
1709 fprintf(stdout
, "\n");
1710 hkl_binoculars_cube_fprintf(stdout
, self
);
1711 fprintf(stdout
, "\nLEAVING hkl_binoculars_cube_add_space:\n");