1059 lines
27 KiB
C
1059 lines
27 KiB
C
/*---------------------------------------------------------------------------
|
|
H K L
|
|
|
|
Implementation of the SICS object for doing four circle diffractometer
|
|
angle calculations. The actual transformation routines were recoded
|
|
in C from F77 routines provided by J. Allibon, ILL with the MAD
|
|
system.
|
|
|
|
copyright: see copyright.h
|
|
|
|
Mark Koennecke, February 1998
|
|
|
|
Updated to use fourlib.
|
|
|
|
Mark Koennecke, December 2001
|
|
|
|
Introduced HM mode in order to cope with with the fact that TRICS has
|
|
three detectors.
|
|
|
|
Mark Koennecke, May 2002
|
|
|
|
Added handling of the chi ==0 or chi == 180 degree case to tryTweakOmega
|
|
|
|
Mark Koennecke, December 2003
|
|
|
|
Heavily reworked to fit into the new four circle setup
|
|
|
|
Mark Koennecke, July 2008
|
|
-----------------------------------------------------------------------------*/
|
|
#include <math.h>
|
|
#include <ctype.h>
|
|
#include "sics.h"
|
|
#include "fortify.h"
|
|
#include "motor.h"
|
|
#include "selector.h"
|
|
#include "selvar.h"
|
|
#include "fourlib.h"
|
|
#include "matrix/matrix.h"
|
|
#include "hkl.h"
|
|
#include "hkl.i"
|
|
#include "splitter.h"
|
|
#include "singlex.h"
|
|
#include "motorlist.h"
|
|
#include "cell.h"
|
|
#include "ubfour.h"
|
|
/*
|
|
the tolerance in chi we give before we allow to fix omega with phi
|
|
*/
|
|
#define CHITOLERANCE 3.
|
|
#define ABS(x) (x < 0 ? -(x) : (x))
|
|
/*-------------------------------------------------------------------------*/
|
|
static int HKLSave(void *pData, char *name, FILE *fd)
|
|
{
|
|
pHKL self = NULL;
|
|
|
|
self = (pHKL)pData;
|
|
if( (self == NULL) || (fd == NULL) )
|
|
{
|
|
return 1;
|
|
}
|
|
fprintf(fd,"#HKL Settings\n");
|
|
fprintf(fd,"%s scantolerance %f\n", name,self->scanTolerance);
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
pHKL CreateHKL()
|
|
{
|
|
pHKL pNew = NULL;
|
|
|
|
/* allocate memory */
|
|
pNew = (pHKL)malloc(sizeof(HKL));
|
|
if(!pNew)
|
|
{
|
|
return NULL;
|
|
}
|
|
memset(pNew,0,sizeof(HKL));
|
|
|
|
/* create object descriptor */
|
|
pNew->pDes = CreateDescriptor("4-Circle-Calculus");
|
|
pNew->pMotDriv = makeMotListInterface();
|
|
if(!pNew->pDes || pNew->pMotDriv == NULL)
|
|
{
|
|
free(pNew);
|
|
return NULL;
|
|
}
|
|
pNew->pDes->SaveStatus = HKLSave;
|
|
|
|
pNew->iQuad = 1;
|
|
pNew->iHM = 0;
|
|
pNew->UBinv = NULL;
|
|
pNew->scanTolerance = 2.5;
|
|
|
|
return pNew;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
void DeleteHKL(void *pData)
|
|
{
|
|
pHKL self = NULL;
|
|
|
|
self = (pHKL)pData;
|
|
if(!self)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(self->pDes)
|
|
{
|
|
DeleteDescriptor(self->pDes);
|
|
}
|
|
if(self->pMotDriv)
|
|
{
|
|
free(self->pMotDriv);
|
|
}
|
|
|
|
free(self);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
int HKLFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pHKL self = NULL;
|
|
int iRet;
|
|
|
|
/* make a new structure */
|
|
self = CreateHKL();
|
|
if(!self)
|
|
{
|
|
SCWrite(pCon,"ERROR: cannot allocate HKL data structure",eError);
|
|
return 0;
|
|
}
|
|
|
|
/* install a command */
|
|
iRet = AddCommand(pSics,
|
|
"HKL",
|
|
HKLAction,
|
|
DeleteHKL,
|
|
self);
|
|
if(!iRet)
|
|
{
|
|
SCWrite(pCon,"ERROR: duplicate command HKL not created",eError);
|
|
DeleteHKL(self);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
void SetHKLScanTolerance(pHKL self, float fVal)
|
|
{
|
|
assert(self);
|
|
self->scanTolerance = fVal;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int GetLambda(pHKL self, float *fVal)
|
|
{
|
|
assert(self);
|
|
double val;
|
|
|
|
val = SXGetLambda();
|
|
*fVal = (float)val;
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
int GetCurrentHKL(pHKL self, float fHKL[3])
|
|
{
|
|
int i;
|
|
|
|
assert(self);
|
|
|
|
for(i = 0; i < 3; i++)
|
|
{
|
|
fHKL[i] = self->fLastHKL[i];
|
|
}
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static void invertMatrix(pHKL self, float fUB[9]){
|
|
int i;
|
|
MATRIX m;
|
|
|
|
if(self->UBinv != NULL)
|
|
{
|
|
mat_free(self->UBinv);
|
|
}
|
|
m = mat_creat(3,3,ZERO_MATRIX);
|
|
for(i = 0; i < 3; i++)
|
|
{
|
|
m[0][i] = fUB[i];
|
|
m[1][i] = fUB[3+i];
|
|
m[2][i] = fUB[6+i];
|
|
}
|
|
self->UBinv = mat_inv(m);
|
|
mat_free(m);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
int SetUB(pHKL self, float fUB[9])
|
|
{
|
|
int i;
|
|
double dUB[9];
|
|
|
|
assert(self);
|
|
|
|
for(i = 0; i < 9; i++){
|
|
dUB[i] = fUB[i];
|
|
}
|
|
SXSetUB(dUB);
|
|
invertMatrix(self,fUB);
|
|
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
int GetUB(pHKL self, float fUB[9])
|
|
{
|
|
int i;
|
|
const double *dUB;
|
|
|
|
dUB = SXGetUB();
|
|
for(i = 0; i < 9; i++)
|
|
{
|
|
fUB[i] = (float)dUB[i];
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int SetNOR(pHKL self, int iNOB)
|
|
{
|
|
assert(self);
|
|
|
|
/* cannot set normal beam geometry if no nu motor */
|
|
if( (iNOB == 1) && (SXGetMotor(Nu) == NULL))
|
|
return 0;
|
|
|
|
switch(iNOB){
|
|
case 0:
|
|
SXSetMode(Bisecting);
|
|
break;
|
|
case 1:
|
|
SXSetMode(NB);
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
static int checkTheta(pHKL self, double *stt){
|
|
char pError[132];
|
|
int iTest;
|
|
float fHard;
|
|
pMotor pTheta;
|
|
|
|
pTheta = SXGetMotor(TwoTheta);
|
|
if(pTheta == NULL){
|
|
return 0;
|
|
}
|
|
|
|
iTest = MotorCheckBoundary(pTheta,(float)*stt, &fHard,pError,131);
|
|
if(!iTest){
|
|
return -1;
|
|
}
|
|
return iTest;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
int hklInRange(void *data, double fSet[4], int mask[4])
|
|
{
|
|
pHKL self = (pHKL)data;
|
|
float fHard, fLimit;
|
|
char pError[132];
|
|
int i, test;
|
|
double dTheta;
|
|
pMotor pOmega, pChi, pPhi;
|
|
|
|
pOmega = SXGetMotor(Omega);
|
|
pChi = SXGetMotor(Chi);
|
|
pPhi = SXGetMotor(Phi);
|
|
if(pOmega == NULL || pChi == NULL || pPhi == NULL){
|
|
return 0;
|
|
}
|
|
|
|
/* check two theta */
|
|
dTheta = fSet[0];
|
|
mask[0] = checkTheta(self, &dTheta);
|
|
fSet[0] = dTheta;
|
|
|
|
/* for omega check against the limits +- SCANBORDER in order to allow for
|
|
a omega scan.
|
|
*/
|
|
MotorGetPar(pOmega,"softlowerlim",&fLimit);
|
|
if((float)fSet[1] < fLimit + self->scanTolerance){
|
|
mask[1] = 1;
|
|
} else {
|
|
mask[1] = 0;
|
|
MotorGetPar(pOmega,"softupperlim",&fLimit);
|
|
if((float)fSet[1] > fLimit - self->scanTolerance){
|
|
mask[1] = 0;
|
|
} else {
|
|
mask[1] = 1;
|
|
}
|
|
}
|
|
|
|
/* check chi and phi*/
|
|
mask[2] = MotorCheckBoundary(pChi,fSet[2], &fHard,pError,131);
|
|
mask[3] = MotorCheckBoundary(pPhi,fSet[3], &fHard,pError,131);
|
|
for(i = 0, test = 0; i < 4; i++){
|
|
test += mask[i];
|
|
}
|
|
if(test != 4) {
|
|
return 0;
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
/*-------------------------------------------------------------------------
|
|
calculates the four circle settings. If the position can not be reached
|
|
because of a limit violation, then psi is rotated in 10 degree steps
|
|
until either the loop ends or we finally succeed. If there is a omega
|
|
violation we first try to calculate a delta omega which puts omega
|
|
into the right range. This is a fix because the omega movement is quite
|
|
often restricted due to the cryogenic garbage around the sample.
|
|
*/
|
|
int CalculateSettings(pHKL self, float fHKL[3], float fPsi, int iHamil,
|
|
float fSet[4], SConnection *pCon)
|
|
{
|
|
char pBueffel[512];
|
|
double myPsi = fPsi;
|
|
int i,status;
|
|
pSingleDiff single = NULL;
|
|
double dHkl[4], dSet[4];
|
|
|
|
/* catch shitty input */
|
|
if( (fHKL[0] == 0.) && (fHKL[1] == 0.) && (fHKL[2] == 0.))
|
|
{
|
|
SCWrite(pCon,"ERROR: I will not calculate angles for HKL = (0,0,0) ",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
/* some people are stupid.......... */
|
|
myPsi = circlify(fPsi);
|
|
|
|
single = SXGetDiffractometer();
|
|
assert(single != NULL);
|
|
|
|
for(i = 0; i < 3; i++){
|
|
dHkl[i] = fHKL[i];
|
|
}
|
|
dHkl[3] = myPsi;
|
|
|
|
status = single->calculateSettings(single,dHkl, dSet);
|
|
for(i = 0; i < 4; i++){
|
|
fSet[i] = dSet[i];
|
|
}
|
|
|
|
if(!status){
|
|
sprintf(pBueffel,
|
|
"ERROR: cannot calculate %4.1f %4.1f %4.1f, psi = %4.1f",
|
|
fHKL[0], fHKL[1], fHKL[2], dHkl[3]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
}
|
|
return status;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
void stopHKLMotors(pHKL self)
|
|
{
|
|
pSingleDiff single = NULL;
|
|
|
|
single = SXGetDiffractometer();
|
|
assert(single != NULL);
|
|
self->pMotDriv->Halt(&single->motList);
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int startHKLMotors(pHKL self, SConnection *pCon, float fSet[4]){
|
|
char pBueffel[512];
|
|
pSingleDiff single = NULL;
|
|
double dSet[4];
|
|
int i, status;
|
|
|
|
single = SXGetDiffractometer();
|
|
assert(single != NULL);
|
|
|
|
for(i = 0; i < 4; i++){
|
|
dSet[i] = fSet[i];
|
|
}
|
|
single->settingsToList(single,dSet);
|
|
|
|
status = self->pMotDriv->SetValue(&single->motList,pCon,.1);
|
|
|
|
return status;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
int RunHKL(pHKL self, float fHKL[3],
|
|
float fPsi, int iHamil, SConnection *pCon)
|
|
{
|
|
float fSet[4];
|
|
int iRet,i;
|
|
char pBueffel[512];
|
|
pDummy pDum;
|
|
|
|
assert(self);
|
|
iRet = CalculateSettings(self,fHKL,fPsi,iHamil,fSet,pCon);
|
|
if(!iRet)
|
|
{
|
|
SCWrite(pCon,"ERROR: NOT started",eError);
|
|
return 0;
|
|
}
|
|
|
|
iRet = startHKLMotors(self,pCon,fSet);
|
|
if(iRet != 1){
|
|
return iRet;
|
|
}
|
|
|
|
for(i = 0; i < 3; i++)
|
|
{
|
|
self->fLastHKL[i] = fHKL[i];
|
|
}
|
|
return 1;
|
|
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
int DriveSettings(pHKL self, float fSet[4], SConnection *pCon)
|
|
{
|
|
int iRet;
|
|
|
|
iRet = startHKLMotors(self, pCon, fSet);
|
|
if(iRet != 1){
|
|
stopHKLMotors(self);
|
|
}
|
|
|
|
/* wait for end */
|
|
iRet = Wait4Success(pServ->pExecutor);
|
|
switch(iRet)
|
|
{
|
|
case DEVINT:
|
|
if(SCGetInterrupt(pCon) == eAbortOperation)
|
|
{
|
|
SCSetInterrupt(pCon,eContinue);
|
|
SCWrite(pCon,"Driving to HKL Aborted",eLogError);
|
|
}
|
|
return 0;
|
|
break;
|
|
case DEVDONE:
|
|
SCWrite(pCon,"Driving to Reflection done",eValue);
|
|
break;
|
|
default:
|
|
SCWrite(pCon,"WARNING: driving to HKL finished with problems",
|
|
eWarning);
|
|
if(SCGetInterrupt(pCon) != eContinue)
|
|
{
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
return iRet;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int DriveHKL(pHKL self, float fHKL[3],
|
|
float fPsi, int iHamil, SConnection *pCon)
|
|
{
|
|
int iRet, iReturn;
|
|
long lID;
|
|
char pBueffel[132];
|
|
|
|
assert(self);
|
|
|
|
/* start running */
|
|
iReturn = 1;
|
|
iRet = RunHKL(self,fHKL,fPsi,iHamil,pCon);
|
|
if(!iRet){
|
|
StopExe(pServ->pExecutor,"all");
|
|
iReturn = 0;
|
|
}
|
|
|
|
/* wait for end */
|
|
iRet = Wait4Success(pServ->pExecutor);
|
|
switch(iRet)
|
|
{
|
|
case DEVINT:
|
|
if(SCGetInterrupt(pCon) == eAbortOperation)
|
|
{
|
|
SCSetInterrupt(pCon,eContinue);
|
|
SCWrite(pCon,"Driving to HKL Aborted",eError);
|
|
}
|
|
return 0;
|
|
break;
|
|
case DEVDONE:
|
|
if(fPsi > .01)
|
|
{
|
|
snprintf(pBueffel,131,
|
|
"Driving to %8.4f %8.4f %8.4f, psi = %8.4f done",
|
|
fHKL[0], fHKL[1], fHKL[2],fPsi);
|
|
}
|
|
else
|
|
{
|
|
snprintf(pBueffel,131,"Driving to %8.4f %8.4f %8.4f done",
|
|
fHKL[0], fHKL[1], fHKL[2]);
|
|
}
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
break;
|
|
default:
|
|
SCWrite(pCon,"WARNING: driving to HKL finished with problems",
|
|
eWarning);
|
|
if(SCGetInterrupt(pCon) != eContinue)
|
|
{
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
return iReturn;
|
|
}
|
|
/*-----------------------------------------------------------------------
|
|
* This is only used in mesure, remove when mesure can be killed
|
|
* ----------------------------------------------------------------------*/
|
|
int GetCurrentPosition(pHKL self, SConnection *pCon, float fPos[4])
|
|
{
|
|
float fVal;
|
|
int iRet, iResult;
|
|
pMotor pTheta, pOmega, pChi, pPhi, pNu;
|
|
|
|
pTheta = SXGetMotor(TwoTheta);
|
|
pOmega = SXGetMotor(Omega);
|
|
pChi = SXGetMotor(Chi);
|
|
pPhi = SXGetMotor(Phi);
|
|
if(pTheta == NULL || pOmega == NULL || pChi == NULL || pPhi == NULL){
|
|
SCWrite(pCon,"ERROR: configuration problem, stt,om,chi,phi motors not found,",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
assert(self);
|
|
assert(pCon);
|
|
|
|
iResult = 1;
|
|
iRet = MotorGetSoftPosition(pTheta,pCon, &fVal);
|
|
if(iRet == 1)
|
|
{
|
|
fPos[0] = fVal;
|
|
}
|
|
else
|
|
{
|
|
iResult = 0;
|
|
}
|
|
iRet = MotorGetSoftPosition(pOmega,pCon, &fVal);
|
|
if(iRet == 1)
|
|
{
|
|
fPos[1] = fVal;
|
|
}
|
|
else
|
|
{
|
|
iResult = 0;
|
|
}
|
|
|
|
/* normal beam geometry */
|
|
if(SXGetMode() == NB)
|
|
{
|
|
pNu = SXGetMotor(Nu);
|
|
if(pNu){
|
|
SCWrite(pCon,"ERROR: configuration problem, nu motor not found,",
|
|
eError);
|
|
return 0;
|
|
}
|
|
iRet = MotorGetSoftPosition(pNu,pCon, &fVal);
|
|
if(iRet == 1)
|
|
{
|
|
fPos[2] = fVal;
|
|
}
|
|
else
|
|
{
|
|
iResult = 0;
|
|
}
|
|
return iResult;
|
|
}
|
|
|
|
/* bissecting geometry */
|
|
iRet = MotorGetSoftPosition(pChi,pCon, &fVal);
|
|
if(iRet == 1)
|
|
{
|
|
fPos[2] = fVal;
|
|
}
|
|
else
|
|
{
|
|
iResult = 0;
|
|
}
|
|
iRet = MotorGetSoftPosition(pPhi,pCon, &fVal);
|
|
if(iRet == 1)
|
|
{
|
|
fPos[3] = fVal;
|
|
}
|
|
else
|
|
{
|
|
iResult = 0;
|
|
}
|
|
|
|
return iResult;
|
|
}
|
|
/*-------------------------------------------------------------------------
|
|
For the conversion from angles to HKL.
|
|
-------------------------------------------------------------------------*/
|
|
int GetHKLFromAngles(pHKL self, SConnection *pCon, float fHKL[3]){
|
|
pSingleDiff single = NULL;
|
|
double dHkl[3];
|
|
int i, status;
|
|
|
|
single = SXGetDiffractometer();
|
|
assert(single != NULL);
|
|
|
|
status = single->hklFromAngles(single,dHkl);
|
|
for(i = 0; i < 3; i++){
|
|
fHKL[i] = dHkl[i];
|
|
}
|
|
return status;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int GetCommandData(int argc, char *argv[], float fHKL[3],
|
|
float *fPsi, int *iHamil, SConnection *pCon)
|
|
{
|
|
int iRet, i;
|
|
double d;
|
|
char pBueffel[512];
|
|
|
|
if(argc < 3)
|
|
{
|
|
SCWrite(pCon,
|
|
"ERROR: Insufficient reflection data specified for calculation",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
/* get the reflection */
|
|
for(i = 0; i < 3; i++)
|
|
{
|
|
if(!isNumeric(argv[i]))
|
|
{
|
|
sprintf(pBueffel,"ERROR: %s is NOT recognized as a number",argv[i]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
fHKL[i] = atof(argv[i]);
|
|
}
|
|
|
|
*fPsi = 0.;
|
|
*iHamil = 0;
|
|
|
|
/* has psi been specicifed ? */
|
|
if(argc > 3)
|
|
{
|
|
if(!isNumeric(argv[3]))
|
|
{
|
|
sprintf(pBueffel,"ERROR: %s is NOT recognized as a number",argv[3]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
}
|
|
*fPsi = atof(argv[3]);
|
|
}
|
|
|
|
/* has iHamil been specified ? */
|
|
if(argc > 4)
|
|
{
|
|
if(!isNumeric(argv[4]))
|
|
{
|
|
sprintf(pBueffel,"ERROR: %s is NOT recognized as a number",argv[4]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
}
|
|
*iHamil = atof(argv[4]);
|
|
}
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int HKLCalculateTheta(pHKL self,float fHKL[3], double *stt){
|
|
int status, i;
|
|
MATRIX B, HC, H;
|
|
double theta, d;
|
|
const double *cell;
|
|
reflection r;
|
|
lattice direct;
|
|
|
|
B = mat_creat(3,3,UNIT_MATRIX);
|
|
H = mat_creat(3,1,ZERO_MATRIX);
|
|
if(B == NULL) {
|
|
return UBNOMEMORY;
|
|
}
|
|
cell = SXGetCell();
|
|
direct.a = cell[0];
|
|
direct.b = cell[1];
|
|
direct.c = cell[2];
|
|
direct.alpha = cell[3];
|
|
direct.beta = cell[4];
|
|
direct.gamma = cell[5];
|
|
|
|
status = calculateBMatrix(direct,B);
|
|
if(status < 0) {
|
|
return status;
|
|
}
|
|
for(i = 0; i < 3; i++){
|
|
H[i][0] = fHKL[i];
|
|
}
|
|
HC = mat_mul(B,H);
|
|
status = calcTheta(SXGetLambda(), HC, &d, &theta);
|
|
mat_free(HC);
|
|
mat_free(B);
|
|
mat_free(H);
|
|
*stt = 2.*theta;
|
|
return status;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int HKLAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
int iRet,i, iHamil;
|
|
char pBueffel[512];
|
|
float fUB[9], fPsi, fVal;
|
|
float fHKL[3], fSet[4];
|
|
double dHKL[3], dSet[4];
|
|
double dVal, lambda, stt;
|
|
const double *dUB;
|
|
pHKL self = NULL;
|
|
CommandList *pCom = NULL;
|
|
pDummy pDum = NULL;
|
|
pSingleDiff single = NULL;
|
|
|
|
assert(pCon);
|
|
assert(pSics);
|
|
|
|
self = (pHKL)pData;
|
|
assert(self);
|
|
|
|
single = SXGetDiffractometer();
|
|
|
|
/* enough arguments ? */
|
|
if(argc < 2)
|
|
{
|
|
SCWrite(pCon,"Insufficient number of arguments to HKL",eError);
|
|
return 0;
|
|
}
|
|
|
|
/*-------- handle list */
|
|
strtolower(argv[1]);
|
|
if(strcmp(argv[1],"list") == 0 )
|
|
{
|
|
sprintf(pBueffel,
|
|
"lambda = %f Normal Beam = %d Quadrant = %d HM = %d",
|
|
SXGetLambda(), self->iNOR,
|
|
self->iQuad,self->iHM);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
dUB = SXGetUB();
|
|
sprintf(pBueffel,"UB = { %f %f %f",
|
|
dUB[0], dUB[1], dUB[2]);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
sprintf(pBueffel," %f %f %f",
|
|
dUB[3], dUB[4],dUB[5]);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
sprintf(pBueffel," %f %f %f }",
|
|
dUB[6], dUB[7],dUB[8]);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
sprintf(pBueffel,"Last HKL: %f %f %f ",
|
|
self->fLastHKL[0], self->fLastHKL[1],self->fLastHKL[2]);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
snprintf(pBueffel,510,"%s.scantolerance = %f", argv[0],
|
|
self->scanTolerance);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
/*----------- current */
|
|
else if(strcmp(argv[1],"current") == 0)
|
|
{
|
|
GetHKLFromAngles(self,pCon,fHKL);
|
|
sprintf(pBueffel,"Current HKL: %8.4f %8.4f %8.4f ",
|
|
fHKL[0], fHKL[1],fHKL[2]);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
else if(strcmp(argv[1],"fromangles") == 0)
|
|
{
|
|
if(argc < 6)
|
|
{
|
|
SCWrite(pCon,
|
|
"ERROR: need stt, om, chi,phi to calculate HKL from angles",
|
|
eError);
|
|
return 0;
|
|
}
|
|
for(i = 0; i < 4; i++)
|
|
{
|
|
iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[i+2],&dVal);
|
|
if(iRet != TCL_OK){
|
|
snprintf(pBueffel,511,"ERROR: failed to convert %s to number",
|
|
argv[i+2]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
dSet[i] = dVal;
|
|
}
|
|
single->hklFromAnglesGiven(single,dSet,dHKL);
|
|
for(i = 0; i < 3; i++){
|
|
fHKL[i] = dHKL[i];
|
|
}
|
|
sprintf(pBueffel,"HKL from angles: %8.4f %8.4f %8.4f ",
|
|
fHKL[0], fHKL[1],fHKL[2]);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
/*------------- lambda */
|
|
else if(strcmp(argv[1],"lambda") == 0)
|
|
{
|
|
lambda = SXGetLambda();
|
|
snprintf(pBueffel,132,"%s.lambda = %f", argv[0],lambda);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
}
|
|
/*------------- getub*/
|
|
else if(strcmp(argv[1],"getub") == 0)
|
|
{
|
|
dUB = SXGetUB();
|
|
snprintf(pBueffel,510,"%s.ub = %f %f %f %f %f %f %f %f %f",
|
|
argv[0], dUB[0], dUB[1], dUB[2],
|
|
dUB[3], dUB[4], dUB[5],
|
|
dUB[6], dUB[7], dUB[8]);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
/*------------ UB */
|
|
else if(strcmp(argv[1],"setub") == 0)
|
|
{
|
|
if(argc < 11)
|
|
{
|
|
SCWrite(pCon,"ERROR: Insufficient number of arguments to HKL setUB",eError);
|
|
return 0;
|
|
}
|
|
if(!SCMatchRights(pCon,usUser))
|
|
{
|
|
return 0;
|
|
}
|
|
for(i = 2; i < 11; i++)
|
|
{
|
|
if(!isNumeric(argv[i]))
|
|
{
|
|
sprintf(pBueffel,"ERROR: %s was not recognized as a number", argv[i]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
fUB[i-2] = atof(argv[i]);
|
|
}
|
|
iRet = SetUB(self,fUB);
|
|
if(!iRet)
|
|
{
|
|
SCWrite(pCon,"ERROR: cannot set UB Matrix",eError);
|
|
return 0;
|
|
}
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/*------------- HM mode */
|
|
else if(strcmp(argv[1],"hm") == 0)
|
|
{
|
|
if(argc < 3)
|
|
{
|
|
sprintf(pBueffel,"%s.hm = %d", argv[0],self->iHM);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
if(!SCMatchRights(pCon,usUser))
|
|
{
|
|
return 0;
|
|
}
|
|
if(!isNumeric(argv[2]))
|
|
{
|
|
sprintf(pBueffel,"ERROR: %s was not recognized as a number", argv[2]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
self->iHM = atoi(argv[2]);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/*------------- normal beam */
|
|
else if(strcmp(argv[1],"nb") == 0)
|
|
{
|
|
if(argc < 3)
|
|
{
|
|
snprintf(pBueffel,511,"%s.nb = %d",argv[0],self->iNOR);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
if(!SCMatchRights(pCon,usUser))
|
|
{
|
|
return 0;
|
|
}
|
|
if(!isNumeric(argv[2]))
|
|
{
|
|
sprintf(pBueffel,"ERROR: %s was not recognized as a number", argv[2]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
iRet = SetNOR(self,atoi(argv[2]));
|
|
if(!iRet)
|
|
{
|
|
SCWrite(pCon,
|
|
"ERROR: cannot set Normal Beam geometry, probably nu motor undefined",
|
|
eError);
|
|
return 0;
|
|
}
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/*------------- quadrant */
|
|
else if(strcmp(argv[1],"quadrant") == 0)
|
|
{
|
|
if(argc < 3)
|
|
{
|
|
SCWrite(pCon,"ERROR: Insufficient number of arguments to HKL quadrant",eError);
|
|
return 0;
|
|
}
|
|
if(!SCMatchRights(pCon,usUser))
|
|
{
|
|
return 0;
|
|
}
|
|
if(!isNumeric(argv[2]))
|
|
{
|
|
sprintf(pBueffel,"ERROR: %s was not recognized as a number", argv[2]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
iRet = atoi(argv[2]);
|
|
if(!( (iRet == 1) || (iRet == 0)) )
|
|
{
|
|
sprintf(pBueffel,"ERROR: Invalid parameter %d for quadrant, posiible: 0,1",
|
|
iRet);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
self->iQuad = iRet;
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/*------------- scantolerance */
|
|
else if(strcmp(argv[1],"scantolerance") == 0)
|
|
{
|
|
if(argc < 3)
|
|
{
|
|
snprintf(pBueffel,510,"%s.scantolerance = %f",argv[0],
|
|
self->scanTolerance);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
if(!SCMatchRights(pCon,usUser))
|
|
{
|
|
return 0;
|
|
}
|
|
if(!isNumeric(argv[2]))
|
|
{
|
|
sprintf(pBueffel,"ERROR: %s was not recognized as a number", argv[2]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
self->scanTolerance = atof(argv[2]);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/*------------- calculate */
|
|
else if(strcmp(argv[1],"calc") == 0)
|
|
{
|
|
iRet = GetCommandData(argc-2,&argv[2],fHKL, &fPsi, &iHamil,pCon);
|
|
if(!iRet)
|
|
{
|
|
return 0;
|
|
}
|
|
iRet = CalculateSettings(self,fHKL, fPsi, iHamil, fSet,pCon);
|
|
if(SXGetMode() == NB)
|
|
{
|
|
sprintf(pBueffel," gamma = %f, omega = %f, nu = %f",
|
|
fSet[0], fSet[1], fSet[2]);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
}
|
|
else
|
|
{
|
|
sprintf(pBueffel," 2-theta = %f, omega = %f, chi = %f, phi = %f",
|
|
fSet[0], fSet[1], fSet[2],fSet[3]);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
}
|
|
if(!iRet)
|
|
{
|
|
SCWrite(pCon,
|
|
"WARNING: Cannot drive to the hkl of your desire",
|
|
eWarning);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
/*------------- calculate theta*/
|
|
else if(strcmp(argv[1],"calctth") == 0)
|
|
{
|
|
iRet = GetCommandData(argc-2,&argv[2],fHKL, &fPsi, &iHamil,pCon);
|
|
if(!iRet)
|
|
{
|
|
return 0;
|
|
}
|
|
HKLCalculateTheta(self,fHKL, &stt);
|
|
SCPrintf(pCon,eValue,"two-theta = %lf", stt);
|
|
return 1;
|
|
}
|
|
/*------------------ run */
|
|
else if(strcmp(argv[1],"run") == 0)
|
|
{
|
|
if(!SCMatchRights(pCon,usUser))
|
|
{
|
|
return 0;
|
|
}
|
|
iRet = GetCommandData(argc-2,&argv[2],fHKL, &fPsi, &iHamil,pCon);
|
|
if(!iRet)
|
|
{
|
|
return 0;
|
|
}
|
|
iRet = RunHKL(self,fHKL,fPsi, iHamil, pCon);
|
|
if(!iRet)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
}
|
|
/*------------------ drive */
|
|
else if(strcmp(argv[1],"drive") == 0)
|
|
{
|
|
if(!SCMatchRights(pCon,usUser))
|
|
{
|
|
return 0;
|
|
}
|
|
iRet = GetCommandData(argc-2,&argv[2],fHKL, &fPsi, &iHamil,pCon);
|
|
if(!iRet)
|
|
{
|
|
return 0;
|
|
}
|
|
iRet = DriveHKL(self,fHKL,fPsi, iHamil, pCon);
|
|
if(!iRet)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sprintf(pBueffel,"ERROR: subcommand --> %s <-- not recognized",
|
|
argv[1]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
return 0; /* not reached */
|
|
}
|
|
|
|
|
|
|
|
|
|
|