Files
sics/hkl.w
Ferdi Franceschini 3168325921 PSI update
r1464 | ffr | 2007-02-12 12:20:21 +1100 (Mon, 12 Feb 2007) | 2 lines
2012-11-15 12:58:05 +11:00

229 lines
9.9 KiB
OpenEdge ABL

\subsection{Crystallographic Computations}
The HKL object performs standard four circle calculations. I.e., given a UB
matrix it calculates the four circle diffractometer setting angles required
for a reflection with index hkl. The UB must be determined from a set of
reflections found manually or automatically. This is done in an offline
program. The code in this module is a direct reimplementation of fortran code
provided by Jean Allibon, ILL with the MAD four circle diffractometer
control program in ANSI-C. For theory, see the contribution by
W.C. Hamilton in the International Tables for Crystallography, 1974 edition.
There is a sister object to HKL which uses HKL to implement virtual motors for
H, K, and L. See below for the description
The object uses the following object data structure:
@d hkldat @{
typedef struct __HKL {
pObjectDescriptor pDes;
MATRIX UBinv;
int iManual;
double fLastHKL[5];
int iNOR;
int iQuad;
int iHM;
long lID;
float scanTolerance;
float targetHKL[3];
int targetDirty;
pIDrivable pMotDriv;
pIDrivable pMotList;
} HKL;
@}
The fields are more or less self explaining:
\begin{description}
\item[pDes] The standard object descriptor.
\item[iManual] A flag which defines if the wavelength has been set manually
or is updated automatically from a wavelength variable.
\item[fLastHKL] the HKL of the last reflection calculated.
\item[iNor] a flag for normal beam calculation mode.
\item[iHM] a flag for histogram memory mode. In this mode two theta
limits are checked alos for detector 2 and 3.
\item[scanTolerance] The hkl module refuses to position a reflection if it is
to close to omega limits for scanning. This is the tolerance to use.
\item[targetHKL] The target HKL values to support the H, K, L virtual motors
\item[targetDirty] A flag which is set when the virtual motors have to recalculate the
settings and to drive.
\end{description}
The wavelength is a bit tricky. As it would be to time consuming to read two
motors each time a calculation is performed, the lambda variable is updated
by registering a callback with the selector variable handling the
monochromator wavelength. As TriCS will be run with two monochromators on a
lift a means has to be provided to change the selector variable online. An
additonal feature is that the wavelength can be manipulated manually. This
adresses the issue that automatic wavelength may be inaccurate due to
lazy instrument scientists not adjusting their instruments.
In terms of an interface the following functions will be provided by this
module:
@d hklint @{
typedef struct __HKL *pHKL;
/*-------------------------------------------------------------------------*/
pHKL CreateHKL();
void DeleteHKL(void *pData);
int HKLFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
/*------------------------------------------------------------------------*/
void SetHKLScanTolerance(pHKL self, float value);
int SetUB(pHKL self, float fUB[9]);
int GetUB(pHKL self, float fUB[9]);
int SetNOR(pHKL self, int iNOB);
int GetLambda(pHKL self, float *fVal);
int GetCurrentHKL(pHKL self, float fVal[3]);
int GetCurrentPosition(pHKL self, SConnection *pCon, float fPosition[4]);
int GetHKLFromAngles(pHKL self, SConnection *pCon, float fVal[3]);
int CalculateSettings(pHKL self, float fHKL[3], float fPsi, int iHamil,
float fSet[4],SConnection *pCon);
int RunHKL(pHKL self, float fHKL[3], float fPsi, int iHamil, SConnection
*pCon);
int DriveHKL(pHKL self, float fHKL[3], float fPsi, int iHamil,
SConnection *pCon);
int DriveSettings(pHKL self, float fSet[4],SConnection *pCon);
int HKLAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
int hklInRange(void *data, double fSet[4], int mask[4]);
int startHKLMotors(pHKL self, SConnection *pCon, float fSet[4]);
void stopHKLMotors(pHKL self);
@}
All functions return 0 on failure, 1 on success if not stated otherwise.
Most functions take a pointer to a HKL data structure as first parameter.
The function in more detail:
\begin{description}
\item[CreateHKL] creates a HKL object. The parameters are pointers to the
four four circle motors. Returns NULL on failure, a pointer to the new
object on success.
\item[DeleteHKL] properly removes an HKL object from the system.
\item[HKLFactory] The factory function which initialises an HKL object from
the initialisation script.
\item[SetWavelengthVariable] sets a new wavelength variable. Installs all
necesarry callbacks for automatic update.
\item[SetWaveLengthManual] deinstall all callbacks and forces the wavelength
to the value specified a second parameter.
\item[SetUB] sets the UB matrix.
\item[SetNOR] sets the normal beam calculation flag to iNOR.
\item[CalculateSettings] is the heart of this all. As the name suggests
calculates the settings for a four circle diffractometer. The parameters
are:
\begin{description}
\item[self] A pointer to a HKL data structure.
\item[fHKL] The reflection indices to calculate the settings for.
\item[fPsi] The psi value for the reflection. For psi scans. Set to 0 if not
used.
\item[iHamil] The index of the hamilton position to calculate. Can be an
integer between 0 to 8. 0 denotes the normal case.
\item[fSet] contains the required settings if the function returns with
success. 0 = two theta, 1 = omega, 2 = chi, 3 = phi.
\end{description}
The function returns 1 on success, a negative value on failure. Possible
error returns are:
\begin{description}
\item[HKLIMPOSSIBLE] the calculation was impossible.
\item[HKLTHETALIMIT] a setting could be calculated but can not be accessed
due to a limit on two theta.
\end{description}
\item[DriveHKL] calculates a setting and drives to the position. The
parameters are the same as with CalculateSettings. With the addition of a
pointer to the connection object doing the command for error messages and
everything. The error returns are the same as with CalculateSettings
well. With the addition of HKJMOTFAIL, which means that a motor failed to
drive properly.
\item[GetHKLFromAngles] calculates the current HKL from Angles.
\item[DriveSettings] drives to the the settings given in fSet.
\item[HKLAction] is the interpreter wrapper function for the HKL object.
\end{description}
@o hkl.i @{
/*-------------------------------------------------------------------------
H K L
Internal data structure description. See hkl.h, c,w for more details.
Mark Koennecke, February 1998
----------------------------------------------------------------------------*/
@<hkldat@>
@}
@o hkl.h @{
/*---------------------------------------------------------------------------
H K L
This SICS object performs angle setting calculations for a four circle
diffractometer. The heart of this code is a C transcriptions of routines
written by Jean Allibon at ILL for the MAD program. Theory is explained in
the article by W. C. Hamilton in International Tables for Crystallography,
1974 edition.
copyright: see copyright.h
Mark Koennecke, February 1998
----------------------------------------------------------------------------*/
#ifndef SICSHKL
#define SICSHKL
#include "selector.h"
#include "selvar.h"
@<hklint@>
#endif
@}
\subsubsection{The Crystallographic Virtual Motor Object}
This module implements virtual motors H, K and L on top of the HKL object. It was choosen to implement this
in a separate module because the hkl module is already big and complex enough. The problem is how to
keep track of the necessary settings for HKL because the motors are interrelated. This is solved in the
following scheme:
\begin{itemize}
\item Starting any of the motors H, K or L results in new values to be set in the HKL internal data
structure and a dirty flag to be set.
\item On a call to the drivable interfaces status function the dirty flag is checked and, if
appropriate, the motor positions are recalculated and the motors started.
\item H, K and L values are recalculated from motors on each read.
\end{itemize}
For each virtual motor an internal data structure is required:
@d hklmotdat @{
typedef struct __HKLMOT {
pObjectDescriptor pDes;
pHKL pHkl;
pIDrivable pDriv;
int index;
}HKLMot, *pHKLMot;
@}
The fields are:\begin{description}
\item[pDes] The required object descriptor.
\item[pHkl] The HKL object to use for calculations.
\item[pDriv] The drivable interface.
\item[index] The index of the motors target in the targetHKL array in the HKL structure.
\end{description}
The target HKL and the dirty flag is in the main HKL data structure.
There is no external interface to this, all the functionality is hidden in the drivable interface
functions. The interpreter interface is minimal: only a value request is supported. There is
however a factory function in order to install the HKL motors into the interpreter.
@o hklmot.h @{
/*------------------------------------------------------------------------------------------------------
Virtual motor interface to reciprocal space coordinates H, K and L for a four circle diffractometer.
Requires a HKL object for calculations.
copyright: see file COPYRIGHT
Mark Koennecke, February 2005
--------------------------------------------------------------------------------------------------------*/
#ifndef SICSHKLMOT
#define SICSHKLMOT
/*====================== data structure ==============================================================*/
@<hklmotdat@>
/*======================= interpreter interface ======================================================*/
int HKLMotAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]);
int HKLMotInstall(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]);
#endif
@}