1 #+TITLE: Welcome to hkl's @VERSION@ documentation!
2 #+AUTHOR: Picca Frédéric-Emmanuel
3 #+EMAIL: picca at synchrotron dash soleil dot fr
8 The purpose of the library is to factorise single crystal
9 diffraction angles computation for different kind of diffractometer
10 geometries. It is used at the SOLEIL, Desy and Alba synchrotron with
11 the Tango control system to pilot diffractometers.
13 - mode computation (aka PseudoAxis)
14 - item for different diffractometer geometries.
15 - UB matrix computation.
16 - busing & Levy with 2 reflections
17 - simplex computation with more than 2 reflections using the GSL
19 - Eulerians angles to pre-orientate your sample.
20 - Crystal lattice affinement
21 - with more than 2 reflections you can select which parameter must
24 - psi, eulerians, q, ...
26 In all this document the next convention will be used to describe
27 the diffractometers geometries.
28 - right handed convention for all the angles.
29 - direct space orthogonal base.
30 - description of the diffractometer geometries is done with all
31 axes values set to zero.
35 A periodic crystal is the association of a pattern and a lattice. The
36 pattern is located at each points of the lattice node. Positions of
37 those nodes are given by:
40 R_{uvw}=u\cdot\vec{a}+v\cdot\vec{b}+w\cdot\vec{c}
43 $\vec{a}$, $\vec{b}$, $\vec{c}$ are the former vector of a base of the
44 space. =u=, =v=, =w= are integrers. The pattern contain atomes
45 associated to each lattice node. the purpose of diffraction is to study
46 the interaction of this crystal (pattern+lattice) with X-rays.
48 #+CAPTION: Crystal direct lattice.
49 [[./figures/crystal.png]]
51 this lattice is defined by $\vec{a}$, $\vec{b}$, $\vec{c}$ vectors, and
52 the angles $\alpha$, $\beta$, $\gamma$. In general cases this lattice is
55 Nevertheless to compute the interaction of this real space lattice and
56 the X-Rays, it is convenient to define another lattice called reciprocal
57 lattice defined like this:
60 \vec{a}^{\star} & = & \tau\frac{\vec{b}\wedge\vec{c}}{\vec{a}\cdot(\vec{b}\wedge\vec{c})}\\
61 \vec{b}^{\star} & = & \tau\frac{\vec{c}\wedge\vec{a}}{\vec{b}\cdot(\vec{c}\wedge\vec{a})}\\
62 \vec{c}^{\star} & = & \tau\frac{\vec{a}\wedge\vec{b}}{\vec{c}\cdot(\vec{a}\wedge\vec{b})}
65 $\tau=2\pi$ or $\tau=1$ depending on the conventions.
67 It is then possible to define thoses orthogonal properties:
70 \vec{a}^{\star}\cdot\vec{a}=\tau & \vec{b}^{\star}\cdot\vec{a}=0 & \vec{c}^{\star}\cdot\vec{a}=0\\
71 \vec{a}^{\star}\cdot\vec{b}=0 & \vec{b}^{\star}\cdot\vec{b}=\tau & \vec{c}^{\star}\cdot\vec{b}=0\\
72 \vec{a}^{\star}\cdot\vec{c}=0 & \vec{b}^{\star}\cdot\vec{c}=0 & \vec{c}^{\star}\cdot\vec{c}=\tau
75 This reciprocal space lattice allow to write in a simpler form the
76 interaction between the crystal and the X-Rays. We often only know about
77 $\vec{a}$, $\vec{b}$, $\vec{c}$ vectors and the angles $\alpha$,
78 $\beta$, $\gamma$. Using the previous equations reciprocal, we can
79 compute the reciprocal lattice this way:
83 a^{\star} & = & \frac{\sin\alpha}{aD}\\
84 b^{\star} & = & \frac{\sin\beta}{bD}\\
85 c^{\star} & = & \frac{\sin\gamma}{cD}
91 D=\sqrt{1-\cos^{2}\alpha-\cos^{2}\beta-\cos^{2}\gamma+2\cos\alpha\cos\beta\cos\gamma}
94 To compute the angles between the reciprocal space vectors, it is once
95 again possible to use the previous equations reciprocal to obtain the
96 sinus and cosinus of the angles $\alpha^\star$, $\beta^\star$ et
100 \cos\alpha^{\star}=\frac{\cos\beta\cos\gamma-\cos\alpha}{\sin\beta\sin\gamma} & \, & \sin\alpha^{\star}=\frac{D}{\sin\beta\sin\gamma} \\
101 \cos\beta^{\star}=\frac{\cos\gamma\cos\alpha-\cos\beta}{\sin\gamma\sin\alpha} & \, & \sin\beta^{\star}=\frac{D}{\sin\gamma\sin\alpha}\\
102 \cos\gamma^{\star}=\frac{\cos\alpha\cos\beta-\cos\gamma}{\sin\alpha\sin\beta} & \, & \sin\gamma^{\star}=\frac{D}{\sin\alpha\sin\beta}
107 Let the incomming X-rays beam whose wave vector is $\vec{k_{i}}$,
108 $|k_{i}|=\tau/\lambda$ where $\lambda$ is the wavelength of the signal.
109 The $\vec{k_{d}}$ vector wavelength of the diffracted beam. There is
110 diffusion if the diffusion vector $\vec{q}$ can be expressed as follows:
113 \vec{q}=\vec{k_{d}}-\vec{k_{i}}=h.\vec{a}^{*}+k.\vec{b}^{*}+l.\vec{c}^{*}
116 where $(h,k,l)\in\mathbb{N}^{3}$ and $(h,k,l)\neq(0,0,0)$. Thoses
117 indices $(h,k,l)$ are named Miller indices.
119 Another way of looking at things has been given by Bragg and that famous
123 n\lambda=2d\sin\theta
126 where $d$ is the inter-plan distance and $n \in \mathbb{N}$.
128 The diffusion accure for a unique $\theta$ angle. Then we got $\vec{q}$
129 perpendicular to the diffraction plan.
131 The Ewald construction allow to represent this diffraction in the
137 The quaternions will be used to discribe the diffractometers geometries.
138 Thoses quaternions can represent 3D rotations. There is different way to
139 describe then like complex numbers.
151 To compute the quaternion's norm, we can proceed like for complex
155 \lvert q \rvert = \sqrt{a{{}^2}+b{{}^2}+c{{}^2}+d{{}^2}}
161 q^{*}=[a,-\vec{u}]=a-bi-cj-dk
166 The difference with the complexnumber algebre is about
175 ~ & 1 & i & j & k \cr
176 1 & 1 & i & j & k \cr
177 i & i & -1 & k & -j \cr
178 j & j & -k & -1 & i \cr
183 The product of two quaternions can be express by the Grassman product
184 Grassman product. So for two quaternions $p$ and $q$:
187 q &= a+\vec{u} = a+bi+cj+dk\\
188 p &= t+\vec{v} = t+xi+yj+zk
194 pq = at - \vec{u} \cdot \vec{v} + a \vec{v} + t \vec{u} + \vec{v} \times \vec{u}
200 pq = (at - bx - cy - dz) + (bt + ax + cz - dy) i + (ct + ay + dx - bz) j + (dt + az + by - cx) k
205 L'ensemble des quaternions unitaires (leur norme est égale à 1) est le
206 groupe qui représente les rotations dans l'espace 3D. Si on a un vecteur
207 unitaire $\vec{u}$ et un angle de rotation $\theta$ alors le quaternion
208 $[\cos\frac{\theta}{2},\sin\frac{\theta}{2}\vec{u]}$ représente la
209 rotation de $\theta$ autour de l'axe $\vec{u}$ dans le sens
210 trigonométrique. Nous allons donc utiliser ces quaternions unitaires
211 pour représenter les mouvements du diffractomètre.
213 Alors que dans le plan 2D une simple multiplication entre un nombre
214 complex et le nombre $e^{i\theta}$ permet de calculer simplement la
215 rotation d'angle $\theta$ autour de l'origine, dans l'espace 3D
216 l'expression équivalente est:
222 où $q$ est le quaternion de norme 1 représentant la rotation dans
223 l'espace et $z$ le quaternion représentant le vecteur qui subit la
224 rotation (sa partie réelle est nulle).
226 Dans le cas des quaternions de norme 1, il est très facile de calculer
227 $q^{-1}$. En effet l'inverse d'une rotation d'angle $\theta$ est la
228 rotation d'angle $-\theta$. On a donc directement:
231 q^{-1}=[\cos\frac{-\theta}{2},\sin\frac{-\theta}{2}\vec{u}]=[\cos\frac{\theta}{2},-\sin\frac{\theta}{2}\vec{u}]=q^{*}
234 Le passage aux matrices de rotation se fait par la formule suivante
239 a{{}^2}+b{{}^2}-c{{}^2}-d{{}^2} & 2bc-2ad & 2ac+2bd\\
240 2ad+2bc & a{{}^2}-b{{}^2}+c{{}^2}-d{{}^2} & 2cd-2ab\\
241 2bd-2ac & 2ab+2cd & a{{}^2}-b{{}^2}-c{{}^2}+d{{}^2}
245 La composition de rotation se fait simplement en multipliant les
246 quaternions entre eux. Si l'on à $q$
248 ** Modes de fonctionnement
249 ** Equations fondamentales
251 Le problème que nous devons résoudre est de calculer pour une famille de
252 plan $(h,k,l)$ donné, les angles de rotation du diffractomètre qui
253 permettent de le mettre en condition de diffraction. Il faut donc
254 exprimer les relations mathématiques qui lient les différents angles
255 entre eux lorsque la condition de Bragg est vérifiée. L'équation
256 fondamentale est la suivante:
259 \left(\prod_{i}S_{i}\right)\cdot U\cdot B\cdot\vec{h} & =\left(\prod_{j}D_{j}-I\right)\cdot\vec{k_{i}}\\
260 R\cdot U\cdot B\cdot\vec{h} & =\vec{Q}
263 ou $\vec{h}$ est le vecteur $(h,k,l)$, $\vec{k_{i}}$ est le vecteur
264 incident, $S_{i}$ les matrices de rotations des mouvements liés à
265 l'échantillon, $D_{j}$ les matrices de rotation des mouvements liés au
266 détecteur, $I$ la matrice identité, $U$ la matrice d'orientation du
267 cristal par rapport au repère de l'axe sur lequel ce dernier est monté
268 et $B$ la matrice de passage d'un repère non orthonormé ( celui du
269 crystal réciproque) à un repère orthonormé.
273 Si l'on connaît les paramètres cristallins du cristal étudié, il est
274 très simple de calculer $B$:
279 a^{\star} & b^{\star}\cos\gamma^{\star} & c^{\star}\cos\beta^{\star}\\
280 0 & b^{\star}\sin\gamma^{\star} & -c^{\star}\sin\beta^{\star}\cos\alpha\\
287 Il existe plusieurs façons de calculer $U$. Busing et Levy en a proposé
288 plusieurs. Nous allons présenter celle qui nécessite la mesure de
289 seulement deux réflections ainsi que la connaissance des paramètres
290 cristallins. Cette façon de calculer la matrice d'orientation $U$, peut
291 être généralisée à n'importe quel diffractomètre pour peu que la
292 description des axes de rotation permette d'obtenir la matrice de
293 rotation de la machine $R$ et le vecteur de diffusion $\vec{Q}$.
295 Il est également possible de calculer $U$ sans la connaîssance des
296 paramètres cristallins. il faut alors faire un affinement des
297 paramètres. Cela revient à minimiser une fonction. Nous allons utiliser
298 la méthode du simplex pour trouver ce minimum et donc ajuster l'ensemble
299 des paramètres cristallins ainsi que la matrice d'orientation.
301 *** Algorithme de Busing Levy
303 L'idée est de se placer dans le repère de l'axe sur lequel est monté
304 l'échantillon. On mesure deux réflections $(\vec{h}_{1},\vec{h}_{2})$
305 ainsi que leurs angles associés. Cela nous permet de calculer $R$ et
306 $\vec{Q}$ pour chacune de ces reflections. nous avons alors ce système:
309 U\cdot B\cdot\vec{h}_{1} & = & \tilde{R}_{1}\cdot\vec{Q}_{1}\\
310 U\cdot B\cdot\vec{h}_{2} & = & \tilde{R}_{2}\cdot\vec{Q}_{2}
313 De façon à calculer facilement $U$, il est intéressant de définir deux
314 trièdres orthonormé $T_{\vec{h}}$ et $T_{\vec{Q}}$ à partir des vecteurs
315 $(B\vec{h}_{1},B\vec{h}_{2})$ et
316 $(\tilde{R}_{1}\vec{Q}_{1},\tilde{R}_{2}\vec{Q}_{2})$. On a alors très
320 U \cdot T_{\vec{h}} = T_{\vec{Q}}
326 U = T_{\vec{Q}} \cdot \tilde{T}_{\vec{h}}
329 *** Affinement par la méthode du simplex
331 Dans ce cas nous ne connaissons pas la matrice $B$, il faut donc mesurer
332 plus que deux réflections pour ajuster les 9 paramètres. Six paramètres
333 pour le crystal et trois pour la matrice d'orientation $U$. Les trois
334 paramètres qui permennt de representer $U$ sont en fait les angles
335 d'euler. il faut donc être en mesure de passer d'une représentation
336 eulérien à cette matrice :math::U et réciproquement.
339 U = X \cdot Y \cdot Z
342 où $X$ est la matrice rotation suivant l'axe Ox et le premier angle
343 d'Euler, $Y$ la matrice de rotation suivant l'axe Oy et le deuxième
344 angle d'Euler et $Z$ la matrice du troisième angle d'Euler pour l'axe
348 $X$ & $Y$ & $Z$\tabularnewline
374 BDE+AF & -BDF+AE & -BC\\
375 -ADE+BF & ADF+BE & AC
379 Il est donc facile de passer des angles d'Euler à la matrice
382 Il faut maintenant faire la transformation inverse de la matrice $U$
383 vers les angles d'euler.
386 This section describe the calculations done by the library for the
387 different kind of pseudo axes.
388 ** Eulerians to Kappa angles
393 \kappa_\omega & = & \omega - p + \frac{\pi}{2} \\
394 \kappa & = & 2 \arcsin\left(\frac{\sin\frac{\chi}{2}}{\sin\alpha}\right) \\
395 \kappa_\phi & = & \phi - p - \frac{\pi}{2}
401 \kappa_\omega & = & \omega - p - \frac{\pi}{2} \\
402 \kappa & = & -2 \arcsin\left(\frac{\sin\frac{\chi}{2}}{\sin\alpha}\right) \\
403 \kappa_\phi & = & \phi - p + \frac{\pi}{2}
409 p = \arcsin\left(\frac{\tan\frac{\chi}{2}}{\tan\alpha}\right)
412 and $\alpha$ is the angle of the kappa axis with the $\vec{y}$ axis.
414 ** Kappa to Eulerians angles
419 \omega & = & \kappa_\omega + p - \frac{\pi}{2} \\
420 \chi & = & 2 \arcsin\left(\sin\frac{\kappa}{2} \sin\alpha\right) \\
421 \phi & = & \kappa_\phi + p + \frac{\pi}{2}
427 \omega & = & \kappa_\omega + p + \frac{\pi}{2} \\
428 \chi & = & -2 \arcsin\left(\sin\frac{\kappa}{2} \sin\alpha\right) \\
429 \phi & = & \kappa_\phi + p - \frac{\pi}{2}
435 p = \arctan\left(\tan\frac{\kappa}{2} \cos\alpha\right)
438 #+CAPTION: $\omega = 0$, $\chi = 0$, $\phi = 0$, 1st solution
439 [[./figures/e2k_1.png]]
441 #+CAPTION: $\omega = 0$, $\chi = 0$, $\phi = 0$, 2nd solution
442 [[./figures/e2k_2.png]]
444 #+CAPTION: $\omega = 0$, $\chi = 90$, $\phi = 0$, 1st solution
445 [[./figures/e2k_3.png]]
447 #+CAPTION: $\omega = 0$, $\chi = 90$, $\phi = 0$, 2nd solution
448 [[./figures/e2k_4.png]]
452 ./figures/qper_qpar.png]]
454 this pseudo axis engine compute the perpendicular
455 ($\left|\left|\vec{Q_\text{per}}\right|\right|$) and parallel
456 ($\left|\left|\vec{Q_\text{par}}\right|\right|$) contribution of
457 $\vec{Q}$ relatively to the surface of the sample defined by the
461 \vec{q} & = & \vec{k_\text{f}} - \vec{k_\text{i}} \\
462 \vec{q} & = & \vec{q_\text{per}} + \vec{q_\text{par}} \\
463 \vec{q_\text{per}} & = & \frac{\vec{q} \cdot \vec{n}}{\left|\left|\vec{n}\right|\right|} \frac{\vec{n}}{\left|\left|\vec{n}\right|\right|}
469 This section is automatically generating by introspecting the hkl library.
472 #+BEGIN_SRC python :exports results :results value raw
473 from gi.repository import Hkl
476 return ["\"*" + _ + "*\"" for _ in l]
478 diffractometers = Hkl.factories().iterkeys()
481 for diffractometer in sorted(diffractometers):
482 factory = Hkl.factories()[diffractometer]
483 output += "** " + diffractometer + "\n"
484 detector = Hkl.Detector.factory_new(Hkl.DetectorType(0))
485 sample = Hkl.Sample.new("toto")
486 geometry = factory.create_new_geometry()
487 engines = factory.create_new_engine_list()
488 engines.init(geometry, detector, sample)
490 output += "*** Axes: \n"
491 for axis in geometry.axes_names_get():
492 axis_v = geometry.axis_get(axis).axis_v_get().data
493 output += " + \"*" + axis + "*\": rotation around the *" + repr(axis_v) + "* axis\n"
495 output += "*** Engines: \n"
496 for engine in engines.engines_get():
497 output += " * \"*" + engine.name_get() + "*\":"
498 for pseudo in engine.pseudo_axes_names_get():
499 output += " \"*" + pseudo + "*\""
501 for mode in engine.modes_names_get():
502 output += " "*6 + "+ mode: \"*" + mode + "*\"\n"
503 engine.current_mode_set(mode)
504 axes_r = engine.axes_names_get(Hkl.EngineAxesNamesGet.READ)
505 axes_w = engine.axes_names_get(Hkl.EngineAxesNamesGet.WRITE)
506 parameters = engine.parameters_names_get() or ["No parameter"]
507 output += " "*8 + "+ axes (read) : " + ", ".join(bold(axes_r)) + "\n"
508 output += " "*8 + "+ axes (write): " + ", ".join(bold(axes_w)) + "\n"
509 output += " "*8 + "+ parameters: " + ", ".join(bold(parameters)) + "\n"
516 To get hkl, you can download the last stable version from sourceforge or
517 if you want the latest development version use
518 [[http://git.or.cz/][git]] or
519 [[http://code.google.com/p/msysgit/downloads/list][msysgit]] on windows
523 git clone git://repo.or.cz/hkl.git
529 git clone http://repo.or.cz/r/hkl.git (slower)
532 then checkout the next branch like this:
536 git checkout -b next origin/next
541 To build hkl you need [[http://www.python.org][Python 2.3+]] the
542 [[http://www.gnu.org/software/gsl/][GNU Scientific Library 1.12]] and
543 [[https://developer.gnome.org/glib/][GLib-2.0 >= 2.3.4]]:
546 ./configure --disable-gui
551 you can also build a GUI interfaces which use
552 [[http://www.gtk.org][gtk]]:
560 optionnaly you can build an experimental /libhkl3d/ library (no public
561 API for now) which is used by the GUI to display and compute
562 diffractometer collisions (only the /K6C/ model). To build it you need
563 also [[https://projects.gnome.org/gtkglext/][gtkglext]] and
564 [[http://bulletphysics.org/wordpress/][bullet 2.82]]:
567 ./configure --enable-hkl3d
572 if you want to work on the documentation you need the extra
574 - [[http://www.gtk.org/gtk-doc/][gtk-doc]] for the api
575 - [[http://sphinx.pocoo.org/][sphinx]] for the html and latex doc.
576 - [[http://asymptote.sourceforge.net/][asymptote]] for the figures
577 - [[http://www.gnu.org/software/emacs/][emacs]] the well known editor
578 - [[https://github.com/emacsmirror/htmlize][htmlize]] used to highlight the source code
579 - [[http://orgmode.org][org-mode]] litteral programming
580 - [[http://savannah.nongnu.org/projects/dvipng/][dvipng]] convert latex equation into pictures
582 On Debian/Ubuntu you just need to install
585 sudo apt-get install emacs dvipng emacs-goodies-el org-mode
589 ./configure --enable-gtk-doc
598 You can find the bug tracker here
599 [[https://bugs.debian.org/cgi-bin/pkgreport.cgi?repeatmerged=no&src=hkl][libhkl]]
609 You just need to send an email:
612 To: submit@bugs.debian.org
614 Subject: My problem with hkl...
619 I found this problem in hkl...
624 you can send your patch to [[picca@synchrotron-soleil.fr][Picca
625 Frédéric-Emmanuel]] using =git=
627 Here a minimalist exemple of the workflow to prepare and send a patch
628 for hkl. Suppose you wan to add a new feature to hkl create first a new
629 branch from the next one:
632 git checkout -b my-next next
647 now that your new feature is ready for a review, you can send by email
648 your work using git format-patch:
651 git format-patch origin/next
654 and send generated files 0001\_xxx, 0002\_xxx, ... to the author.
656 ** Howto add a diffractometer
658 To add a new diffractometer, you just need to copy the
659 hkl/hkl-engine-template.c into
660 hkl/hkl-engine-INSTITUT-BEAMLINE-INSTRUMENT.c where you replace the
661 upper case with the appropriate values.
663 The template file is compiled during the build process to ensure that it
666 Then you just need to follow the instruction found in the template. If
667 you need some precision about the process, do not hesitate to contact
670 do not forgot also to add this new file into hkl/Makefile.am with other
671 diffractometers in the hkl\_c\_sources variable (please keep the
675 The hkl library use the gobject-introspection to provide automatic
676 binding for a few languages.
682 has you can see there is 4 available solutions.
684 let's compute an hkl trajectory and select the first solution.
686 if we look at the 3 other solutions we can see that there is a problem
687 of continuity at the begining of the trajectory.
689 hey what's happend with theses solutions ! let's look closely to real
690 numbers. the last column is the distance to the diffractometer current
691 position. This distance is for now express like this:
693 $\sum_{axes} \left|\text{current position} - \text{target position}\right|$
696 [0.0, 119.99999999999999, 0.0, -90.0, 0.0, 59.99999999999999] 0.0
697 [0.0, -119.99999999999999, 0.0, -90.0, 0.0, -59.99999999999999] 6.28318530718
698 [0.0, -60.00000000000005, 0.0, 90.0, 0.0, 59.99999999999999] 6.28318530718
699 [0.0, 60.00000000000001, 0.0, 90.0, 0.0, -59.99999999999999] 6.28318530718
701 [0.0, 117.7665607657826, 7.456826294401656, -92.39856410531434, 0.0, 60.33024982425957] 0.216753826612
702 [0.0, -57.436310940366894, -7.456826294401656, 92.39856418853617, 0.0, 60.33024982425957] 6.41621345188
703 [0.0, 62.2334392342174, -7.456826294401656, 92.39856410531434, 0.0, -60.33024982425957] 6.42197739723
704 [0.0, -122.5636890596331, 7.456826294401656, -92.3985641885362, 0.0, -60.33024982425957] 6.50570308205
706 [0.0, 115.89125602137928, 14.781064139466098, -94.7660423112577, 0.0, 61.314597086440706] 0.219062698235
707 [0.0, -125.42334103772737, 14.781064139466098, -94.7660427050904, 0.0, -61.314597086440706] 6.53671995288
708 [0.0, -54.57665896227262, -14.781064139466098, 94.76604270509038, 0.0, 61.314597086440706] 6.67989976726
709 [0.0, 64.10874397862072, -14.781064139466098, 94.7660423112577, 0.0, -61.314597086440706] 6.71437170098
711 [0.0, 114.39338605351007, 21.85448296702796, -97.074145033719, 0.0, 62.93506298693471] 0.218163667981
712 [0.0, -128.54167683157993, 21.85448296702796, -97.07414574435087, 0.0, -62.93506298693471] 6.59846359365
713 [0.0, -51.45832316842005, -21.85448296702796, 97.07414574435087, 0.0, 62.93506298693471] 6.93673746356
714 [0.0, 65.60661394648993, -21.85448296702796, 97.074145033719, 0.0, -62.93506298693471] 7.03385205725
716 [0.0, 113.28316795475283, 28.583837575232764, -99.29953499008337, 0.0, 65.16540747008955] 0.21459359225
717 [0.0, -131.88223933078322, 28.583837575232764, -99.29953638594702, 0.0, -65.16540747008955] 6.69038531388
718 [0.0, -48.11776066921677, -28.583837575232764, 99.29953638594702, 0.0, 65.16540747008955] 7.18296350386
719 [0.0, 66.71683204524717, -28.583837575232764, 99.29953499008337, 0.0, -65.16540747008955] 7.37556986959
721 [0.0, 112.56286877075006, 34.90573305321372, -101.42496979586187, 0.0, 67.97568017857415] 0.209053830457
722 [0.0, -135.4128111996365, 34.90573305321372, -101.42497263302461, 0.0, -67.97568017857415] 6.81174779784
723 [0.0, -44.58718880036348, -34.90573305321372, 101.4249726330246, 0.0, 67.97568017857415] 7.41581162393
724 [0.0, 67.43713122924994, -34.90573305321372, 101.42496979586187, 0.0, -67.97568017857415] 7.7353201851
726 [0.0, 112.2291126083182, 40.78594007247402, -103.43941832567457, 0.0, 71.33706722449408] 0.202280147961
727 [0.0, -139.10795451001587, 40.78594007247402, -103.43942357602316, 0.0, -71.33706722449408] 6.96173845391
728 [0.0, -40.89204548998411, -40.78594007247402, 103.43942357602312, 0.0, 71.33706722449408] 7.63358787543
729 [0.0, 67.7708873916818, -40.78594007247402, 103.43941832567457, 0.0, -71.33706722449408] 8.10986069093
731 [0.0, 112.27578927291766, 46.214916130901734, -105.33741042812996, 0.0, 75.22640762217479] 0.196576175748
732 [0.0, -142.95061850160724, 46.214916130901734, -105.3374188005596, 0.0, -75.22640762217479] 7.13962155618
733 [0.0, -37.04938149839278, -46.214916130901734, 105.33741880055959, 0.0, 75.22640762217479] 7.83557762281
734 [0.0, 67.72421072708234, -46.214916130901734, 105.33741042812996, 0.0, -75.22640762217479] 8.49706672677
736 [0.0, 112.697137434232, 51.201667684695856, -107.11797492933192, 0.0, 79.63023536264535] 0.202327153157
737 [0.0, -146.9330984641471, 51.201667684695856, -107.11798610058318, 0.0, -79.63023536264535] 7.34491897177
738 [0.0, -33.0669015358529, -51.201667684695856, 107.11798610058317, 0.0, 79.63023536264535] 8.02185610877
739 [0.0, 67.30286256576798, -51.201667684695856, 107.11797492933192, 0.0, -79.63023536264535] 8.89597005568
741 [0.0, 113.49085964586432, 55.76762791023837, -108.78347437395287, 0.0, 84.54867879242364] 0.208455586312
742 [0.0, -151.05782007465257, 55.76762791023837, -108.78348605483542, 0.0, -84.54867879242364] 7.57761473366
743 [0.0, -28.942179925347414, -55.76762791023837, 108.78348605483538, 0.0, 84.54867879242364] 8.19307323084
744 [0.0, 66.50914035413568, -55.76762791023837, 108.78347437395287, 0.0, -84.54867879242364] 9.30675279514
746 [0.0, 114.6614608037443, 59.941489465646214, -110.3385360479293, 0.0, 90.00000081324956] 0.215562935229
747 [0.0, -155.33854118146962, 59.941489465646214, -110.33854432979601, 0.0, -89.99999918675044] 7.83839602383
748 [0.0, -24.661458818530395, -59.941489465646214, 110.33854432979601, 0.0, 90.00000081324956] 8.3502621071
749 [0.0, 65.3385391962557, -59.941489465646214, 110.3385360479293, 0.0, -89.99999918675044] 9.7307712883
752 as you can see for the first point of the trajectory, the 2nd, 3rd and
753 4th solutions have identical distances to the current position of the
754 diffractometer so they are un-ordered:
757 [0.0, 119.99999999999999, 0.0, -90.0, 0.0, 59.99999999999999] 0.0
758 [0.0, -119.99999999999999, 0.0, -90.0, 0.0, -59.99999999999999] 6.28318530718
759 [0.0, -60.00000000000005, 0.0, 90.0, 0.0, 59.99999999999999] 6.28318530718
760 [0.0, 60.00000000000001, 0.0, 90.0, 0.0, -59.99999999999999] 6.28318530718
763 then the problem arise with the second and third solution. you can see a
764 sort of reorganisation of the solution. 2 -> 3, 3 -> 4 and 4 -> 2 then
765 the order will stick unchanged until the end of the trajectory. this is
766 because the distance is computed relatively to the current position of
770 [0.0, 117.7665607657826, 7.456826294401656, -92.39856410531434, 0.0, 60.33024982425957] 0.216753826612
771 [0.0, -57.436310940366894, -7.456826294401656, 92.39856418853617, 0.0, 60.33024982425957] 6.41621345188
772 [0.0, 62.2334392342174, -7.456826294401656, 92.39856410531434, 0.0, -60.33024982425957] 6.42197739723
773 [0.0, -122.5636890596331, 7.456826294401656, -92.3985641885362, 0.0, -60.33024982425957] 6.50570308205
775 [0.0, 115.89125602137928, 14.781064139466098, -94.7660423112577, 0.0, 61.314597086440706] 0.219062698235
776 [0.0, -125.42334103772737, 14.781064139466098, -94.7660427050904, 0.0, -61.314597086440706] 6.53671995288
777 [0.0, -54.57665896227262, -14.781064139466098, 94.76604270509038, 0.0, 61.314597086440706] 6.67989976726
778 [0.0, 64.10874397862072, -14.781064139466098, 94.7660423112577, 0.0, -61.314597086440706] 6.71437170098
784 when you compute a trajectory, start from a valid position (the
785 starting point must be the real first point of your trajectory) then
786 use only the closest solution for the next points of the trajectory.
787 (first solution of the geometries list)
791 *** TODO [2/4] HklParameter
792 - [X] method to use min/max to check for the validity
793 - [X] add a method to get the axis_v and quaternion of the HklAxis
794 this method will return NULL if this is not relevant.
795 hkl_parameter_axis_v_get and hkl_parameter_quaternion_get
796 - [ ] degenerated an axis is degenerated if its position have no
797 effect on the HklPseudoAxis calculus. Add a degenerated member
798 to the axis. that way it would be possible to check a posteriori
799 for this degenerescencence.
800 - [ ] Add a description for each parameters.
801 This will help for the documentation and the gui.
802 *** TODO HklGeometryList different method to help select a solution.
803 this select solution can depend on the geometry
804 for example the kappa axis must be in one side of the plane.
805 *** TODO add a fit on the Hklaxis offsets.
806 *** TODO API to put a detector and a sample on the Geometry.
807 *** TODO HklSample add the cell volum computation.
808 *** TODO HklEngine "zone"
809 *** TODO HklEngine "custom"
810 for now this pseudoaxis let you select the axis you
811 want to use for the computation.
812 *** TODO create a macro to help compare two real the right way
813 fabs(a-b) < epsilon * max(1, abs(a), abs(b))
814 *** TODO add an hkl_sample_set_lattice_unit()
816 **** DONE find the right solutions. :zaxis:
817 The cosinus and sinus properties are not enough to find the solution expected by the users.
818 The idea is to use the Ewalds construction to generate a valid solution from the first one
819 obtain numerically. The basic idea is to rotate the hkl vector around the last axis of the
820 sample holder until it intersect again the Ewalds sphere. Then we just need to fit the
821 detector position. This way the solution can be entirely generic (not geometry specific).
822 Nevertheless it is necessary to propose this only for the hkl pseudo axes. I will add this
823 special feature in the Mode. So it will be possible to add thoses special cases easily.
824 **** TODO Add the DEP diffractometer geometry
825 This diffractometer is a Newport one based on the kappa 6 circles ones.
826 But instead of a kappa head, they use an Hexapod head.
827 This head can be put horizontally or vertically.
828 *** TODO generalisation of the z-axis hkl solver
829 first we need the degenerated member of the Axis. thaht way it could be possible
830 to find the last non degenerated axis for the detector fit.
831 *** TODO investigate the prigo geometry.
832 *** TODO augeas/elektra for the plugin configure part.
834 **** TODO [1/2] add in a few methods.
835 + [X] hkl_pseudo_axes_values_set
836 + [ ] hkl_sample_affine
837 **** TODO gir logging
838 It would be nice to generate the library logging using the .gir
839 information. So instead of writing the logging code for each
840 method, it would be better to have a generic method for this
842 **** TODO parsable logging information.
843 A parsable logging format would help to setup some re-play unit
844 test. This way it could help during the developpement process
845 (modification of the hkl internals) to be confident that
847 *** TODO performances
848 Investigate [[http://liboil.freedesktop.org/wiki/][liboil]] to speed calculation (in HklVector, HklMatrix
851 *** TODO [1/4] rewrite documentation in org-mode
852 - [ ] embed code into the org-mode
854 - [ ] auto generation of the diffractometer descriptions
855 - [ ] trajectories explanations
856 - [ ] trajectories tests.
857 - [ ] unit tests output ?
859 - [X] need to check if templates could be generated using the hkl
860 python binding for all diffractometer geometries.
861 - [ ] need to add a description for the diffractometer, the mode, the parameters.
862 - [ ] need a nice css for the generated doc.
864 *** TODO change the color of fitparameter cells if they differ from the current
867 https://github.com/jonathanslenders/python-prompt-toolkit/tree/master/examples/tutorial
870 *** TODO add a method to find the 3D models in the right directories.
873 *** TODO add a .spec file for rpm generation.