post release commit
[hkl.git] / Documentation / hkl.org.in
blob4bcecf554d1276d0b3619737413eea1f22a631a0
1 #+TITLE: Welcome to hkl's @VERSION@ documentation!
2 #+AUTHOR: Picca Frédéric-Emmanuel
3 #+EMAIL: picca at synchrotron dash soleil dot fr
4 #+LANGUAGE: en
5 #+HTML_MATHJAX: path:"/usr/share/javascript/mathjax/MathJax.js"
6 #+STYLE: <style>table.center {margin-left:auto; margin- right:auto;}</style>
8 #+HTML_HEAD: <link rel="stylesheet" type="text/css" href="http://www.pirilampo.org/styles/readtheorg/css/htmlize.css"/>
9 #+HTML_HEAD: <link rel="stylesheet" type="text/css" href="http://www.pirilampo.org/styles/readtheorg/css/readtheorg.css"/>
11 #+HTML_HEAD: <script src="http://code.jquery.com/jquery-2.2.0.min.js"></script>
12 #+HTML_HEAD: <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
13 #+HTML_HEAD: <script type="text/javascript" src="http://www.pirilampo.org/styles/lib/js/jquery.stickytableheaders.js"></script>
14 #+HTML_HEAD: <script type="text/javascript" src="http://www.pirilampo.org/styles/readtheorg/js/readtheorg.js"></script>
16 * Introduction
17   The purpose of the library is to factorize single crystal
18   diffraction angles computation for different kind of diffractometer
19   geometries. It is used at the SOLEIL, Desy and Alba synchrotron with
20   the Tango control system to pilot diffractometers.
21 ** Features
22    - mode computation (aka PseudoAxis)
23    - item for different diffractometer geometries.
24    - UB matrix computation.
25      - busing & Levy with 2 reflections
26      - simplex computation with more than 2 reflections using the GSL
27        library.
28      - Eulerians angles to pre-orientate your sample.
29    - Crystal lattice refinement
30      - with more than 2 reflections you can select which parameter must
31        be fitted.
32    - Pseudoaxes
33      - psi, eulerians, q, ...
34 ** Conventions
35    In all this document the next convention will be used to describe
36    the diffractometers geometries.
37    - right handed convention for all the angles.
38    - direct space orthogonal base.
39    - description of the diffractometer geometries is done with all
40      axes values set to zero.
41 ** Diffraction
42 *** the crystal
44     A periodic crystal is the association of a pattern and a lattice. The
45     pattern is located at each points of the lattice node. Positions of
46     those nodes are given by:
48     \begin{displaymath}
49     R_{uvw}=u\cdot\vec{a}+v\cdot\vec{b}+w\cdot\vec{c}
50     \end{displaymath}
52     $\vec{a}$, $\vec{b}$, $\vec{c}$ are the former vector of a base of the
53     space. =u=, =v=, =w= are integers. The pattern contain atoms
54     associated to each lattice node. the purpose of diffraction is to study
55     the interaction of this crystal (pattern+lattice) with X-rays.
57     #+CAPTION: Crystal direct lattice.
58     [[./figures/crystal.png]]
60     this lattice is defined by $\vec{a}$, $\vec{b}$, $\vec{c}$ vectors, and
61     the angles $\alpha$, $\beta$, $\gamma$. In general cases this lattice is
62     not orthonormal.
64     Nevertheless to compute the interaction of this real space lattice and
65     the X-Rays, it is convenient to define another lattice called reciprocal
66     lattice defined like this:
68     \begin{eqnarray*}
69     \vec{a}^{\star} & = & \tau\frac{\vec{b}\wedge\vec{c}}{\vec{a}\cdot(\vec{b}\wedge\vec{c})}\\
70     \vec{b}^{\star} & = & \tau\frac{\vec{c}\wedge\vec{a}}{\vec{b}\cdot(\vec{c}\wedge\vec{a})}\\
71     \vec{c}^{\star} & = & \tau\frac{\vec{a}\wedge\vec{b}}{\vec{c}\cdot(\vec{a}\wedge\vec{b})}
72     \end{eqnarray*}
74     $\tau=2\pi$ or $\tau=1$ depending on the conventions.
76     It is then possible to define theses orthogonal properties:
78     \begin{eqnarray*}
79     \vec{a}^{\star}\cdot\vec{a}=\tau & \vec{b}^{\star}\cdot\vec{a}=0    & \vec{c}^{\star}\cdot\vec{a}=0\\
80     \vec{a}^{\star}\cdot\vec{b}=0    & \vec{b}^{\star}\cdot\vec{b}=\tau & \vec{c}^{\star}\cdot\vec{b}=0\\
81     \vec{a}^{\star}\cdot\vec{c}=0    & \vec{b}^{\star}\cdot\vec{c}=0    & \vec{c}^{\star}\cdot\vec{c}=\tau
82     \end{eqnarray*}
84     This reciprocal space lattice allow to write in a simpler form the
85     interaction between the crystal and the X-Rays. We often only know about
86     $\vec{a}$, $\vec{b}$, $\vec{c}$ vectors and the angles $\alpha$,
87     $\beta$, $\gamma$. Using the previous equations reciprocal, we can
88     compute the reciprocal lattice this way:
91     \begin{eqnarray*}
92     a^{\star} & = & \frac{\sin\alpha}{aD}\\
93     b^{\star} & = & \frac{\sin\beta}{bD}\\
94     c^{\star} & = & \frac{\sin\gamma}{cD}
95     \end{eqnarray*}
97     where
99     \begin{displaymath}
100     D=\sqrt{1-\cos^{2}\alpha-\cos^{2}\beta-\cos^{2}\gamma+2\cos\alpha\cos\beta\cos\gamma}
101     \end{displaymath}
103     To compute the angles between the reciprocal space vectors, it is once
104     again possible to use the previous equations reciprocal to obtain the
105     sines and cosines of the angles $\alpha^\star$, $\beta^\star$ and
106     $\gamma^\star$:
108     \begin{eqnarray*}
109     \cos\alpha^{\star}=\frac{\cos\beta\cos\gamma-\cos\alpha}{\sin\beta\sin\gamma} & \, & \sin\alpha^{\star}=\frac{D}{\sin\beta\sin\gamma} \\
110     \cos\beta^{\star}=\frac{\cos\gamma\cos\alpha-\cos\beta}{\sin\gamma\sin\alpha} & \, & \sin\beta^{\star}=\frac{D}{\sin\gamma\sin\alpha}\\
111     \cos\gamma^{\star}=\frac{\cos\alpha\cos\beta-\cos\gamma}{\sin\alpha\sin\beta} & \, & \sin\gamma^{\star}=\frac{D}{\sin\alpha\sin\beta}
112     \end{eqnarray*}
114     the volume of the lattice can be compute this way:
116     \begin{displaymath}
117     V = abcD
118     \end{displaymath}
120     or
122     \begin{displaymath}
123     V = \vec{a} \dot (\vec{b} \wedge \vec{c}) = \vec{b} \dot (\vec{c} \wedge \vec{a}) = \vec{c} \dot (\vec{a} \wedge \vec{b})
124     \end{displaymath}
127 *** Diffraction
129     Let the incoming X-rays beam whose wave vector is $\vec{k_{i}}$,
130     $|k_{i}|=\tau/\lambda$ where $\lambda$ is the wavelength of the signal.
131     The $\vec{k_{d}}$ vector wavelength of the diffracted beam. There is
132     diffusion if the diffusion vector $\vec{q}$ can be expressed as follows:
134     \begin{displaymath}
135     \vec{q}=\vec{k_{d}}-\vec{k_{i}}=h.\vec{a}^{*}+k.\vec{b}^{*}+l.\vec{c}^{*}
136     \end{displaymath}
138     where $(h,k,l)\in\mathbb{N}^{3}$ and $(h,k,l)\neq(0,0,0)$. Theses
139     indices $(h,k,l)$ are named Miller indices.
141     Another way of looking at things has been given by Bragg and that famous
142     relationship:
144     \begin{displaymath}
145     n\lambda=2d\sin\theta
146     \end{displaymath}
148     where $d$ is the inter-plan distance and $n \in \mathbb{N}$.
150     The diffusion occurs for an unique $\theta$ angle. Then we got
151     $\vec{q}$ perpendicular to the diffraction plan.
153     The Ewald construction allow to represent this diffraction in the
154     reciprocal space.
156 *** Quaternions
157 **** Properties
159      The quaternions will be used to describe the diffractometers geometries.
160      Theses quaternions can represent 3D rotations. There is different way to
161      describe then like complex numbers.
163      \begin{displaymath}
164      q=a+bi+cj+dk
165      \end{displaymath}
167      or
169      \begin{displaymath}
170      q=[a,\vec{v}]
171      \end{displaymath}
173      To compute the quaternion's norm, we can proceed like for complex
174      numbers
176      \begin{displaymath}
177      \lvert q \rvert = \sqrt{a{{}^2}+b{{}^2}+c{{}^2}+d{{}^2}}
178      \end{displaymath}
180      Its conjugate is :
182      \begin{displaymath}
183      q^{*}=[a,-\vec{u}]=a-bi-cj-dk
184      \end{displaymath}
186 **** Operations
188      The difference with the complex number algebra is about
189      non-commutativity.
191      \begin{displaymath}
192      qp \neq pq
193      \end{displaymath}
195      \begin{displaymath}
196      \begin{bmatrix}
197      ~ & 1 & i  & j  & k \cr
198      1 & 1 & i  & j  & k \cr
199      i & i & -1 & k  & -j \cr
200      j & j & -k & -1 & i \cr
201      k & k & j  & -i & -1
202      \end{bmatrix}
203      \end{displaymath}
205      The product of two quaternions can be express by the Grassman product
206      Grassman product. So for two quaternions $p$ and $q$:
208      \begin{align*}
209      q &= a+\vec{u} = a+bi+cj+dk\\
210      p &= t+\vec{v} = t+xi+yj+zk
211      \end{align*}
213      we got
215      \begin{displaymath}
216      pq = at - \vec{u} \cdot \vec{v} + a \vec{v} + t \vec{u} + \vec{v} \times \vec{u}
217      \end{displaymath}
219      or equivalent
221      \begin{displaymath}
222      pq = (at - bx - cy - dz) + (bt + ax + cz - dy) i + (ct + ay + dx - bz) j + (dt + az + by - cx) k
223      \end{displaymath}
225 **** 3D rotations
227      L'ensemble des quaternions unitaires (leur norme est égale à 1) est le
228      groupe qui représente les rotations dans l'espace 3D. Si on a un vecteur
229      unitaire $\vec{u}$ et un angle de rotation $\theta$ alors le quaternion
230      $[\cos\frac{\theta}{2},\sin\frac{\theta}{2}\vec{u]}$ représente la
231      rotation de $\theta$ autour de l'axe $\vec{u}$ dans le sens
232      trigonométrique. Nous allons donc utiliser ces quaternions unitaires
233      pour représenter les mouvements du diffractomètre.
235      Alors que dans le plan 2D une simple multiplication entre un nombre
236      complex et le nombre $e^{i\theta}$ permet de calculer simplement la
237      rotation d'angle $\theta$ autour de l'origine, dans l'espace 3D
238      l'expression équivalente est:
240      \begin{displaymath}
241      z'=qzq^{-1}
242      \end{displaymath}
244      où $q$ est le quaternion de norme 1 représentant la rotation dans
245      l'espace et $z$ le quaternion représentant le vecteur qui subit la
246      rotation (sa partie réelle est nulle).
248      Dans le cas des quaternions de norme 1, il est très facile de calculer
249      $q^{-1}$. En effet l'inverse d'une rotation d'angle $\theta$ est la
250      rotation d'angle $-\theta$. On a donc directement:
252      \begin{displaymath}
253      q^{-1}=[\cos\frac{-\theta}{2},\sin\frac{-\theta}{2}\vec{u}]=[\cos\frac{\theta}{2},-\sin\frac{\theta}{2}\vec{u}]=q^{*}
254      \end{displaymath}
256      Le passage aux matrices de rotation se fait par la formule suivante
257      $q\rightarrow M$.
259      \begin{displaymath}
260      \begin{bmatrix}
261      a{{}^2}+b{{}^2}-c{{}^2}-d{{}^2} & 2bc-2ad & 2ac+2bd\\
262      2ad+2bc & a{{}^2}-b{{}^2}+c{{}^2}-d{{}^2} & 2cd-2ab\\
263      2bd-2ac & 2ab+2cd & a{{}^2}-b{{}^2}-c{{}^2}+d{{}^2}
264      \end{bmatrix}
265      \end{displaymath}
267      La composition de rotation se fait simplement en multipliant les
268      quaternions entre eux. Si l'on à $q$
270 ** Modes de fonctionnement
271 ** Equations fondamentales
273    Le problème que nous devons résoudre est de calculer pour une famille de
274    plan $(h,k,l)$ donné, les angles de rotation du diffractomètre qui
275    permettent de le mettre en condition de diffraction. Il faut donc
276    exprimer les relations mathématiques qui lient les différents angles
277    entre eux lorsque la condition de Bragg est vérifiée. L'équation
278    fondamentale est la suivante:
280    \begin{align*}
281    \left(\prod_{i}S_{i}\right)\cdot U\cdot B\cdot\vec{h} & =\left(\prod_{j}D_{j}-I\right)\cdot\vec{k_{i}}\\
282    R\cdot U\cdot B\cdot\vec{h} & =\vec{Q}
283    \end{align*}
285    ou $\vec{h}$ est le vecteur $(h,k,l)$, $\vec{k_{i}}$ est le vecteur
286    incident, $S_{i}$ les matrices de rotations des mouvements liés à
287    l'échantillon, $D_{j}$ les matrices de rotation des mouvements liés au
288    détecteur, $I$ la matrice identité, $U$ la matrice d'orientation du
289    cristal par rapport au repère de l'axe sur lequel ce dernier est monté
290    et $B$ la matrice de passage d'un repère non orthonormé ( celui du
291    crystal réciproque) à un repère orthonormé.
293 *** Calcule de B
295     Si l'on connaît les paramètres cristallins du cristal étudié, il est
296     très simple de calculer $B$:
298     \begin{displaymath}
299     B=
300     \begin{bmatrix}
301     a^{\star} & b^{\star}\cos\gamma^{\star} & c^{\star}\cos\beta^{\star}\\
302     0 & b^{\star}\sin\gamma^{\star} & -c^{\star}\sin\beta^{\star}\cos\alpha\\
303     0 & 0 & 1/c
304     \end{bmatrix}
305     \end{displaymath}
307 *** Calcule de U
309     Il existe plusieurs façons de calculer $U$. Busing et Levy en a proposé
310     plusieurs. Nous allons présenter celle qui nécessite la mesure de
311     seulement deux réflections ainsi que la connaissance des paramètres
312     cristallins. Cette façon de calculer la matrice d'orientation $U$, peut
313     être généralisée à n'importe quel diffractomètre pour peu que la
314     description des axes de rotation permette d'obtenir la matrice de
315     rotation de la machine $R$ et le vecteur de diffusion $\vec{Q}$.
317     Il est également possible de calculer $U$ sans la connaîssance des
318     paramètres cristallins. il faut alors faire un affinement des
319     paramètres. Cela revient à minimiser une fonction. Nous allons utiliser
320     la méthode du simplex pour trouver ce minimum et donc ajuster l'ensemble
321     des paramètres cristallins ainsi que la matrice d'orientation.
323 *** Algorithme de Busing Levy
325     L'idée est de se placer dans le repère de l'axe sur lequel est monté
326     l'échantillon. On mesure deux réflections $(\vec{h}_{1},\vec{h}_{2})$
327     ainsi que leurs angles associés. Cela nous permet de calculer $R$ et
328     $\vec{Q}$ pour chacune de ces reflections. nous avons alors ce système:
330     \begin{eqnarray*}
331     U\cdot B\cdot\vec{h}_{1} & = & \tilde{R}_{1}\cdot\vec{Q}_{1}\\
332     U\cdot B\cdot\vec{h}_{2} & = & \tilde{R}_{2}\cdot\vec{Q}_{2}
333     \end{eqnarray*}
335     De façon à calculer facilement $U$, il est intéressant de définir deux
336     trièdres orthonormé $T_{\vec{h}}$ et $T_{\vec{Q}}$ à partir des vecteurs
337     $(B\vec{h}_{1},B\vec{h}_{2})$ et
338     $(\tilde{R}_{1}\vec{Q}_{1},\tilde{R}_{2}\vec{Q}_{2})$. On a alors très
339     simplement:
341     \begin{displaymath}
342     U \cdot T_{\vec{h}} = T_{\vec{Q}}
343     \end{displaymath}
345     Et donc
347     \begin{displaymath}
348     U = T_{\vec{Q}} \cdot \tilde{T}_{\vec{h}}
349     \end{displaymath}
351 *** Affinement par la méthode du simplex
353     Dans ce cas nous ne connaissons pas la matrice $B$, il faut donc mesurer
354     plus que deux réflections pour ajuster les 9 paramètres. Six paramètres
355     pour le crystal et trois pour la matrice d'orientation $U$. Les trois
356     paramètres qui permennt de representer $U$ sont en fait les angles
357     d'euler. il faut donc être en mesure de passer d'une représentation
358     eulérien à cette matrice :math::U et réciproquement.
360     \begin{displaymath}
361     U = X \cdot Y \cdot Z
362     \end{displaymath}
364     où $X$ est la matrice rotation suivant l'axe Ox et le premier angle
365     d'Euler, $Y$ la matrice de rotation suivant l'axe Oy et le deuxième
366     angle d'Euler et $Z$ la matrice du troisième angle d'Euler pour l'axe
367     Oz.
369     #+ATTR_HTML: class="center"
370     | $X$        | $Y$        | $Z$        |
371     | <10>       | <10>       | <10>       |
372     | $\begin{bmatrix} 1 & 0 & 0\\ 0 & A & -B\\ 0 & B & A \end{bmatrix}$ | $\begin{bmatrix}C & 0 & D\\0 & 1 & 0\\-D & 0 & C\end{bmatrix}$ | $\begin{bmatrix}E & -F & 0\\F & E & 0\\0 & 0 & 1\end{bmatrix}$ |
374     et donc:
376     \begin{displaymath}
377     U=
378     \begin{bmatrix}
379     CE & -CF & D\\
380     BDE+AF & -BDF+AE & -BC\\
381     -ADE+BF & ADF+BE & AC
382     \end{bmatrix}
383     \end{displaymath}
385     Il est donc facile de passer des angles d'Euler à la matrice
386     d'orientation.
388     Il faut maintenant faire la transformation inverse de la matrice $U$
389     vers les angles d'euler.
391 * PseudoAxes
392   This section describe the calculations done by the library for the
393   different kind of pseudo axes.
394 ** General process
395 *** First Solution
396     The hkl library use the gsl library in order to find the first
397     valid solution.
398 *** Multiplication of the solutions.
399     Once we have got the first solution different strategies are
400     applyed in order to generate more solutions.
401 **** Geometry Multiplication
402      For kappa diffractometers, once you have one solution it is
403      possible to générate another one using a property of this
404      geometry. (Left arm and right arm).
405 *** Restrains of the Solutions
406     We apply then some constrains to reduce these solutions to only a
407     bunch of acceptable ones. Usualy we take the axis range into
408     account.
409 ** Eulerians to Kappa angles
411    1st solution
413    \begin{eqnarray*}
414    \kappa_\omega & = & \omega - p + \frac{\pi}{2} \\
415    \kappa & = & 2 \arcsin\left(\frac{\sin\frac{\chi}{2}}{\sin\alpha}\right) \\
416    \kappa_\phi & = &  \phi - p - \frac{\pi}{2}
417    \end{eqnarray*}
419    or 2nd one
421    \begin{eqnarray*}
422    \kappa_\omega & = & \omega - p - \frac{\pi}{2} \\
423    \kappa & = & -2 \arcsin\left(\frac{\sin\frac{\chi}{2}}{\sin\alpha}\right) \\
424    \kappa_\phi & = &  \phi - p + \frac{\pi}{2}
425    \end{eqnarray*}
427    where
429    \begin{displaymath}
430    p = \arcsin\left(\frac{\tan\frac{\chi}{2}}{\tan\alpha}\right)
431    \end{displaymath}
433    and $\alpha$ is the angle of the kappa axis with the $\vec{y}$ axis.
435 ** Kappa to Eulerians angles
437    1st solution
439    \begin{eqnarray*}
440    \omega & = & \kappa_\omega + p - \frac{\pi}{2} \\
441    \chi   & = & 2 \arcsin\left(\sin\frac{\kappa}{2} \sin\alpha\right) \\
442    \phi   & = & \kappa_\phi + p + \frac{\pi}{2}
443    \end{eqnarray*}
445    or 2nd one
447    \begin{eqnarray*}
448    \omega & = & \kappa_\omega + p + \frac{\pi}{2} \\
449    \chi   & = & -2 \arcsin\left(\sin\frac{\kappa}{2} \sin\alpha\right) \\
450    \phi   & = & \kappa_\phi + p - \frac{\pi}{2}
451    \end{eqnarray*}
453    where
455    \begin{displaymath}
456    p = \arctan\left(\tan\frac{\kappa}{2} \cos\alpha\right)
457    \end{displaymath}
459    #+CAPTION: $\omega = 0$, $\chi = 0$, $\phi = 0$, 1st solution
460    [[./figures/e2k_1.png]]
462    #+CAPTION: $\omega = 0$, $\chi = 0$, $\phi = 0$, 2nd solution
463    [[./figures/e2k_2.png]]
465    #+CAPTION: $\omega = 0$, $\chi = 90$, $\phi = 0$, 1st solution
466    [[./figures/e2k_3.png]]
468    #+CAPTION: $\omega = 0$, $\chi = 90$, $\phi = 0$, 2nd solution
469    [[./figures/e2k_4.png]]
471 ** Qper and Qpar
472    [[./figures/qper_qpar.png]]
474    this pseudo axis engine compute the perpendicular
475    ($\left|\left|\vec{Q_\text{per}}\right|\right|$) and parallel
476    ($\left|\left|\vec{Q_\text{par}}\right|\right|$) contribution of
477    $\vec{Q}$ relatively to the surface of the sample defined by the
478    $\vec{n}$ vector.
480    \begin{eqnarray*}
481    \vec{q} & = & \vec{k_\text{f}} - \vec{k_\text{i}} \\
482    \vec{q} & = & \vec{q_\text{per}} + \vec{q_\text{par}} \\
483    \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|}
484    \end{eqnarray*}
485 * Diffractometers
486   #+BEGIN_QUOTE
487   *warning*
489   This section is automatically generating by introspecting the hkl library.
490   #+END_QUOTE
492 #+BEGIN_SRC python :exports results :results value raw
493   from gi.repository import Hkl
495   def bold(l):
496       return ["\"*" + _ + "*\"" for _ in l]
498   def level(indent=1, s=None):
499       return "  "*indent + s
501   diffractometers = Hkl.factories().iterkeys()
503   output = ''
504   for diffractometer in sorted(diffractometers):
505       factory = Hkl.factories()[diffractometer]
506       output += "** " + diffractometer + "\n\n"
507       detector = Hkl.Detector.factory_new(Hkl.DetectorType(0))
508       sample = Hkl.Sample.new("toto")
509       geometry = factory.create_new_geometry()
510       engines = factory.create_new_engine_list()
511       engines.init(geometry, detector, sample)
513       output += "*** Axes: \n"
514       for axis in geometry.axis_names_get():
515           axis_v = geometry.axis_get(axis).axis_v_get().data
516           output += level(2, "+ \"*" + axis + "*\": rotation around the *" + repr(axis_v) + "* axis\n")
518       output += "*** Engines: \n"
519       for engine in engines.engines_get():
520           output += "**** \"*" + engine.name_get() + "*\":\n\n"
521           output += level(3, "* pseudo axes:\n")
522           for pseudo in engine.pseudo_axis_names_get():
523               p = engine.pseudo_axis_get(pseudo)
524               description = p.description_get()
525               output += level(4, "* \"*" + pseudo + "*\" : " + description + '\n\n')
526           output += "\n"
527           for mode in engine.modes_names_get():
528               output += level(3, "+ mode: \"*" + mode + "*\"\n")
529               engine.current_mode_set(mode)
530               axes_r = engine.axis_names_get(Hkl.EngineAxisNamesGet.READ)
531               axes_w = engine.axis_names_get(Hkl.EngineAxisNamesGet.WRITE)
532               output += level(4, "+ axes (read) : " + ", ".join(bold(axes_r)) + "\n")
533               output += level(4, "+ axes (write): " + ", ".join(bold(axes_w)) + "\n")
534               parameters = engine.parameters_names_get()
535               output += level(4, "+ parameters: ")
536               if parameters:
537                   output += "\n"
538                   for parameter in parameters:
539                       p = engine.parameter_get(parameter)
540                       description = p.description_get()
541                       value = p.value_get(Hkl.UnitEnum.USER)
542                       output += level(5, "+ *" + parameter + "* [" + str(value) + "]: " + description + "\n")
543               else:
544                   output += "No parameter\n"
546   return output
547 #+END_SRC
548 * Developpement
549 ** Getting hkl
551    To get hkl, you can download the last stable version from sourceforge or
552    if you want the latest development version use
553    [[http://git.or.cz/][git]] or
554    [[http://code.google.com/p/msysgit/downloads/list][msysgit]] on windows
555    system and do:
557    #+BEGIN_SRC sh
558 git clone git://repo.or.cz/hkl.git
559    #+END_SRC
561    or:
563    #+BEGIN_SRC sh
564     git clone http://repo.or.cz/r/hkl.git (slower)
565    #+END_SRC
567    then checkout the next branch like this:
569    #+BEGIN_SRC sh
570     cd hkl
571     git checkout -b next origin/next
572    #+END_SRC
574 ** Building hkl
576    To build hkl you need [[http://www.python.org][Python 2.3+]] the
577    [[http://www.gnu.org/software/gsl/][GNU Scientific Library 1.12]] and
578    [[https://developer.gnome.org/glib/][GLib-2.0 >= 2.3.4]]:
580    #+BEGIN_SRC sh
581     ./configure --disable-gui
582     make
583     sudo make install
584    #+END_SRC
586    you can also build a GUI interfaces which use
587    [[http://www.gtk.org][gtk]]:
589    #+BEGIN_SRC sh
590     ./configure
591     make
592     sudo make install
593    #+END_SRC
595    optionnaly you can build an experimental /libhkl3d/ library (no public
596    API for now) which is used by the GUI to display and compute
597    diffractometer collisions (only the /K6C/ model). To build it you need
598    also [[https://projects.gnome.org/gtkglext/][gtkglext]] and
599    [[http://bulletphysics.org/wordpress/][bullet 2.82]]:
601    #+BEGIN_SRC sh
602     ./configure --enable-hkl3d
603     make
604     sudo make install
605    #+END_SRC
607    if you want to work on the documentation you need the extra
609    - [[http://www.gtk.org/gtk-doc/][gtk-doc]] for the api
610    - [[http://sphinx.pocoo.org/][sphinx]] for the html and latex doc.
611    - [[http://asymptote.sourceforge.net/][asymptote]] for the figures
612    - [[http://www.gnu.org/software/emacs/][emacs]] the well known editor
613    - [[https://github.com/emacsmirror/htmlize][htmlize]] used to highlight the source code
614    - [[http://orgmode.org][org-mode]] litteral programming
616    On Debian/Ubuntu you just need to install
618    #+BEGIN_SRC sh
619     sudo apt-get install emacs dvipng emacs-goodies-el org-mode
620    #+END_SRC
622    #+BEGIN_SRC sh
623     ./configure --enable-gtk-doc
624     make
625     make html
626 #+END_SRC
628    nevertheless if you do not want to build the documentation you can do:
630    #+BEGIN_SRC sh
631    ./configure --disable-hkl-doc
632    #+END_SRC
634 ** Hacking hkl
635 *** Bug reporting
637     You can find the bug tracker here
638     [[https://bugs.debian.org/cgi-bin/pkgreport.cgi?repeatmerged=no&src=hkl][libhkl]]
640 -  Debian/Ubuntu:
642    #+BEGIN_SRC sh
643        reportbug hkl
644    #+END_SRC
646 -  Other OS
648    You just need to send an [[mailto:submit@bugs.debian.org?subject=%20My%20problem%20with%20hkl...&body=Package:%20hkl%0AVersion:%20@VERSION@%0A%0AI%20found%20this%20problem%20in%20hkl][email]]
650 *** Providing patches
652     you can send your patch to [[mailto:picca@synchrotron-soleil.fr][Picca Frédéric-Emmanuel]] using =git=
654     Here a minimalist example of the workflow to prepare and send
655     patches for integration into the hkl library. Suppose you wan to
656     add a new feature, you need first to create a new branch from the
657     =next= one:
659     #+BEGIN_SRC sh
660     git checkout -b my-next next
661     #+END_SRC
663     hack, hack:
665     #+BEGIN_SRC sh
666     git commit -a
667     #+END_SRC
669     more hacks:
671     #+BEGIN_SRC sh
672     git commit -a
673     #+END_SRC
675     now that your new feature is ready, you can send by email your
676     work using =git format-patch= for review:
678     #+BEGIN_SRC sh
679     git format-patch origin/next
680     #+END_SRC
682     which will generate a bunch of ~0001\_xxx~, ~0002\_xxx~,
683     ... patches
685     Then you can configure =git send-email= in order to send the
686     patches for review.
688     #+BEGIN_SRC sh
689     git config sendemail.to "picca@synchrotron-soleil.fr"
690     #+END_SRC
692     and send then with this command:
694     #+BEGIN_SRC sh
695     git send-email 0001-xxx.patch, 0002-xxx.patch, ...
696     #+END_SRC
698     If it does not work you can use your usually email software and
699     send these generated patches to the [[mailto:picca@synchrotron-soleil.fr][author]].
701 ** Howto's
702 *** Add a diffractometer
703     To add a new diffractometer, you just need to copy the
704     ~hkl/hkl-engine-template.c~ into
705     ~hkl/hkl-engine-INSTITUT-BEAMLINE-INSTRUMENT.c~ where you replace
706     the upper case with the appropriate values.
708     The template file is compiled during the build process to ensure
709     that it is always valid.
711     Then you just need to follow the instruction found in the
712     template. If you need some precision about the process, do not
713     hesitate to contact the main author.
715     do not forgot also to add this new file into ~hkl/Makefile.am~
716     with other diffractometers in the hkl_c_sources variable (please
717     keep the alphabetic order).
718 *** Work on the documentation
719     The documentation system is written with [[http://orgmode.org/][org-mode]], and the [[http://orgmode.org/worg/org-contrib/babel/][babel]]
720     extension which allow to introspect the library and generate part
721     of the doc using the hkl library. Python code is executed during
722     the build process to generate the Diffractometer section of the
723     documentation. To work on the doc and test the embedded python
724     code it is necessary to setup a few environment variables and
725     start emacs with the right LD_LIBRARY_PATH. In order to simplify
726     the process a make target was written. You just need to type:
727     #+BEGIN_SRC sh
728       cd Documentation
729       make doc-edit
730     #+END_SRC
731     and start to contribute.
733     If you do not have emacs, you can nevertheless contribute by
734     editing the ~Documentation/hkl.org.in~ file which is text only.
736     The most expected contributions are for now:
737     * english correctness
738     * a nicer css
739 * Bindings
741   The hkl library use the gobject-introspection to provide automatic
742   binding for a few languages.
744 ** Python
746    You can test the binding directly from the source directory with
747    these commandes if ipython is installed.
749     #+BEGIN_SRC sh
750       cd tests/bindings
751       make ipython
752     #+END_SRC
754    then you have the Hkl module preloaded into the ipython environment.
756    hkl computation:
758    has you can see there is 4 available solutions.
760    let's compute an hkl trajectory and select the first solution.
762    if we look at the 3 other solutions we can see that there is a problem
763    of continuity at the begining of the trajectory.
765    hey what's happend with theses solutions ! let's look closely to real
766    numbers. the last column is the distance to the diffractometer current
767    position. This distance is for now express like this:
769    $\sum_{axes} \left|\text{current position} - \text{target position}\right|$
771    #+BEGIN_EXAMPLE
772     [0.0, 119.99999999999999, 0.0, -90.0, 0.0, 59.99999999999999] 0.0
773     [0.0, -119.99999999999999, 0.0, -90.0, 0.0, -59.99999999999999] 6.28318530718
774     [0.0, -60.00000000000005, 0.0, 90.0, 0.0, 59.99999999999999] 6.28318530718
775     [0.0, 60.00000000000001, 0.0, 90.0, 0.0, -59.99999999999999] 6.28318530718
777     [0.0, 117.7665607657826, 7.456826294401656, -92.39856410531434, 0.0, 60.33024982425957] 0.216753826612
778     [0.0, -57.436310940366894, -7.456826294401656, 92.39856418853617, 0.0, 60.33024982425957] 6.41621345188
779     [0.0, 62.2334392342174, -7.456826294401656, 92.39856410531434, 0.0, -60.33024982425957] 6.42197739723
780     [0.0, -122.5636890596331, 7.456826294401656, -92.3985641885362, 0.0, -60.33024982425957] 6.50570308205
782     [0.0, 115.89125602137928, 14.781064139466098, -94.7660423112577, 0.0, 61.314597086440706] 0.219062698235
783     [0.0, -125.42334103772737, 14.781064139466098, -94.7660427050904, 0.0, -61.314597086440706] 6.53671995288
784     [0.0, -54.57665896227262, -14.781064139466098, 94.76604270509038, 0.0, 61.314597086440706] 6.67989976726
785     [0.0, 64.10874397862072, -14.781064139466098, 94.7660423112577, 0.0, -61.314597086440706] 6.71437170098
787     [0.0, 114.39338605351007, 21.85448296702796, -97.074145033719, 0.0, 62.93506298693471] 0.218163667981
788     [0.0, -128.54167683157993, 21.85448296702796, -97.07414574435087, 0.0, -62.93506298693471] 6.59846359365
789     [0.0, -51.45832316842005, -21.85448296702796, 97.07414574435087, 0.0, 62.93506298693471] 6.93673746356
790     [0.0, 65.60661394648993, -21.85448296702796, 97.074145033719, 0.0, -62.93506298693471] 7.03385205725
792     [0.0, 113.28316795475283, 28.583837575232764, -99.29953499008337, 0.0, 65.16540747008955] 0.21459359225
793     [0.0, -131.88223933078322, 28.583837575232764, -99.29953638594702, 0.0, -65.16540747008955] 6.69038531388
794     [0.0, -48.11776066921677, -28.583837575232764, 99.29953638594702, 0.0, 65.16540747008955] 7.18296350386
795     [0.0, 66.71683204524717, -28.583837575232764, 99.29953499008337, 0.0, -65.16540747008955] 7.37556986959
797     [0.0, 112.56286877075006, 34.90573305321372, -101.42496979586187, 0.0, 67.97568017857415] 0.209053830457
798     [0.0, -135.4128111996365, 34.90573305321372, -101.42497263302461, 0.0, -67.97568017857415] 6.81174779784
799     [0.0, -44.58718880036348, -34.90573305321372, 101.4249726330246, 0.0, 67.97568017857415] 7.41581162393
800     [0.0, 67.43713122924994, -34.90573305321372, 101.42496979586187, 0.0, -67.97568017857415] 7.7353201851
802     [0.0, 112.2291126083182, 40.78594007247402, -103.43941832567457, 0.0, 71.33706722449408] 0.202280147961
803     [0.0, -139.10795451001587, 40.78594007247402, -103.43942357602316, 0.0, -71.33706722449408] 6.96173845391
804     [0.0, -40.89204548998411, -40.78594007247402, 103.43942357602312, 0.0, 71.33706722449408] 7.63358787543
805     [0.0, 67.7708873916818, -40.78594007247402, 103.43941832567457, 0.0, -71.33706722449408] 8.10986069093
807     [0.0, 112.27578927291766, 46.214916130901734, -105.33741042812996, 0.0, 75.22640762217479] 0.196576175748
808     [0.0, -142.95061850160724, 46.214916130901734, -105.3374188005596, 0.0, -75.22640762217479] 7.13962155618
809     [0.0, -37.04938149839278, -46.214916130901734, 105.33741880055959, 0.0, 75.22640762217479] 7.83557762281
810     [0.0, 67.72421072708234, -46.214916130901734, 105.33741042812996, 0.0, -75.22640762217479] 8.49706672677
812     [0.0, 112.697137434232, 51.201667684695856, -107.11797492933192, 0.0, 79.63023536264535] 0.202327153157
813     [0.0, -146.9330984641471, 51.201667684695856, -107.11798610058318, 0.0, -79.63023536264535] 7.34491897177
814     [0.0, -33.0669015358529, -51.201667684695856, 107.11798610058317, 0.0, 79.63023536264535] 8.02185610877
815     [0.0, 67.30286256576798, -51.201667684695856, 107.11797492933192, 0.0, -79.63023536264535] 8.89597005568
817     [0.0, 113.49085964586432, 55.76762791023837, -108.78347437395287, 0.0, 84.54867879242364] 0.208455586312
818     [0.0, -151.05782007465257, 55.76762791023837, -108.78348605483542, 0.0, -84.54867879242364] 7.57761473366
819     [0.0, -28.942179925347414, -55.76762791023837, 108.78348605483538, 0.0, 84.54867879242364] 8.19307323084
820     [0.0, 66.50914035413568, -55.76762791023837, 108.78347437395287, 0.0, -84.54867879242364] 9.30675279514
822     [0.0, 114.6614608037443, 59.941489465646214, -110.3385360479293, 0.0, 90.00000081324956] 0.215562935229
823     [0.0, -155.33854118146962, 59.941489465646214, -110.33854432979601, 0.0, -89.99999918675044] 7.83839602383
824     [0.0, -24.661458818530395, -59.941489465646214, 110.33854432979601, 0.0, 90.00000081324956] 8.3502621071
825     [0.0, 65.3385391962557, -59.941489465646214, 110.3385360479293, 0.0, -89.99999918675044] 9.7307712883
826    #+END_EXAMPLE
828    as you can see for the first point of the trajectory, the 2nd, 3rd and
829    4th solutions have identical distances to the current position of the
830    diffractometer so they are un-ordered:
832    #+BEGIN_EXAMPLE
833     [0.0, 119.99999999999999, 0.0, -90.0, 0.0, 59.99999999999999] 0.0
834     [0.0, -119.99999999999999, 0.0, -90.0, 0.0, -59.99999999999999] 6.28318530718
835     [0.0, -60.00000000000005, 0.0, 90.0, 0.0, 59.99999999999999] 6.28318530718
836     [0.0, 60.00000000000001, 0.0, 90.0, 0.0, -59.99999999999999] 6.28318530718
837    #+END_EXAMPLE
839    then the problem arise with the second and third solution. you can see a
840    sort of reorganisation of the solution. 2 -> 3, 3 -> 4 and 4 -> 2 then
841    the order will stick unchanged until the end of the trajectory. this is
842    because the distance is computed relatively to the current position of
843    the diffractometer.:
845    #+BEGIN_EXAMPLE
846     [0.0, 117.7665607657826, 7.456826294401656, -92.39856410531434, 0.0, 60.33024982425957] 0.216753826612
847     [0.0, -57.436310940366894, -7.456826294401656, 92.39856418853617, 0.0, 60.33024982425957] 6.41621345188
848     [0.0, 62.2334392342174, -7.456826294401656, 92.39856410531434, 0.0, -60.33024982425957] 6.42197739723
849     [0.0, -122.5636890596331, 7.456826294401656, -92.3985641885362, 0.0, -60.33024982425957] 6.50570308205
851     [0.0, 115.89125602137928, 14.781064139466098, -94.7660423112577, 0.0, 61.314597086440706] 0.219062698235
852     [0.0, -125.42334103772737, 14.781064139466098, -94.7660427050904, 0.0, -61.314597086440706] 6.53671995288
853     [0.0, -54.57665896227262, -14.781064139466098, 94.76604270509038, 0.0, 61.314597086440706] 6.67989976726
854     [0.0, 64.10874397862072, -14.781064139466098, 94.7660423112577, 0.0, -61.314597086440706] 6.71437170098
855    #+END_EXAMPLE
857    #+BEGIN_QUOTE
858    *warning*
860    when you compute a trajectory, start from a valid position (the
861    starting point must be the real first point of your trajectory) then
862    use only the closest solution for the next points of the trajectory.
863    (first solution of the geometries list)
864    #+END_QUOTE
865 * Releases
866 ** @VERSION@
867 ** 5.0.0.2080 <2016-04-27 mer.>
868 *** DONE =HklEngine= <2016-01-20 mer.>
869     emergence_fixed for the SOLEIL SIX MED 2+2 geometry.
870 *** DONE =HklVector= <2016-02-09 mar.>
871     The hkl_vector_init method is now public.
872 *** DONE =HklParameter= <2016-02-25 Thu>
873     at the end of the computation all solutions are filtered in order
874     to check that they are valid (min < value < range). BUT for a
875     rotation axis this check was instead (min < value % 2pi < max).
876 *** DONE =HklGeometry= <2016-04-20 mer.>
877     Add hkl_geometry_[sample/detector]_rotation_get method. It is now
878     possible to get the sample or the detector rotation expressed as a
879     =HklQuaternion=.
880 #+BEGIN_SRC python :export code
881   qr = geometry.sample_rotation_get(sample)
882   qd = geometry.detector_rotation_get(detector)
883 #+END_SRC
884 *** DONE =HklQuaternion= <2016-04-20 mer.>
885     Add hkl_quaternion_to_matrix in order to convert a =HklQuaternion=
886     into a =HklMatrix=. Then you just need to convert this HklMatrix
887     into a numpy array when used from the python binding
888 #+BEGIN_SRC python :export code
889   def hkl_matrix_to_numpy(m):
890       M = empty((3, 3))
891       for i in range(3):
892           for j in range(3):
893               M[i, j] = m.get(i, j)
894       return M
895   
896   
897   M = hkl_matrix_to_numpy(q.to_matrix())
898 #+END_SRC
899 *** DONE Soleil Sirius Turret <2016-04-26 mar.>
900     Add the =basepitch= axis which rotate around $\vec{y}$ in mrad.
901 ** 4.99.99.1955 <2015-07-15 mer.>
902    Add the ccan_config.h public header. This header is generated with
903    the ccan configurator program.
904 ** 4.99.99.1950 <2015-07-07 mar.>
905    Fix an FTBFS observed on the sparc arch
906 ** 4.99.99.1949 <2015-07-03 ven.>
907 *** DONE =HklInterval= <2015-07-03 ven.>
908     =hkl_interval_cmp= was wrong. Now the comparison is done between
909     =HKL_EPSILON= and the distance between minimum and maximum. This
910     problem was triggered first on ppc64el architecture.
911 *** DONE PATH_MAX <2015-07-03 ven.>
912     Replace getcwd called by get_current_dir_path instead in order to
913     avoid PATH_MAX which is not available on hurd.
914 ** 4.99.99.1946 <2015-06-30 mar.>
915 *** DONE =HklEngine=
916 **** "emergence" <2015-06-22 lun.>
917      Add a new emergence engine which contain only one pseudo axis.
918      + =emergence= the outgoing beam emergence from the sample's surface.
919      + =azimuth= the sample's surface azimuth.
920 ** 4.99.99.1940 <2015-05-04 lun.>
921 *** DONE =HklLattice= add an =hkl_lattice_volume_get=
922 #+BEGIN_SRC c
923   volume = hkl_lattice_volume_get(lattice);
924 #+END_SRC
925 *** DONE =HklEngine=
926 **** "nrj, sample, ...  dependencies" <2015-03-24 mar.>
927      Add the =hkl_engine_dependencies_get= method which return if the
928      =HklEngine= depends of the axes, the energy, or the sample. the
929      possible values are stored in the =HklEngineDependencies= enum.
931 #+BEGIN_SRC c
932   dependencies = hkl_engine_dependencies_get(engine);
933   if (dependencies & HKL_ENGINE_DEPENDENCIES_ENERGY) {
934           ...
935   }
936   if (dependencies & HKL_ENGINE_DEPENDENCIES_SAMPLE) {
937           ...
938   }
939   ...
940 #+END_SRC
941 **** "tth2" <2015-04-03 ven>
942      Add a new hkl engine which contain two pseudo axes.
943      + =tth=  two times the diffraction angle $\theta$
944      + =alpha= the azimuth of q in the zOy plan.
945 **** "incidence" <2015-04-21 mar.>
946      Add a new incidence engine which contain only one pseudo axis.
947      + =incidence= the incoming beam incidence on the sample surface.
948      + =azimuth= the sample surface azimuth.
949 **** =hkl_engine_parameter_set= <2015-05-04 lun.>
950      Fix a bug and expose the method in the binding.
951 **** general
952      - use #define AXIS "axis_name" in all the code to set the axes
953        names at only one place. <2015-04-23 jeu.>
954 *** DONE =HklLattice= expose in the binding the _x_get/set methods <2015-03-24 mar.>
955     Now you can use hkl_lattice_x_get where x=a, b, c, alpha, beta,
956     gamma in the bindings.
957 #+BEGIN_SRC python :export code
958   a = lattice.a_get()
959   lattice.a_set(a)
960 #+END_SRC
961 *** DONE =HklSampleReflection= expose the flag_get/set and geometry_get/set method <2015-03-24 mar.>
962     It is now possible to change the geometry stored in a reflection
963     via the bindings.
964 #+BEGIN_SRC python :export code
965   flag = reflection.flag_get()
966   reflection.flag_set(flag)
968   geometry = reflection.geometry_get()
969   geometry.axes_values_set([omega, chi, phi, ...])
970   reflection.geometry_set(geometry)
971 #+END_SRC
972 * Todo
973 ** hkl
974 *** TODO [#A] =HklEngine= *q/q2*
975     Fix all these engines... This engine takes into account only the
976     *gamma* and *delta* axes.  so diffractometers with 3 axes for the
977     detector are wrong.  It would be nice to take into account all the
978     detector holder AND the position of the detecteor on the
979     diffractometer arms (for now the detector is always on the last
980     axis).
981 *** TODO [#A] HklSource
982     Create a parameter for the wavelength. This is just internally for
983     the futur trajectory system, so no need to change the signature of
984     hkl_geometry_vawelength get/set
985 *** TODO [0/2] PetraIII
986 **** TODO computation problem
987      Dear Teresa,
989      Using the prruptest.txt ubmatrix I see that the value of psi is
990      offset by 45 degrees. I expect it to be 0 degrees when azimuth
991      reference vector is 0 0 1 that is along the beam. See below
992      thereturned numbers. This might have to do with the definition of
993      the beam axis in the controller.  Otherwise now when I change
994      reference vector by 90 degrees the computed value is changed by
995      90 degrees. That is a progress. Can you contact Frederic and ask
996      him about this ?
998      Best regards,
1000      Sonia
1002      See below
1003      p09/door/haspp09.01 [9]: setaz 1 0 0
1005      p09/door/haspp09.01 [10]: wh
1007      Engine: hkl
1009      Mode: psi_constant_vertical
1011      H K L =    0.00000   3.00605  -0.00000
1012      Ref   =    1.00000   0.00000   0.00000
1013      Azimuth (Psi - calculated) =  -45.00005
1014      Azimuth (Psi - set) =  0.00000
1015      Wavelength =  2.07957
1017      Delta       Theta          Chi         Phi         Mu       Gamma
1018      45.77575    22.88783     90.00000   182.85400    0.00000    -0.00000
1020      p09/door/haspp09.01 [11]: setaz 0 0 1
1022      p09/door/haspp09.01 [12]: wh
1024      Engine: hkl
1026      Mode: psi_constant_vertical
1028      H K L =    0.00000   3.00605  -0.00000
1029      Ref   =    0.00000   0.00000   1.00000
1030      Azimuth (Psi - calculated) =  -135.00005
1031      Azimuth (Psi - set) =  0.00000
1032      Wavelength =  2.07957
1034      Delta       Theta          Chi         Phi         Mu       Gamma
1035      45.77575    22.88783     90.00000   182.85400    0.00000    -0.00000
1037      where:
1039      Azimuth (Psi - calculated) is the value of the pseudomotor psi.
1040      Azimuth (Psi - set) is the value set in the parameter psi of the current mode.
1042    Hi Frederic,
1044    This is the UB matrix:
1046    Best regards,
1048    Sonia
1050    Created at 2015-01-21 12:35
1052    Crystal    prruptest
1054    Wavelength 2.07957463938
1056    A 8.03656 B 8.03656 C 8.03656
1057    Alpha 90.0 Beta 90.0 Gamma 90.0
1059    R0 0 0.0 1.0 0.0 0 1 0.0 14.8979 90.0 182.854 0.0 29.7959
1060    R1 1 1.0 0.0 1.0 0 1 0.0 14.8979 0.0 182.854 0.0 29.7959
1062    Mode psi_constant_vertical
1064    PsiRef 0.0 0.0 1.0
1066    U00 -0.580 U01 0.000 U02 0.525
1067    U10 0.000 U11 0.782 U12 -0.000
1068    U20 -0.525 U21 -0.000 U22 -0.580
1070    Ux 179.999952315 Uy 42.14605 Uz -179.999932647
1072    SaveDirectory /home/p09user/crystals/
1074 **** TODO another question
1075      J'ai un probleme avec la position que le controlleur calcule avec la
1076      matrice UB que nous t'avons envoye.
1077      See sequence of emails echanges avec Teresa.
1079      >>>> I am at 0 3.00605 0 with phi -182 and psi calculated is -135
1080      >>>> When I freeze psi at -135  and type ca 0 3.00605 0 the controller
1081      >> should return to me the positions at which I am. But no he tells me
1082      that I
1083      >> have to go to 178 degrees in  phi that is turning by 360 degrees.
1085      Est-ce un probleme avec la trajectoire selectionnee ?
1086      Est-ce qu'il est possible de definir des cut-points comme dans spec avec
1087      ta librairie ?
1088 *** TODO [2/4] HklParameter
1089     - [X] method to use min/max to check for the validity
1090     - [X] add a method to get the axis_v and quaternion of the HklAxis
1091       this method will return NULL if this is not relevant.
1092       hkl_parameter_axis_v_get and hkl_parameter_quaternion_get
1093     - [ ] degenerated an axis is degenerated if its position have no
1094       effect on the HklPseudoAxis calculus. Add a degenerated member
1095       to the axis. that way it would be possible to check a posteriori
1096       for this degenerescencence.
1097     - [ ] Add a description for each parameters.
1098 *** TODO This will help for the documentation and the gui.
1099 *** TODO HklGeometryList different method to help select a solution.
1100     this select solution can depend on the geometry
1101     for example the kappa axis must be in one side of the plane.
1102 *** TODO add a fit on the Hklaxis offsets.
1103 *** TODO API to put a detector and a sample on the Geometry.
1104 *** TODO HklSample
1105 **** TODO [#B] unit test: hkl_sample_affine.
1106      Check this:
1107      lattice=1.540000;1.540000;1.540000;90.000000;90.000000;90.000000;0;0;0;0;0;0
1108      uxuyuz=0.000000;0.000000;0.000000
1109      reflection=1.540000;0.159010;1.256718;0.796660;1;0.000000;0.000000;0.000000;0.000000;0.000000
1110      reflection=1.540000;0.206208;0.342357;-0.080346;1;0.000000;0.000000;0.000000;0.000000;0.000000
1111      reflection=1.540000;0.206208;0.342357;-0.080346;1;0.000000;0.000000;0.000000;0.000000;0.000000
1113      A,  B, C, Alpha,  Beta, Gamma, Ux, Uy, Uy:
1114      17764892.133, 5793679.092, 15733785.198,  179.997,  179.999,452408725.23,  -575727594.04,  -1913661011.01 (affine) 1rst finetness
1116      all the reflections are non collinear the affine method should
1117      warn the user about this.
1118 *** TODO HklEngine "zone"
1119 *** TODO HklEngine "custom"
1120     for now this pseudoaxis let you select the axis you
1121     want to use for the computation.
1122 *** TODO HklEngine "q/q2" add a "reflectivity" mode
1123     This mode should have the surface as parameters and the incident
1124     angle is equal to the emergence angle.
1125 *** TODO create a macro to help compare two real the right way
1126     fabs(a-b) < epsilon * max(1, abs(a), abs(b))
1127 *** TODO add an hkl_sample_set_lattice_unit()
1128 *** TODO SOLEIL SIXS
1129 **** DONE find the right solutions.                                   :zaxis:
1130      The cosinus and sinus properties are not enough to find the solution expected by the users.
1131      The idea is to use the Ewalds construction to generate a valid solution from the first one
1132      obtain numerically. The basic idea is to rotate the hkl vector around the last axis of the
1133      sample holder until it intersect again the Ewalds sphere. Then we just need to fit the
1134      detector position. This way the solution can be entirely generic (not geometry specific).
1135      Nevertheless it is necessary to propose this only for the hkl pseudo axes. I will add this
1136      special feature in the Mode. So it will be possible to add thoses special cases easily.
1137 **** TODO Add the DEP diffractometer geometry
1138      This diffractometer is a Newport one based on the kappa 6 circles ones.
1139      But instead of a kappa head, they use an Hexapod head.
1140      This head can be put horizontally or vertically.
1141 *** TODO generalisation of the z-axis hkl solver
1142     first we need the degenerated member of the Axis. thaht way it could be possible
1143     to find the last non degenerated axis for the detector fit.
1144 *** TODO investigate the prigo geometry.
1145 *** TODO augeas/elektra for the plugin configure part.
1146 *** TODO logging
1147 **** TODO [1/2] add in a few methods.
1148      + [X] hkl_pseudo_axes_values_set
1149      + [ ] hkl_sample_affine
1150 **** TODO gir logging
1151      It would be nice to generate the library logging using the .gir
1152      information. So instead of writing the logging code for each
1153      method, it would be better to have a generic method for this
1154      purpose.
1155 **** TODO parsable logging information.
1156      A parsable logging format would help to setup some re-play unit
1157      test. This way it could help during the developpement process
1158      (modification of the hkl internals) to be confident that
1159      computation are ok.
1160 *** TODO performances
1161     + Investigate [[http://liboil.freedesktop.org/wiki/][liboil]] to speed calculation (in HklVector, HklMatrix
1162       and HklQuaternion)
1163     + Avoid to call =hkl_engine_prepare_internal= at each computation.
1164 ** documentation
1165 *** TODO [1/6] rewrite documentation in org-mode
1166     - [-] embedding code into the org file
1167       - [-] [1/4] python
1168         - [X] auto generation of the diffractometer descriptions
1169         - [ ] trajectories explanations
1170         - [ ] trajectories tests.
1171         - [ ] unit tests output ?
1172       - [ ] asymptote
1173     - [X] need to check if templates could be generated using the hkl
1174       python binding for all diffractometer geometries.
1175     - [ ] need to add a description for the diffractometer, the mode, the parameters.
1176     - [ ] need a nice css for the generated doc.
1177     - [ ] check if org-info.js could be usefull
1178     - [ ] add documentation explaining the sector-cuts a la hkl
1179 ** [0/3] gui
1180    - [ ] change the color of fitparameter cells if they differ from
1181      the current sample values
1182    - [ ] check if a [[https://github.com/jonathanslenders/python-prompt-toolkit/tree/master/examples/tutorial][REPL]] could be integrated to provide an autocad
1183       like interface.
1184    - [ ] add tooltips using hkl_parameter_description_get for the
1185      pseudo axes and the mode parameters.
1186 ** hkl3d
1187 *** TODO add a method to find the 3D models in the right directories.
1189 ** packaging
1190 *** TODO add a .spec file for rpm generation.