\subsection{Optimise}
In instrument control the need arises to optimise a peak with respect to
several variables. This is usually the case during instrument calibration.
Four circle diffractometers however use this facility on a day to day basis
for finding and verifying the exact position of reflections. In order to
support both usages a more general module has been implemented. The way of
operation is like this:
\begin{verbatim}
while errors > precision and cycles < maxcycles
  for all variables treated
      do a scan
      Try find the maximum, two halfwidth points and the peak center.
      if failure extend the scan.
      if success shift the variable, remember last shift. 
      If shift < precicison mark this variable as done
   end for
end while
\end{verbatim}
Possible outcomes of this procedure are: success, the peak was lost or the
maximum number of cycles was reached. This routine requires that the
instrument is currently placed somewhere on the peak and not miles away.

In order to use this scheme some general control variables are required:
\begin{description}
\item[iMaxCycles] The maximum number of cycles to run.
\item[lThreshold] A threshold value used when determining if the peak was
lost.
\item[eMode] The counter mode to count in.
\item[fPreset] The preset to use when counting.
\item[iChannel] The channel to use as signal when counting. This is to
support this technique on a monitor rather then with a counter. Useful for
calibration.  
\end{description}

For each variable to optimise we have to hold the following items:
\begin{description}
\item[name] Variable name.
\item[fStep] The step size to use for scanning
\item[nStep] The number of steps to go in each direction by default. This
parameter and the step size should together encompass somewhat more then the
width of the peak.
\item[fPrecision] The precision required or expected for this variable.
\item[fShift] The shift necessary for the last variable.
\end{description}
Of this the user is required to enter: name, fStep, nStep and fPrecision.

For some of its work, this module relies on the scan object (scan.*) and the
fitcenter object (fitcenter.*).

Internally the optimiser uses the following data structures:
\begin{verbatim}
   typedef struct {
                    char *pName;
                    float fStep;
                    int iStep;
                    float fPrecision;
                    float fCenter;
                    float fShift;
                    pIDrivable pDriv; 
                    void       *pData;
                    int iLost;
                  } OVarEntry, *pOVarEntry;
\end{verbatim}
This is the data structure for each variable to optimise during an
optimser run.  The fields are:
\begin{description}
\item[pName] the name of the variable.
\item[fStep] The step width to use for scanning the variable.
\item[fPrecision] The precision required for this variable. Used to
mark this variable OK if the last shift is less then this precision
value.
\item[fCenter] The calculated center of this variable.
\item[fShift] The last shift calculated for this variable.
\item[pDriv] A pointer to the drivable interface of this variable.
\item[pData] A  pointer to this variables data structure. 
\item[iLost] A flag which marks if the peak has been lost with respect
to this variable. 
\end{description}


The optimiser itself uses the following data structure:
\begin{verbatim}
   typedef struct __OptimiseStruct {
                                     pObjectDescriptor pDes;
                                     int               iMaxCycles;
                                     CounterMode       eCount;
                                     float             fPreset;
                                     int               iChannel;
                                     float             fThreshold;
                                     int               iVar;
                                     pDynar            pVariables;
                                     pScanData         pScanner;
                                     pFit              pPeakFitter;
                                    } Optimiser;
\end{verbatim}
The fields are:
\begin{description}
\item[pDes]The usual object descriptor.
\item[iMaxCycles] The maximum number of cycles to perform.
\item[eCount] The countmode to use for scanning.
\item[fPreset] The preset to use for scanning.
\item[iChannel] The channel to use for scanning. 
\item[fThreshold] The threshold to use for identifying lost peaks.
\item[iVar] The number of variables to optimise.
\item[pVariables] A dynamic array of variables to optimise.
\item[pScanner] The scan object to use for scanning.
\item[pFit] The peak center determination object to use. 
\end{description}


The interface to this object looks like this:
@o optimise.h @{
/*-------------------------------------------------------------------------
                   O P T I M I S E

  Optimise a peak with respect to several variables.

  copyright: see copyright.h

  Mark Koennecke, March 1998-1999
-----------------------------------------------------------------------------*/
#ifndef SICSOPTIMISE
#define SICSOPTIMISE

     typedef struct __OptimiseStruct *pOptimise;

/*------------------- live & death -----------------------------------------*/
   pOptimise CreateOptimiser(pCounter pCount);
   void      DeleteOptimiser(void *pData);
   int       MakeOptimiser(SConnection *pCon, SicsInterp *pSics,
                           void *pData, int argc, char *argv[]);
/*------------------- operation  -------------------------------------------*/
#define PEAKLOST   -1
#define MAXCYCLE   -2
#define SCANERROR  -3
#define SCANABORT  -4
#define SYSERROR   -5
#define DRIVEERROR -6
#define VARREDO    -7


  void OptimiserClear(pOptimise self);
  int  OptimiserAdd(pOptimise self,
                   char *pVarName, 
                   float fStep, 
                   int nStep, 
                   float fPrecision);
  int OptimiserSetPar(pOptimise self, char *name, float fVal);
  int OptimiserGetPar(pOptimise self, char *name, float *fVal);

  int OptimiserRun(pOptimise self, SConnection *pCon); 

  int OptimiserAction(SConnection *pCon, SicsInterp *pSics, void *pData,
                      int argc, char *argv[]);
#endif
@}


All functions except the installation functions take a pointer to the
optimiser structure as first parameter. The function reference:
\begin{description}
\item[CreateOptimiser] creates an optimiser object. Takes a pointer to
a counter object as a parameter. Returns a pointer to a nice and good
optimiser object on return. Or NULL, if there was some sort of
problem. 
\item[DeleteOptimiser] is the deletion function used in the
interpreter for properly removing the optimiser object from the
system. 
\item[MakeOptimiser] is the installation function which configures an
optimiser into SICS.
\item[OptimiserClear] removes all configured optimisation variables
and all remnants of a previous optimiser run.
\item[OptimiserAdd] adds a variable to be optimised. Parameter to this
call are:  pVarName, the name of the variable to optimise, fStep, the
step width to use for scanning, nStep, the initial number of steps to
use for scanning, fPrecision, the precision to achive for this
variable.
\item[OptimiserSetPar] sets the configuration parameters for the
optimiser. The parameter name is the same name as stated in the
command reference.
\item[OptimiserGetPar] retrieves the value of  a configuration
parameters  for the
optimiser. The parameter name is the same name as stated in the
command reference.
\item[OptimiserRun] starts the optimser run with the current
parameters. Output is sent to the connection pCon.
\item[OptimiserAction] is the interpreter interface function for the
optimiser. 
\end{description}
