1278 lines
35 KiB
C
1278 lines
35 KiB
C
/*--------------------------------------------------------------------------
|
|
This is the implementation for the TAS scan code. It mainly implements
|
|
writing of the ILL file format, which the TAS'lers adore.
|
|
|
|
Mark Koennecke, May 2005, using code from an earlier TASAMAD emulation
|
|
core.
|
|
|
|
Modified to write UV matrix.
|
|
|
|
Mark Koennecke, July 2011
|
|
---------------------------------------------------------------------------*/
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <time.h>
|
|
#include <ctype.h>
|
|
#include <tcl.h>
|
|
#include <fortify.h>
|
|
#include <sics.h>
|
|
#include <sicsvar.h>
|
|
#include <counter.h>
|
|
#include <motor.h>
|
|
#include <scan.h>
|
|
#include <scan.i>
|
|
#include <lld.h>
|
|
#include "scanvar.h"
|
|
#include <evcontroller.h>
|
|
#include <splitter.h>
|
|
#include <status.h>
|
|
#include "tasscanub.h"
|
|
#include "nxscript.h"
|
|
/*------------------------------------------------------------------------
|
|
a little local utility for making a line of characters
|
|
-------------------------------------------------------------------------*/
|
|
static void charLine(char *pBueffel, char c)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 80; i++) {
|
|
pBueffel[i] = c;
|
|
}
|
|
pBueffel[80] = '\n';
|
|
pBueffel[81] = '\0';
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static void strtoupper(char *pText)
|
|
{
|
|
assert(pText);
|
|
|
|
while (*pText != '\0') {
|
|
*pText = toupper(*pText);
|
|
pText++;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
static void strcenter(char *str, char *target, int iLength)
|
|
{
|
|
int iPtr, i;
|
|
|
|
/*
|
|
catch the error if target is to long
|
|
*/
|
|
if (strlen(str) >= iLength) {
|
|
strlcpy(target, str, iLength);
|
|
}
|
|
|
|
iPtr = (iLength - strlen(str)) / 2;
|
|
for (i = 0; i < iPtr; i++) {
|
|
target[i] = ' ';
|
|
}
|
|
target[iPtr] = '\0';
|
|
strcat(target, str);
|
|
for (i = iPtr + strlen(str); i < iLength - 1; i++) {
|
|
target[i] = ' ';
|
|
}
|
|
target[iLength - 1] = '\0';
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
static char *GetVarText(char *name)
|
|
{
|
|
pSicsVariable pVar = NULL;
|
|
|
|
pVar =
|
|
(pSicsVariable) FindCommandData(pServ->pSics, name, "SicsVariable");
|
|
if (pVar != NULL) {
|
|
return pVar->text;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------
|
|
helper function for TASHeader
|
|
------------------------------------------------------------------------*/
|
|
static void writePolFile(FILE * fd, pTASdata pTAS)
|
|
{
|
|
char pLine[132];
|
|
FILE *fpol = NULL;
|
|
|
|
assert(fd);
|
|
assert(pTAS);
|
|
|
|
fpol = fopen(GetVarText("polfile"), "r");
|
|
if (!fpol) {
|
|
/*
|
|
error gets reported anyway later on
|
|
*/
|
|
return;
|
|
}
|
|
|
|
while (fgets(pLine, 131, fpol) != NULL) {
|
|
if (strstr(pLine, "\n") == NULL) {
|
|
fprintf(fd, "POLAN: %s\n", pLine);
|
|
} else {
|
|
fprintf(fd, "POLAN: %s", pLine);
|
|
}
|
|
}
|
|
fclose(fpol);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
static char *findLastPoint(char *text)
|
|
{
|
|
char *pPtr;
|
|
int i;
|
|
|
|
pPtr = text + strlen(text) - 1;
|
|
for (i = strlen(text); i > 0; i--, pPtr--) {
|
|
if (*pPtr == '.') {
|
|
return pPtr;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------
|
|
readDrivable tries to read the value of one of the magnet currents.
|
|
All errors are ignored because most of the time currents will not be
|
|
present in the system.
|
|
-----------------------------------------------------------------------*/
|
|
static float readDrivable(char *val, SConnection * pCon)
|
|
{
|
|
pIDrivable pDriv;
|
|
CommandList *pCom;
|
|
pDummy pDum;
|
|
pMotor pMot = NULL;
|
|
float fVal;
|
|
|
|
/*
|
|
read general drivable
|
|
*/
|
|
pCom = FindCommand(pServ->pSics, val);
|
|
if (pCom != NULL) {
|
|
pDriv = GetDrivableInterface(pCom->pData);
|
|
if (pDriv != NULL) {
|
|
return pDriv->GetValue(pCom->pData, pCon);
|
|
}
|
|
}
|
|
return -999.99;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
static float GetVarFloat(char *name)
|
|
{
|
|
pSicsVariable pVar = NULL;
|
|
|
|
pVar =
|
|
(pSicsVariable) FindCommandData(pServ->pSics, name, "SicsVariable");
|
|
if (pVar != NULL) {
|
|
return pVar->fVal;
|
|
} else {
|
|
return -999.99;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
TASHeader writes the header of a TAS data file. The format is an
|
|
obscure format from ILL ( not ill but Institute Laue Langevin). No
|
|
documentation about this exists except the files themselves. This is long
|
|
and tiresome code.
|
|
---------------------------------------------------------------------------*/
|
|
static int TASUBHeader(pScanData self)
|
|
{
|
|
pTASdata pTAS = (pTASdata) self->pSpecial;
|
|
int i, iCount, status, iFileNO = 0;
|
|
char pBueffel[1024], pHeader[1024], pWork[132], pWork2[60], pTen[12],
|
|
*pcPtr;
|
|
time_t iDate;
|
|
struct tm *psTime;
|
|
pVarEntry pVar = NULL;
|
|
void *pPtr = NULL;
|
|
pMotor pMot;
|
|
float fVal, fVal2;
|
|
CommandList *pCom = NULL;
|
|
pDummy pDum = NULL;
|
|
pIDrivable pDrive = NULL;
|
|
pEVControl pTem = NULL;
|
|
int fx;
|
|
tasReflection r;
|
|
double kfix;
|
|
pSicsVariable sVar = NULL;
|
|
float f1=.0, f2=.0, f3=.0, f4=.0;
|
|
|
|
assert(self);
|
|
assert(pTAS);
|
|
assert(self->pCon);
|
|
assert(self->pSics);
|
|
|
|
/* open data file */
|
|
self->fd = fopen(self->pFile, "w");
|
|
if (!self->fd) {
|
|
SCWrite(self->pCon, "ERROR: cannot write data file", eLogError);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
extract the file number from the name for entry into the
|
|
datafile
|
|
*/
|
|
pcPtr = findLastPoint(self->pFile);
|
|
if (pcPtr != NULL) {
|
|
pcPtr -= 6; /* 6 digits for number */
|
|
for (i = 0; i < 6; i++, pcPtr++) {
|
|
pWork[i] = *pcPtr;
|
|
}
|
|
pWork[6] = '\0';
|
|
iFileNO = atoi(pWork);
|
|
} else {
|
|
SCWrite(self->pCon, "WARNING: failed to decode file number", eLog);
|
|
}
|
|
|
|
/* the bizarre R, A, V header */
|
|
charLine(pBueffel, 'R');
|
|
fputs(pBueffel, self->fd);
|
|
fprintf(self->fd, "%8d%8d%8d\n", iFileNO, 1, 0);
|
|
fputs
|
|
("ILL TAS data in the new ASCII format follow after the line VV...V\n",
|
|
self->fd);
|
|
charLine(pBueffel, 'A');
|
|
fputs(pBueffel, self->fd);
|
|
fprintf(self->fd, "%8d%8d\n", 42, 0);
|
|
|
|
/*
|
|
format time to TAS format
|
|
*/
|
|
iDate = time(NULL);
|
|
psTime = localtime(&iDate);
|
|
memset(pWork, 0, 59);
|
|
strftime(pWork, 59, "%d-%b-%Y %H:%M:%S", psTime);
|
|
fprintf(self->fd, "%-10s%-12s%-s\n", GetVarText("instrument"),
|
|
GetVarText("user"), pWork);
|
|
|
|
charLine(pBueffel, 'V');
|
|
fputs(pBueffel, self->fd);
|
|
|
|
/*
|
|
output a plethora of parameters
|
|
*/
|
|
fprintf(self->fd, "INSTR: %s\n", GetVarText("instrument"));
|
|
fprintf(self->fd, "EXPNO: \n");
|
|
fprintf(self->fd, "USER_: %s\n", GetVarText("user"));
|
|
fprintf(self->fd, "LOCAL: %s\n", GetVarText("local"));
|
|
fprintf(self->fd, "FILE_: %d\n", iFileNO);
|
|
fprintf(self->fd, "DATE_: %s\n", pWork);
|
|
fprintf(self->fd, "TITLE: %s\n", GetVarText("title"));
|
|
fprintf(self->fd, "COMND: %s\n", GetVarText("lastscancommand"));
|
|
tasUpdate(self->pCon,pTAS->ub);
|
|
fprintf(self->fd,
|
|
"POSQE: QH=%8.4f, QK=%8.4f, QL=%8.4f, EN=%8.4f, UN=MEV\n",
|
|
pTAS->ub->current.qh,
|
|
pTAS->ub->current.qk,
|
|
pTAS->ub->current.ql, getTasPar(pTAS->ub->current, EN));
|
|
/*
|
|
build the steps line
|
|
*/
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "STEPS: ");
|
|
for (i = 0; i < self->iScanVar; i++) {
|
|
DynarGet(self->pScanVar, i, &pPtr);
|
|
pVar = (pVarEntry) pPtr;
|
|
if (pVar) {
|
|
strlcpy(pWork2, ScanVarName(pVar), 59);
|
|
strtoupper(pWork2);
|
|
snprintf(pWork,sizeof(pWork)-1, "D%s=%8.4f, ", pWork2, ScanVarStep(pVar));
|
|
strcat(pBueffel, pWork);
|
|
}
|
|
}
|
|
strcat(pBueffel, "\n");
|
|
fputs(pBueffel, self->fd);
|
|
|
|
/*
|
|
a lot of parameters
|
|
*/
|
|
fprintf(self->fd, "PARAM: DM=%8.4f, DA=%8.4f, SM=%2d, SS=%2d, SA=%2d\n",
|
|
pTAS->ub->machine.monochromator.dd,
|
|
pTAS->ub->machine.analyzer.dd,
|
|
pTAS->ub->machine.monochromator.ss,
|
|
pTAS->ub->machine.ss_sample, pTAS->ub->machine.analyzer.ss);
|
|
if (pTAS->ub->tasMode == KICONST) {
|
|
fx = 2;
|
|
kfix = getTasPar(pTAS->ub->current, KI);
|
|
} else {
|
|
fx = 1;
|
|
kfix = getTasPar(pTAS->ub->current, KF);
|
|
}
|
|
|
|
fprintf(self->fd, "PARAM: FX=%3d, KFIX=%8.4f\n", fx, kfix);
|
|
fprintf(self->fd,
|
|
"PARAM: ALF1=%8.4f, ALF2=%8.4f, ALF3=%8.4f, ALF4=%8.4f\n",
|
|
GetVarFloat("alf1"), GetVarFloat("alf2"), GetVarFloat("alf3"),
|
|
GetVarFloat("alf4"));
|
|
fprintf(self->fd,
|
|
"PARAM: BET1=%8.4f, BET2=%8.4f, BET3=%8.4f, BET4=%8.4f\n",
|
|
GetVarFloat("bet1"), GetVarFloat("bet2"), GetVarFloat("bet3"),
|
|
GetVarFloat("bet4"));
|
|
fprintf(self->fd, "PARAM: ETAM=%8.4f, ETAA=%8.4f\n", GetVarFloat("etam"),
|
|
GetVarFloat("etaa"));
|
|
|
|
fprintf(self->fd, "PARAM: AS=%8.4f, BS=%8.4f, CS=%8.4f\n",
|
|
pTAS->ub->cell.a, pTAS->ub->cell.b, pTAS->ub->cell.c);
|
|
fprintf(self->fd, "PARAM: AA=%8.4f, BB=%8.4f, CC=%8.4f\n",
|
|
pTAS->ub->cell.alpha, pTAS->ub->cell.beta, pTAS->ub->cell.gamma);
|
|
|
|
fprintf(self->fd, "PARAM: UB11=%8.4f, UB12=%8.4f, UB13=%8.4f\n",
|
|
pTAS->ub->machine.UB[0][0], pTAS->ub->machine.UB[0][1], pTAS->ub->machine.UB[0][2]);
|
|
fprintf(self->fd, "PARAM: UB21=%8.4f, UB22=%8.4f, UB23=%8.4f\n",
|
|
pTAS->ub->machine.UB[1][0], pTAS->ub->machine.UB[1][1], pTAS->ub->machine.UB[1][2]);
|
|
fprintf(self->fd, "PARAM: UB31=%8.4f, UB32=%8.4f, UB33=%8.4f\n",
|
|
pTAS->ub->machine.UB[2][0], pTAS->ub->machine.UB[2][1], pTAS->ub->machine.UB[2][2]);
|
|
|
|
fprintf(self->fd, "PARAM: PN1=%8.4f, PN2=%8.4f, PN3=%8.4f\n",
|
|
pTAS->ub->machine.planeNormal[0][0], pTAS->ub->machine.planeNormal[1][0], pTAS->ub->machine.planeNormal[2][0]);
|
|
|
|
|
|
r = pTAS->ub->r1;
|
|
fprintf(self->fd, "PARAM: AX=%8.4f, AY=%8.4f, AZ=%8.4f\n",
|
|
r.qe.qh, r.qe.qk, r.qe.ql);
|
|
|
|
r = pTAS->ub->r2;
|
|
fprintf(self->fd, "PARAM: BX=%8.4f, BY=%8.4f, BZ=%8.4f\n",
|
|
r.qe.qh, r.qe.qk, r.qe.ql);
|
|
|
|
/*
|
|
* write mupad stuff if available
|
|
*/
|
|
sVar = FindCommandData(pServ->pSics, "w1", "SicsVariable");
|
|
if (sVar != NULL) {
|
|
f1 = sVar->fVal;
|
|
sVar = FindCommandData(pServ->pSics, "w2", "SicsVariable");
|
|
if (sVar != NULL) {
|
|
f2 = sVar->fVal;
|
|
}
|
|
sVar = FindCommandData(pServ->pSics, "w3", "SicsVariable");
|
|
if (sVar != NULL) {
|
|
f3 = sVar->fVal;
|
|
}
|
|
sVar = FindCommandData(pServ->pSics, "w4", "SicsVariable");
|
|
if (sVar != NULL) {
|
|
f4 = sVar->fVal;
|
|
}
|
|
fprintf(self->fd, "PARAM: W1=%8.4f, W2=%8.4f, W3=%8.4f, W4=%8.4f\n",
|
|
f1, f2, f3, f4);
|
|
|
|
sVar = FindCommandData(pServ->pSics, "p1", "SicsVariable");
|
|
if (sVar != NULL) {
|
|
f1 = sVar->fVal;
|
|
}
|
|
sVar = FindCommandData(pServ->pSics, "p2", "SicsVariable");
|
|
if (sVar != NULL) {
|
|
f2 = sVar->fVal;
|
|
}
|
|
sVar = FindCommandData(pServ->pSics, "p3", "SicsVariable");
|
|
if (sVar != NULL) {
|
|
f3 = sVar->fVal;
|
|
}
|
|
sVar = FindCommandData(pServ->pSics, "p4", "SicsVariable");
|
|
if (sVar != NULL) {
|
|
f4 = sVar->fVal;
|
|
}
|
|
fprintf(self->fd, "PARAM: P1=%8.4f, P2=%8.4f, P3=%8.4f, P4=%8.4f\n",
|
|
f1, f2, f3, f4);
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
write currents if in polarisation mode
|
|
*/
|
|
if (pTAS->iPOL >= 0) {
|
|
fprintf(self->fd, "VARIA: ");
|
|
iCount = 0;
|
|
for (i = 0; i < 8; i++) {
|
|
snprintf(pWork2, 59, "i%1.1d", i);
|
|
fVal = readDrivable(pWork2, self->pCon);
|
|
strtoupper(pWork2);
|
|
fprintf(self->fd, "%-8s=%8.4f, ", pWork2, fVal);
|
|
iCount++;
|
|
}
|
|
fprintf(self->fd, "\n");
|
|
}
|
|
|
|
/*
|
|
write motors
|
|
*/
|
|
fprintf(self->fd, "VARIA: ");
|
|
iCount = 0;
|
|
pCom = pServ->pSics->pCList;
|
|
while (pCom != NULL) {
|
|
pDum = (pDummy) pCom->pData;
|
|
if (pDum != NULL) {
|
|
if (strcmp(pDum->pDescriptor->name, "Motor") == 0) {
|
|
fVal = readDrivable(pCom->pName, self->pCon);
|
|
if (iCount == 3) {
|
|
iCount = 0;
|
|
fprintf(self->fd, "\nVARIA: ");
|
|
}
|
|
strlcpy(pWork2, pCom->pName,60);
|
|
strtoupper(pWork2);
|
|
fprintf(self->fd, "%-8s=%8.4f, ", pWork2, fVal);
|
|
iCount++;
|
|
}
|
|
}
|
|
pCom = pCom->pNext;
|
|
}
|
|
fprintf(self->fd, "\n");
|
|
|
|
/*
|
|
write zeros
|
|
*/
|
|
fprintf(self->fd, "ZEROS: ");
|
|
iCount = 0;
|
|
pCom = pServ->pSics->pCList;
|
|
while (pCom != NULL) {
|
|
pDum = (pDummy) pCom->pData;
|
|
if (pDum != NULL) {
|
|
if (strcmp(pDum->pDescriptor->name, "Motor") == 0) {
|
|
pMot = (pMotor) pCom->pData;
|
|
if (pMot) {
|
|
status = MotorGetPar(pMot, "softzero", &fVal);
|
|
if (!status) {
|
|
fVal = -9999.77;
|
|
}
|
|
fVal *= -1;
|
|
if (iCount == 3) {
|
|
iCount = 0;
|
|
fprintf(self->fd, "\nZEROS: ");
|
|
}
|
|
strlcpy(pWork2, pCom->pName,60);
|
|
strtoupper(pWork2);
|
|
fprintf(self->fd, "%-8s=%8.4f, ", pWork2, fVal);
|
|
iCount++;
|
|
}
|
|
}
|
|
}
|
|
pCom = pCom->pNext;
|
|
}
|
|
fprintf(self->fd, "\n");
|
|
|
|
if (pTAS->iPOL >= 0) {
|
|
writePolFile(self->fd, pTAS);
|
|
}
|
|
|
|
/*
|
|
write counter parameters
|
|
*/
|
|
fVal = GetCounterPreset(self->pCounterData);
|
|
if (GetCounterMode(self->pCounterData) == eTimer) {
|
|
fprintf(self->fd, "PARAM: TI=%8.4f\n", fVal);
|
|
} else {
|
|
fprintf(self->fd, "PARAM: MN=%8f\n", fVal);
|
|
}
|
|
|
|
/*
|
|
write temperature data
|
|
*/
|
|
pCom = FindCommand(self->pSics, "temperature");
|
|
if (pCom) {
|
|
pDum = (pDummy) pCom->pData;
|
|
pDrive = pDum->pDescriptor->GetInterface(pDum, DRIVEID);
|
|
if (pDrive) { /* a proper environment device */
|
|
fVal = pDrive->GetValue(pDum, self->pCon);
|
|
pTem = (pEVControl) pCom->pData;
|
|
EVCGetPar(pTem, "target", &fVal2);
|
|
fprintf(self->fd, "PARAM: TT=%8.4f, RT=%8.4f\n", fVal, fVal2);
|
|
}
|
|
}
|
|
|
|
/*
|
|
build both the format and the data header line,
|
|
start with the scan variables
|
|
*/
|
|
if (pTAS->iPOL >= 0) {
|
|
strcpy(pBueffel, "FORMT: (I3,1X,I3,1X,");
|
|
strcpy(pHeader, " PNT PAL");
|
|
} else {
|
|
strcpy(pBueffel, "FORMT: (I4,1X,");
|
|
strcpy(pHeader, " PNT ");
|
|
}
|
|
for (i = 0; i < self->iScanVar; i++) {
|
|
DynarGet(self->pScanVar, i, &pPtr);
|
|
pVar = (pVarEntry) pPtr;
|
|
if (pVar) {
|
|
strlcat(pBueffel, "F9.4,1X,",1024);
|
|
strlcpy(pWork2, pVar->Name, 59);
|
|
strtoupper(pWork2);
|
|
strcenter(pWork2, pTen, 11);
|
|
strlcat(pHeader, pTen,1024);
|
|
}
|
|
}
|
|
/*
|
|
put the standard counter things
|
|
*/
|
|
strcat(pBueffel, "F8.0,1X,F8.0,1X,F9.2,1X,F8.0,1X,F8.0,1X,");
|
|
strcat(pHeader, " M1 M2 TIME CNTS M3 ");
|
|
/*
|
|
now the additional variables
|
|
*/
|
|
for (i = 0; i < pTAS->addCount; i++) {
|
|
if (i == pTAS->addCount - 1) {
|
|
strlcat(pBueffel, "F9.4",1024);
|
|
} else {
|
|
strlcat(pBueffel, "F9.4,1X,",1024);
|
|
}
|
|
strlcpy(pWork2, pTAS->out[i],60);
|
|
strtoupper(pWork2);
|
|
strcenter(pWork2, pTen, 11);
|
|
strlcat(pHeader, pTen,1024);
|
|
}
|
|
strlcat(pBueffel, ")",1024);
|
|
|
|
/*
|
|
write the final bit
|
|
*/
|
|
fprintf(self->fd, "%s\nDATA_:\n%s\n", pBueffel, pHeader);
|
|
|
|
/*
|
|
write header to screen as well
|
|
*/
|
|
SCWrite(self->pCon, pHeader, eLog);
|
|
|
|
/*
|
|
close the file, we will reopen later with append for the data
|
|
*/
|
|
fclose(self->fd);
|
|
self->fd = NULL;
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
TASScanPoint writes the data at each ScanPoint
|
|
---------------------------------------------------------------------------*/
|
|
static int TASUBScanPoint(pScanData self, int iPoint)
|
|
{
|
|
pTASdata pTAS = (pTASdata) self->pSpecial;
|
|
pVarEntry pVar = NULL;
|
|
void *pPtr = NULL;
|
|
int i, status, iPtr;
|
|
float fVal;
|
|
pMotor pMot = NULL;
|
|
long m1, m2, m3, cnts;
|
|
char pBueffel[1024], pWork[80], pError[132];
|
|
|
|
/*
|
|
* force an update to write the right things
|
|
*/
|
|
tasUpdate(self->pCon,pTAS->ub);
|
|
|
|
/*
|
|
after polarisation analysis, this has to be ignored as it is called
|
|
another time from the ScanLoop
|
|
*/
|
|
if (pTAS->iIgnore) {
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
reopen file for appending
|
|
*/
|
|
self->fd = fopen(self->pFile, "a");
|
|
if (!self->fd) {
|
|
SCWrite(self->pCon, "ERROR: cannot append to data file", eLogError);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
write point number
|
|
*/
|
|
if (pTAS->iPOL >= 0) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "%3d %3d ", iPoint + 1, pTAS->iPOL);
|
|
} else {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "%4d ", iPoint + 1);
|
|
}
|
|
|
|
/*
|
|
write the scan variables
|
|
*/
|
|
for (i = 0; i < self->iScanVar; i++) {
|
|
DynarGet(self->pScanVar, i, &pPtr);
|
|
pVar = (pVarEntry) pPtr;
|
|
if (pVar) {
|
|
fVal = readDrivable(ScanVarName(pVar), self->pCon);
|
|
}
|
|
snprintf(pWork,sizeof(pWork)-1, "%9.4f ", fVal);
|
|
strcat(pBueffel, pWork);
|
|
}
|
|
|
|
/*
|
|
write monitors and counters
|
|
*/
|
|
m1 = GetMonitor(self->pCounterData, 1, self->pCon);
|
|
m2 = GetMonitor(self->pCounterData, 2, self->pCon);
|
|
m3 = GetMonitor(self->pCounterData, 3, self->pCon);
|
|
cnts = GetCounts(self->pCounterData, self->pCon);
|
|
fVal = GetCountTime(self->pCounterData, self->pCon);
|
|
snprintf(pWork,sizeof(pWork)-1, "%8ld %8ld %9.2f %8ld %8ld ", m1, m2, fVal, cnts, m3);
|
|
strcat(pBueffel, pWork);
|
|
|
|
/*
|
|
write additional parameters
|
|
*/
|
|
for (i = 0; i < pTAS->addCount; i++) {
|
|
fVal = -999.99;
|
|
fVal = readDrivable(pTAS->out[i], self->pCon);
|
|
if (fVal < -990.) {
|
|
snprintf(pError, 131, "WARNING: problem reading %s", pTAS->out[i]);
|
|
SCWrite(self->pCon, pError, eWarning);
|
|
}
|
|
snprintf(pWork,sizeof(pWork)-1, "%9.4f ", fVal);
|
|
strcat(pBueffel, pWork);
|
|
}
|
|
|
|
/*
|
|
write both to file and onto screen
|
|
*/
|
|
fprintf(self->fd, "%s\n", pBueffel);
|
|
SCWrite(self->pCon, pBueffel, eLog);
|
|
|
|
/*
|
|
close the file
|
|
*/
|
|
fclose(self->fd);
|
|
self->fd = NULL;
|
|
return 1;
|
|
|
|
}
|
|
|
|
/*------------------------------------------------------------------------
|
|
TASScanDrive starts all the motors necessary to drive to a new scan
|
|
position. It thereby takes care of the TAS calculation if necessary.
|
|
-------------------------------------------------------------------------*/
|
|
static int TASUBScanDrive(pScanData self, int iPoint)
|
|
{
|
|
pTASdata pTAS = (pTASdata) self->pSpecial;
|
|
pVarEntry pVar = NULL;
|
|
void *pPtr = NULL;
|
|
int i, status, iPtr;
|
|
int iTAS = 0;
|
|
pMotor pMot;
|
|
pDynString err;
|
|
|
|
pTAS->ub->silent = 1;
|
|
/*
|
|
loop through all the scan variables
|
|
*/
|
|
if(iPoint == 0 && pTAS->iFast != 1) {
|
|
pTAS->ub->stopFixed = 0;
|
|
} else {
|
|
pTAS->ub->stopFixed = 1;
|
|
}
|
|
for (i = 0; i < self->iScanVar; i++) {
|
|
DynarGet(self->pScanVar, i, &pPtr);
|
|
pVar = (pVarEntry) pPtr;
|
|
if (pVar) {
|
|
status = StartMotor(pServ->pExecutor, self->pSics, self->pCon, pVar->Name,
|
|
RUNDRIVE, pVar->fStart + iPoint * pVar->fStep);
|
|
/*
|
|
Ignore errors. TAS scans continues when a motor runs into
|
|
a limit.
|
|
*/
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
now wait for our motors to arrive, thereby ignoring any error
|
|
returns. DO NOT WAIT if fast scan!
|
|
*/
|
|
if (pTAS->iFast) {
|
|
return 1;
|
|
} else {
|
|
status = Wait4Success(GetExecutor());
|
|
pTAS->ub->silent = 0;
|
|
pTAS->ub->stopFixed = 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------
|
|
RunPolScan does a polarized scan
|
|
------------------------------------------------------------------------*/
|
|
static int RunPolScan(pScanData self, int iPoint)
|
|
{
|
|
FILE *fd = NULL;
|
|
char buffer[132];
|
|
pTASdata pTAS = (pTASdata) self->pSpecial;
|
|
|
|
fd = fopen(GetVarText("polfile"), "r");
|
|
if (!fd) {
|
|
SCWrite(self->pCon, "ERROR: failed to open polarisation analysis file",
|
|
eError);
|
|
return 0;
|
|
}
|
|
pTAS->iPOL = 0;
|
|
while (fgets(buffer, 131, fd) != NULL) {
|
|
/*
|
|
ignore all errors here
|
|
*/
|
|
InterpExecute(self->pSics, self->pCon, buffer);
|
|
strtolower(buffer);
|
|
if (strstr(buffer, "co") != NULL) {
|
|
pTAS->iPOL++;
|
|
self->WriteScanPoints(self, iPoint);
|
|
}
|
|
/*
|
|
but allow for interrupts
|
|
*/
|
|
if (SCGetInterrupt(self->pCon) != eContinue) {
|
|
break;
|
|
}
|
|
}
|
|
pTAS->iIgnore = 1;
|
|
fclose(fd);
|
|
pTAS->iPOL = 1;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
TASScanCount starts the counter for a TAS scan or runs the polarization
|
|
analysis.
|
|
---------------------------------------------------------------------------*/
|
|
static int TASUBScanCount(pScanData self, int iPoint)
|
|
{
|
|
pTASdata pTAS = (pTASdata) self->pSpecial;
|
|
float fVal;
|
|
int status, iRet;
|
|
Status eOld;
|
|
|
|
pTAS->iIgnore = 0;
|
|
/*
|
|
call the polarisation scan function if necessary
|
|
*/
|
|
if (pTAS->iPOL >= 0) {
|
|
return RunPolScan(self, iPoint);
|
|
}
|
|
|
|
/*
|
|
this is easy, just an ordinary scan, start a counter
|
|
*/
|
|
fVal = GetCounterPreset(self->pCounterData);
|
|
eOld = GetStatus();
|
|
status = DoCount(self->pCounterData, fVal, self->pCon, 1);
|
|
iRet = Wait4Success(GetExecutor());
|
|
if (iRet == DEVINT) {
|
|
SCWrite(self->pCon, "Counting aborted due to Interrupt", eLog);
|
|
status = 0;
|
|
} else if (iRet == DEVERROR) {
|
|
SCWrite(self->pCon, "Counting finished with Problems", eLog);
|
|
status = 0;
|
|
} else {
|
|
status = 1;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------
|
|
TAS stores the scan data. This is necessary in order to support things
|
|
like peak or center which require the scan data for operation
|
|
--------------------------------------------------------------------------*/
|
|
static int TASUBCollect(pScanData self, int iPoint)
|
|
{
|
|
pVarEntry pVar = NULL;
|
|
void *pDings;
|
|
int i, iRet, status, iPtr;
|
|
float fVal;
|
|
CountEntry sCount;
|
|
char *pAns = NULL, *pPtr = NULL;
|
|
pTASdata pTAS = (pTASdata) self->pSpecial;
|
|
pMotor pMot;
|
|
char pError[132];
|
|
|
|
assert(self);
|
|
assert(self->pCon);
|
|
|
|
/* loop over all scan variables */
|
|
status = 1;
|
|
memset(&sCount,0,sizeof(CountEntry));
|
|
|
|
pTAS->ub->silent = 0;
|
|
for (i = 0; i < self->iScanVar; i++) {
|
|
DynarGet(self->pScanVar, i, &pDings);
|
|
pVar = (pVarEntry) pDings;
|
|
fVal = readDrivable(ScanVarName(pVar), self->pCon);
|
|
if (fVal < -990) {
|
|
snprintf(pError, 131, "WARNING: failed to read %s",
|
|
ScanVarName(pVar));
|
|
SCWrite(self->pCon, pError, eLog);
|
|
}
|
|
AppendScanVar(pVar, fVal);
|
|
}
|
|
|
|
/* store counter data */
|
|
/* monitors */
|
|
for (i = 1; i < 10; i++) {
|
|
sCount.Monitors[i - 1] = GetMonitor((pCounter) self->pCounterData, i,
|
|
self->pCon);
|
|
}
|
|
if (self->iChannel != 0 && self->iChannel != -10) {
|
|
sCount.Monitors[self->iChannel - 1] =
|
|
GetCounts((pCounter) self->pCounterData, self->pCon);
|
|
}
|
|
|
|
/* counts, depending on iChannel */
|
|
if (self->iChannel == 0) {
|
|
sCount.lCount = GetCounts((pCounter) self->pCounterData, self->pCon);
|
|
} else {
|
|
sCount.lCount = GetMonitor((pCounter) self->pCounterData,
|
|
self->iChannel, self->pCon);
|
|
}
|
|
|
|
/* get time */
|
|
sCount.fTime = GetCountTime((pCounter) self->pCounterData, self->pCon);
|
|
/* stow away */
|
|
DynarReplace(self->pCounts, self->iCounts, &sCount, sizeof(CountEntry));
|
|
self->iCounts++;
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------
|
|
prepare2Parse removes all unnecessary delimiters from the parse string.
|
|
These are: ' =
|
|
----------------------------------------------------------------------*/
|
|
static void prepare2Parse(char *line)
|
|
{
|
|
int i, iLang;
|
|
|
|
iLang = strlen(line);
|
|
for (i = 0; i < iLang; i++) {
|
|
if (line[i] == ',' || line[i] == '=') {
|
|
line[i] = ' ';
|
|
}
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------*/
|
|
extern char *stptok(const char *s, char *t, int len, char *brk);
|
|
extern char *trim(char *txt);
|
|
/*-----------------------------------------------------------------------
|
|
During a TAS scan additional output variables can be printed. These are
|
|
defined in a text variable called ouput. ParseOutput now parses this
|
|
variable and enters the variables found in there into the TAS data
|
|
structure so that they can be printed during the scan.
|
|
------------------------------------------------------------------------*/
|
|
static void ParseOutput(pTASdata pTAS, SConnection * pCon)
|
|
{
|
|
char *pText = NULL, *pPtr, pToken[20], pWarn[256];
|
|
int iPtr;
|
|
|
|
/*
|
|
get a copy of output
|
|
*/
|
|
pText =
|
|
(char *) malloc((strlen(GetVarText("output")) + 1) * sizeof(char));
|
|
if (!pText) {
|
|
SCWrite(pCon, "WARNING: out of memory while parsing output variable",
|
|
eWarning);
|
|
return;
|
|
}
|
|
strcpy(pText, GetVarText("output"));
|
|
|
|
/*
|
|
wash it
|
|
*/
|
|
prepare2Parse(pText);
|
|
|
|
/*
|
|
parse
|
|
*/
|
|
pTAS->addCount = 0;
|
|
pPtr = pText;
|
|
while (pPtr != NULL) {
|
|
pPtr = stptok(pPtr, pToken, 20, " ,=");
|
|
if (strlen(pToken) < 1 || pPtr == NULL)
|
|
continue;
|
|
|
|
if (FindCommand(pServ->pSics, trim(pToken))) {
|
|
strlcpy(pTAS->out[pTAS->addCount], trim(pToken), 10);
|
|
pTAS->addCount++;
|
|
} else {
|
|
strtolower(pToken);
|
|
if (strcmp(pToken, "unknown") != 0) {
|
|
snprintf(pWarn,sizeof(pWarn)-1, "WARNING: ignored invalid token > %s < in output",
|
|
pToken);
|
|
SCWrite(pCon, pWarn, eWarning);
|
|
}
|
|
}
|
|
}
|
|
free(pText);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
int TASUBPrepare(pScanData self)
|
|
{
|
|
int status;
|
|
pTASdata pTAS = (pTASdata) self->pSpecial;
|
|
time_t iDate;
|
|
struct tm *psTime;
|
|
char pWork[70];
|
|
char pLine[1024];
|
|
|
|
status = NonCheckPrepare(self);
|
|
|
|
ParseOutput(pTAS, self->pCon);
|
|
|
|
/*
|
|
print some status information for the looser
|
|
*/
|
|
iDate = time(NULL);
|
|
psTime = localtime(&iDate);
|
|
memset(pWork, 0, 69);
|
|
strftime(pWork, 69, "%d-%b-%Y %H:%M:%S", psTime);
|
|
snprintf(pLine, 1023, "%8s %3d Points Scan %3d Scanned Variable(s) %s",
|
|
GetVarText("instrument"),
|
|
pTAS->pScan->iNP, pTAS->pScan->iScanVar, pWork);
|
|
SCWrite(self->pCon, pLine, eLog);
|
|
|
|
if (GetCounterMode(pTAS->pScan->pCounterData) == eTimer) {
|
|
snprintf(pLine,sizeof(pLine)-1, " %8f Seconds per point",
|
|
GetCounterPreset(pTAS->pScan->pCounterData));
|
|
} else {
|
|
snprintf(pLine,sizeof(pLine)-1, " %8f Monitor Counts per point",
|
|
GetCounterPreset(pTAS->pScan->pCounterData));
|
|
|
|
}
|
|
SCWrite(self->pCon, pLine, eLog);
|
|
SCWrite(self->pCon, " ", eLog);
|
|
SCWrite(self->pCon, " ", eLog);
|
|
|
|
/*
|
|
snprintf(pLine,1023,
|
|
" %12s %6s HKLE: %5.2f %5.2f %5.2f %8.4f %6.3f %6.3f %6.3f %6.3f",
|
|
GetVarText("title"),
|
|
GetVarText("user"),
|
|
pTAS->tasPar[QH]->fVal - (pTAS->pScan->iNP/2)*pTAS->tasPar[DQH]->fVal,
|
|
pTAS->tasPar[QK]->fVal - (pTAS->pScan->iNP/2)*pTAS->tasPar[DQL]->fVal,
|
|
pTAS->tasPar[QL]->fVal - (pTAS->pScan->iNP/2)*pTAS->tasPar[DQK]->fVal,
|
|
pTAS->tasPar[EN]->fVal - (pTAS->pScan->iNP/2)*pTAS->tasPar[DEN]->fVal,
|
|
pTAS->tasPar[DQH]->fVal,
|
|
pTAS->tasPar[DQK]->fVal,
|
|
pTAS->tasPar[DQL]->fVal,
|
|
pTAS->tasPar[DEN]->fVal);
|
|
SCWrite(pCon,pLine,eWarning);
|
|
*/
|
|
if (pTAS->ub->tasMode == KICONST) {
|
|
snprintf(pLine, 1023,
|
|
" Constant KI Scan: KI= %7.4f Angs-1; EI= %9.4f",
|
|
getTasPar(pTAS->ub->current, KI), getTasPar(pTAS->ub->current,
|
|
EI));
|
|
} else {
|
|
snprintf(pLine, 1023,
|
|
" Constant KF Scan: KF= %7.4f Angs-1; EF= %9.4f",
|
|
getTasPar(pTAS->ub->current, KF), getTasPar(pTAS->ub->current,
|
|
EF));
|
|
}
|
|
SCWrite(self->pCon, pLine, eLog);
|
|
|
|
return status;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------*/
|
|
static void TASUBDump(pTASdata self, SicsInterp * pSics,
|
|
SConnection * pCon, int argc, char *argv[])
|
|
{
|
|
float v[9], ub[3][3], cell[6];
|
|
int status, i, j;
|
|
pNXScript nxscript = NULL;
|
|
char pBueffel[256];
|
|
tasReflection r;
|
|
|
|
if (argc < 4) {
|
|
SCWrite(pCon, "ERROR: not enough argument to dump tasub", eError);
|
|
return;
|
|
}
|
|
|
|
nxscript = (pNXScript) FindCommandData(pSics, argv[2], "NXScript");
|
|
if (nxscript == NULL) {
|
|
snprintf(pBueffel, 255, "ERROR: %s is no NXScript object", argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return;
|
|
}
|
|
if (nxscript->fileHandle == NULL) {
|
|
SCWrite(pCon, "ERROR: files is closed, cannot write", eError);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
write cell
|
|
*/
|
|
snprintf(pBueffel, 255, "%s_cell", argv[3]);
|
|
cell[0] = self->ub->cell.a;
|
|
cell[1] = self->ub->cell.b;
|
|
cell[2] = self->ub->cell.c;
|
|
cell[3] = self->ub->cell.alpha;
|
|
cell[4] = self->ub->cell.beta;
|
|
cell[5] = self->ub->cell.gamma;
|
|
status =
|
|
NXDputalias(nxscript->fileHandle, nxscript->dictHandle, pBueffel,
|
|
cell);
|
|
if (status != NX_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to write cell to %s_cell",
|
|
argv[3]);
|
|
SCWrite(pCon, pBueffel, eWarning);
|
|
}
|
|
|
|
/*
|
|
write planenormal
|
|
*/
|
|
for (i = 0; i < 3; i++) {
|
|
v[i] = self->ub->machine.planeNormal[i][0];
|
|
}
|
|
snprintf(pBueffel, 255, "%s_norm", argv[3]);
|
|
status =
|
|
NXDputalias(nxscript->fileHandle, nxscript->dictHandle, pBueffel, v);
|
|
if (status != NX_OK) {
|
|
snprintf(pBueffel, 255,
|
|
"ERROR: failed to write plane_normal to %s_norm", argv[3]);
|
|
SCWrite(pCon, pBueffel, eWarning);
|
|
}
|
|
|
|
/*
|
|
write orienting reflections
|
|
*/
|
|
snprintf(pBueffel, 255, "%s_vec1", argv[3]);
|
|
r = self->ub->r1;
|
|
v[0] = r.qe.qh;
|
|
v[1] = r.qe.qk;
|
|
v[2] = r.qe.ql;
|
|
v[3] = r.angles.a3;
|
|
v[4] = r.angles.sample_two_theta;
|
|
v[5] = r.angles.sgl;
|
|
v[6] = r.angles.sgu;
|
|
v[7] = KtoEnergy(r.qe.ki);
|
|
v[8] = KtoEnergy(r.qe.kf);
|
|
status =
|
|
NXDputalias(nxscript->fileHandle, nxscript->dictHandle, pBueffel, v);
|
|
if (status != NX_OK) {
|
|
snprintf(pBueffel, 255,
|
|
"ERROR: failed to write plane vector 1 to %s_vec1", argv[3]);
|
|
SCWrite(pCon, pBueffel, eWarning);
|
|
}
|
|
snprintf(pBueffel, 255, "%s_vec2", argv[3]);
|
|
r = self->ub->r2;
|
|
v[0] = r.qe.qh;
|
|
v[1] = r.qe.qk;
|
|
v[2] = r.qe.ql;
|
|
v[3] = r.angles.a3;
|
|
v[4] = r.angles.sample_two_theta;
|
|
v[5] = r.angles.sgl;
|
|
v[6] = r.angles.sgu;
|
|
v[7] = KtoEnergy(r.qe.ki);
|
|
v[8] = KtoEnergy(r.qe.kf);
|
|
status =
|
|
NXDputalias(nxscript->fileHandle, nxscript->dictHandle, pBueffel, v);
|
|
if (status != NX_OK) {
|
|
snprintf(pBueffel, 255,
|
|
"ERROR: failed to write plane vector 2 to %s_vec2", argv[3]);
|
|
SCWrite(pCon, pBueffel, eWarning);
|
|
}
|
|
|
|
/*
|
|
write UB
|
|
*/
|
|
for (i = 0; i < 3; i++) {
|
|
for (j = 0; j < 3; j++) {
|
|
ub[i][j] = self->ub->machine.UB[i][j];
|
|
}
|
|
}
|
|
snprintf(pBueffel, 255, "%s_ub", argv[3]);
|
|
status =
|
|
NXDputalias(nxscript->fileHandle, nxscript->dictHandle, pBueffel,
|
|
ub);
|
|
if (status != NX_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to write UB to %s_ub", argv[3]);
|
|
SCWrite(pCon, pBueffel, eWarning);
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
int TASUBScan(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pTASdata self = NULL;
|
|
char pBueffel[256];
|
|
int np;
|
|
|
|
self = (pTASdata) pData;
|
|
assert(self);
|
|
|
|
self->pScan->pSpecial = self;
|
|
|
|
if (argc < 2) {
|
|
SCWrite(pCon, "ERROR: not enough arguments to tasscan", eError);
|
|
return 0;
|
|
}
|
|
strtolower(argv[1]);
|
|
|
|
if (strcmp(argv[1], "pol") == 0) {
|
|
if (argc > 2) {
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
self->iPOL = atoi(argv[2]);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
snprintf(pBueffel, 255, "%s.pol = %d", argv[0], self->iPOL);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "fast") == 0) {
|
|
if (argc > 2) {
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
self->iFast = atoi(argv[2]);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
snprintf(pBueffel, 255, "%s.fast = %d", argv[0], self->iFast);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "prepare") == 0) {
|
|
return TASUBPrepare(self->pScan);
|
|
} else if (strcmp(argv[1], "nxdump") == 0) {
|
|
TASUBDump(self, pSics, pCon, argc, argv);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "drive") == 0) {
|
|
if (argc < 5) {
|
|
SCWrite(pCon,
|
|
"ERROR: insufficient number of arguments to tasscan drive",
|
|
eError);
|
|
return 0;
|
|
}
|
|
np = atoi(argv[4]);
|
|
return TASUBScanDrive(self->pScan, np);
|
|
} else if (strcmp(argv[1], "header") == 0) {
|
|
return TASUBHeader(self->pScan);
|
|
} else if (strcmp(argv[1], "count") == 0) {
|
|
if (argc < 7) {
|
|
SCWrite(pCon,
|
|
"ERROR: insufficient number of arguments to tasscan count",
|
|
eError);
|
|
return 0;
|
|
}
|
|
np = atoi(argv[4]);
|
|
return TASUBScanCount(self->pScan, np);
|
|
} else if (strcmp(argv[1], "collect") == 0) {
|
|
if (argc < 5) {
|
|
SCWrite(pCon,
|
|
"ERROR: insufficient number of arguments to tasscan collect",
|
|
eError);
|
|
return 0;
|
|
}
|
|
np = atoi(argv[4]);
|
|
return TASUBCollect(self->pScan, np);
|
|
} else if (strcmp(argv[1], "writepoint") == 0) {
|
|
if (argc < 5) {
|
|
SCWrite(pCon,
|
|
"ERROR: insufficient number of arguments to tasscan writepoint",
|
|
eError);
|
|
return 0;
|
|
}
|
|
np = atoi(argv[4]);
|
|
return TASUBScanPoint(self->pScan, np);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: subcommand to tasscan not understood", eError);
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------*/
|
|
static void KillTAS(void *pData)
|
|
{
|
|
pTASdata self = (pTASdata) pData;
|
|
if (self == NULL) {
|
|
return;
|
|
}
|
|
if (self->pDes != NULL) {
|
|
DeleteDescriptor(self->pDes);
|
|
}
|
|
free(self);
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
int TASUBScanFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pTASdata pNew = NULL;
|
|
char pBueffel[512];
|
|
int i;
|
|
char *pVar[] = {
|
|
"polfile",
|
|
"instrument",
|
|
"user",
|
|
"local",
|
|
"title",
|
|
"lastscancommand",
|
|
"output",
|
|
NULL
|
|
};
|
|
|
|
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: not enough arguments to TASUBScanFactory",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
pNew = (pTASdata) malloc(sizeof(TASdata));
|
|
if (!pNew) {
|
|
SCWrite(pCon, "ERROR: out of memory creating tasscan object", eError);
|
|
return 0;
|
|
}
|
|
memset(pNew, 0, sizeof(TASdata));
|
|
pNew->pDes = CreateDescriptor("TAS Scan Stuff");
|
|
if (!pNew->pDes) {
|
|
SCWrite(pCon, "ERROR: out of memory creating tasscan object", eError);
|
|
free(pNew);
|
|
return 0;
|
|
}
|
|
|
|
pNew->pScan = (pScanData) FindCommandData(pSics, argv[1], "ScanObject");
|
|
if (!pNew->pScan) {
|
|
snprintf(pBueffel, 511, "ERROR: cannot locate scan object %s",
|
|
argv[1]);
|
|
free(pNew);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
pNew->counter = (pCounter) pNew->pScan->pCounterData;
|
|
|
|
pNew->ub = (ptasUB) FindCommandData(pSics, argv[2], "TAS-UB");
|
|
if (!pNew->ub) {
|
|
snprintf(pBueffel, 511, "ERROR: cannot locate TAS-UB object %s",
|
|
argv[2]);
|
|
free(pNew);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
i = 0;
|
|
while (pVar[i] != NULL) {
|
|
if (FindCommandData(pSics, pVar[i], "SicsVariable") == NULL) {
|
|
snprintf(pBueffel, 511, "ERROR: variable %s missing", pVar[i]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
free(pNew);
|
|
return 0;
|
|
}
|
|
i++;
|
|
}
|
|
return AddCommand(pSics, "tasscan", TASUBScan, KillTAS, pNew);
|
|
}
|