\subsection{Monochromators} The code in these modules support standard crystal monochromators. The code is divided into two groups: There is the selector module which does most of the monochromator handling. And there are selvars, virtual motors which allow to drive the wavelength or the energy (for those triple axis guys) directly via the drive command. The monochromator module does not only adjust theta and two theta for the monochromator but also horizontal and vertical benders. The formula used for calculating the bending radius is: $b = C1 + \frac{C2}{sin(Theta)}$. This object is implemented in the files selector.h and selector.c. As the configuration parameters of this object include the scattering sense, ss, it is also suitable for running the analyzer of a triple axis instrument. \subsubsection{The Selector Device} The monochromator is described by the following data structure: \begin{verbatim} typedef struct __SicsSelector { ObjectDescriptor *pDes; ObPar *pParams; char *name; pMotor pTheta; pMotor pTwoTheta; pMotor pBend1; pMotor pBend2; char *pType; } SicsSelector; \end{verbatim} The fields: \begin{description} \item[pDes] A pointer to the usual SICS object descriptor. \item[pParams] A pointer to a SICS parameter array (see helper modules for more details). \item[name] The name of the monochromator. \item[pTheta] A pointer to the data structure for the Theta motor. \item[pTwoTheta] A pointer to the data structure for the Two Theta motor. \item[pBend1] A pointer to the data structure for the first bender motor. \item[pBend2] A pointer to the data structure for the second bender motor. \end{description} Please note, that troughout the code the bender motors are handled as optional. The monochromator can be accessed with the following functions: \begin{description} \item[pSicsSelector CreateSelector(char *name, pMotor pTheta, pMotor pTwoTheta,\\ pMotor pBend1, pMotor pBend2)] creates a new monochromator name with motors. The bender motors are optional, theta and two theta are required. Returns a pointer to a new monochromator data structure on success or NULL on failure. \item[int MonoInit(SConnection *pCon,SicsInterp *pSics, void *pData, \\ int argc, char *argv[])] The monochromator factory function. \item[void DeleteSelector(void *self)] deletes a monochromator. \item[int MonoAction(SConnection *pCon, SicsInterp *pSics, void *pData,\\ int argc, char *argv[])] The object wrapper function for the monochromator. \item[int MonoRun(pSicsSelector self, SConnection *pCon, float fWaveLength)] starts the selector to run to wavelength fWaveLength. Does not wait for finish. Eventual error messages are sent to pCon. \item[int MonoLimits(pSicsSelector self, float fWaveLength, char *error, \\ int iErrLen)] checks if fWaveLength violates any motor limits. If so maximum iErrLen characters of description are copied to error. \item[int MonoCheck(pSicsSelector self, SConnection *pCon)] does a status check on all the monochromator motors. The result is the worst of the motor status codes as returned from the motors. \item[int MonoHalt(pSicsSelector self)] emergency halts the monochromator. \item[float GetMonoPosition(pSicsSelector self, SConnection *pCon)] get the current wavelength of the monochromator. Possible errors are rported to pcon. On error this function returns -999, else the current wavelength is returned. \item[char *MonoGetType(pSicsSelector self)] gets the type of the monochromator. \item[int GetMonoPositions(pSicsSelector self, SConnection *pCon, \\ float *fTheta, float *fTwtTh, float *fB1, float *fB2)] gets the positions for all the monochromators motors. \end{description} \subsubsection{The Monochromator Virtual Motors} This module implements the wavelength or energy variable to act upon a monochromator. Both types are represented by a special data structure: \begin{verbatim} typedef struct __SelVar { pObjectDescriptor pDes; pSicsSelector pSel; pIDrivable pDrivInt; float fValue; char *name; } SelVar; \end{verbatim} The fields: \begin{description} \item[pDes] A pointer to the usual SICS object descriptor. \item[pSel] A pointer to the monochromator object to use for adjusting. \item[pDrivInt] A pointer to the drivable interface implemented. \item[fValue] The current value of the variable. \item[name] The name of the virtual motor. \end{description} Most of the action for these variables is hidden in the drivable interface. This is also where the conversions between energy and wavelength are done. Consequently the interface to this module consists mostly of creation and deletion functions: \begin{description} \item[pSelVar CreateWLVar(char *name, pSicsSelector pSel)] creates a wavelength variable. \item[pSelVar CreateEnergy(char *name, pSicsSelector pSel)] creates an energy variable for monochromator pSel Both functions return NULL on failure and a pointer to a selector variable data structure in case of success. \item[void DeleteSelVar(void *pSelf)] deletes a selector variable. \item[int MakeWaveLengthVar(SConnection *pCon, SicsInterp *pSics, void *pData,\\ int argc, char *argv[])] factory function for a wavelength variable. \item[int MakeEnergyVar(SConnection *pCon, SicsInterp *pSics, void *pData,\\ int argc, char *argv[])] factory function for a energy variable. \item[float GetSelValue(pSelVar self, SConnection *pCon)] retrieves the current value of the variable. In case of errors -999 is returned and error messages are printed to pCon. \item[int WaveLengthAction(SConnection *pCon, SicsInterp *pSics, void *pData,\\ int argc, char *argv[])] The object wrapper function for a wavelength variable. \item[int EnergyAction(SConnection *pCon, SicsInterp *pSics, void *pData,\\ int argc, char *argv[])] The object wrapper function for a energy variable. \end{description} Please note, that most of the important variables for handling a monochromator reside with the monochromator object and not with the virtual motors.