\subsection{Scan} The first version of the scan command was implemented in Tcl. This prooved to be inefficient. Therefore the main lop for scan is reimplemented in C. A scan is in principle simple. However some complications are due to the fact that data files need to be written. Disk files need to be updated after each scan point. It must be possible to create derivations of the scan command which create other data formats. Another complication is, that users might want to interrupt scans and restart from the last safe position. All this requires a fairly complicated data structure. Scan makes use of the dynamic array package described elsewhere. @d scandata @{ typedef struct { char Name[132]; pIDrivable pInter; pDummy pObject; float fStart; float fStep; float *fData; }VarEntry, *pVarEntry; /*--------------------------------------------------------------------------*/ typedef struct { int i; long lCount; long Monitors[10]; float fTime; } CountEntry, *pCountEntry; /*---------------------------------------------------------------------------*/ typedef struct __ScanData { pObjectDescriptor pDes; pICallBack pCall; pDynar pScanVar; int iScanVar; int iNP; int iMode; float fPreset; char pFile[1024]; FILE *fd; SicsInterp *pSics; SConnection *pCon; char pRecover[1024]; char pHeaderFile[1024]; int (*WriteHeader)(pScanData self); int (*WriteScanPoints) (pScanData self); long lPos; void *pCounterData; char pCounterName[512]; int iChannel; pDynar pCounts; int iCounts; int iActive; int iWindow; char *pCommand; } ScanData; @} This datastructure contains the following fields: \begin{description} \item[pDes] The standard SICS object descriptor. \item[pCall] A pointer to the standard SICS callback interface. Scan support the SCANPOINT message which will be executed after each scan point. \item[pScanVar, iScanVar] A dynamic array of VarEntry structures which define the variables to drive in the scan. iScanVar is the total number of scan variables. A scan might drive more then one motor or variable. \item[iNP] is the number of scan points. \item[iMode] is the counter mode to use. \item[fPreset] is the preset value for the counter at each scan point. The exponents set for the counter apply. \item[pFile] is the name of the data file to write. This will be created automatically from SICS variables at the start of a scan. \item[fd] is the file descriptor for the open file when writing. fd will be opened by WriteHeader and closed again after WriteScanPoints. \item[pRecover] is the name of the recover file. After each scan point scan writes some data to file which allows to restart an aborted scan. \item[pHeaderFile] is the name of a template file which will be used for generating the scan file header. Its format is simple: Everything except a few keywords will be copied verbatim. The keywords will be replaced by their apropriate values. Valid keywords are: !!DATE!! for the current date, !!VAR(name)!! for the value of a simple Sics variable, !!DRIV(name)!! for a Sics scan variable. The name of the variable is given in parenthesis. !!VAR!! and !!DRIV!! can be distinguished easily: Try a run or drive command on the variable in question. If it works and does not complain, it is the second sort. The second sort are mostly motors or collective variables such as lambda etc. Only one value of such a type per line is permitted. \item[pSics] a pointer to a SICS interpreter to use while running for finding data. \item[pCon] The connection object to use for error reporting during scan execution. \item[WriteHeader] is a pointer to a function which writes the header part of the scan file. Replace this function if another data format is needed. \item[WriteScanPoints] is a pointer to a function which will be called after each scan point to write the scan data to the data file. Replace this function when another data format is needed. \item[pCounterData] is a pointer to a counter structure. This defines the counter to use and is initialized at creation of the scan data structure. \item[pCountername] is the name of the counter used. \item[iChannel] is the channel to use for counting. 0 is the main counter, everything baove one of the monitors. \item[pCount, iCounts] is a dynamic array containing iCounts sets of counting infomation. For each scan point this array holds the counts measured. iCounts is also the current scan position. \item[iWindow] the width of the window used for peak integration. See integrate.w,c for more details. \item[pCommand] It turned out that a way is needed to define user defined speciality scans. This is implemented by setting the channel number to -10 and then have the scan command execute a Tcl script for each scan point. This Tcl script has to return a Tcl list containing the values to enter for counter and monitor for the scan point. pCommand now is the name of the Tcl procedure to invoke. \end{description} The functional interface to the scan module includes the following functions: @d scaninter @{ /*------------------------- live & death ----------------------------------*/ pScanData CreateScanObject(char *pRecover, char *pHeader, pCounter pCount); void DeleteScanObject(void *self); /*-------------------------------------------------------------------------*/ int AddScanVar(pScanData self, SicsInterp *pSics, SConnection *pCon, char *name, float fStart, float fStep); int ClearScanVar(pScanData self); int DoScan(pScanData self, int iNP, int iMode, float fPreset, SicsInterp *pSics, SConnection *pCon); int SilentScan(pScanData self, int iNP, int iMode, float fPreset, SicsInterp *pSics, SConnection *pCon); int RecoverScan(pScanData self, SicsInterp *pSics, SConnection *pCon); int GetScanCounts(pScanData self, long *lData, int iDataLen); int GetScanVar(pScanData self, int iWhich, float *fData, int iDataLen); int GetScanVarName(pScanData self, int iWhich, char *pName, int iLength); int GetScanMonitor(pScanData self, int iWhich, long *lData, int iDataLen); int GetScanNP(pScanData self); int ScanIntegrate(pScanData self, float *fSum, float *fVariance); int SimScan(pScanData self, float fPos, float FHWM, float fHeight); /*------------------------ Interpreter Interface --------------------------*/ int ScanFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); int ScanWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); @} @o scan.h @{ /*--------------------------------------------------------------------------- S C A N Header file for the SICS scan object. Mark Koennecke, October 1997 copyright: see copyright.h -----------------------------------------------------------------------------*/ #ifndef SICSSCAN1 #define SICSSCAN1 typedef struct __ScanData *pScanData; /*--------------------------------------------------------------------------*/ #include "counter.h" @ #endif @} @o scan.i @{ /*-------------------------------------------------------------------------- Internal header file holding the definition of the scan objects data structure. Mark Koennecke, October 1997 ----------------------------------------------------------------------------*/ @ @}