Welcome to hkl's 5.0.0.3367 documentation!

Table of Contents

1. Introduction

The purpose of the library is to factorize single crystal diffraction angles computation for different kind of diffractometer geometries. It is used at the SOLEIL, Desy and Alba synchrotron with the Tango control system to pilot diffractometers.

1.1. Features

  • mode computation (aka PseudoAxis)
  • item for different diffractometer geometries.
  • UB matrix computation.
    • busing & Levy with 2 reflections
    • simplex computation with more than 2 reflections using the GSL library.
    • Eulerians angles to pre-orientate your sample.
  • Crystal lattice refinement
    • with more than 2 reflections you can select which parameter must be fitted.
  • Pseudoaxes
    • psi, eulerians, q, …

1.2. Conventions

In all this document the next convention will be used to describe the diffractometers geometries.

  • right handed convention for all the angles.
  • direct space orthogonal base.
  • description of the diffractometer geometries is done with all axes values set to zero.

1.3. Diffraction

1.3.1. the crystal

A periodic crystal is the association of a pattern and a lattice. The pattern is located at each points of the lattice node. Positions of those nodes are given by:

\[ R_{uvw}=u\cdot\vec{a}+v\cdot\vec{b}+w\cdot\vec{c} \]

\(\vec{a}\), \(\vec{b}\), \(\vec{c}\) are the former vector of a base of the space. u, v, w are integers. The pattern contain atoms associated to each lattice node. the purpose of diffraction is to study the interaction of this crystal (pattern+lattice) with X-rays.

crystal.png

Figure 1: Crystal direct lattice.

this lattice is defined by \(\vec{a}\), \(\vec{b}\), \(\vec{c}\) vectors, and the angles \(\alpha\), \(\beta\), \(\gamma\). In general cases this lattice is not orthonormal.

Nevertheless to compute the interaction of this real space lattice and the X-Rays, it is convenient to define another lattice called reciprocal lattice defined like this:

\begin{eqnarray*} \vec{a}^{\star} & = & \tau\frac{\vec{b}\wedge\vec{c}}{\vec{a}\cdot(\vec{b}\wedge\vec{c})}\\ \vec{b}^{\star} & = & \tau\frac{\vec{c}\wedge\vec{a}}{\vec{b}\cdot(\vec{c}\wedge\vec{a})}\\ \vec{c}^{\star} & = & \tau\frac{\vec{a}\wedge\vec{b}}{\vec{c}\cdot(\vec{a}\wedge\vec{b})} \end{eqnarray*}

\(\tau=2\pi\) or \(\tau=1\) depending on the conventions.

It is then possible to define theses orthogonal properties:

\begin{eqnarray*} \vec{a}^{\star}\cdot\vec{a}=\tau & \vec{b}^{\star}\cdot\vec{a}=0 & \vec{c}^{\star}\cdot\vec{a}=0\\ \vec{a}^{\star}\cdot\vec{b}=0 & \vec{b}^{\star}\cdot\vec{b}=\tau & \vec{c}^{\star}\cdot\vec{b}=0\\ \vec{a}^{\star}\cdot\vec{c}=0 & \vec{b}^{\star}\cdot\vec{c}=0 & \vec{c}^{\star}\cdot\vec{c}=\tau \end{eqnarray*}

This reciprocal space lattice allow to write in a simpler form the interaction between the crystal and the X-Rays. We often only know about \(\vec{a}\), \(\vec{b}\), \(\vec{c}\) vectors and the angles \(\alpha\), \(\beta\), \(\gamma\). Using the previous equations reciprocal, we can compute the reciprocal lattice this way:

\begin{eqnarray*} a^{\star} & = & \frac{\sin\alpha}{aD}\\ b^{\star} & = & \frac{\sin\beta}{bD}\\ c^{\star} & = & \frac{\sin\gamma}{cD} \end{eqnarray*}

where

\[ D=\sqrt{1-\cos^{2}\alpha-\cos^{2}\beta-\cos^{2}\gamma+2\cos\alpha\cos\beta\cos\gamma} \]

To compute the angles between the reciprocal space vectors, it is once again possible to use the previous equations reciprocal to obtain the sines and cosines of the angles \(\alpha^\star\), \(\beta^\star\) and \(\gamma^\star\):

\begin{eqnarray*} \cos\alpha^{\star}=\frac{\cos\beta\cos\gamma-\cos\alpha}{\sin\beta\sin\gamma} & \, & \sin\alpha^{\star}=\frac{D}{\sin\beta\sin\gamma} \\ \cos\beta^{\star}=\frac{\cos\gamma\cos\alpha-\cos\beta}{\sin\gamma\sin\alpha} & \, & \sin\beta^{\star}=\frac{D}{\sin\gamma\sin\alpha}\\ \cos\gamma^{\star}=\frac{\cos\alpha\cos\beta-\cos\gamma}{\sin\alpha\sin\beta} & \, & \sin\gamma^{\star}=\frac{D}{\sin\alpha\sin\beta} \end{eqnarray*}

the volume of the lattice can be compute this way:

\[ V = abcD \]

or

\[ 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}) \]

1.3.2. Diffraction

Let the incoming X-rays beam whose wave vector is \(\vec{k_{i}}\), \(|k_{i}|=\tau/\lambda\) where \(\lambda\) is the wavelength of the signal. The \(\vec{k_{d}}\) vector wavelength of the diffracted beam. There is diffusion if the diffusion vector \(\vec{q}\) can be expressed as follows:

\[ \vec{q}=\vec{k_{d}}-\vec{k_{i}}=h.\vec{a}^{*}+k.\vec{b}^{*}+l.\vec{c}^{*} \]

where \((h,k,l)\in\mathbb{N}^{3}\) and \((h,k,l)\neq(0,0,0)\). Theses indices \((h,k,l)\) are named Miller indices.

Another way of looking at things has been given by Bragg and that famous relationship:

\[ n\lambda=2d\sin\theta \]

where \(d\) is the inter-plan distance and \(n \in \mathbb{N}\).

The diffusion occurs for an unique \(\theta\) angle. Then we got \(\vec{q}\) perpendicular to the diffraction plan.

The Ewald construction allow to represent this diffraction in the reciprocal space.

1.3.3. Quaternions

  1. Properties

    The quaternions will be used to describe the diffractometers geometries. Theses quaternions can represent 3D rotations. There is different way to describe then like complex numbers.

    \[ q=a+bi+cj+dk \]

    or

    \[ q=[a,\vec{v}] \]

    To compute the quaternion's norm, we can proceed like for complex numbers

    \[ \|q\|=\sqrt{a²+b²+c²+d²} \]

    Its conjugate is :

    \[ q^{*}=[a,-\vec{u}]=a-bi-cj-dk \]

  2. Operations

    The difference with the complex number algebra is about non-commutativity.

    \[ qp \neq pq \]

    \[

    \begin{bmatrix} ~ & 1 & i & j & k \cr 1 & 1 & i & j & k \cr i & i & -1 & k & -j \cr j & j & -k & -1 & i \cr k & k & j & -i & -1 \end{bmatrix}

    \]

    The product of two quaternions can be express by the Grassman product Grassman product. So for two quaternions \(p\) and \(q\):

    \begin{align*} q &= a+\vec{u} = a+bi+cj+dk\\ p &= t+\vec{v} = t+xi+yj+zk \end{align*}

    we got

    \[ pq = at - \vec{u} \cdot \vec{v} + a \vec{v} + t \vec{u} + \vec{v} \times \vec{u} \]

    or equivalent

    \[ pq = (at - bx - cy - dz) + (bt + ax + cz - dy) i + (ct + ay + dx - bz) j + (dt + az + by - cx) k \]

  3. 3D rotations

    L'ensemble des quaternions unitaires (leur norme est égale à 1) est le groupe qui représente les rotations dans l'espace 3D. Si on a un vecteur unitaire \(\vec{u}\) et un angle de rotation \(\theta\) alors le quaternion \([\cos\frac{\theta}{2},\sin\frac{\theta}{2}\vec{u]}\) représente la rotation de \(\theta\) autour de l'axe \(\vec{u}\) dans le sens trigonométrique. Nous allons donc utiliser ces quaternions unitaires pour représenter les mouvements du diffractomètre.

    Alors que dans le plan 2D une simple multiplication entre un nombre complex et le nombre \(e^{i\theta}\) permet de calculer simplement la rotation d'angle \(\theta\) autour de l'origine, dans l'espace 3D l'expression équivalente est:

    \[ z'=qzq^{-1} \]

    où \(q\) est le quaternion de norme 1 représentant la rotation dans l'espace et \(z\) le quaternion représentant le vecteur qui subit la rotation (sa partie réelle est nulle).

    Dans le cas des quaternions de norme 1, il est très facile de calculer \(q^{-1}\). En effet l'inverse d'une rotation d'angle \(\theta\) est la rotation d'angle \(-\theta\). On a donc directement:

    \[ q^{-1}=[\cos\frac{-\theta}{2},\sin\frac{-\theta}{2}\vec{u}]=[\cos\frac{\theta}{2},-\sin\frac{\theta}{2}\vec{u}]=q^{*} \]

    Le passage aux matrices de rotation se fait par la formule suivante \(q\rightarrow M\).

    \[

    \begin{bmatrix} a{{}^2}+b{{}^2}-c{{}^2}-d{{}^2} & 2bc-2ad & 2ac+2bd\\ 2ad+2bc & a{{}^2}-b{{}^2}+c{{}^2}-d{{}^2} & 2cd-2ab\\ 2bd-2ac & 2ab+2cd & a{{}^2}-b{{}^2}-c{{}^2}+d{{}^2} \end{bmatrix}

    \]

    La composition de rotation se fait simplement en multipliant les quaternions entre eux. Si l'on à \(q\)

1.4. Modes de fonctionnement

1.5. Equations fondamentales

Le problème que nous devons résoudre est de calculer pour une famille de plan \((h,k,l)\) donné, les angles de rotation du diffractomètre qui permettent de le mettre en condition de diffraction. Il faut donc exprimer les relations mathématiques qui lient les différents angles entre eux lorsque la condition de Bragg est vérifiée. L'équation fondamentale est la suivante:

\begin{align*} \left(\prod_{i}S_{i}\right)\cdot U\cdot B\cdot\vec{h} & =\left(\prod_{j}D_{j}-I\right)\cdot\vec{k_{i}}\\ R\cdot U\cdot B\cdot\vec{h} & =\vec{Q} \end{align*}

ou \(\vec{h}\) est le vecteur \((h,k,l)\), \(\vec{k_{i}}\) est le vecteur incident, \(S_{i}\) les matrices de rotations des mouvements liés à l'échantillon, \(D_{j}\) les matrices de rotation des mouvements liés au détecteur, \(I\) la matrice identité, \(U\) la matrice d'orientation du cristal par rapport au repère de l'axe sur lequel ce dernier est monté et \(B\) la matrice de passage d'un repère non orthonormé ( celui du crystal réciproque) à un repère orthonormé.

1.5.1. Calcule de B

Si l'on connaît les paramètres cristallins du cristal étudié, il est très simple de calculer \(B\):

\[ B=

\begin{bmatrix} a^{\star} & b^{\star}\cos\gamma^{\star} & c^{\star}\cos\beta^{\star}\\ 0 & b^{\star}\sin\gamma^{\star} & -c^{\star}\sin\beta^{\star}\cos\alpha\\ 0 & 0 & 1/c \end{bmatrix}

\]

1.5.2. Calcule de U

Il existe plusieurs façons de calculer \(U\). Busing et Levy en a proposé plusieurs. Nous allons présenter celle qui nécessite la mesure de seulement deux réflections ainsi que la connaissance des paramètres cristallins. Cette façon de calculer la matrice d'orientation \(U\), peut être généralisée à n'importe quel diffractomètre pour peu que la description des axes de rotation permette d'obtenir la matrice de rotation de la machine \(R\) et le vecteur de diffusion \(\vec{Q}\).

Il est également possible de calculer \(U\) sans la connaîssance des paramètres cristallins. il faut alors faire un affinement des paramètres. Cela revient à minimiser une fonction. Nous allons utiliser la méthode du simplex pour trouver ce minimum et donc ajuster l'ensemble des paramètres cristallins ainsi que la matrice d'orientation.

1.5.3. Algorithme de Busing Levy

L'idée est de se placer dans le repère de l'axe sur lequel est monté l'échantillon. On mesure deux réflections \((\vec{h}_{1},\vec{h}_{2})\) ainsi que leurs angles associés. Cela nous permet de calculer \(R\) et \(\vec{Q}\) pour chacune de ces reflections. nous avons alors ce système:

\begin{eqnarray*} U\cdot B\cdot\vec{h}_{1} & = & \tilde{R}_{1}\cdot\vec{Q}_{1}\\ U\cdot B\cdot\vec{h}_{2} & = & \tilde{R}_{2}\cdot\vec{Q}_{2} \end{eqnarray*}

De façon à calculer facilement \(U\), il est intéressant de définir deux trièdres orthonormé \(T_{\vec{h}}\) et \(T_{\vec{Q}}\) à partir des vecteurs \((B\vec{h}_{1},B\vec{h}_{2})\) et \((\tilde{R}_{1}\vec{Q}_{1},\tilde{R}_{2}\vec{Q}_{2})\). On a alors très simplement:

\[ U \cdot T_{\vec{h}} = T_{\vec{Q}} \]

Et donc

\[ U = T_{\vec{Q}} \cdot \tilde{T}_{\vec{h}} \]

1.5.4. Affinement par la méthode du simplex

Dans ce cas nous ne connaissons pas la matrice \(B\), il faut donc mesurer plus que deux réflections pour ajuster les 9 paramètres. Six paramètres pour le crystal et trois pour la matrice d'orientation \(U\). Les trois paramètres qui permennt de representer \(U\) sont en fait les angles d'euler. il faut donc être en mesure de passer d'une représentation eulérien à cette matrice :math::U et réciproquement.

\[ U = X \cdot Y \cdot Z \]

où \(X\) est la matrice rotation suivant l'axe Ox et le premier angle d'Euler, \(Y\) la matrice de rotation suivant l'axe Oy et le deuxième angle d'Euler et \(Z\) la matrice du troisième angle d'Euler pour l'axe Oz.

\(X\) \(Y\) \(Z\)
\(\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}\)

et donc:

\[ U=

\begin{bmatrix} CE & -CF & D\\ BDE+AF & -BDF+AE & -BC\\ -ADE+BF & ADF+BE & AC \end{bmatrix}

\]

Il est donc facile de passer des angles d'Euler à la matrice d'orientation.

Il faut maintenant faire la transformation inverse de la matrice \(U\) vers les angles d'euler.

2. PseudoAxes

This section describe the calculations done by the library for the different kind of pseudo axes.

2.1. General process

2.1.1. First Solution

The hkl library use the gsl library in order to find the first valid solution.

2.1.2. Multiplication of the solutions.

Once we have got the first solution different strategies are applyed in order to generate more solutions.

  1. Geometry Multiplication

    For kappa diffractometers, once you have one solution it is possible to générate another one using a property of this geometry. (Left arm and right arm).

2.1.3. Restrains of the Solutions

We apply then some constrains to reduce these solutions to only a bunch of acceptable ones. Usualy we take the axis range into account.

2.2. Eulerians to Kappa angles

1st solution

\begin{eqnarray*} \kappa_\omega & = & \omega - p + \frac{\pi}{2} \\ \kappa & = & 2 \arcsin\left(\frac{\sin\frac{\chi}{2}}{\sin\alpha}\right) \\ \kappa_\phi & = & \phi - p - \frac{\pi}{2} \end{eqnarray*}

or 2nd one

\begin{eqnarray*} \kappa_\omega & = & \omega - p - \frac{\pi}{2} \\ \kappa & = & -2 \arcsin\left(\frac{\sin\frac{\chi}{2}}{\sin\alpha}\right) \\ \kappa_\phi & = & \phi - p + \frac{\pi}{2} \end{eqnarray*}

where

\[ p = \arcsin\left(\frac{\tan\frac{\chi}{2}}{\tan\alpha}\right) \]

and \(\alpha\) is the angle of the kappa axis with the \(\vec{y}\) axis.

2.3. Kappa to Eulerians angles

1st solution

\begin{eqnarray*} \omega & = & \kappa_\omega + p - \frac{\pi}{2} \\ \chi & = & 2 \arcsin\left(\sin\frac{\kappa}{2} \sin\alpha\right) \\ \phi & = & \kappa_\phi + p + \frac{\pi}{2} \end{eqnarray*}

or 2nd one

\begin{eqnarray*} \omega & = & \kappa_\omega + p + \frac{\pi}{2} \\ \chi & = & -2 \arcsin\left(\sin\frac{\kappa}{2} \sin\alpha\right) \\ \phi & = & \kappa_\phi + p - \frac{\pi}{2} \end{eqnarray*}

where

\[ p = \arctan\left(\tan\frac{\kappa}{2} \cos\alpha\right) \]

e2k_1.png

Figure 2: \(\omega = 0\), \(\chi = 0\), \(\phi = 0\), 1st solution

e2k_2.png

Figure 3: \(\omega = 0\), \(\chi = 0\), \(\phi = 0\), 2nd solution

e2k_3.png

Figure 4: \(\omega = 0\), \(\chi = 90\), \(\phi = 0\), 1st solution

e2k_4.png

Figure 5: \(\omega = 0\), \(\chi = 90\), \(\phi = 0\), 2nd solution

2.4. Qper and Qpar

qper_qpar.png

this pseudo axis engine compute the perpendicular (\(\left|\left|\vec{Q_\text{per}}\right|\right|\)) and parallel (\(\left|\left|\vec{Q_\text{par}}\right|\right|\)) contribution of \(\vec{Q}\) relatively to the surface of the sample defined by the \(\vec{n}\) vector.

\begin{eqnarray*} \vec{q} & = & \vec{k_\text{f}} - \vec{k_\text{i}} \\ \vec{q} & = & \vec{q_\text{per}} + \vec{q_\text{par}} \\ \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|} \end{eqnarray*}

3. Diffractometers

warning

This section is automatically generating by introspecting the hkl library.

4. Developpement

4.1. Getting hkl

To get hkl, you can download the last stable version from sourceforge or if you want the latest development version use git or msysgit on windows system and do:

git clone git://repo.or.cz/hkl.git

or:

git clone http://repo.or.cz/r/hkl.git (slower)

then checkout the next branch like this:

cd hkl
git checkout -b next origin/next

4.2. Building hkl

To build hkl you need Python 2.3+ the GNU Scientific Library 1.12 and GLib-2.0 >= 2.3.4:

./configure --disable-gui
make
sudo make install

you can also build a GUI interfaces which use gtk:

./configure
make
sudo make install

optionnaly you can build an experimental libhkl3d library (no public API for now) which is used by the GUI to display and compute diffractometer collisions (only the K6C model). To build it you need also gtkglext and bullet 2.82:

./configure --enable-hkl3d
make
sudo make install

if you want to work on the documentation you need the extra

On Debian/Ubuntu you just need to install

sudo apt-get install emacs dvipng emacs-goodies-el org-mode
./configure --enable-gtk-doc
make
make html

nevertheless if you do not want to build the documentation you can do:

./configure --disable-hkl-doc

4.3. Hacking hkl

4.3.1. Bug reporting

You can find the bug tracker here libhkl

  • Debian/Ubuntu:

    reportbug hkl
    
  • Other OS

    You just need to send an email

4.3.2. Providing patches

you can send your patch to Picca Frédéric-Emmanuel using git and git-email.

Here a minimalist example of the workflow to prepare and send patches for integration into the hkl library. Suppose you wan to add a new feature, you need first to create a new branch from the next one:

git checkout -b my-next next

hack, hack:

git commit -a

more hacks:

git commit -a

now that your new feature is ready, you can send by email your work using git format-patch for review:

git format-patch origin/next

which will generate a bunch of 0001\_xxx, 0002\_xxx, … patches

Then you can configure git send-email in order to send the patches for review.

git config sendemail.to "picca@synchrotron-soleil.fr"

and send then with this command:

git send-email 0001-xxx.patch, 0002-xxx.patch, ...

If it does not work you can use your usually email software and send these generated patches to the author.

4.4. Howto's

4.4.1. Add a diffractometer

To add a new diffractometer, you just need to copy the hkl/hkl-engine-template.c into hkl/hkl-engine-INSTITUT-BEAMLINE-INSTRUMENT.c where you replace the upper case with the appropriate values.

The template file is compiled during the build process to ensure that it is always valid.

Then you just need to follow the instruction found in the template. If you need some precision about the process, do not hesitate to contact the main author.

do not forgot also to add this new file into hkl/Makefile.am with other diffractometers in the hkl_c_sources variable (please keep the alphabetic order).

4.4.2. Work on the documentation

The documentation system is written with org-mode, and the babel extension which allow to introspect the library and generate part of the doc using the hkl library. Python code is executed during the build process to generate the Diffractometer section of the documentation. To work on the doc and test the embedded python code it is necessary to setup a few environment variables and start emacs with the right LD_LIBRARY_PATH. In order to simplify the process a make target was written. You just need to type:

cd Documentation
make doc-edit

and start to contribute.

If you do not have emacs, you can nevertheless contribute by editing the Documentation/hkl.org.in file which is text only.

The most expected contributions are for now:

  • english correctness
  • a nicer css

5. Bindings

The hkl library use the gobject-introspection to provide automatic binding for a few languages.

5.1. Python

You can test the binding directly from the source directory with these commandes if ipython is installed.

cd tests/bindings
make ipython

then you have the Hkl module preloaded into the ipython environment.

hkl computation:

has you can see there is 4 available solutions.

let's compute an hkl trajectory and select the first solution.

if we look at the 3 other solutions we can see that there is a problem of continuity at the begining of the trajectory.

hey what's happend with theses solutions ! let's look closely to real numbers. the last column is the distance to the diffractometer current position. This distance is for now express like this:

\(\sum_{axes} \left|\text{current position} - \text{target position}\right|\)

[0.0, 119.99999999999999, 0.0, -90.0, 0.0, 59.99999999999999] 0.0
[0.0, -119.99999999999999, 0.0, -90.0, 0.0, -59.99999999999999] 6.28318530718
[0.0, -60.00000000000005, 0.0, 90.0, 0.0, 59.99999999999999] 6.28318530718
[0.0, 60.00000000000001, 0.0, 90.0, 0.0, -59.99999999999999] 6.28318530718

[0.0, 117.7665607657826, 7.456826294401656, -92.39856410531434, 0.0, 60.33024982425957] 0.216753826612
[0.0, -57.436310940366894, -7.456826294401656, 92.39856418853617, 0.0, 60.33024982425957] 6.41621345188
[0.0, 62.2334392342174, -7.456826294401656, 92.39856410531434, 0.0, -60.33024982425957] 6.42197739723
[0.0, -122.5636890596331, 7.456826294401656, -92.3985641885362, 0.0, -60.33024982425957] 6.50570308205

[0.0, 115.89125602137928, 14.781064139466098, -94.7660423112577, 0.0, 61.314597086440706] 0.219062698235
[0.0, -125.42334103772737, 14.781064139466098, -94.7660427050904, 0.0, -61.314597086440706] 6.53671995288
[0.0, -54.57665896227262, -14.781064139466098, 94.76604270509038, 0.0, 61.314597086440706] 6.67989976726
[0.0, 64.10874397862072, -14.781064139466098, 94.7660423112577, 0.0, -61.314597086440706] 6.71437170098

[0.0, 114.39338605351007, 21.85448296702796, -97.074145033719, 0.0, 62.93506298693471] 0.218163667981
[0.0, -128.54167683157993, 21.85448296702796, -97.07414574435087, 0.0, -62.93506298693471] 6.59846359365
[0.0, -51.45832316842005, -21.85448296702796, 97.07414574435087, 0.0, 62.93506298693471] 6.93673746356
[0.0, 65.60661394648993, -21.85448296702796, 97.074145033719, 0.0, -62.93506298693471] 7.03385205725

[0.0, 113.28316795475283, 28.583837575232764, -99.29953499008337, 0.0, 65.16540747008955] 0.21459359225
[0.0, -131.88223933078322, 28.583837575232764, -99.29953638594702, 0.0, -65.16540747008955] 6.69038531388
[0.0, -48.11776066921677, -28.583837575232764, 99.29953638594702, 0.0, 65.16540747008955] 7.18296350386
[0.0, 66.71683204524717, -28.583837575232764, 99.29953499008337, 0.0, -65.16540747008955] 7.37556986959

[0.0, 112.56286877075006, 34.90573305321372, -101.42496979586187, 0.0, 67.97568017857415] 0.209053830457
[0.0, -135.4128111996365, 34.90573305321372, -101.42497263302461, 0.0, -67.97568017857415] 6.81174779784
[0.0, -44.58718880036348, -34.90573305321372, 101.4249726330246, 0.0, 67.97568017857415] 7.41581162393
[0.0, 67.43713122924994, -34.90573305321372, 101.42496979586187, 0.0, -67.97568017857415] 7.7353201851

[0.0, 112.2291126083182, 40.78594007247402, -103.43941832567457, 0.0, 71.33706722449408] 0.202280147961
[0.0, -139.10795451001587, 40.78594007247402, -103.43942357602316, 0.0, -71.33706722449408] 6.96173845391
[0.0, -40.89204548998411, -40.78594007247402, 103.43942357602312, 0.0, 71.33706722449408] 7.63358787543
[0.0, 67.7708873916818, -40.78594007247402, 103.43941832567457, 0.0, -71.33706722449408] 8.10986069093

[0.0, 112.27578927291766, 46.214916130901734, -105.33741042812996, 0.0, 75.22640762217479] 0.196576175748
[0.0, -142.95061850160724, 46.214916130901734, -105.3374188005596, 0.0, -75.22640762217479] 7.13962155618
[0.0, -37.04938149839278, -46.214916130901734, 105.33741880055959, 0.0, 75.22640762217479] 7.83557762281
[0.0, 67.72421072708234, -46.214916130901734, 105.33741042812996, 0.0, -75.22640762217479] 8.49706672677

[0.0, 112.697137434232, 51.201667684695856, -107.11797492933192, 0.0, 79.63023536264535] 0.202327153157
[0.0, -146.9330984641471, 51.201667684695856, -107.11798610058318, 0.0, -79.63023536264535] 7.34491897177
[0.0, -33.0669015358529, -51.201667684695856, 107.11798610058317, 0.0, 79.63023536264535] 8.02185610877
[0.0, 67.30286256576798, -51.201667684695856, 107.11797492933192, 0.0, -79.63023536264535] 8.89597005568

[0.0, 113.49085964586432, 55.76762791023837, -108.78347437395287, 0.0, 84.54867879242364] 0.208455586312
[0.0, -151.05782007465257, 55.76762791023837, -108.78348605483542, 0.0, -84.54867879242364] 7.57761473366
[0.0, -28.942179925347414, -55.76762791023837, 108.78348605483538, 0.0, 84.54867879242364] 8.19307323084
[0.0, 66.50914035413568, -55.76762791023837, 108.78347437395287, 0.0, -84.54867879242364] 9.30675279514

[0.0, 114.6614608037443, 59.941489465646214, -110.3385360479293, 0.0, 90.00000081324956] 0.215562935229
[0.0, -155.33854118146962, 59.941489465646214, -110.33854432979601, 0.0, -89.99999918675044] 7.83839602383
[0.0, -24.661458818530395, -59.941489465646214, 110.33854432979601, 0.0, 90.00000081324956] 8.3502621071
[0.0, 65.3385391962557, -59.941489465646214, 110.3385360479293, 0.0, -89.99999918675044] 9.7307712883

as you can see for the first point of the trajectory, the 2nd, 3rd and 4th solutions have identical distances to the current position of the diffractometer so they are un-ordered:

[0.0, 119.99999999999999, 0.0, -90.0, 0.0, 59.99999999999999] 0.0
[0.0, -119.99999999999999, 0.0, -90.0, 0.0, -59.99999999999999] 6.28318530718
[0.0, -60.00000000000005, 0.0, 90.0, 0.0, 59.99999999999999] 6.28318530718
[0.0, 60.00000000000001, 0.0, 90.0, 0.0, -59.99999999999999] 6.28318530718

then the problem arise with the second and third solution. you can see a sort of reorganisation of the solution. 2 -> 3, 3 -> 4 and 4 -> 2 then the order will stick unchanged until the end of the trajectory. this is because the distance is computed relatively to the current position of the diffractometer.:

[0.0, 117.7665607657826, 7.456826294401656, -92.39856410531434, 0.0, 60.33024982425957] 0.216753826612
[0.0, -57.436310940366894, -7.456826294401656, 92.39856418853617, 0.0, 60.33024982425957] 6.41621345188
[0.0, 62.2334392342174, -7.456826294401656, 92.39856410531434, 0.0, -60.33024982425957] 6.42197739723
[0.0, -122.5636890596331, 7.456826294401656, -92.3985641885362, 0.0, -60.33024982425957] 6.50570308205

[0.0, 115.89125602137928, 14.781064139466098, -94.7660423112577, 0.0, 61.314597086440706] 0.219062698235
[0.0, -125.42334103772737, 14.781064139466098, -94.7660427050904, 0.0, -61.314597086440706] 6.53671995288
[0.0, -54.57665896227262, -14.781064139466098, 94.76604270509038, 0.0, 61.314597086440706] 6.67989976726
[0.0, 64.10874397862072, -14.781064139466098, 94.7660423112577, 0.0, -61.314597086440706] 6.71437170098

warning

when you compute a trajectory, start from a valid position (the starting point must be the real first point of your trajectory) then use only the closest solution for the next points of the trajectory. (first solution of the geometries list)

6. Releases

6.1. 5.0.0.3367

6.1.1. DONE fix the segfault when trying to create a non valid HklLattice <2023-11-17 Fri>

6.1.2. DONE added the q_sampleaxis_timestamp custom projection to binoculars-ng <2023-11-17 Fri>

6.2. 5.0.0.2661 <2020-10-02 Fri>

6.2.1. DONE Only finite float values are allow when setting an HklParameter value or range.

When using hkl_parameter_value_set or hkl_parameter_min_max_set functions it is not allow to use the float NaN, -Inf, +Inf value.

6.2.2. DONE use python3 instead of python3 for unit tests

In order to prepare the removal of python2 for Debian 11, we switched the unit test. The remaining part is during the build of the documentation. The best would be to report a bug against emacs in order to set python3 as default python interpreter.

6.2.3. DONE Added the Soleil Nanoscopium robot setup.

6.3. 5.0.0.2456 <2018-02-22 Thu>

6.3.1. DONE add emergence on all e4c diffractometers <2017-03-16 Thu>

The emergence pseudo axis is was added to SOLEIL MARS and E4CV

6.3.2. DONE Fix for multiarch (headers) <2016-05-04 Wed>

The ccan_config.h generated file is arch specific. It is then necessary to install this file under /usr/include/<triplet> on Debian like systems. This way it will be possible to co-installa 32/64 bit version of hkl, or to do cross-compilation (arm on x86_64, etc…)

6.3.3. DONE Fix the FTBFS with the new bullet 2.86.1 version <2017-08-13 Sun>

In order to update the internal structures of Hkl3DObject (the is-colliding member), we were using a callback which became un-effectiv with this new version of bullet. The logic was rewritten in order to be much more efficent using the manifold informations. Now we iterate on Hkl3DObject object only once (n) complexity instead of (n²) with the previous one.

6.3.4. DONE Added "SOLEIL SIXS MED2+3 v2" geometry <2019-03-29 Fri>

This diffractometer contain a global HklEngineList parameter in order to activate or not the rotation of the Detector. A new public API was added in order to deal with these parameters.

const darray_string *hkl_engine_list_parameters_names_get(const HklEngineList *self);

const HklParameter *hkl_engine_list_parameter_get(const HklEngineList *self, const char *name,
                                                  GError **error);

int hkl_engine_list_parameter_set(HklEngineList *self,
                                  const char *name, const HklParameter *parameter,
                                  GError **error);

void hkl_engine_list_parameters_values_get(const HklEngineList *self,
                                           double values[], size_t n_values,
                                           HklUnitEnum unit_type);

int hkl_engine_list_parameters_values_set(HklEngineList *self,
                                          double values[], size_t n_values,
                                          HklUnitEnum unit_type, GError **error);

And also available via the Python binding.

engines = factory.create_new_engine_list()

# get parameters names
names = engines.parameters_names_get()

# get the parameters values
values = engines.parameters_values_get(Hkl.UnitEnum.USER)

# set the parameters values
engines.parameters_values_set(values, Hkl.UnitEnum.USER)

6.4. 5.0.0.2080 <2016-04-27 Wed>

6.4.1. DONE HklEngine <2016-01-20 Wed>

emergence_fixed for the SOLEIL SIX MED 2+2 geometry.

6.4.2. DONE HklVector <2016-02-09 Tue>

The hkl_vector_init method is now public.

6.4.3. DONE HklParameter <2016-02-25 Thu>

at the end of the computation all solutions are filtered in order to check that they are valid (min < value < range). BUT for a rotation axis this check was instead (min < value % 2pi < max).

6.4.4. DONE HklGeometry <2016-04-20 Wed>

Add hkl_geometry_[sample/detector]_rotation_get method. It is now possible to get the sample or the detector rotation expressed as a HklQuaternion.

qr = geometry.sample_rotation_get(sample)
qd = geometry.detector_rotation_get(detector)

6.4.5. DONE HklQuaternion <2016-04-20 Wed>

Add hkl_quaternion_to_matrix in order to convert a HklQuaternion into a HklMatrix. Then you just need to convert this HklMatrix into a numpy array when used from the python binding

def hkl_matrix_to_numpy(m):
    M = empty((3, 3))
    for i in range(3):
        for j in range(3):
            M[i, j] = m.get(i, j)
    return M


M = hkl_matrix_to_numpy(q.to_matrix())

6.4.6. DONE Soleil Sirius Turret <2016-04-26 Tue>

Add the basepitch axis which rotate around \(\vec{y}\) in mrad.

6.5. 4.99.99.1955 <2015-07-15 Wed>

Add the ccan_config.h public header. This header is generated with the ccan configurator program.

6.6. 4.99.99.1950 <2015-07-07 Tue>

Fix an FTBFS observed on the sparc arch

6.7. 4.99.99.1949 <2015-07-03 Fri>

6.7.1. DONE HklInterval <2015-07-03 Fri>

hkl_interval_cmp was wrong. Now the comparison is done between HKL_EPSILON and the distance between minimum and maximum. This problem was triggered first on ppc64el architecture.

6.7.2. DONE PATH_MAX <2015-07-03 Fri>

Replace getcwd called by get_current_dir_path instead in order to avoid PATH_MAX which is not available on hurd.

6.8. 4.99.99.1946 <2015-06-30 Tue>

6.8.1. DONE HklEngine

  1. "emergence" <2015-06-22 Mon>

    Add a new emergence engine which contain only one pseudo axis.

    • emergence the outgoing beam emergence from the sample's surface.
    • azimuth the sample's surface azimuth.

6.9. 4.99.99.1940 <2015-05-04 Mon>

6.9.1. DONE HklLattice add an hkl_lattice_volume_get

volume = hkl_lattice_volume_get(lattice);

6.9.2. DONE HklEngine

  1. "nrj, sample, … dependencies" <2015-03-24 Tue>

    Add the hkl_engine_dependencies_get method which return if the HklEngine depends of the axes, the energy, or the sample. the possible values are stored in the HklEngineDependencies enum.

    dependencies = hkl_engine_dependencies_get(engine);
    if (dependencies & HKL_ENGINE_DEPENDENCIES_ENERGY) {
            ...
    }
    if (dependencies & HKL_ENGINE_DEPENDENCIES_SAMPLE) {
            ...
    }
    ...
    
  2. "tth2" <2015-04-03 Fri>

    Add a new hkl engine which contain two pseudo axes.

    • tth two times the diffraction angle \(\theta\)
    • alpha the azimuth of q in the zOy plan.
  3. "incidence" <2015-04-21 Tue>

    Add a new incidence engine which contain only one pseudo axis.

    • incidence the incoming beam incidence on the sample surface.
    • azimuth the sample surface azimuth.
  4. hkl_engine_parameter_set <2015-05-04 Mon>

    Fix a bug and expose the method in the binding.

  5. general
    • use #define AXIS "axis_name" in all the code to set the axes names at only one place. <2015-04-23 Thu>

6.9.3. DONE HklLattice expose in the binding the _x_get/set methods <2015-03-24 Tue>

Now you can use hkl_lattice_x_get where x=a, b, c, alpha, beta, gamma in the bindings.

a = lattice.a_get()
lattice.a_set(a)

6.9.4. DONE HklSampleReflection expose the flag_get/set and geometry_get/set method <2015-03-24 Tue>

It is now possible to change the geometry stored in a reflection via the bindings.

flag = reflection.flag_get()
reflection.flag_set(flag)

geometry = reflection.geometry_get()
geometry.axes_values_set([omega, chi, phi, ...])
reflection.geometry_set(geometry)

7. Todo

7.1. hkl

7.1.1. TODO HklEngine q/q2

Fix all these engines… This engine takes into account only the gamma and delta axes. so diffractometers with 3 axes for the detector are wrong. It would be nice to take into account all the detector holder AND the position of the detecteor on the diffractometer arms (for now the detector is always on the last axis).

7.1.2. TODO HklSource

Create a parameter for the wavelength. This is just internally for the futur trajectory system, so no need to change the signature of hkl_geometry_vawelength get/set

7.1.3. TODO SOLEIL SIRIUS KAPPA

Investigation of a problem saw on Sirius Kappa geometry. The idea is to compute a trajectory from \([0, 0, 1]\) to \([0, 0, 6]\) on a \(GaAs\) sample.

Geometry SOLEIL SIRIUS KAPPA (Source 1.4586370000000007e-9 m) (fromList [-0.5193202,40.795148838481424,134.08834052117254,-55.57809067120416,-2.23369e-2,14.824478553649875]) (Just [Parameter "mu" (-0.5193202) (Range (-180.0) 180.0),Parameter "komega" 40.795148838481424 (Range (-180.0) 180.0),Parameter "kappa" 134.08834052117254 (Range (-180.0) 180.0),Parameter "kphi" (-55.57809067120416) (Range (-180.0) 180.0),Parameter "delta" (-2.23369e-2) (Range (-180.0) 180.0),Parameter "gamma" 14.824478553649875 (Range (-180.0) 180.0)])
[Engine "hkl" [Parameter "h" 2.1481674408578524e-8 (Range (-1.0) 1.0),Parameter "k" 6.392014061803081e-8 (Range (-1.0) 1.0),Parameter "l" 1.0000000132413767 (Range (-1.0) 1.0)] (Mode "bissector_vertical" []),Engine "eulerians" [Parameter "omega" 7.412239314132745 (Range (-180.0) 180.0),Parameter "chi" 89.72020738176312 (Range (-180.0) 180.0),Parameter "phi" 91.03899980444716 (Range (-180.0) 180.0)] (Mode "eulerians" [Parameter "solutions" 1.0 (Range 0.0 1.0)]),Engine "psi" [Parameter "psi" 154.5513657893786 (Range (-180.0) 180.0)] (Mode "psi_vertical_soleil_sirius_kappa" [Parameter "h2" 1.0 (Range (-1.0) 1.0),Parameter "k2" 1.0 (Range (-1.0) 1.0),Parameter "l2" 1.0 (Range (-1.0) 1.0)]),Engine "q2" [Parameter "q" 1.1114190632688228 (Range 0.0 1.0),Parameter "alpha" 89.91560430137815 (Range (-180.0) 180.0)] (Mode "q2" []),Engine "qper_qpar" [Parameter "qper" 1.1114162413072137 (Range (-1.0) 1.0),Parameter "qpar" 2.5045470426602284e-3 (Range (-1.0) 1.0)] (Mode "qper_qpar" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)]),Engine "tth2" [Parameter "tth" 14.824495004588014 (Range (-180.0) 180.0),Parameter "alpha" 89.91560430137815 (Range (-180.0) 180.0)] (Mode "tth2" []),Engine "incidence" [Parameter "incidence" 7.414401593159588 (Range (-180.0) 180.0),Parameter "azimuth" 89.78541978058817 (Range (-180.0) 180.0)] (Mode "incidence" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)]),Engine "emergence" [Parameter "emergence" 7.410055570443473 (Range (-180.0) 180.0),Parameter "azimuth" 89.78541978058817 (Range (-180.0) 180.0)] (Mode "emergence" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)])]
Geometry SOLEIL SIRIUS KAPPA (Source 1.4586370000000007e-9 m) (fromList [-0.5193202,47.97247473743512,134.654265266118,124.92415016158583,-2.23369e-2,29.904632884360968]) (Just [Parameter "mu" (-0.5193202) (Range (-180.0) 180.0),Parameter "komega" 47.97247473743512 (Range (-180.0) 180.0),Parameter "kappa" 134.654265266118 (Range (-180.0) 180.0),Parameter "kphi" 124.92415016158583 (Range (-180.0) 180.0),Parameter "delta" (-2.23369e-2) (Range (-180.0) 180.0),Parameter "gamma" 29.904632884360968 (Range (-180.0) 180.0)])
[Engine "hkl" [Parameter "h" (-1.3839931497468412e-9) (Range (-1.0) 1.0),Parameter "k" (-4.913404854447784e-10) (Range (-1.0) 1.0),Parameter "l" 2.000000003360829 (Range (-1.0) 1.0)] (Mode "bissector_vertical" []),Engine "eulerians" [Parameter "omega" 14.95231642186499 (Range (-180.0) 180.0),Parameter "chi" 89.9575990161042 (Range (-180.0) 180.0),Parameter "phi" 271.9039918460157 (Range (-180.0) 180.0)] (Mode "eulerians" [Parameter "solutions" 1.0 (Range 0.0 1.0)]),Engine "psi" [Parameter "psi" (-26.325999847139332) (Range (-180.0) 180.0)] (Mode "psi_vertical_soleil_sirius_kappa" [Parameter "h2" 1.0 (Range (-1.0) 1.0),Parameter "k2" 1.0 (Range (-1.0) 1.0),Parameter "l2" 1.0 (Range (-1.0) 1.0)]),Engine "q2" [Parameter "q" 2.2228381008394895 (Range 0.0 1.0),Parameter "alpha" 89.96116221471468 (Range (-180.0) 180.0)] (Mode "q2" []),Engine "qper_qpar" [Parameter "qper" 2.222832456913507 (Range (-1.0) 1.0),Parameter "qpar" (-5.009095284686147e-3) (Range (-1.0) 1.0)] (Mode "qper_qpar" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)]),Engine "tth2" [Parameter "tth" 29.90464045486422 (Range (-180.0) 180.0),Parameter "alpha" 89.96116221471468 (Range (-180.0) 180.0)] (Mode "tth2" []),Engine "incidence" [Parameter "incidence" 14.952081490954424 (Range (-180.0) 180.0),Parameter "azimuth" 90.09480115642252 (Range (-180.0) 180.0)] (Mode "incidence" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)]),Engine "emergence" [Parameter "emergence" 14.952481262345229 (Range (-180.0) 180.0),Parameter "azimuth" 90.09480115642252 (Range (-180.0) 180.0)] (Mode "emergence" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)])]
Geometry SOLEIL SIRIUS KAPPA (Source 1.4586370000000007e-9 m) (fromList [-0.5193202,56.25907471532187,133.92128004831832,-55.45556970293517,-2.23369e-2,45.53873596992208]) (Just [Parameter "mu" (-0.5193202) (Range (-180.0) 180.0),Parameter "komega" 56.25907471532187 (Range (-180.0) 180.0),Parameter "kappa" 133.92128004831832 (Range (-180.0) 180.0),Parameter "kphi" (-55.45556970293517) (Range (-180.0) 180.0),Parameter "delta" (-2.23369e-2) (Range (-180.0) 180.0),Parameter "gamma" 45.53873596992208 (Range (-180.0) 180.0)])
[Engine "hkl" [Parameter "h" 8.37724528421826e-9 (Range (-1.0) 1.0),Parameter "k" 2.018612859089285e-8 (Range (-1.0) 1.0),Parameter "l" 2.999999983141756 (Range (-1.0) 1.0)] (Mode "bissector_vertical" []),Engine "eulerians" [Parameter "omega" 22.76936798418434 (Range (-180.0) 180.0),Parameter "chi" 89.64969149765572 (Range (-180.0) 180.0),Parameter "phi" 91.0547235659273 (Range (-180.0) 180.0)] (Mode "eulerians" [Parameter "solutions" 1.0 (Range 0.0 1.0)]),Engine "psi" [Parameter "psi" 154.50191592522592 (Range (-180.0) 180.0)] (Mode "psi_vertical_soleil_sirius_kappa" [Parameter "h2" 1.0 (Range (-1.0) 1.0),Parameter "k2" 1.0 (Range (-1.0) 1.0),Parameter "l2" 1.0 (Range (-1.0) 1.0)]),Engine "q2" [Parameter "q" 3.334257126919726 (Range 0.0 1.0),Parameter "alpha" 89.97807925598289 (Range (-180.0) 180.0)] (Mode "q2" []),Engine "qper_qpar" [Parameter "qper" 3.334248661038927 (Range (-1.0) 1.0),Parameter "qpar" 7.513639271725189e-3 (Range (-1.0) 1.0)] (Mode "qper_qpar" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)]),Engine "tth2" [Parameter "tth" 45.53874024285007 (Range (-180.0) 180.0),Parameter "alpha" 89.97807925598289 (Range (-180.0) 180.0)] (Mode "tth2" []),Engine "incidence" [Parameter "incidence" 22.771374111123095 (Range (-180.0) 180.0),Parameter "azimuth" 89.8380685773065 (Range (-180.0) 180.0)] (Mode "incidence" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)]),Engine "emergence" [Parameter "emergence" 22.767244039797937 (Range (-180.0) 180.0),Parameter "azimuth" 89.8380685773065 (Range (-180.0) 180.0)] (Mode "emergence" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)])]
Geometry SOLEIL SIRIUS KAPPA (Source 1.4586370000000007e-9 m) (fromList [-0.5193202,64.64191214924969,133.78682078017752,-55.41938838621407,-2.23369e-2,62.132688461209455]) (Just [Parameter "mu" (-0.5193202) (Range (-180.0) 180.0),Parameter "komega" 64.64191214924969 (Range (-180.0) 180.0),Parameter "kappa" 133.78682078017752 (Range (-180.0) 180.0),Parameter "kphi" (-55.41938838621407) (Range (-180.0) 180.0),Parameter "delta" (-2.23369e-2) (Range (-180.0) 180.0),Parameter "gamma" 62.132688461209455 (Range (-180.0) 180.0)])
[Engine "hkl" [Parameter "h" 9.177457430250849e-9 (Range (-1.0) 1.0),Parameter "k" 2.5693823994163015e-8 (Range (-1.0) 1.0),Parameter "l" 3.9999999929703476 (Range (-1.0) 1.0)] (Mode "bissector_vertical" []),Engine "eulerians" [Parameter "omega" 31.06634423136446 (Range (-180.0) 180.0),Parameter "chi" 89.5927920859556 (Range (-180.0) 180.0),Parameter "phi" 91.00504369590071 (Range (-180.0) 180.0)] (Mode "eulerians" [Parameter "solutions" 1.0 (Range 0.0 1.0)]),Engine "psi" [Parameter "psi" 154.51996903181714 (Range (-180.0) 180.0)] (Mode "psi_vertical_soleil_sirius_kappa" [Parameter "h2" 1.0 (Range (-1.0) 1.0),Parameter "k2" 1.0 (Range (-1.0) 1.0),Parameter "l2" 1.0 (Range (-1.0) 1.0)]),Engine "q2" [Parameter "q" 4.44567618639551 (Range 0.0 1.0),Parameter "alpha" 89.9881895320358 (Range (-180.0) 180.0)] (Mode "q2" []),Engine "qper_qpar" [Parameter "qper" 4.445664898550648 (Range (-1.0) 1.0),Parameter "qpar" 1.0018187400499787e-2 (Range (-1.0) 1.0)] (Mode "qper_qpar" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)]),Engine "tth2" [Parameter "tth" 62.13269076337942 (Range (-180.0) 180.0),Parameter "alpha" 89.9881895320358 (Range (-180.0) 180.0)] (Mode "tth2" []),Engine "incidence" [Parameter "incidence" 31.068363501362125 (Range (-180.0) 180.0),Parameter "azimuth" 89.83747231179481 (Range (-180.0) 180.0)] (Mode "incidence" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)]),Engine "emergence" [Parameter "emergence" 31.064152026450454 (Range (-180.0) 180.0),Parameter "azimuth" 89.83747231179481 (Range (-180.0) 180.0)] (Mode "emergence" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)])]
Geometry SOLEIL SIRIUS KAPPA (Source 1.4586370000000007e-9 m) (fromList [-0.5193202,73.83399863752925,133.64586701159254,-55.35712475482595,-2.23369e-2,80.33702663350934]) (Just [Parameter "mu" (-0.5193202) (Range (-180.0) 180.0),Parameter "komega" 73.83399863752925 (Range (-180.0) 180.0),Parameter "kappa" 133.64586701159254 (Range (-180.0) 180.0),Parameter "kphi" (-55.35712475482595) (Range (-180.0) 180.0),Parameter "delta" (-2.23369e-2) (Range (-180.0) 180.0),Parameter "gamma" 80.33702663350934 (Range (-180.0) 180.0)])
[Engine "hkl" [Parameter "h" 2.7577312257761425e-9 (Range (-1.0) 1.0),Parameter "k" 7.650403950118726e-9 (Range (-1.0) 1.0),Parameter "l" 4.999999999622215 (Range (-1.0) 1.0)] (Mode "bissector_vertical" []),Engine "eulerians" [Parameter "omega" 40.168513316578995 (Range (-180.0) 180.0),Parameter "chi" 89.53300638651663 (Range (-180.0) 180.0),Parameter "phi" 90.9773899242238 (Range (-180.0) 180.0)] (Mode "eulerians" [Parameter "solutions" 1.0 (Range 0.0 1.0)]),Engine "psi" [Parameter "psi" 154.50326819560394 (Range (-180.0) 180.0)] (Mode "psi_vertical_soleil_sirius_kappa" [Parameter "h2" 1.0 (Range (-1.0) 1.0),Parameter "k2" 1.0 (Range (-1.0) 1.0),Parameter "l2" 1.0 (Range (-1.0) 1.0)]),Engine "q2" [Parameter "q" 5.557095242340622 (Range 0.0 1.0),Parameter "alpha" 89.99619673890915 (Range (-180.0) 180.0)] (Mode "q2" []),Engine "qper_qpar" [Parameter "qper" 5.557081132533362 (Range (-1.0) 1.0),Parameter "qpar" 1.2522734784728349e-2 (Range (-1.0) 1.0)] (Mode "qper_qpar" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)]),Engine "tth2" [Parameter "tth" 80.33702737486469 (Range (-180.0) 180.0),Parameter "alpha" 89.99619673890915 (Range (-180.0) 180.0)] (Mode "tth2" []),Engine "incidence" [Parameter "incidence" 40.17045932119529 (Range (-180.0) 180.0),Parameter "azimuth" 89.82724901343079 (Range (-180.0) 180.0)] (Mode "incidence" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)]),Engine "emergence" [Parameter "emergence" 40.16632251480728 (Range (-180.0) 180.0),Parameter "azimuth" 89.82724901343079 (Range (-180.0) 180.0)] (Mode "emergence" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)])]
Geometry SOLEIL SIRIUS KAPPA (Source 1.4586370000000007e-9 m) (fromList [-0.5193202,84.086619565407,134.11156620489382,125.37371040144704,-2.23369e-2,101.43713587367031]) (Just [Parameter "mu" (-0.5193202) (Range (-180.0) 180.0),Parameter "komega" 84.086619565407 (Range (-180.0) 180.0),Parameter "kappa" 134.11156620489382 (Range (-180.0) 180.0),Parameter "kphi" 125.37371040144704 (Range (-180.0) 180.0),Parameter "delta" (-2.23369e-2) (Range (-180.0) 180.0),Parameter "gamma" 101.43713587367031 (Range (-180.0) 180.0)])
[Engine "hkl" [Parameter "h" 8.392762843275724e-10 (Range (-1.0) 1.0),Parameter "k" 2.459154264227675e-9 (Range (-1.0) 1.0),Parameter "l" 6.0000000015375905 (Range (-1.0) 1.0)] (Mode "bissector_vertical" []),Engine "eulerians" [Parameter "omega" 50.718567936651276 (Range (-180.0) 180.0),Parameter "chi" 89.72999512595882 (Range (-180.0) 180.0),Parameter "phi" 272.0056587726913 (Range (-180.0) 180.0)] (Mode "eulerians" [Parameter "solutions" 1.0 (Range 0.0 1.0)]),Engine "psi" [Parameter "psi" (-26.58708882570157) (Range (-180.0) 180.0)] (Mode "psi_vertical_soleil_sirius_kappa" [Parameter "h2" 1.0 (Range (-1.0) 1.0),Parameter "k2" 1.0 (Range (-1.0) 1.0),Parameter "l2" 1.0 (Range (-1.0) 1.0)]),Engine "q2" [Parameter "q" 6.668514293021504 (Range 0.0 1.0),Parameter "alpha" 90.00451897705055 (Range (-180.0) 180.0)] (Mode "q2" []),Engine "qper_qpar" [Parameter "qper" 6.6684973612522915 (Range (-1.0) 1.0),Parameter "qpar" (-1.5027281967821613e-2) (Range (-1.0) 1.0)] (Mode "qper_qpar" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)]),Engine "tth2" [Parameter "tth" 101.43713499280318 (Range (-180.0) 180.0),Parameter "alpha" 90.00451897705055 (Range (-180.0) 180.0)] (Mode "tth2" []),Engine "incidence" [Parameter "incidence" 50.71877816056822 (Range (-180.0) 180.0),Parameter "azimuth" 90.20844936572345 (Range (-180.0) 180.0)] (Mode "incidence" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)]),Engine "emergence" [Parameter "emergence" 50.71800112341318 (Range (-180.0) 180.0),Parameter "azimuth" 90.20844936572345 (Range (-180.0) 180.0)] (Mode "emergence" [Parameter "x" 0.0 (Range (-1.0) 1.0),Parameter "y" 1.0 (Range (-1.0) 1.0),Parameter "z" 0.0 (Range (-1.0) 1.0)])

As we can see the phi and kphi motor switch from time to time to another solution which is at around 180° of the other solutions.

sirius-s.svg

Figure 6: plot the [0,0,1] -> [0,0,6] trajectory from two different starting point and different step size.

sirius-m.svg

Figure 7: plot the [0,0,1] -> [0,0,6] idem previous figure but move the diffractometer.

sirius-m-zoom.svg

Figure 8: zoom on the 2 solutions.

traj_n.svg

Figure 9: plot the [0,0,1] -> [0,0,6] for different number of steps

7.1.4. TODO [0/2] PetraIII

  1. TODO computation problem

    Dear Teresa,

    Using the prruptest.txt ubmatrix I see that the value of psi is offset by 45 degrees. I expect it to be 0 degrees when azimuth reference vector is 0 0 1 that is along the beam. See below thereturned numbers. This might have to do with the definition of the beam axis in the controller. Otherwise now when I change reference vector by 90 degrees the computed value is changed by 90 degrees. That is a progress. Can you contact Frederic and ask him about this ?

    Best regards,

    Sonia

    See below p09/door/haspp09.01 [9]: setaz 1 0 0

    p09/door/haspp09.01 [10]: wh

    Engine: hkl

    Mode: psi_constant_vertical

    H K L = 0.00000 3.00605 -0.00000 Ref = 1.00000 0.00000 0.00000 Azimuth (Psi - calculated) = -45.00005 Azimuth (Psi - set) = 0.00000 Wavelength = 2.07957

    Delta Theta Chi Phi Mu Gamma 45.77575 22.88783 90.00000 182.85400 0.00000 -0.00000

    p09/door/haspp09.01 [11]: setaz 0 0 1

    p09/door/haspp09.01 [12]: wh

    Engine: hkl

    Mode: psi_constant_vertical

    H K L = 0.00000 3.00605 -0.00000 Ref = 0.00000 0.00000 1.00000 Azimuth (Psi - calculated) = -135.00005 Azimuth (Psi - set) = 0.00000 Wavelength = 2.07957

    Delta Theta Chi Phi Mu Gamma 45.77575 22.88783 90.00000 182.85400 0.00000 -0.00000

    where:

    Azimuth (Psi - calculated) is the value of the pseudomotor psi. Azimuth (Psi - set) is the value set in the parameter psi of the current mode.

    Hi Frederic,

    This is the UB matrix:

    Best regards,

    Sonia

    Created at 2015-01-21 12:35

    Crystal prruptest

    Wavelength 2.07957463938

    A 8.03656 B 8.03656 C 8.03656 Alpha 90.0 Beta 90.0 Gamma 90.0

    R0 0 0.0 1.0 0.0 0 1 0.0 14.8979 90.0 182.854 0.0 29.7959 R1 1 1.0 0.0 1.0 0 1 0.0 14.8979 0.0 182.854 0.0 29.7959

    Mode psi_constant_vertical

    PsiRef 0.0 0.0 1.0

    U00 -0.580 U01 0.000 U02 0.525 U10 0.000 U11 0.782 U12 -0.000 U20 -0.525 U21 -0.000 U22 -0.580

    Ux 179.999952315 Uy 42.14605 Uz -179.999932647

    SaveDirectory home/p09user/crystals

  2. TODO another question

    J'ai un probleme avec la position que le controlleur calcule avec la matrice UB que nous t'avons envoye. See sequence of emails echanges avec Teresa.

    >>>> I am at 0 3.00605 0 with phi -182 and psi calculated is -135 >>>> When I freeze psi at -135 and type ca 0 3.00605 0 the controller >> should return to me the positions at which I am. But no he tells me that I >> have to go to 178 degrees in phi that is turning by 360 degrees.

    Est-ce un probleme avec la trajectoire selectionnee ? Est-ce qu'il est possible de definir des cut-points comme dans spec avec ta librairie ?

7.1.5. TODO [2/4] HklParameter

  • [X] method to use min/max to check for the validity
  • [X] add a method to get the axis_v and quaternion of the HklAxis this method will return NULL if this is not relevant. hkl_parameter_axis_v_get and hkl_parameter_quaternion_get
  • [ ] degenerated an axis is degenerated if its position have no effect on the HklPseudoAxis calculus. Add a degenerated member to the axis. that way it would be possible to check a posteriori for this degenerescencence.
  • [ ] Add a description for each parameters.

7.1.6. TODO This will help for the documentation and the gui.

7.1.7. TODO HklGeometryList different method to help select a solution.

this select solution can depend on the geometry for example the kappa axis must be in one side of the plane.

7.1.8. TODO add a fit on the Hklaxis offsets.

7.1.9. TODO API to put a detector and a sample on the Geometry.

7.1.10. TODO HklSample

  1. TODO unit test: hkl_sample_affine.

    Check this: lattice=1.540000;1.540000;1.540000;90.000000;90.000000;90.000000;0;0;0;0;0;0 uxuyuz=0.000000;0.000000;0.000000 reflection=1.540000;0.159010;1.256718;0.796660;1;0.000000;0.000000;0.000000;0.000000;0.000000 reflection=1.540000;0.206208;0.342357;-0.080346;1;0.000000;0.000000;0.000000;0.000000;0.000000 reflection=1.540000;0.206208;0.342357;-0.080346;1;0.000000;0.000000;0.000000;0.000000;0.000000

    A, B, C, Alpha, Beta, Gamma, Ux, Uy, Uy: 17764892.133, 5793679.092, 15733785.198, 179.997, 179.999,452408725.23, -575727594.04, -1913661011.01 (affine) 1rst finetness

    all the reflections are non collinear the affine method should warn the user about this.

7.1.11. TODO HklEngine "zone"

7.1.12. TODO HklEngine "custom"

for now this pseudoaxis let you select the axis you want to use for the computation.

7.1.13. TODO HklEngine "q/q2" add a "reflectivity" mode

This mode should have the surface as parameters and the incident angle is equal to the emergence angle.

7.1.14. TODO create a macro to help compare two real the right way

fabs(a-b) < epsilon * max(1, abs(a), abs(b))

7.1.15. TODO add an hkl_sample_set_lattice_unit()

7.1.16. TODO SOLEIL SIXS

  1. DONE find the right solutions.   zaxis

    The cosinus and sinus properties are not enough to find the solution expected by the users. The idea is to use the Ewalds construction to generate a valid solution from the first one obtain numerically. The basic idea is to rotate the hkl vector around the last axis of the sample holder until it intersect again the Ewalds sphere. Then we just need to fit the detector position. This way the solution can be entirely generic (not geometry specific). Nevertheless it is necessary to propose this only for the hkl pseudo axes. I will add this special feature in the Mode. So it will be possible to add thoses special cases easily.

  2. TODO Add the DEP diffractometer geometry

    This diffractometer is a Newport one based on the kappa 6 circles ones. But instead of a kappa head, they use an Hexapod head. This head can be put horizontally or vertically.

7.1.17. TODO generalisation of the z-axis hkl solver

first we need the degenerated member of the Axis. thaht way it could be possible to find the last non degenerated axis for the detector fit.

7.1.18. TODO investigate the prigo geometry.

7.1.19. TODO augeas/elektra for the plugin configure part.

7.1.20. TODO logging

  1. TODO [1/2] add in a few methods.
    • [X] hkl_pseudo_axes_values_set
    • [ ] hkl_sample_affine
  2. TODO gir logging

    It would be nice to generate the library logging using the .gir information. So instead of writing the logging code for each method, it would be better to have a generic method for this purpose.

  3. TODO parsable logging information.

    A parsable logging format would help to setup some re-play unit test. This way it could help during the developpement process (modification of the hkl internals) to be confident that computation are ok.

7.1.21. TODO performances

  • Investigate liboil to speed calculation (in HklVector, HklMatrix and HklQuaternion)
  • Avoid to call hkl_engine_prepare_internal at each computation.

7.2. documentation

7.2.1. TODO [1/6] rewrite documentation in org-mode

  • [-] embedding code into the org file
    • [-] [1/4] python
      • [X] auto generation of the diffractometer descriptions
      • [ ] trajectories explanations
      • [ ] trajectories tests.
      • [ ] unit tests output ?
    • [ ] asymptote
  • [X] need to check if templates could be generated using the hkl python binding for all diffractometer geometries.
  • [ ] need to add a description for the diffractometer, the mode, the parameters.
  • [ ] need a nice css for the generated doc.
  • [ ] check if org-info.js could be usefull
  • [ ] add documentation explaining the sector-cuts a la hkl

7.3. [0/3] gui

  • [ ] change the color of fitparameter cells if they differ from the current sample values
  • [ ] check if a REPL could be integrated to provide an autocad like interface.
  • [ ] add tooltips using hkl_parameter_description_get for the pseudo axes and the mode parameters.

7.4. hkl3d

7.4.1. TODO add a method to find the 3D models in the right directories.

7.5. packaging

7.5.1. TODO add a .spec file for rpm generation.

Author: Picca Frédéric-Emmanuel

Created: 2023-11-17 Fri 17:26

Validate