Files
sics/hklscan.c
cvs d782d43951 - added backwards calculation of hkl from four circle angles. This
required inclusion of a matrix package.
- modified  counter error handling to send a Stop when the _BAD_BUSY
  error is received.
- added an environment interface to the general controller stuff in choco.*
  Also added setting a parameter directly at the controller object.
- Added a driver for the ETH High Temperature Furnace to be used at
  SANS.
2000-07-12 12:01:19 +00:00

445 lines
12 KiB
C

/*--------------------------------------------------------------------------
H K L S C A N
A class for doing scans in reciprocal space for a four circle
diffractometer. All the hard work is done in the scan and hkl objects.
copyright: see copyright.h
Mark Koennecke, June 1999
--------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <tcl.h>
#include "fortify.h"
#include "sics.h"
#include "scan.h"
#include "hkl.h"
#include "scan.i"
#include "matrix/matrix.h"
#include "hkl.i"
#include "hklscan.i"
#include "hklscan.h"
/*-----------------------------------------------------------------------*/
static void KillHklscan(void *pData)
{
pHklscan self = NULL;
self = (pHklscan)pData;
if(!self)
{
return;
}
if(self->pDes)
{
DeleteDescriptor(self->pDes);
}
free(self);
}
/*------------------------------------------------------------------------*/
int HklscanFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[4])
{
pHklscan pNew = NULL;
char pBueffel[512];
int iRet;
/* check number of arguments */
if(argc < 3)
{
SCWrite(pCon,
"ERROR: expected two arguments to MakeHklscan",eError);
return 0;
}
/* allocate space */
pNew = (pHklscan)malloc(sizeof(sHklscan));
if(!pNew)
{
SCWrite(pCon,"ERROR: out of memory in MakeHklscan",eError);
return 0;
}
memset(pNew,0,sizeof(sHklscan));
pNew->pDes = CreateDescriptor("Hklscan");
/* find scan object */
pNew->pScan = (pScanData)FindCommandData(pSics,argv[1],"ScanObject");
if(!pNew->pScan)
{
sprintf(pBueffel,"ERROR: %s not found or no scan object",argv[1]);
SCWrite(pCon,pBueffel,eError);
KillHklscan(pNew);
return 0;
}
/* find HKL object */
pNew->pCalc = (pHKL)FindCommandData(pSics,argv[2],
"4-Circle-Calculus");
if(!pNew->pCalc)
{
sprintf(pBueffel,"ERROR: %s not found or no HKL object",argv[2]);
SCWrite(pCon,pBueffel,eError);
KillHklscan(pNew);
return 0;
}
/* alright. Install command */
iRet = AddCommand(pSics, "hklscan",
HklscanAction,KillHklscan,pNew);
if(!iRet)
{
SCWrite(pCon,"ERROR: duplicate command hklscan NOT created",eError);
KillHklscan(pNew);
return 0;
}
return 1;
}
/*------------------------------------------------------------------------*/
static int HklscanDrive(pScanData pScan, int iPoint)
{
pHklscan self = NULL;
int i, iRet;
assert(pScan);
self = (pHklscan)pScan->pSpecial;
assert(self);
/* calculate new Positions */
for(i = 0; i < 3; i++)
{
self->fPos[i] = self->fStart[i] + iPoint * self->fStep[i];
}
iRet = DriveHKL(self->pCalc, self->fPos, 0.,0,pScan->pCon);
if(!iRet)
{
SCWrite(pScan->pCon,"ERROR: aborting hklscan",eError);
}
return iRet;
}
/*------------------------------------------------------------------------*/
static int WriteHklscanPoint(pScanData self, int iPoint)
{
pHklscan pHaSca = NULL;
int i, i2;
char pLine[512], pItem[30], pInfo[512];
pVarEntry pVar = NULL;
pCountEntry pData = NULL;
void *pPtr = NULL;
assert(self);
pHaSca = (pHklscan)self->pSpecial;
assert(pHaSca);
assert(self->pCon);
assert(self->pSics);
if(!self->fd)
{
self->fd = fopen(self->pFile,"r+");
if(!self->fd)
{
SCWrite(self->pCon,"ERROR: failed to reopen scan file during scan",eError);
return 0;
}
}
/* jump to end of header */
fseek(self->fd,self->lPos, SEEK_SET);
if(self->iChannel != 0)
{
fprintf(self->fd,"WARNING: Scanning monitor %d\n",self->iChannel);
}
/* make the data header */
sprintf(pLine,"%-5s","NP");
strcpy(pInfo,"Scanning Variables: H, K, L");
strcat(pLine,"H K L ");
for(i = 0; i < self->iScanVar;i++)
{
DynarGet(self->pScanVar,i,&pPtr);
pVar = (pVarEntry)pPtr;
if(pVar)
{
sprintf(pItem,"%-6.6s ",pVar->Name);
strcat(pLine,pItem);
}
}
strcat(pLine,"Counts ");
strcat(pLine,"Monitor1 ");
sprintf(pItem,"\n%d Points,",self->iNP);
strcat(pInfo,pItem);
if(self->iMode == eTimer)
{
strcat(pInfo," Mode: Timer,");
}
else
{
strcat(pInfo," Mode: Monitor,");
}
sprintf(pItem," Preset %f",self->fPreset);
strcat(pInfo,pItem);
fprintf(self->fd,"%s\n",pInfo);
fprintf(self->fd,"%s\n",pLine);
/* print an addon to the status line going to the screen */
sprintf(pLine,"NP H K L ");
SCWrite(self->pCon,pLine,eWarning);
sprintf(pLine,"%-5d%-6.2f%-6.2f%-6.2f ",iPoint,pHaSca->fPos[0],
pHaSca->fPos[1], pHaSca->fPos[2]);
SCWrite(self->pCon,pLine,eWarning);
/* now the scan points */
for(i = 0; i < self->iCounts; i++)
{
sprintf(pLine,"%-5d",i);
/* print HKL */
for(i2 = 0; i2 < 3; i2++)
{
sprintf(pItem,"%-6.2f",pHaSca->fStart[i2] + i * pHaSca->fStep[i2]);
strcat(pLine,pItem);
}
/* print chi, ph, om */
for(i2 = 0; i2 < self->iScanVar; i2++)
{
DynarGet(self->pScanVar,i2,&pPtr);
pVar = (pVarEntry)pPtr;
if(pVar)
{
sprintf(pItem,"%-7.2f",pVar->fData[i]);
strcat(pLine,pItem);
}
}
/* print Counts & Monitor */
DynarGet(self->pCounts,i,&pPtr);
pData = (pCountEntry)pPtr;
if(pData)
{
sprintf(pItem,"%-12ld",pData->lCount);
strcat(pLine,pItem);
sprintf(pItem,"%-12ld",pData->Monitors[0]);
strcat(pLine,pItem);
}
fprintf(self->fd,"%s\n",pLine);
}
/* done */
fprintf(self->fd,"END-OF-DATA\n");
fclose(self->fd);
self->fd = NULL;
return 1;
}
/*------------------------------------------------------------------------*/
int Hklscan(pHklscan self, SConnection *pCon,
int iNP, int iMode, float fPreset)
{
int iRet;
float fVal;
assert(self);
/* configure the scan thing for our bizarre purpose */
ClearScanVar(self->pScan);
MotorGetPar(self->pCalc->pTheta, "softlowerlim",&fVal);
fVal += .5;
AddScanVar(self->pScan,pServ->pSics,pCon,self->pCalc->pTheta->name,
fVal,0.);
MotorGetPar(self->pCalc->pOmega, "softlowerlim",&fVal);
fVal += .5;
AddScanVar(self->pScan,pServ->pSics,pCon,self->pCalc->pOmega->name,
fVal,0.);
MotorGetPar(self->pCalc->pChi, "softlowerlim",&fVal);
fVal += .5;
AddScanVar(self->pScan,pServ->pSics,pCon,self->pCalc->pChi->name,
fVal,0.);
MotorGetPar(self->pCalc->pPhi, "softlowerlim",&fVal);
fVal += .5;
AddScanVar(self->pScan,pServ->pSics,pCon,self->pCalc->pPhi->name,
fVal,0.);
self->pScan->WriteScanPoints = WriteHklscanPoint;
self->pScan->ScanDrive = HklscanDrive;
self->pScan->pSpecial = self;
/* scan */
iRet = DoScan(self->pScan,iNP, iMode, fPreset, pServ->pSics,pCon);
/* unset all */
ClearScanVar(self->pScan);
ResetScanFunctions(self->pScan);
self->pScan->pSpecial = NULL;
return iRet;
}
/*-------------------------------------------------------------------------*/
int HklscanAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
char pBueffel[512];
int iRet, iMode, iNP;
pHklscan self = NULL;
double dVal;
float fPreset;
assert(pCon);
assert(pSics);
assert(pData);
self = (pHklscan)pData;
/* check for the command word */
if(argc < 2)
{
SCWrite(pCon,"ERROR: Insufficient number of arguments to hklscan",
eError);
return 0;
}
/* do work according to command word */
strtolower(argv[1]);
if(strcmp(argv[1],"start") == 0)
{
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
if(argc < 5)
{
SCWrite(pCon,
"Insufficient number of arguments to hklscan",
eError);
return 0;
}
iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dVal);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: failed to convert %s to number",
argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
self->fStart[0] = (float)dVal;
iRet = Tcl_GetDouble(pSics->pTcl,argv[3],&dVal);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: failed to convert %s to number",
argv[3]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
self->fStart[1] = (float)dVal;
iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&dVal);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: failed to convert %s to number",
argv[4]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
self->fStart[2] = (float)dVal;
SCSendOK(pCon);
return 1;
}
else if(strcmp(argv[1],"step") == 0)
{
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
if(argc < 5)
{
SCWrite(pCon,
"Insufficient number of arguments to hklscan",
eError);
return 0;
}
iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dVal);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: failed to convert %s to number",
argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
self->fStep[0] = (float)dVal;
iRet = Tcl_GetDouble(pSics->pTcl,argv[3],&dVal);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: failed to convert %s to number",
argv[3]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
self->fStep[1] = (float)dVal;
iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&dVal);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: failed to convert %s to number",
argv[4]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
self->fStep[2] = (float)dVal;
SCSendOK(pCon);
return 1;
}
else if(strcmp(argv[1],"run") == 0)
{
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
if(argc < 5)
{
SCWrite(pCon,
"Insufficient number of arguments to hklscan run",
eError);
return 0;
}
iRet = Tcl_GetInt(pSics->pTcl,argv[2],&iNP);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: failed to convert %s to number",
argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* interpret Mode */
if(strcmp(argv[3],"timer") == 0)
{
iMode = eTimer;
}
else if(strcmp(argv[3],"monitor") == 0)
{
iMode = ePreset;
}
else
{
sprintf(pBueffel,"ERROR: %s not recognized as valid counter mode",
argv[3]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* preset */
iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&dVal);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
fPreset = (float)dVal;
iRet = Hklscan(self,pCon,iNP,iMode,fPreset);
if(iRet)
{
SCSendOK(pCon);
}
return iRet;
}
sprintf(pBueffel,
"ERROR: %s not recognized as command word to hklscan",argv[1]);
SCWrite(pCon,pBueffel,eError);
return 0;
}