Files
sics/hklscan.c
koennecke b737b4d936 - Many fixes to accomodate a nitty picky TRICS wishlist
- Added a log facility to scan which includes a variable which is logged but
  not driven during a scan.
- Fixed normal beam operation
2006-01-27 11:33:06 +00:00

456 lines
13 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
This is obsolete: h,k,l are now drivable. Logged variables have been added
to the scan module. The command is now implemented through scripts.
This module is left in the source tree in order to allow for a quick
reinstallation in case of problems but should be retired from the
source tree in the shutdown 2007
Mark Koennecke, January 2006
--------------------------------------------------------------------------*/
#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");
sprintf(pInfo,"Scanning Variables: H, K, L STEP: %8.3f %8.3f %8.3f",
pHaSca->fStep[0],pHaSca->fStep[1], pHaSca->fStep[2]);
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%-8.4f%-8.4f%-8.4f ",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," %-8.4f",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",GetScanVarPos(pVar,i));
strcat(pLine,pItem);
}
}
/* print Counts & Monitor */
DynarGet(self->pCounts,i,&pPtr);
pData = (pCountEntry)pPtr;
if(pData)
{
sprintf(pItem," %-13ld",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;
self->pScan->PrepareScan = NonCheckPrepare;
/* 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, iPoint;
pHklscan self = NULL;
double dVal;
float fPreset;
void *pPtr;
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;
}