- Added support for accessing the exe file management functions from scripts

- Fixed a bug in hmdata.c
- Fixed an issue with tempoerature writing through RemObjects in mesure
- Added auxiliary reflections to tasub
- Make maximize use soft motor positions
This commit is contained in:
koennecke
2006-11-24 15:51:19 +00:00
parent f15cb4c6db
commit 0825c48986
24 changed files with 328 additions and 253 deletions

View File

@ -134,6 +134,7 @@ static void freeList(int listID);
SICSLogWrite(pBueffel,eInternal);
return 0;
}
memset(pNew,0,sizeof(CommandList));
/* if no data given, initialise with Dummy struct */
if(!pData)
@ -431,7 +432,7 @@ extern char *SkipSpace(char *pPtr);
}
if(fVal > -990.)
{
fprintf(fd,"run %s %f\n",pCurrent->pName, fVal);
fprintf(fd,"drive %s %f\n",pCurrent->pName, fVal);
}
}
}

View File

@ -113,6 +113,7 @@ static long ColliderSetValue(void *pData, SConnection *pCon, float fTarget){
iRet = Tcl_Eval(pServ->pSics->pTcl,Tcl_DStringValue(&command));
if(iRet != TCL_OK){
SCWrite(pCon,"ERROR: Movement not possible or bad collider script",eError);
SCWrite(pCon,Tcl_DStringValue(&command),eError);
/*
SCWrite(pCon,pServ->pSics->pTcl->result,eError);
*/

View File

@ -634,7 +634,7 @@ static int doSockWrite(SConnection *self, char *buffer)
iRet = NETWrite(self->pSock,buffer,strlen(buffer));
if(!HasNL(buffer))
{
iRet = NETWrite(self->pSock,"\n",strlen("\n"));
iRet = NETWrite(self->pSock,"\r\n",strlen("\r\n"));
}
}
if(!iRet)

1
exe.w
View File

@ -173,6 +173,7 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
int runExeBatchBuffer(void *pData, SConnection *pCon, SicsInterp *pSics,
char *name);
pDynString findBatchFile(SicsInterp *pSics, char *name);
@}
@o exeman.i -d @{

View File

@ -1,5 +1,5 @@
#line 209 "exe.w"
#line 210 "exe.w"
/**
* Buffer handling code for the Exe Buffer batch file processing
@ -89,7 +89,7 @@
*/
char *exeBufName(pExeBuf self);
#line 222 "exe.w"
#line 223 "exe.w"
#endif

View File

@ -1,5 +1,5 @@
#line 200 "exe.w"
#line 201 "exe.w"
/*--------------------------------------------------------------------
Internal header file for the exe buffer module. Do not edit. This is
@ -16,6 +16,6 @@ typedef struct __EXEBUF{
int lineno;
} ExeBuf;
#line 205 "exe.w"
#line 206 "exe.w"

View File

@ -175,6 +175,43 @@ static pDynString locateBatchBuffer(pExeMan self, char *name){
DeleteDynString(result);
return NULL;
}
/*-------------------------------------------------------------------
* Generate a full path name for the argument in the first
* directory of batch path
* -------------------------------------------------------------------*/
static int makeExePath(pExeMan self, SConnection *pCon, int argc, char *argv[]){
char buffer[512], *pPtr = NULL, pPath[132];
if(argc < 3) {
SCWrite(pCon,"ERROR: require a file name for makepath",eError);
return 0;
}
strcpy(buffer,"exe.makepath = ");
/*
* do nothing to absolute path
*/
if(argv[2][0] == '/'){
strncat(buffer,argv[2],511-strlen(buffer));
SCWrite(pCon,buffer,eValue);
return 1;
}
pPtr = self->batchPath;
pPtr = stptok(pPtr,pPath,131,":");
strncat(buffer,pPath,511-strlen(buffer));
strncat(buffer,"/",511-strlen(buffer));
strncat(buffer,argv[2],511-strlen(buffer));
SCWrite(pCon,buffer,eValue);
return 1;
}
/*--------------------------------------------------------------------*/
pDynString findBatchFile(SicsInterp *pSics, char *name){
pExeMan self = (pExeMan)FindCommandData(pSics,"exe","ExeManager");
if(self == NULL){
return NULL;
}
return locateBatchBuffer(self,name);
}
/*--------------------------------------------------------------------*/
static int runBatchBuffer(pExeMan self, SConnection *pCon,
SicsInterp *pSics, char *name){
@ -937,6 +974,7 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
char pBufferName[256];
int status;
pDynString dirList = NULL;
pDynString fullPath = NULL;
self = (pExeMan)pData;
assert(self != NULL);
@ -1012,6 +1050,24 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
SCWrite(pCon,"Nothing found",eValue);
}
return 1;
}else if(strcmp(argv[1],"fullpath") == 0){
if(argc < 2){
SCWrite(pCon,"ERROR: not enough arguments to exe fullpath",eError);
return 0;
}
fullPath = locateBatchBuffer(self,argv[2]);
if(fullPath == NULL){
SCWrite(pCon,"ERROR: buffer NOT found",eError);
return 0;
} else {
DynStringInsert(fullPath,"exe.fullpath=",0);
SCWrite(pCon,GetCharArray(fullPath),eValue);
DeleteDynString(fullPath);
return 1;
}
return 1;
}else if(strcmp(argv[1],"makepath") == 0){
return makeExePath(self,pCon,argc,argv);
}else if(strcmp(argv[1],"clear") == 0){
clearQueue(self);
SCSendOK(pCon);

View File

@ -15,5 +15,6 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
int runExeBatchBuffer(void *pData, SConnection *pCon, SicsInterp *pSics,
char *name);
pDynString findBatchFile(SicsInterp *pSics, char *name);
#endif

View File

@ -1,5 +1,5 @@
#line 178 "exe.w"
#line 179 "exe.w"
/*-------------------------------------------------------------------
Internal header file for the exe manager module. Do not edit. This
@ -20,5 +20,5 @@ typedef struct __EXEMAN{
int echo;
}ExeMan, *pExeMan;
#line 183 "exe.w"
#line 184 "exe.w"

View File

@ -1584,7 +1584,7 @@ static int checkHMEnd(pHistMem self, char *text){
Tcl_DStringAppend(&tResult,"histogram.timebins =",-1);
for(i = 0; i < self->pDriv->data->nTimeChan; i++)
{
sprintf(pBueffel," %8.2f", self->pDriv->data->timeBinning[i]);
sprintf(pBueffel,"%.2f ", self->pDriv->data->timeBinning[i]);
Tcl_DStringAppend(&tResult,pBueffel,-1);
}
/* Write it */

View File

@ -310,7 +310,7 @@ int HMControlAction(SConnection *pCon, SicsInterp *pSics,
assert(self);
if(argc < 4)
{
sprintf("ERROR: Usage %s start preset mode", argv[0]);
snprintf(pBueffel,131,"ERROR: Usage %s start preset mode", argv[0]);
SCWrite(pCon,pBueffel,eError);
return 0;
}

View File

@ -358,7 +358,7 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
int iStart[MAXDIM], int iEnd[MAXDIM]) {
HistInt *iData;
pHMdata self = hist->pDriv->data;
int i, iHistLength, status, iIndex;
int i, iHistLength, status, iIndex, myrank;
char pBueffel[256];
unsigned long lSum, lRowSum;
@ -367,7 +367,12 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
/*
error checking
*/
for(i = 0; i < self->rank; i++){
myrank = self->rank;
if(isInTOFMode(self)){
self->iDim[self->rank] = getNoOfTimebins(self);
myrank++;
}
for(i = 0; i < myrank; i++){
if( (iStart[i] < 0) || (iStart[i] > self->iDim[i]) ) {
sprintf(pBueffel,"ERROR: %d is out of data dimension range",
iStart[i]);
@ -398,13 +403,14 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
iHistLength = getHMDataLength(self);
/* actually sum */
switch(self->rank)
switch(myrank)
{
case 1:
lSum = SumRow(self->localBuffer, iHistLength,
iStart[0], iEnd[0]);
break;
case 2:
/*
lSum = 0;
for(i = iStart[1]; i < iEnd[1]; i++){
iIndex = i*self->iDim[0];
@ -412,11 +418,19 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
iIndex+iStart[0], iIndex+iEnd[0]);
lSum += lRowSum;
}
*/
lSum = 0;
for(i = iStart[0]; i < iEnd[0]; i++){
iIndex = i*self->iDim[1];
lRowSum = SumRow(self->localBuffer,iHistLength,
iIndex+iStart[1], iIndex+iEnd[1]);
lSum += lRowSum;
}
break;
default:
sprintf(pBueffel,
"ERROR: summing in %d dimensions not yet implemented",
self->rank);
myrank);
SCWrite(pCon,pBueffel,eError);
return -1;
break;

View File

@ -47,6 +47,7 @@
#include "counter.h"
#include "drive.h"
#include "maximize.h"
#include "motor.h"
#define MAXPTS 100
#define DEBUG 1
@ -135,7 +136,25 @@
}
return 1;
}
/*----------------------------------------------------------------------*/
static float readMPDrivable(void *pVar, SConnection *pCon)
{
float value = -999.99;
pIDrivable pDriv = NULL;
pDummy pDum = (pDummy)pVar;
pDriv = GetDrivableInterface(pVar);
assert(pDriv != NULL);
if(strcmp(pDum->pDescriptor->name,"Motor") == 0)
{
MotorGetSoftPosition((pMotor)pVar,pCon,&value);
}
else
{
value = pDriv->GetValue(pVar,pCon);
}
return value;
}
/*-----------------------------------------------------------------------*/
int MaximizePeak(pMax self, void *pVar, char *pVarName,
float fStep, CounterMode eMode,
@ -160,7 +179,7 @@
start:
lMax = 0;
lMin = 0x7fffffff;
fStart = pDriv->GetValue(pVar,pCon);
fStart = readMPDrivable(pVar,pCon);
if(fStart < -999999.)
{
return 0;
@ -177,7 +196,7 @@
{
return 0;
}
x[i] = pDriv->GetValue(pVar,pCon);
x[i] = readMPDrivable(pVar,pCon);
/* count */
if(maxCount(self->pCount,eMode,fPreset, &lCts,pCon) != 1)
{
@ -256,7 +275,7 @@
{
return 0;
}
x[i] = pDriv->GetValue(pVar,pCon);
x[i] = readMPDrivable(pVar,pCon);
/* count */
if(maxCount(self->pCount,eMode,fPreset, &lCts,pCon) != 1)
{
@ -426,7 +445,9 @@
AddCommand(pSics,"max",MaximizeAction,MaxKill,pNew);
return 1;
}
/*------------------------------------------------------------------*/
/*------------------------------------------------------------------
* max motor step preset mode
* ---------------------------------------------------------------------*/
int MaximizeAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{

View File

@ -33,6 +33,7 @@
#include "fourtable.h"
#include "lld.h"
#include "stdscan.h"
#include "exeman.h"
extern void SNXFormatTime(char *pBueffel, int iLen);
extern float nintf(float f);
@ -994,6 +995,8 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
int iRet, i,ii, iLF, iNP;
char pBueffel[512], pNum[10], pTime[132];
pEVControl pEva = NULL;
pDummy pPtr = NULL;
pIDrivable pDriv = NULL;
assert(self);
assert(pCon);
@ -1079,7 +1082,20 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
fTemp = -777.77;
pEva = (pEVControl)FindCommandData(pServ->pSics,"temperature",
"Environment Controller");
if(pEva)
if(pEva == NULL)
{
pPtr = (pDummy)FindCommandData(pServ->pSics,"temperature",
"RemObject");
if(pPtr != NULL)
{
pDriv = pPtr->pDescriptor->GetInterface(pPtr,DRIVEID);
if(pDriv != NULL)
{
fTemp = pDriv->GetValue(pPtr,pCon);
}
}
}
else
{
iRet = EVCGetPos(pEva, pCon,&fTemp);
}
@ -1141,6 +1157,19 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
}
return 1;
}
/*---------------------------------------------------------------------*/
static FILE *openListFile(char *pName){
FILE *fd = NULL;
pDynString filename = NULL;
filename = findBatchFile(pServ->pSics,pName);
if(filename != NULL){
fd = fopen(GetCharArray(filename),"r");
DeleteDynString(filename);
} else {
fd = fopen(pName,"r");
}
return fd;
}
/*------------------------------------------------------------------------*/
int MesureFile(pMesure self, char *pFile, int iSkip, SConnection *pCon)
{
@ -1153,7 +1182,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
assert(pCon);
/* well before doing a thing, open the list file */
fd = fopen(pFile,"r");
fd = openListFile(pFile);
if(!fd)
{
sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);
@ -1242,7 +1271,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
assert(pCon);
/* well before doing a thing, open the list file */
fd = fopen(pFile,"r");
fd = openListFile(pFile);
if(!fd)
{
sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);
@ -1301,7 +1330,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
assert(pCon);
/* well before doing a thing, open the list file */
fd = fopen(pFile,"r");
fd = openListFile(pFile);
if(!fd)
{
sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);

View File

@ -315,6 +315,7 @@
char pError[132];
int i, iToken, iRet;
sParser PP;
CommandList *pCom = NULL;
assert(pCon);
assert(pSics);
@ -345,9 +346,10 @@
break;
case ENDCONFIG:
/* reconfigure command to final state */
RemoveCommand(pSics,argv[0]);
AddCommand(pSics,argv[0],MultiWrapper,KillMultiMotor,
self);
pCom = FindCommand(pSics,argv[0]);
assert(pCom != NULL);
pCom->OFunc = MultiWrapper;
pCom->KFunc = KillMultiMotor;
return 1;
break;
case ALIAS:

View File

@ -424,9 +424,14 @@ CreateSocketAdress(
return 0;
}
/*
* Check if the we can write to the socket first....
* Well, this how it should be. However, on linux I observe that
* there is a problem with Java clients not reliably receiving data when
* this is active.
*/
#ifndef CYGNUS
/* setup for select first */
tmo.tv_usec = 100;
tmo.tv_usec = 10;
FD_ZERO(&lMask);
FD_SET(self->sockid,&lMask);
if((self->sockid >= FD_SETSIZE) || (self->sockid < 0) )
@ -446,6 +451,7 @@ CreateSocketAdress(
return -2;
}
#endif
iRet = send(self->sockid,buffer,lLen,0);
if(iRet != lLen)
{

View File

@ -750,7 +750,10 @@ static void putArray(SConnection *pCon, SicsInterp *pSics,
data = (float *)malloc(length*sizeof(float));
}
if(data == NULL){
SCWrite(pCon,"ERROR: out of memory or invalid length",eError);
snprintf(buffer,255,
"ERROR: out of memory or invalid length at %s, length = %s",
argv[2],argv[4]);
SCWrite(pCon,buffer,eError);
return;
}
memset(data,0,length*sizeof(float));

View File

@ -434,6 +434,42 @@ void getRS232Error(int iCode, char *errorBuffer,
}
}
/*--------------------------------------------------------------------*/
int fixRS232Error(prs232 self, int iCode){
int i, status, read;
char buffer[8192];
switch(iCode){
case BADMEMORY:
case FAILEDCONNECT:
return 0;
break;
case INCOMPLETE:
case TIMEOUT:
/*
* try to clear possibly pending stuff
*/
for(i = 0; i < 3; i++){
if(availableRS232(self)){
read = 8192;
readRS232(self,buffer,&read);
}
}
return 1;
break;
case NOTCONNECTED:
case BADSEND:
closeRS232(self);
status = initRS232(self);
if(status){
return 1;
} else {
return 0;
}
break;
}
return 0;
}
/*--------------------------------------------------------------------*/
int getRS232Timeout(prs232 self){
return self->timeout;
}

View File

@ -65,6 +65,7 @@
void getRS232Error(int iCode, char *errorBuffer,
int errorBufferLen);
int fixRS232Error(prs232 self, int iCode);
int getRS232Timeout(prs232 self);
int initRS232(prs232 self);
int initRS232WithFlags(prs232 self, int flags);

209
sans.tcl
View File

@ -1,209 +0,0 @@
# --------------------------------------------------------------------------
# Initialization script the instrument SANS at SINQ
#
# Dr. Mark Koennecke, June 1997
#---------------------------------------------------------------------------
# O P T I O N S
set root "/data/koenneck/src/sics"
# first all the server options are set
ServerOption SaveFile $root/bin/sansstat.tcl
# File to save the status of the instrument too
ServerOption ReadTimeOut 10
# timeout when checking for commands. In the main loop SICS checks for
# pending commands on each connection with the above timeout, has
# PERFORMANCE impact!
ServerOption AcceptTimeOut 10
# timeout when checking for connection req.
# Similar to above, but for connections
ServerOption ReadUserPasswdTimeout 500000
# time to wiat for a user/passwd to be sent from a client. Increase this
# if there is a problem connecting to a server due to network overload\
ServerOption LogFileBaseName $root/log/sanslog
# the path and base name of the internal server logfile to which all
# activity will be logged.
ServerOption ServerPort 2915
# the port number the server is going to listen at. The client MUST know
# this number in order to connect. It is in client.ini
ServerOption InterruptPort 2917
# The UDP port where the server will wait for Interrupts from clients.
# Obviously, clients wishing to interrupt need to know this number.
# Telnet Options
ServerOption TelnetPort 1301
ServerOption TelWord sicslogin
# The token system
TokenInit connan
#---------------------------------------------------------------------------
# U S E R S
# than the SICS users are specified
# Syntax: SicsUser name password userRightsCode
SicsUser Manager Joachim 1
SicsUser User Kohl 2
SicsUser Spy 007 3
#--------------------------------------------------------------------------
# S I M P L E V A R I A B L E S
# now a few general variables are created
# Syntax: VarMake name type access
# type can be one of: Text, Int, Float
#access can be one of: Internal, Mugger, user, Spy
VarMake Instrument Text Internal
Instrument "SANS at SINQ,PSI"
#initialisation
Instrument lock
VarMake title Text User
VarMake User Text User
User "Albert von Villigen"
VarMake SubTitle Text User
VarMake environment Text User
VarMake comment Text User
VarMake SampleName Text User
SampleName KohlSulfid
#----------- Initialize data storage stuff
VarMake SicsDataPath Text Mugger
SicsDataPath $root/data/
SicsDataPath lock
VarMake SicsDataPrefix Text Mugger
SicsDataPrefix sans
SicsDataPrefix lock
VarMake SicsDataPostFix Text Mugger
SicsDataPostFix ".hdf"
SicsDataPostFix lock
MakeDataNumber SicsDataNumber $root/data/2001/DataNumber
InitSANS $root/sansdict.dic
#--------------------------------------------------------------------------
# D E V I C E S : M O T O R S
#Motor a4 EL734 LNSP22 4000 5 6
# EL734 motor with parameters: hostname PortNumber Channel MotorID
#Motor a4 EL734DC LNSP22 4000 5 6
# EL734DC motor with parameters: hostname PortNumber Channel MotorID
# Motor nam SIM -20. 20. 5. 1.0
# Simulated motor with name nam, lower limit -20, upper limit +20,
# error ratio 5% and speed 1.0. Speed may be omitted
# Motors for sample movement
Motor schi SIM -22.0 +22. 10.
Motor sphi SIM -22.0 +22.0 10.
Motor som EL734 lnsp25.psi.ch 4000 2 8
Motor sax EL734 lnsp25.psi.ch 4000 2 6
Motor say EL734 lnsp25.psi.ch 4000 2 7
Motor saz EL734 lnsp25.psi.ch 4000 2 1
Motor spos EL734 lnsp25.psi.ch 4000 2 5
#Motors for detector movement
Motor DetectorX EL734DC lnsp25.psi.ch 4000 3 1
DetectorX Precision 0.5
Motor DetectorY EL734DC lnsp25.psi.ch 4000 3 2
DetectorY Precision 0.2
Motor DetectorRotation EL734DC lnsp25.psi.ch 4000 3 3
DetectorRotation Precision 0.1
#Motors for beamstop
Motor BeamStopX EL734 lnsp25.psi.ch 4000 2 3
BeamStopX Precision 0.2
Motor BeamStopY EL734 lnsp25.psi.ch 4000 2 4
BeamStopY Precision 0.2
#------------------------------------------------------------------------
# Velocity selector
Motor tilt EL734 lnsp25.psi.ch 4000 2 2
set dornen(Host) lnsp25.psi.ch
set dornen(Port) 4000
set dornen(Channel) 6
set dornen(Timeout) 3000
VelocitySelector nvs tilt DORNIER dornen
nvs add -20 28800
nvs add 3800 4500
nvs add 5900 6700
nvs add 8100 9600
unset dornen
#--------------------------------------------------------------------------
# P R O C E D U R E S
# create the drive command
MakeDrive
#--------------------------------------------------------------------------
# MultiMotor is an object which groups several motors together.
#--------------------------------- sample position
MakeMulti sample
# creates a MultiMotor with name sample
sample alias schi chi
# alias creates an internal name (chi) for motor schi
sample alias sphi phi
sample alias som omega
sample alias sax x
sample alias say y
sample alias saz z
sample pos Jo schi 0. sphi 0. som 45. sax 2. say 3. saz 10.
# define Jo as a named position. This means with sample Jo you'll reach
# the positions specified
sample pos Mo schi 0. sphi 0. som 180. sax 2. say 3. saz 10.
sample endconfig
# ends configuration of sample and install the command. This is REQUIRED
#---------------------------------- detector position
MakeMulti detector
detector alias DetectorX X
detector alias DetectorY Y
detector alias DetectorRotation phi
detector endconfig
#----------------------------------- beamstop
MakeMulti BeamStop
BeamStop alias BeamStopX X
BeamStop alias BeamStopY Y
BeamStop pos out BeamStopX 817.
BeamStop endconfig
#------------------------------------ Shortcuts
SicsAlias BeamStop bs
SicsAlias detector dt
#------------------------------------ Histogram Memory
MakeCounter counter EL737 lnsp25.psi.ch 4000 4
counter SetExponent 6
MakeHM banana SINQHM
banana configure HistMode Normal
banana configure OverFlowMode Ceil
banana configure Rank 1
banana configure Length 16384
banana configure BinWidth 4
banana preset 100.
banana CountMode Timer
banana configure HMComputer lnse02.psi.ch
banana configure HMPort 2400
banana configure Counter counter
banana init
banana exponent 6
#-----------------------------------------------------------------------------
# R U E N B U F F E R
MakeRuenBuffer
#---------------------- some special Tcl commands
source $root/bin/log.tcl
Publish LogBook User
source $root/bin/count.tcl
Publish count User
Publish Repeat User

View File

@ -13,9 +13,9 @@ struct Statistics {
Statistics *next;
};
static Statistics *current;
static Statistics *current = NULL;
static tv_t last, lastStat;
static Statistics *idle = NULL, *list;
static Statistics *idle = NULL, *list = NULL;
static int init = 1;
/*-----------------------------------------------------------------------*/
tv_t timeDif(tv_t t1, tv_t t2) {
@ -128,7 +128,9 @@ Statistics *StatisticsBegin(Statistics *stat) {
res = current;
gettimeofday(&now, 0);
if(current != NULL){
timeAdd(&current->tim, timeDif(last, now));
}
last = now;
current = stat;
stat->last = now;
@ -142,10 +144,12 @@ void StatisticsEnd(Statistics *stat) {
gettimeofday(&now, 0);
timeAdd(&current->tim, timeDif(last, now));
last = now;
if(current != NULL){
if (current->last.tv_sec >= 0) {
timeAdd(&current->total, timeDif(current->last, now));
}
current->last.tv_sec = -1;
}
current = stat;
}
/*-----------------------------------------------------------------------*/

78
tasub.c
View File

@ -875,6 +875,80 @@ static void listDiagnostik(ptasUB self, SConnection *pCon){
status = LLDnodePtr2Next(self->reflectionList);
}
}
/*-----------------------------------------------------------------*/
static int addAuxReflection(ptasUB self, SConnection *pCon,
SicsInterp *pSics, int argc, char *argv[]){
int status;
tasReflection r1, r2;
float value = -999.99;
char pBueffel[256];
MATRIX UB = NULL, B = NULL;
if(argc < 5){
SCWrite(pCon,
"ERROR: not enough arguments auxiliary reflection, need HKL",
eError);
return 0;
}
if(!SCMatchRights(pCon,usUser)){
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[2],&r2.qe.qh);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&r2.qe.qk);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&r2.qe.ql);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[4]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
B = mat_creat(3,3,ZERO_MATRIX);
if(B == NULL){
SCWrite(pCon,"ERROR: out of memory creating B matrix",eError);
return 0;
}
status = calculateBMatrix(self->cell,B);
if(status < 0){
SCWrite(pCon,"ERROR: bad cell constants, no volume",eError);
mat_free(B);
return 0;
}
status = findReflection(self->reflectionList, 0,&r1);
if(status != 1){
r2.qe.kf = self->current.kf;
r2.qe.ki = self->current.ki;
MotorGetSoftPosition(self->motors[A3],pCon,&value);
r2.angles.a3 = value + 180.;
r2.angles.sgu = .0;
r2.angles.sgl = .0;
calcTwoTheta(B,r2.qe,self->machine.ss_sample,&r2.angles.sample_two_theta);
r1 = r2;
}
status = makeAuxReflection(B, r1, &r2,self->machine.ss_sample);
mat_free(B);
if(status < 0){
SCWrite(pCon,"ERROR: out of memory in makeAuxUB or scattering angle not closed",
eError);
return 0;
}
LLDnodeAppend(self->reflectionList,&r2);
SCSendOK(pCon);
return 1;
}
/*------------------------------------------------------------------*/
static int calcAuxUB(ptasUB self, SConnection *pCon, SicsInterp *pSics,
int argc, char *argv[]){
@ -885,7 +959,7 @@ static int calcAuxUB(ptasUB self, SConnection *pCon, SicsInterp *pSics,
if(argc < 5){
SCWrite(pCon,
"ERROR: not enough arguments for UB calculation, need HKJL of second plane vector",
"ERROR: not enough arguments for UB calculation, need HKL of second plane vector",
eError);
return 0;
}
@ -1564,6 +1638,8 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
return calcUB(self,pCon,pSics,argc,argv);
} else if(strcmp(argv[1],"makeauxub") == 0){
return calcAuxUB(self,pCon,pSics,argc,argv);
} else if(strcmp(argv[1],"addauxref") == 0){
return addAuxReflection(self,pCon,pSics,argc,argv);
} else if(strcmp(argv[1],"makeubfromcell") == 0){
return calcUBFromCell(self,pCon);
} else if(strcmp(argv[1],"calcang") == 0){

View File

@ -246,6 +246,29 @@ int makeAuxReflection(MATRIX B, tasReflection r1, tasReflection *r2,
return 1;
}
/*------------------------------------------------------------------*/
int calcTwoTheta(MATRIX B, tasQEPosition ref, int ss, double *value){
MATRIX QC;
double cos2t, q;
QC = tasReflectionToHC(ref,B);
if(QC == NULL){
return UBNOMEMORY;
}
q = vectorLength(QC);
q = 2.*PI*vectorLength(QC);
killVector(QC);
cos2t = (ref.ki*ref.ki + ref.kf*ref.kf - q*q)/
(2. * ABS(ref.ki) * ABS(ref.kf));
if(ABS(cos2t) > 1.){
return TRIANGLENOTCLOSED;
}
*value = ss*Acosd(cos2t);
return 1;
}
/*-------------------------------------------------------------------*/
MATRIX calcPlaneNormal(tasReflection r1, tasReflection r2){
MATRIX u1 = NULL, u2 = NULL, planeNormal = NULL;

View File

@ -137,6 +137,15 @@ double maCalcK(maCrystal data, double two_theta);
*/
int makeAuxReflection(MATRIX B, tasReflection r1,
tasReflection *r2, int ss);
/**
* calculate two theta for the reflection ref
* @param B the metric matrix, or the UB
* @param ref The reflection for which to calculate two theta
* @param ss The scattering sense
* @param twoTheta The new two theta value (output)
* @return a negative error code on failure, 1 on success
*/
int calcTwoTheta(MATRIX B, tasQEPosition ref, int ss, double *twoTheta);
/**
* calculate a UB from two reflections and the cell.
* @param cell The lattice constant of the crystal