4.13. - Least-Squares Refinement of Lattice Parameters
In the previous sections, the procedure described for determining the orientation matrix required a knowledge of the lattice parameters of the crystal and the position of two reflections. When such information is unknown, the orientation matrix can be fit to an unlimited number of observed peak positions using a least-squares procedure. ( J. Matthews and R.L. Walker, Mathematical Methods of Physics, (Benjamin, Menlo Park, 1970), p. 391. ) Lattice parameters derived from the fitted orientation matrix can then be calculated, although such lattice parameters are not constrained to exhibit any symmetry whatsoever.
In spec's implementation of least square refinement, three macros are used to create a file that contains the observed peak positions. That file is eventually run as a command file, and the least squares analysis is performed.
The
reflex_beg
macro initializes the reflections
file:
global REFLEX # Variable for file name # Open the file, save old one as .bak and write header def reflex_beg '{ if ("$1" == "0") { if (REFLEX == ") REFLEX = "reflex" REFLEX = getsval("Reflections file", REFLEX) } else REFLEX = "$1" if (open(REFLEX)) exit close(REFLEX) if (file_info(REFLEX, "-s")) unix(sprintf("mv %s %s.bak", REFLEX, REFLEX)) fprintf(REFLEX,"# %s\n\n_begUB\n\n",date()) }'
The
reflex
macro adds lines to the file that
contain
the (H,K,L)
and (2θ,θ,χ,φ)
of each reflection:
# Add reflection to the file def reflex ' if ($# != 3) { print "Usage: reflex H K L" exit } if (REFLEX == ") { REFLEX = getsval("Reflections file", "reflex") if (REFLEX == ") exit } waitmove; get_angles; calcHKL fprintf(REFLEX,"H = %g; K = %g; L = %g\n",$1,$2,$3) { local i for (i=0; i<_numgeo; i++) fprintf(REFLEX,"A[%s]=%9.4f; ",motor_mne(mA[i]),A[mA[i]]) fprintf(REFLEX,"\n") } fprintf(REFLEX,"# counts = %g\n", S[DET]) fprintf(REFLEX,"_addUB\n\n") '
Finally, the
reflex_end
macro puts the proper trailer on the file:
# Add trailer to file def reflex_end ' fprintf(REFLEX,"_fitUB\n") printf("Type \"qdo %s\" to calculate new orientation matrix\n",\ REFLEX) '
When you are ready to calculate the orientation matrix, simply run the command file. There is no limit to the number of reflections contained in the file. You can also edit the file by hand to add or subtract reflections.
The calculated orientation matrix will remain valid until you type
calcG
,
or invoke a macro that calls
calcG
. Those macros are
or0
, or1
, or_swap
and
setlat
. The six original lattice parameters will remain unchanged when using the above macros to fit the orientation matrix to the reflections. The
calcL
macro can be invoked to calculate the lattice parameters
derived from the fitted orientation matrix and place their values
in the appropriate elements of the parameter
array.
The old lattice parameters will be lost.
Here is a sketch of the commands you use to perform the least squares refinement of the lattice parameters.
1.FOURC> reflex_beg
Reflections file (reflex)? <return> 2.FOURC> (find and move to a reflection ...)
3.FOURC> reflex 2 2 0
4.FOURC> (find and move to another reflection ...)
5.FOURC> reflex 2 0 2
6.FOURC> ...
7.FOURC> reflex_end
Type "qdo reflex" to recalculate orientation matrix. 8.FOURC> qdo reflex
Opened command file `reflex' at level 1. 9.FOURC>
At least three reflections must be used for the least-squares fitting to work.
To calculate the new lattice parameters, use the
calcL
macro:
1.FOURC> calcL
2.FOURC> pa
Four-Circle Geometry, Omega fixed (mode 1) Frozen values: Omega = 5 Sector 0 Primary Reflection (at lambda 1.54): tth th chi phi = 74.212 42.106 89.898 -80.2141 H K L = 2 2 0 Secondary Reflection (at lambda 1.54): tth th chi phi = 24.631 17.3155 135.315 -82.9029 H K L = 0 1 0 Lattice Constants (lengths / angles): real space = 4.127 4.123 4.111 / 90.04 89.98 90.12 reciprocal space = 1.523 1.524 1.528 / 89.96 90.02 89.88 Azimuthal Reference: H K L = 0 0 1 Cut Points: tth th chi phi -180 -180 -180 -180 3.FOURC>
Here is a typical reflections file created by the above macros:
# Wed Jan 31 21:55:01 1990 _begUB H = 2; K = 2; L = 0 A[tth]= 63.8185; A[th]= 36.9320; A[chi]= 89.8765; A[phi]= -80.0815 # counts = 3456 _addUB H = 2; K = 0; L = 2 A[tth]= 63.8335; A[th]= 36.8920; A[chi]= 145.4185; A[phi]= 42.8145 # counts = 6345 _addUB H = 0; K = 2; L = -1 A[tth]= 49.4100; A[th]= 29.6725; A[chi]= 35.8180; A[phi]= 45.9070 # counts = 5634 _addUB H = 0; K = 2; L = -1 A[tth]= 49.3550; A[th]= 29.7225; A[chi]= 35.9380; A[phi]= 45.9070 # counts = 4563 _addUB _fitUBWithin this file, the
calc()
function codes defined by the macros
_begUB
, _addUB
and
_fitUB
are used to access the C code that performs the least squares operations.