198 lines
7.4 KiB
C
198 lines
7.4 KiB
C
/*
|
|
F O U R L I B
|
|
|
|
This is a library of routines for doing transformations between the
|
|
various coordinate systems used on a four circle diffractometer as
|
|
used for neutron or X-ray diffraction. The coordinate systems used are
|
|
described in Busing, Levy, Acta Cryst (1967),22, 457 ff.
|
|
|
|
Generally we have:
|
|
|
|
Z = [OM][CHI][PHI][UB]h
|
|
|
|
where: Z is a vector in the diffractometer coordinate system
|
|
OM CHI PHI are rotation matrices around the respective angles
|
|
UB is the UB matrix
|
|
h is the reciprocal lattice vector.
|
|
|
|
The vector Z cannot only be expressed in terms of the angles stt, om, chi,
|
|
and phi put also by polar coordinates gamma and nu.
|
|
|
|
This code is a reimplementation based on a F77 code from Gary McIntyre, ILL
|
|
and code extracted from the ILL MAD control program.
|
|
|
|
Mark Koennecke, November - December 2001
|
|
*/
|
|
#ifndef FOURLIB
|
|
#define FOURLIB
|
|
#include "matrix/matrix.h"
|
|
|
|
/**---------------------- PSD specific code -------------------------------
|
|
Some diffractometers are equipped with position sensitive detectors.
|
|
The scheme to handle them implemented here is to convert the detector
|
|
coordinates to polar coordinates gamma and nu and use the normal beam
|
|
functions for any further work. A lot of information about the detector
|
|
is required for this transformation which is held in the datastruture
|
|
as defined below
|
|
----------------------------------------------------------------------*/
|
|
|
|
typedef struct {
|
|
double xScale; /* scale factor pixel --> mm for x */
|
|
double yScale; /* scale factor pixel --> mm for y */
|
|
double distance; /* distance sample detector in mm */
|
|
double gamma; /* gamma == two theta position of the detector */
|
|
double nu; /* tilt angle of the detector */
|
|
int xZero; /* x pixel coordinate of the zero point of the detector */
|
|
int yZero; /* y pixel coordinate of the zero point of the detector */
|
|
} psdDescription;
|
|
/**
|
|
* det2pol converts the pixel coordinates x and y on the detector described
|
|
* by psd to polar coordinates gamma and nu.
|
|
*/
|
|
|
|
void det2pol(psdDescription * psd, int x, int y, double *gamma,
|
|
double *nu);
|
|
|
|
/**
|
|
* pol2det converts the polar coordinates gamma and nu to detector coordinates
|
|
* x and y on the detector described psd
|
|
*/
|
|
void pol2det(psdDescription * psd, double gamma, double nu, int *x,
|
|
int *y);
|
|
|
|
/*------------------------------------------------------------------------
|
|
calculation of four circle diffractometer angles stt, om, chi and phi
|
|
in order to put a reflection onto the equatorial plane and into a
|
|
diffraction condition. In order to cope with angular restrictions
|
|
imposed for instance by sample environment devices or the eulerian
|
|
cradle itself various variations are implemented.
|
|
|
|
These routines start at or target the vector Z1:
|
|
|
|
Z1 = UB *h
|
|
------------------------------------------------------------------------*/
|
|
/**
|
|
* calculate stt, om, chi and phi in order to put z1 into the bissecting
|
|
* diffraction condition. Returns 1 on success and 0 if z1 and lambda
|
|
* were invalid. The m version acts upon a matrix.
|
|
*/
|
|
int z1ToBisecting(double lambda, double z1[3], double *stt, double *om,
|
|
double *chi, double *phi);
|
|
|
|
int z1mToBisecting(double lambda, MATRIX z1, double *stt, double *om,
|
|
double *chi, double *phi);
|
|
/**
|
|
* calculates diffraction angles to put z1 into a detector with a given
|
|
* offset in omega against the bisecting position. Useful for tweaking
|
|
* if omega is restricted.
|
|
*/
|
|
int z1ToAnglesWithOffset(double lambda, MATRIX z1, double omOffset,
|
|
double *stt, double *om,
|
|
double *chi, double *phi);
|
|
|
|
/**
|
|
* calculates a PSI for a given offset in omega from the bisecting
|
|
* position. This can be useful for tweaking reflections to be
|
|
* measurable at omega restricted diffractometers.
|
|
*/
|
|
int psiForOmegaOffset(MATRIX z1, double omOffset,
|
|
double chi, double phi, double *psi);
|
|
|
|
/**
|
|
* calculate new setting angles for a psi rotation. Input are the angles
|
|
* calculated for a bisecting diffraction position. Output angles represent
|
|
* the new psi setting. This is the method described by Busing & Levy as the
|
|
* version when om == theta is psi = 0.
|
|
*/
|
|
void rotatePsi(double om, double chi, double phi, double psi,
|
|
double *newom, double *newchi, double *newphi);
|
|
|
|
/**
|
|
* calculate z1 from angles stt, om, chi and phi. The angles must not describe
|
|
* a bissecting position, however it is required that the angles describe a
|
|
* reflection measured in the horizontal plane.
|
|
*/
|
|
void z1FromAngles(double lambda, double stt, double om,
|
|
double chi, double phi, double z1[3]);
|
|
/*-----------------------------------------------------------------------
|
|
Normal beam calculations. Here the diffraction vector is expressed as
|
|
polar angles gamma and nu and omega.
|
|
-----------------------------------------------------------------------*/
|
|
/**
|
|
* calculate the normal beam angles omeganb, gamma and nu from the four
|
|
* circle angles twotheta, omega, chi and phi.
|
|
*/
|
|
int bisToNormalBeam(double twotheta, double omega, double chi, double phi,
|
|
double *omeganb, double *gamma, double *nu);
|
|
/**
|
|
* calculate normal beam angles from z1
|
|
*/
|
|
int z1mToNormalBeam(double lambda, MATRIX z1, double *gamma, double *om,
|
|
double *nu);
|
|
|
|
/**
|
|
* calculate the vector z1 from the normal beam angles omega, gamma and nu.
|
|
* chi and phi either do not exist or are 0.
|
|
*/
|
|
void z1FromNormalBeam(double lambda, double omega, double gamma,
|
|
double nu, double z1[3]);
|
|
|
|
/**
|
|
* calculate z1 from four circle angles plus gamma, nu
|
|
*/
|
|
void z1FromAllAngles(double lambda, double omega, double gamma,
|
|
double nu, double chi, double phi, double z1[3]);
|
|
/*------------------------------------------------------------------------
|
|
Utility
|
|
-------------------------------------------------------------------------*/
|
|
/**
|
|
* return val put into the 0 - 360 degree range
|
|
*/
|
|
double circlify(double val);
|
|
|
|
/**
|
|
* converts a vector to a Matrix type
|
|
*/
|
|
MATRIX vectorToMatrix(double z[3]);
|
|
|
|
/**
|
|
* converts Matrix zm to the vector z
|
|
*/
|
|
void matrixToVector(MATRIX zm, double z[3]);
|
|
|
|
/**
|
|
* chi rotation matrix for chi into chim
|
|
*/
|
|
void chimat(MATRIX chim, double chi);
|
|
|
|
/**
|
|
* phi rotation matrix for phi into phim
|
|
*/
|
|
void phimat(MATRIX phim, double phi);
|
|
/**
|
|
* calcTheta calculates theta for a z1
|
|
* returns 1 on success, 0 else
|
|
*/
|
|
int calcTheta(double lambda, MATRIX z1, double *d, double *theta);
|
|
|
|
/**
|
|
* try very hard to calculate settings for the bisecting position
|
|
* within the instruments limits. Tries to tweak omega and to rotate
|
|
* psi until a usable position can be found.
|
|
* @param lambda The wavelength
|
|
* @param z1 The scattering for which to find a position
|
|
* @param fSet The output setting angles. In case of a failure this
|
|
* contains the normal setting angles for psi = 0. The order is:
|
|
* 2 theta, om, chi, phi
|
|
* @testFunc A user supplied function which test if the setting angles
|
|
* are in range.
|
|
* @param userData A user specified pointer to some data which may be needed
|
|
* in testing the range.
|
|
* @return 0 on failure, 1 on success.
|
|
*/
|
|
typedef int (*inRange) (void *userData, double dSet[4], int mask[4]);
|
|
int findAllowedBisecting(double lambda, MATRIX z1, double fSet[4],
|
|
inRange testFunc, void *userData);
|
|
|
|
#endif
|