Files
sics/tasscanub.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);
}