PSI sics-cvs-psi_pre-ansto
This commit is contained in:
539
difrac.c
Normal file
539
difrac.c
Normal file
@@ -0,0 +1,539 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
D I F R A C
|
||||
|
||||
A four-circle diffractometer requires sophicticated procedures for
|
||||
searching peaks, orienting crystals and for performing data collection.
|
||||
Rather then invent all of this again the DIFRAC-F77 program written by
|
||||
Peter White and Eric Gabe has been incoporated into SICS. This module
|
||||
provides the C-language side of the interface between DIFRAC and SICS.
|
||||
DIFRAC can only be included once into SICS, it is not possible to have
|
||||
more then one copy of this. This is why there is file static global data
|
||||
here.
|
||||
|
||||
copyright: see copyright.h
|
||||
|
||||
Mark Koennecke, November 1999
|
||||
--------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "motor.h"
|
||||
#include "counter.h"
|
||||
#include "status.h"
|
||||
#include "splitter.h"
|
||||
#include "difrac.h"
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
In order to deal with multiple request to the DIFRAC subsystem we need to
|
||||
keep the connection objects on a stack. This stack is defined here.
|
||||
---------------------------------------------------------------------------*/
|
||||
#define MAXSTACK 50
|
||||
|
||||
static SConnection *ConStack[MAXSTACK];
|
||||
static int iConStackPtr = -1;
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
In order to do the four circle work we need to know the motors of the
|
||||
eulerian cradle and access to the counter. Furthermore we need to know
|
||||
about the omega2theta motor and the scanning routine.
|
||||
These data structures are initialized by the installation routine.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
static pMotor pTTH, pOM, pCHI, pPHI;
|
||||
static pCounter counter;
|
||||
/*---------------------------------------------------------------------------
|
||||
The following routines will be called from F77. Their names take care of the
|
||||
system dependent name mangling scheme for calling C from F77. This may
|
||||
need adjustment when porting to another system
|
||||
---------------------------------------------------------------------------*/
|
||||
/*========= read angles */
|
||||
void sicsanget_(float *fTH, float *fOM, float *fCHI, float *fPHI)
|
||||
{
|
||||
int iRet;
|
||||
|
||||
/* this is just security, may never happen */
|
||||
if(iConStackPtr < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(ConStack[iConStackPtr] == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
iRet = MotorGetSoftPosition(pTTH,ConStack[iConStackPtr],fTH);
|
||||
if(iRet != 1)
|
||||
{
|
||||
SCWrite(ConStack[iConStackPtr],
|
||||
"ERROR: failed to read two theta, DIFRAC may be confused now",
|
||||
eError);
|
||||
}
|
||||
iRet = MotorGetSoftPosition(pOM,ConStack[iConStackPtr],fOM);
|
||||
if(iRet != 1)
|
||||
{
|
||||
SCWrite(ConStack[iConStackPtr],
|
||||
"ERROR: failed to read omega, DIFRAC may be confused now",
|
||||
eError);
|
||||
}
|
||||
iRet = MotorGetSoftPosition(pCHI,ConStack[iConStackPtr],fCHI);
|
||||
if(iRet != 1)
|
||||
{
|
||||
SCWrite(ConStack[iConStackPtr],
|
||||
"ERROR: failed to read chi, DIFRAC may be confused now",
|
||||
eError);
|
||||
}
|
||||
iRet = MotorGetSoftPosition(pPHI,ConStack[iConStackPtr],fPHI);
|
||||
if(iRet != 1)
|
||||
{
|
||||
SCWrite(ConStack[iConStackPtr],
|
||||
"ERROR: failed to read two theta, DIFRAC may be confused now",
|
||||
eError);
|
||||
}
|
||||
}
|
||||
#define ABS(x) (x < 0 ? -(x) : (x))
|
||||
/*=========== check angles */
|
||||
void sicsangcheck_(float *fTH, float *fOM, float *fCHI, float *fPHI,
|
||||
int *iInvalid)
|
||||
{
|
||||
int iRet;
|
||||
SConnection *pCon = NULL;
|
||||
float fHard;
|
||||
char pBueffel[256], pError[131];
|
||||
|
||||
/* this is just security, may never happen */
|
||||
if(iConStackPtr < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(ConStack[iConStackPtr] == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pCon = ConStack[iConStackPtr];
|
||||
|
||||
*iInvalid = 0;
|
||||
iRet = MotorCheckBoundary(pTTH,*fTH,&fHard,pError,131);
|
||||
if(iRet != 1)
|
||||
{
|
||||
sprintf(pBueffel,
|
||||
"ERROR: %6.2f %6.2f %6.2f %6.2f violates twotheta limits",
|
||||
*fTH, *fOM, *fCHI, *fPHI);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
*iInvalid = 4;
|
||||
return;
|
||||
}
|
||||
iRet = MotorCheckBoundary(pOM,*fOM,&fHard,pError,131);
|
||||
if(iRet != 1)
|
||||
{
|
||||
sprintf(pBueffel,
|
||||
"ERROR: %6.2f %6.2f %6.2f %6.2f violates omega limits",
|
||||
*fTH, *fOM, *fCHI, *fPHI);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
*iInvalid = 4;
|
||||
return;
|
||||
}
|
||||
iRet = MotorCheckBoundary(pCHI,*fCHI,&fHard,pError,131);
|
||||
if(iRet != 1)
|
||||
{
|
||||
sprintf(pBueffel,
|
||||
"ERROR: %6.2f %6.2f %6.2f %6.2f violates chi limits",
|
||||
*fTH, *fOM, *fCHI, *fPHI);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
*iInvalid = 4;
|
||||
return;
|
||||
}
|
||||
iRet = MotorCheckBoundary(pPHI,*fPHI,&fHard,pError,131);
|
||||
if(iRet != 1)
|
||||
{
|
||||
sprintf(pBueffel,
|
||||
"ERROR: %6.2f %6.2f %6.2f %6.2f violates phi limits",
|
||||
*fTH, *fOM, *fCHI, *fPHI);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
*iInvalid = 4;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*======== set angles */
|
||||
void sicsangset_(float *fTTH, float *fOM, float *fCHI, float *fPHI,
|
||||
int *icol)
|
||||
{
|
||||
pDummy pDum;
|
||||
int iRet;
|
||||
SConnection *pCon = NULL;
|
||||
float fT1, fT2, fT3, fT4;
|
||||
|
||||
*icol = 0;
|
||||
|
||||
/* this is just security, may never happen */
|
||||
if(iConStackPtr < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(ConStack[iConStackPtr] == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pCon = ConStack[iConStackPtr];
|
||||
|
||||
|
||||
/* check if this is possible, if not complain */
|
||||
sicsangcheck_(fTTH, fOM,fCHI,fPHI, &iRet);
|
||||
if(iRet >= 4)
|
||||
{
|
||||
*icol = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* start */
|
||||
pDum = (pDummy)pTTH;
|
||||
iRet = StartDevice(pServ->pExecutor, "TTH",
|
||||
pDum->pDescriptor, pDum,pCon, *fTTH);
|
||||
if(!iRet)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: cannot start two theta motor",eError);
|
||||
StopExe(pServ->pExecutor,"all");
|
||||
*icol = 10;
|
||||
}
|
||||
pDum = (pDummy)pOM;
|
||||
iRet = StartDevice(pServ->pExecutor, "OM",
|
||||
pDum->pDescriptor, pDum,pCon, *fOM);
|
||||
if(!iRet)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: cannot start omega motor",eError);
|
||||
StopExe(pServ->pExecutor,"all");
|
||||
*icol = 10;
|
||||
}
|
||||
pDum = (pDummy)pCHI;
|
||||
iRet = StartDevice(pServ->pExecutor, "CHI",
|
||||
pDum->pDescriptor, pDum,pCon, *fCHI);
|
||||
if(!iRet)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: cannot start chi motor",eError);
|
||||
StopExe(pServ->pExecutor,"all");
|
||||
*icol = 10;
|
||||
}
|
||||
pDum = (pDummy)pPHI;
|
||||
iRet = StartDevice(pServ->pExecutor, "PHI",
|
||||
pDum->pDescriptor, pDum,pCon, *fPHI);
|
||||
if(!iRet)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: cannot start two theta motor",eError);
|
||||
StopExe(pServ->pExecutor,"all");
|
||||
*icol = 10;
|
||||
}
|
||||
|
||||
/* wait for end of it */
|
||||
iRet = Wait4Success(pServ->pExecutor);
|
||||
switch(iRet)
|
||||
{
|
||||
case DEVINT:
|
||||
if(SCGetInterrupt(pCon) == eAbortOperation)
|
||||
{
|
||||
SCSetInterrupt(pCon,eContinue);
|
||||
SCSetError(pCon,OKOK);
|
||||
}
|
||||
break;
|
||||
case DEVDONE:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
As TRICS has such a shitty cradle check angles and report error
|
||||
if bad
|
||||
*/
|
||||
sicsanget_(&fT1, &fT2, &fT3, &fT4);
|
||||
if(ABS(fT1 - *fTTH) > .2)
|
||||
{
|
||||
*icol = 10;
|
||||
}
|
||||
if(ABS(fT2 - *fOM) > .2)
|
||||
{
|
||||
*icol = 10;
|
||||
}
|
||||
if(ABS(fT3 - *fCHI) > .2)
|
||||
{
|
||||
*icol = 10;
|
||||
}
|
||||
if(ABS(fT4 - *fPHI) > .2)
|
||||
{
|
||||
*icol = 10;
|
||||
}
|
||||
}
|
||||
/*=========== count */
|
||||
void sicscount_(float *fPreset, float *fCounts)
|
||||
{
|
||||
pDummy pDum;
|
||||
int iRet;
|
||||
SConnection *pCon = NULL;
|
||||
long lTask;
|
||||
|
||||
/* this is just security, may never happen */
|
||||
if(iConStackPtr < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(ConStack[iConStackPtr] == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pCon = ConStack[iConStackPtr];
|
||||
|
||||
pDum = (pDummy)counter;
|
||||
SetCounterPreset(counter,*fPreset);
|
||||
iRet = StartDevice(pServ->pExecutor,
|
||||
"DifracCount",
|
||||
pDum->pDescriptor,
|
||||
counter,
|
||||
pCon,
|
||||
*fPreset);
|
||||
if(!iRet)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: Failed to start counting ",eError);
|
||||
return;
|
||||
}
|
||||
SetStatus(eCounting);
|
||||
/* wait for finish */
|
||||
lTask = GetDevexecID(pServ->pExecutor);
|
||||
if(lTask > 0);
|
||||
{
|
||||
TaskWait(pServ->pTasker,lTask);
|
||||
}
|
||||
*fCounts = (float)GetCounts(counter,pCon);
|
||||
}
|
||||
/*========= sicswrite */
|
||||
void sicswrite_(int *iText, int *iLen)
|
||||
{
|
||||
SConnection *pCon = NULL;
|
||||
char pBueffel[256];
|
||||
int i;
|
||||
|
||||
if(*iLen > 255)
|
||||
return;
|
||||
|
||||
for(i = 0; i < *iLen; i++)
|
||||
{
|
||||
pBueffel[i] = (char)iText[i];
|
||||
}
|
||||
pBueffel[i] = '\0';
|
||||
|
||||
/* this is just security, may never happen */
|
||||
if(iConStackPtr < 0)
|
||||
{
|
||||
puts(pBueffel);
|
||||
return;
|
||||
}
|
||||
if(ConStack[iConStackPtr] == NULL)
|
||||
{
|
||||
puts(pBueffel);
|
||||
return;
|
||||
}
|
||||
pCon = ConStack[iConStackPtr];
|
||||
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
/*========== sicsgetline */
|
||||
void sicsgetline_(int *iText, int *iLen)
|
||||
{
|
||||
SConnection *pCon = NULL;
|
||||
char pBueffel[256];
|
||||
int i, iRet;
|
||||
|
||||
/* this is just security, may never happen */
|
||||
if(iConStackPtr < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(ConStack[iConStackPtr] == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pCon = ConStack[iConStackPtr];
|
||||
|
||||
iRet = SCPrompt(pCon,"Enter data please >>" , pBueffel, 255);
|
||||
/* difrac cannot handle an interrupted input operation */
|
||||
if(iRet == 0)
|
||||
{
|
||||
SCSetInterrupt(pCon,eContinue);
|
||||
}
|
||||
for(i = 0; i < strlen(pBueffel); i++)
|
||||
{
|
||||
iText[i] = (int)pBueffel[i];
|
||||
}
|
||||
*iLen = strlen(pBueffel);
|
||||
}
|
||||
/*============= checkint */
|
||||
void checkint_(int *iK)
|
||||
{
|
||||
SConnection *pCon = NULL;
|
||||
char pBueffel[256];
|
||||
int i;
|
||||
|
||||
/* this is just security, may never happen */
|
||||
if(iConStackPtr < 0)
|
||||
{
|
||||
*iK = 0;
|
||||
return;
|
||||
}
|
||||
if(ConStack[iConStackPtr] == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pCon = ConStack[iConStackPtr];
|
||||
|
||||
if(SCGetInterrupt(pCon) >= eAbortScan)
|
||||
{
|
||||
*iK = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*iK = 1;
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------------
|
||||
DifracAction is the interface routine between the SICS interpreter and
|
||||
the DIFRAC subsystem. What it basically does is: pop the connection onto
|
||||
the stack. Concatenate all pending command line data to a string. Then
|
||||
call DIFRAC with this string as an parameter. On return, remove the
|
||||
connection from the stack again and return.
|
||||
-------------------------------------------------------------------------*/
|
||||
/* some protoypes for things defined in F77 */
|
||||
|
||||
extern void difini_(void);
|
||||
extern void difint_(int *iText, int *iLen);
|
||||
|
||||
int DifracAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char pInput[256];
|
||||
int iInput[256];
|
||||
int iLen, i;
|
||||
|
||||
|
||||
if(argc < 2)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: dif expects at least one argument",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* user privilege required */
|
||||
if(!SCMatchRights(pCon,usUser))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* steal: redirect the I/O to me */
|
||||
strcpy(pInput,argv[1]);
|
||||
strtolower(pInput);
|
||||
if(strcmp(pInput,"steal") == 0)
|
||||
{
|
||||
if(iConStackPtr >= 0)
|
||||
{
|
||||
ConStack[iConStackPtr] = pCon;
|
||||
}
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
|
||||
iConStackPtr++;
|
||||
ConStack[iConStackPtr] = pCon;
|
||||
|
||||
Arg2Text(argc-1, &argv[1],pInput,255);
|
||||
iLen = strlen(pInput);
|
||||
for(i = 0; i < iLen; i++)
|
||||
{
|
||||
iInput[i] = toupper((int)pInput[i]);
|
||||
}
|
||||
|
||||
/* do difrac */
|
||||
difint_(iInput, &iLen);
|
||||
SCWrite(pCon,"Difrac subsystem finished",eWarning);
|
||||
|
||||
iConStackPtr--;
|
||||
if(SCGetInterrupt(pCon) != eContinue)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/*-------------------- The initialization routine ----------------------*/
|
||||
int MakeDifrac(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
CommandList *pCom = NULL;
|
||||
pICountable pCts = NULL;
|
||||
int iRet;
|
||||
|
||||
if(argc < 6)
|
||||
{
|
||||
SCWrite(pCon,
|
||||
"ERROR: Insufficient number of arguments to MakeDifrac",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* find motors */
|
||||
pTTH = FindMotor(pSics,argv[1]);
|
||||
if(!pTTH)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: cannot find two theta motor",eError);
|
||||
return 0;
|
||||
}
|
||||
pOM = FindMotor(pSics,argv[2]);
|
||||
if(!pOM)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: cannot find omega motor",eError);
|
||||
return 0;
|
||||
}
|
||||
pCHI = FindMotor(pSics,argv[3]);
|
||||
if(!pTTH)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: cannot find chi motor",eError);
|
||||
return 0;
|
||||
}
|
||||
pPHI = FindMotor(pSics,argv[4]);
|
||||
if(!pTTH)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: cannot find phi motor",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* locate counter */
|
||||
pCom = FindCommand(pSics,argv[5]);
|
||||
if(pCom == NULL)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: counter not found in MakeDifrac",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
pCts = GetCountableInterface(pCom->pData);
|
||||
if(!pCts)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: argument to MakeDifrac is no counter",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
counter = (pCounter)pCom->pData;
|
||||
|
||||
/* initialize difrac */
|
||||
difini_();
|
||||
|
||||
/* install command */
|
||||
iRet = AddCommand(pSics,
|
||||
"dif",
|
||||
DifracAction,
|
||||
NULL,
|
||||
NULL);
|
||||
if(!iRet)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: duplicate command dif NOT created",
|
||||
eError);
|
||||
}
|
||||
return iRet;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user