Files
sics/mesure.c

1617 lines
43 KiB
C

/*-------------------------------------------------------------------------
M E S U R E
An object for doing four circle diffractometer measurements with
a single counter.
copyright: see copyright.h
Mark Koennecke, April 1998
heavily reworked: Mark Koennecke, February-March 2005
---------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <tcl.h>
#include <math.h>
#include <assert.h>
#include "fortify.h"
#include "sics.h"
#include "motor.h"
#include "o2t.h"
#include "scan.h"
#include "scan.i"
#include "stdscan.h"
#include "danu.h"
#include "integrate.h"
#include "hkl.h"
#include "sicsvar.h"
#include "evcontroller.h"
#include "mesure.h"
#include "nxscript.h"
#include "fourtable.h"
#include "lld.h"
extern void SNXFormatTime(char *pBueffel, int iLen);
extern float nintf(float f);
#define ANGERR 0.2
/*
#define MESSDEBUG 1
define MESSDEBUG for simulated peaks. This helps in debugging
this code and the initial data correction code
*/
extern void SNXFormatTime(char *pBueffel, int iLen); /* nxutil.c */
/*------------------- the data structure -----------------------------------*/
typedef struct __Mesure
{
pObjectDescriptor pDes; /* standard object descriptor */
pICallBack pCall; /* callback interface for automatic notification */
pScanData pScanner; /* scan object to use for scans */
pHKL pCryst; /* hkl object for crystallographic calc
and reflection driving */
pMotor pOmega; /* motor for omega scans */
char *pCOmega; /* name of omega motor */
char *pFileRoot; /* where to write files */
pDataNumber pDanu; /* where to get data file number */
FILE *fRefl; /* reflection profile file */
FILE *fHKL; /* integrated intensity file */
int iLogFile; /* log file num at connection */
SConnection *pCon; /* log file owning connection */
char *pCurrentFile; /* current file root */
int iCount; /* count of reflection */
int CountMode; /* timer or preset */
int np; /* number of scan points */
float fPreset; /* counting preset */
float fStep; /* omega step widths */
long *lCounts; /* array to store counting values */
float fPosition[4]; /* the real positions after driving */
int iCompact; /* true if compact scan ouput. */
int weak; /* weak flag: remeasure weak reflections */
long weakThreshold; /* threshold when a peak is so weak that is has to
remeasured */
int fastScan; /* flag for using fastscans for scanning reflections */
int psiMode; /* 1 for psi scan mode, 0 else */
int stepTable; /* mapping of two theta ranges to step width and
variable to scan */
} Mesure;
/*-------------------------------------------------------------------------*/
static int SaveMesure(void *pData, char *name, FILE *fd)
{
pMesure self = (pMesure)pData;
fprintf(fd,"#Four Circle Dataset Module %s\n",name);
if(self->CountMode == eTimer)
{
fprintf(fd,"%s countmode timer\n",name);
}
else
{
fprintf(fd,"%s countmode monitor\n",name);
}
fprintf(fd,"%s np %d\n", name, self->np);
fprintf(fd,"%s preset %f\n", name, self->fPreset);
fprintf(fd,"%s step %f\n", name, self->fStep);
fprintf(fd,"%s weakthreshold %ld\n", name, self->weakThreshold);
fprintf(fd,"%s compact %d\n", name, self->iCompact);
fprintf(fd,"%s weak %d\n", name, self->weak);
fprintf(fd,"%s fastscan %d\n", name, self->fastScan);
SaveFourCircleTable(self->stepTable,name,fd);
return 1;
}
/*-------------------------------------------------------------------------*/
static void ListMesure(pMesure self, char *name, SConnection *pCon)
{
Tcl_DString list;
char pBuffer[132];
Tcl_DStringInit(&list);
if(self->CountMode == eTimer)
{
snprintf(pBuffer,131,"%s.countmode timer\n",name);
}
else
{
snprintf(pBuffer,131,"%s.countmode monitor\n",name);
}
Tcl_DStringAppend(&list,pBuffer,-1);
snprintf(pBuffer,131,"%s.np %d\n", name, self->np);
Tcl_DStringAppend(&list,pBuffer,-1);
snprintf(pBuffer,131,"%s.preset %f\n", name, self->fPreset);
Tcl_DStringAppend(&list,pBuffer,-1);
snprintf(pBuffer,131,"%s.step %f\n", name, self->fStep);
Tcl_DStringAppend(&list,pBuffer,-1);
snprintf(pBuffer,131,"%s.weakthreshold %ld\n", name, self->weakThreshold);
Tcl_DStringAppend(&list,pBuffer,-1);
snprintf(pBuffer,131,"%s.compact %d\n", name, self->iCompact);
Tcl_DStringAppend(&list,pBuffer,-1);
snprintf(pBuffer,131,"%s.weak %d\n", name, self->weak);
Tcl_DStringAppend(&list,pBuffer,-1);
snprintf(pBuffer,131,"%s.fastscan %d\n", name, self->fastScan);
Tcl_DStringAppend(&list,pBuffer,-1);
SCWrite(pCon,Tcl_DStringValue(&list),eValue);
Tcl_DStringFree(&list);
}
/*--------------------------------------------------------------------------*/
pMesure CreateMesure(pHKL pCryst, pScanData pScanner, pMotor pOmega,
char *pOm, char *pFileRoot,
pDataNumber pDanu)
{
pMesure pNew = NULL;
assert(pCryst);
assert(pScanner);
assert(pOmega);
assert(pFileRoot);
assert(pDanu);
/* allocate space............. */
pNew = (pMesure)malloc(sizeof(Mesure));
if(!pNew)
{
return NULL;
}
memset(pNew,0,sizeof(Mesure));
pNew->pDes = CreateDescriptor("Mesure");
pNew->pDes->SaveStatus = SaveMesure;
pNew->pCall = CreateCallBackInterface();
if( !pNew->pDes || !pNew->pCall)
{
free(pNew);
return NULL;
}
/* asssign defaults */
pNew->pScanner = pScanner;
pNew->pCryst = pCryst;
pNew->pOmega = pOmega;
pNew->pCOmega = strdup(pOm);
pNew->pFileRoot = strdup(pFileRoot);
pNew->pDanu = pDanu;
pNew->iCount = 0;
pNew->CountMode = 0;
pNew->np = 50;
pNew->fStep = 0.05;
pNew->fPreset = 2;
pNew->iCompact = 1;
pNew->weak = 0;
pNew->weakThreshold = 99999;
pNew->fastScan = 0;
pNew->psiMode = 0;
#ifdef MESSDEBUG
pNew->lCounts = (long *)malloc(90*sizeof(long));
#endif
pNew->lCounts = (long *)malloc(50*sizeof(long));
pNew->stepTable = MakeFourCircleTable();
return pNew;
}
/*------------------------------------------------------------------------*/
void DeleteMesure(void *pData)
{
pMesure self = NULL;
self = (pMesure)pData;
if(!pData)
{
return;
}
if(self->pDes)
DeleteDescriptor(self->pDes);
if(self->pCall)
DeleteCallBackInterface(self->pCall);
if(self->pFileRoot)
free(self->pFileRoot);
if(self->pCOmega)
free(self->pCOmega);
if(self->fRefl)
MesureClose(self);
if(self->lCounts)
free(self->lCounts);
DeleteFourCircleTable(self->stepTable);
free(self);
}
/*------------------------------------------------------------------------*/
int MesureFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
pMesure pNew = NULL;
pHKL pCryst = NULL;
pScanData pScan = NULL;
CommandList *pCom = NULL;
pMotor pMot = NULL;
pDataNumber pDanu = NULL;
pSicsO2T pO2T = NULL;
char pBueffel[512];
pDummy pDum = NULL;
int iRet;
assert(pCon);
assert(pSics);
/* check no of parameters
inicom name hkl scan omega root danu
*/
if(argc < 7)
{
SCWrite(pCon,
"ERROR: Insufficient number of parameters to MesureFactory",eError);
return 0;
}
/* work parameters one by one, first hkl */
pCom = FindCommand(pSics,argv[2]);
if(pCom)
{
pDum = (pDummy)pCom->pData;
if(pDum)
{
if(strcmp(pDum->pDescriptor->name,"4-Circle-Calculus") == 0)
{
pCryst = (pHKL)pCom->pData;
}
}
}
if(!pCryst)
{
sprintf(pBueffel,"ERROR: %s is no four circle calculus object",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* scanner */
pCom = FindCommand(pSics,argv[3]);
if(pCom)
{
pDum = (pDummy)pCom->pData;
if(pDum)
{
if(strcmp(pDum->pDescriptor->name,"ScanObject") == 0)
{
pScan = (pScanData)pCom->pData;
}
}
}
if(!pScan)
{
sprintf(pBueffel,"ERROR: %s is no scan object",argv[3]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* omega */
pMot = FindMotor(pSics,argv[4]);
if(!pMot)
{
sprintf(pBueffel,"ERROR: %s is no motor object ",argv[4]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* Data Number */
pCom = FindCommand(pSics,argv[6]);
if(pCom)
{
pDum = (pDummy)pCom->pData;
if(pDum)
{
if(strcmp(pDum->pDescriptor->name,"DataNumber") == 0)
{
pDanu = (pDataNumber)pCom->pData;
}
}
}
if(!pDanu)
{
sprintf(pBueffel,"ERROR: %s is no DataNumber object",argv[6]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* finally create the thing */
pNew = CreateMesure(pCryst,pScan,pMot,argv[4],argv[5],pDanu);
if(!pNew)
{
SCWrite(pCon,"ERROR: no memory in MesureFactory",eError);
return 0;
}
/* add the new command */
iRet = AddCommand(pSics,argv[1],MesureAction,DeleteMesure,pNew);
if(!iRet)
{
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
return 1;
}
/*------------------------------------------------------------------------
This implements the compact scan output for TRICS scans
*/
static int CompactScanData(pScanData self, int iPoint)
{
pVarEntry pVar = NULL;
void *pDings;
int i, iRet, status;
float fVal;
char pStatus[512], pItem[20];
char pHead[512];
CountEntry sCount;
char *pAns = NULL, *pPtr = NULL ;
Tcl_Interp *pTcl;
assert(self);
assert(self->pCon);
/* loop over all scan variables */
status = 1;
for(i = 0; i < self->iScanVar; i++)
{
DynarGet(self->pScanVar,i,&pDings);
pVar = (pVarEntry)pDings;
if(pVar)
{
fVal = pVar->pInter->GetValue(pVar->pObject,self->pCon);
AppendScanVar(pVar,fVal);
sprintf(pItem,"%-10.10s",pVar->Name);
strcat(pHead,pItem);
sprintf(pItem,"%-10.3f",fVal);
strcat(pStatus,pItem);
}
}
/* 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);
}
if(self->iChannel == 0)
{
sCount.lCount = GetCounts((pCounter)self->pCounterData,self->pCon);
}
else
{
sCount.lCount = GetMonitor((pCounter)self->pCounterData,
self->iChannel, self->pCon);
}
/* stow away */
DynarReplace(self->pCounts,self->iCounts,&sCount,sizeof(CountEntry));
self->iCounts++;
return 1;
}
/*-------------------------------------------------------------------------
This is slightly tricky: the crystallography module has a scan tolerance.
This is supposed to be automatically set. In order to do so, I need
the step width which in turn is dependent on two theta. Therefore I calculate
two times: the first time with a scan tolerance of 0 to get two theta, the
second time with teh scan tolerance ste to a decent value to get the
real thing.
---------------------------------------------------------------------------*/
static int MesureCalculateSettings(pMesure self, float fHKL[3], float fSet[4],
float fPsi, SConnection *pCon)
{
int status;
float step, tolerance;
SetHKLScanTolerance(self->pCryst,.0);
status = CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon);
if(!status)
{
return status;
}
step = GetFourCircleStep(self->stepTable, fSet[0]);
if(step < -900.){
step = self->fStep;
}
tolerance = (step * (float)self->np)/2. + .2;
SetHKLScanTolerance(self->pCryst,tolerance);
return CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon);
}
/*--------------------------------------------------------------------------*/
int MesureReflection(pMesure self, float fHKL[3], float fPsi,
SConnection *pCon)
{
int iRet;
float fSet[4];
assert(self);
iRet = MesureCalculateSettings(self,fHKL,fSet,fPsi,pCon);
if(!iRet)
{
return iRet;
}
return MesureGenReflection(self,fHKL,fSet,pCon);
}
/*-----------------------------------------------------------------------*/
static int DriveToReflection(pMesure self, float fSet[4], SConnection *pCon)
{
int iRet, i;
float fDelta;
char pBueffel[132];
iRet = DriveSettings(self->pCryst,fSet,pCon);
if(!iRet)
{
return iRet;
}
/* store achieved position for reporting */
iRet = GetCurrentPosition(self->pCryst,pCon,self->fPosition);
if(iRet != 1)
{
return iRet;
}
/*
check if we are really there.
*/
for(i = 0; i < 4; i++)
{
fDelta = fSet[i] - self->fPosition[i];
if(fDelta < 0.)
fDelta = -fDelta;
if(fDelta > ANGERR)
{
snprintf(pBueffel,131,
"ERROR: angle %d positioned badly, aborting Reflection",
i);
SCWrite(pCon,pBueffel,eError);
return 0;
}
}
return 1;
}
/*-----------------------------------------------------------------------
test if this scan has to be remeasured because it is weak
------------------------------------------------------------------------*/
int weakScan(pMesure self)
{
int i;
long low = 99999, high = -99999;
/*
ths scan is always OK if we do not test for weak conditions
*/
if(self->weak == 0){
return 0;
}
GetScanCounts(self->pScanner,self->lCounts,self->np);
for(i = 0; i < self->np; i++)
{
if(self->lCounts[i] < low)
{
low = self->lCounts[i];
}
if(self->lCounts[i] > high)
{
high = self->lCounts[i];
}
}
/*
I am using the weakest point here as a rough estimate of
the background
*/
if(high - 2 * low > self->weakThreshold)
{
return 0;
}
else
{
return 1;
}
}
/*------------------------------------------------------------------------*/
static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
{
float fStart, stepWidth;
int iRet;
char pBueffel[132];
char *scanVar = NULL;
/* calculate scan start */
iRet = MotorGetSoftPosition(self->pOmega,pCon,&fStart);
if(!iRet)
{
return iRet;
}
scanVar = GetFourCircleScanVar(self->stepTable,(double)twoTheta);
if(strcmp(scanVar,"NOT FOUND") == 0)
{
free(scanVar);
scanVar = strdup(self->pCOmega);
stepWidth = self->fStep;
} else {
stepWidth = GetFourCircleStep(self->stepTable,(double)twoTheta);
}
if(stepWidth != self->fStep)
{
snprintf(pBueffel,130,"Using stepwidth %f",stepWidth);
SCWrite(pCon,pBueffel,eWarning);
}
fStart -= (self->np/2)*stepWidth;
/* set the scan up */
ClearScanVar(self->pScanner);
AddScanVar(self->pScanner, pServ->pSics,pCon,scanVar,
fStart, stepWidth);
free(scanVar);
/* do the scan */
if(self->iCompact)
{
self->pScanner->CollectScanData = CompactScanData;
}
if(self->fastScan >= 1)
{
self->pScanner->ScanDrive = ScanFastDrive;
}
iRet = SilentScan(self->pScanner,self->np,self->CountMode,
self->fPreset,pServ->pSics,pCon);
if(weakScan(self))
{
/*
look for interrupts before restarting scan
*/
if(iRet == 0)
{
if(SCGetInterrupt(pCon) >= eAbortBatch)
{
return 0;
}
else
{
SCSetInterrupt(pCon,eContinue);
}
}
/*
redo scan with preset * 5
*/
SCWrite(pCon,"Remeasuring weak reflection",eWarning);
iRet = SilentScan(self->pScanner,self->np,self->CountMode,
self->fPreset*5.,pServ->pSics,pCon);
}
ResetScanFunctions(self->pScanner);
return iRet;
}
/*------------------------------------------------------------------------*/
int MesureGenReflection(pMesure self, float fHKL[3], float fSet[4],
SConnection *pCon)
{
int iRet, i;
char pBueffel[132];
assert(self);
iRet = DriveToReflection(self,fSet,pCon);
if(!iRet)
{
return iRet;
}
iRet = ScanReflection(self,fSet[0],pCon);
return iRet;
}
/*--------------------------------------------------------------------------*/
int MesureStart(pMesure self, SConnection *pCon)
{
char pFilename[512], pRoot[512];
char pBueffel[1024];
char pBuff[132];
int iYear, iNum, iTaus;
float fVal, fUB[9];
pSicsVariable pVar = NULL;
char *pFile = NULL, *pPtr;
assert(self);
assert(pCon);
/* close open files if so */
if(self->fRefl != NULL)
{
MesureClose(self);
}
/* create filename root */
pFile = makeFilename(pServ->pSics,pCon);
if(!pFile)
{
return 0;
}
pPtr = strrchr(pFile,(int)'.');
pPtr++;
*pPtr = '\0';
self->pCurrentFile = strdup(pFile);
free(pFile);
strncpy(pRoot,self->pCurrentFile,511);
/* do the logfile */
strcpy(pFilename,pRoot);
strcat(pFilename,"log");
self->iLogFile = SCAddLogFile(pCon,pFilename);
self->pCon = pCon;
sprintf(pBueffel,"Writing to %s.log, .ccl, .rfl",pRoot);
SCWrite(pCon,pBueffel,eValue);
/* open the reflection file */
strcpy(pFilename,pRoot);
strcat(pFilename,"ccl");
self->fRefl = fopen(pFilename,"w");
if(!self->fRefl)
{
sprintf(pBueffel,"ERROR: SERIOUS TROUBLE: cannot open %s!",
pFilename);
SCWrite(pCon,pBueffel,eError);
SCSetInterrupt(pCon,eAbortBatch);
return 0;
}
/* put filename
fputs(pFilename,self->fRefl);
fputs("\n",self->fRefl);
*/
/* open hkl-data file */
strcpy(pFilename,pRoot);
strcat(pFilename,"rfl");
self->fHKL = fopen(pFilename,"w");
if(!self->fHKL)
{
sprintf(pBueffel,"ERROR: SERIOUS TROUBLE: cannot open %s!",
pFilename);
SCWrite(pCon,pBueffel,eError);
SCSetInterrupt(pCon,eAbortBatch);
return 0;
}
fputs(pFilename,self->fHKL);
fputs("\n",self->fHKL);
/* write some header data */
SNXFormatTime(pBueffel,1024);
/* fprintf(self->fRefl,"filetime = %s\n",pBueffel); */
fprintf(self->fHKL,"filetime = %s\n",pBueffel);
GetLambda(self->pCryst,&fVal);
/* fprintf(self->fRefl,"lambda = %f Angstroem\n",fVal); */
fprintf(self->fHKL,"lambda = %f Angstroem\n",fVal);
GetUB(self->pCryst,fUB);
/* fprintf(self->fRefl,
"UB = %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f\n",
fUB[0], fUB[1],fUB[2],fUB[3],fUB[4],fUB[5],fUB[6],fUB[7],fUB[8]); */
fprintf(self->fHKL,
"UB = %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f\n",
fUB[0], fUB[1],fUB[2],fUB[3],fUB[4],fUB[5],fUB[6],fUB[7],fUB[8]);
/* write sample & user info */
strcpy(pBueffel,"CCL, Instr=TRICS, ");
pVar = FindVariable(pServ->pSics,"sample");
if(pVar)
{
fprintf(self->fHKL,"sample = %s\n",pVar->text);
sprintf(pBuff,"sample = %s, ",pVar->text);
strcat(pBueffel,pBuff);
}
pVar = FindVariable(pServ->pSics,"user");
if(pVar)
{
fprintf(self->fHKL,"user = %s \n",pVar->text);
sprintf(pBuff,"user = %s",pVar->text);
strcat(pBueffel,pBuff);
}
fprintf(self->fRefl,"%s\n",pBueffel);
return 1;
}
/*---------------------------------------------------------------------------*/
int MesureReopen(pMesure self, char *fileroot, SConnection *pCon)
{
char pBueffel[1024];
char pFile[512];
assert(self);
assert(fileroot);
assert(pCon);
/* close pending files */
if(self->fRefl != NULL)
{
MesureClose(self);
}
/* check if this is possible */
strcpy(pFile,self->pFileRoot);
strcat(pFile,"/");
strcat(pFile,fileroot);
strcat(pFile,".col");
self->fRefl = fopen(pFile,"r");
if(!self->fRefl)
{
fclose(self->fRefl);
sprintf(pBueffel,"ERROR: there is no such measurement at %s",fileroot);
SCWrite(pCon,pBueffel,eError);
return 0;
}
fclose(self->fRefl);
/* well seems to exist, open for append */
self->fRefl = fopen(pFile,"a");
/* rfl file */
strcpy(pFile,self->pFileRoot);
strcat(pFile,"/");
strcat(pFile,fileroot);
self->pCurrentFile = strdup(pFile);
strcat(pFile,".rfl");
self->fHKL = fopen(pFile,"a");
/* log file */
strcpy(pFile,self->pFileRoot);
strcat(pFile,"/");
strcat(pFile,fileroot);
strcat(pFile,".log");
self->iLogFile = SCAddLogFile(pCon,pFile);
self->pCon = pCon;
return 1;
}
/*------------------------------------------------------------------------*/
int MesureClose(pMesure self)
{
assert(self);
if(self->fRefl)
{
fclose(self->fRefl);
self->fRefl = NULL;
}
if(self->fHKL)
{
fclose(self->fHKL);
self->fHKL = NULL;
}
SCDelLogFile(self->pCon,self->iLogFile);
self->pCon = NULL;
self->iLogFile = -1;
if(self->pCurrentFile)
free(self->pCurrentFile);
return 1;
}
/*---------------------------------------------------------------------------*/
static int WriteReflection(pMesure self, float fHKL[3],SConnection *pCon)
{
float fSum, fSigma, fSet[4], fTemp, fPreset, fStep;
static float fMax = 10.;
int iRet, i,ii, iLF, iNP;
char pBueffel[512], pNum[10], pTime[132];
pEVControl pEva = NULL;
assert(self);
assert(pCon);
#ifdef MESSDEBUG
self->np = 90;
fMax += 10;
SimScan(self->pScanner,14.,0.5,fMax);
if(fMax > 1000)
{
fMax = 10.;
}
#endif
/* get necessary data */
fSum = 0.;
fSigma = 0.;
iRet = ScanIntegrate(self->pScanner,&fSum, &fSigma);
if(iRet != 1)
{
switch(iRet)
{
case INTEGLEFT:
sprintf(pBueffel,
"WARNING: integration failed --> no left side to: %f %f %f",
fHKL[0], fHKL[1],fHKL[2]);
break;
case INTEGRIGHT:
sprintf(pBueffel,
"WARNING: integration failed -->no right side to: %f %f %f",
fHKL[0], fHKL[1],fHKL[2]);
break;
case INTEGNOPEAK:
sprintf(pBueffel,
"WARNING: integration failed -->no peak found: %f %f %f",
fHKL[0], fHKL[1],fHKL[2]);
break;
case INTEGFUNNYBACK:
sprintf(pBueffel,
"WARNING: integration problem, asymmetric background: %f %f %f",
fHKL[0], fHKL[1],fHKL[2]);
break;
}
SCWrite(pCon,pBueffel,eWarning);
}
GetScanCounts(self->pScanner,self->lCounts,self->np);
/* write it */
if(self->fRefl)
{
fprintf(self->fRefl,"%4d %7.3f %7.3f %7.3f %7.2f %7.2f %7.2f %7.2f %7.0f %7.2f\n",
self->iCount, fHKL[0],fHKL[1],fHKL[2],
self->fPosition[0], self->fPosition[1],
self->fPosition[2],self->fPosition[3],
fSum,fSigma);
}
if(self->fHKL)
{
fprintf(self->fHKL,"%5d %6.2f %6.2f %6.2f %7.2f %7.2f %7.2f %7.2f %7.0f %7.2f\n",
self->iCount, fHKL[0],fHKL[1],fHKL[2],
self->fPosition[0], self->fPosition[1],
self->fPosition[2],self->fPosition[3],
fSum,fSigma);
}
sprintf(pBueffel,"%5d %6.2f %6.2f %6.2f %7.2f %7.2f %7.2f %7.2f %7.0f %7.2f\n",
self->iCount, fHKL[0],fHKL[1],fHKL[2],
self->fPosition[0], self->fPosition[1],
self->fPosition[2],self->fPosition[3],
fSum,fSigma);
SCWrite(pCon,pBueffel,eStatus);
/* get temperature */
fTemp = -777.77;
pEva = (pEVControl)FindCommandData(pServ->pSics,"temperature",
"Environment Controller");
if(pEva)
{
iRet = EVCGetPos(pEva, pCon,&fTemp);
}
/* write profile */
if(self->fRefl)
{
/* collect data */
SNXFormatTime(pBueffel,512);
GetScanVarStep(self->pScanner,0,&fStep);
iNP = GetScanNP(self->pScanner);
fPreset = GetScanPreset(self->pScanner);
fprintf(self->fRefl,"%3d %7.3f %9.0f %7.3f %s\n",iNP,fStep,
fPreset,fTemp,pBueffel);
for(i = 0; i < iNP; i++)
{
for(ii = 0; ii < 10 && i < iNP; ii++)
{
fprintf(self->fRefl," %7ld",self->lCounts[i]);
iLF = 1;
i++;
}
fprintf(self->fRefl,"\n");
i--;
iLF = 0;
}
if(iLF)
{
fprintf(self->fRefl,"\n");
}
fflush(self->fRefl);
}
/* write data if compact output */
if(self->iCompact == 1)
{
strcpy(pTime,pBueffel);
sprintf(pBueffel,"%3d%8.3f%10.0f%8.3f %s\n",iNP,fStep,
fPreset,fTemp,pTime);
SCWrite(pCon,pBueffel,eValue);
pBueffel[0] = '\0';
for(i = 0; i < iNP; i++)
{
for(ii = 0; ii < 10 && i < iNP; ii++)
{
sprintf(pNum," %6ld",self->lCounts[i]);
strcat(pBueffel,pNum);
iLF = 1;
i++;
}
SCWrite(pCon,pBueffel,eValue);
pBueffel[0] = '\0';
i--;
iLF = 0;
}
if(iLF)
{
SCWrite(pCon,pBueffel,eValue);
}
}
return 1;
}
/*------------------------------------------------------------------------*/
int MesureFile(pMesure self, char *pFile, int iSkip, SConnection *pCon)
{
FILE *fd = NULL;
char pBueffel[512], pTime[132], pError[256];
int i, iRet;
float fHKL[3], fPsi = .0;
assert(self);
assert(pCon);
/* well before doing a thing, open the list file */
fd = fopen(pFile,"r");
if(!fd)
{
sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* check that files are open, if not open */
if(self->fRefl == NULL)
{
MesureStart(self,pCon);
}
/* make a mark */
SNXFormatTime(pTime,131);
sprintf(pBueffel,"Starting at list %s at %s",pFile,pTime);
SCWrite(pCon,pBueffel,eStatus);
/* skippy! */
for(i = 0; i < iSkip; i++)
{
fgets(pBueffel,510,fd);
}
self->iCount = iSkip;
if(self->psiMode > 0){
SCWrite(pCon,"WARNING: measuring in psi mode",eWarning);
}
/* loop through space and measure! */
while(fgets(pBueffel,510,fd) != NULL)
{
for(i = 0; i < 3;i++)
fHKL[i] = 0.;
if(self->psiMode > 0){
iRet = sscanf(pBueffel,"%f%f%f%f",
&fHKL[0],&fHKL[1],&fHKL[2],&fPsi);
if(iRet != 4){
snprintf(pError,255,"WARNING: skipping bad line %s",pBueffel);
SCWrite(pCon,pError,eWarning);
continue;
}
} else {
iRet = sscanf(pBueffel,"%f%f%f",&fHKL[0],&fHKL[1],&fHKL[2]);
if(iRet != 3){
snprintf(pError,255,"WARNING: skipping bad line %s",pBueffel);
SCWrite(pCon,pError,eWarning);
continue;
}
}
self->iCount++;
iRet = MesureReflection(self,fHKL,fPsi,pCon);
if(iRet == 0)
{
if(SCGetInterrupt(pCon) >= eAbortBatch)
{
return 0;
}
else
{
SCSetInterrupt(pCon,eContinue);
continue;
}
}
WriteReflection(self,fHKL,pCon);
}
/* we are done */
SNXFormatTime(pTime,131);
sprintf(pBueffel,"Finishing list %s at %s",pFile,pTime);
SCWrite(pCon,pBueffel,eStatus);
fclose(fd);
return 1;
}
/*------------------------------------------------------------------------*/
int TestFile(pMesure self, char *pFile, SConnection *pCon)
{
FILE *fd = NULL;
char pBueffel[512], pError[256];
int i, iRet;
float fHKL[3], fSet[4], fPsi = .0;
int count = 0, good = 0;
assert(self);
assert(pCon);
/* well before doing a thing, open the list file */
fd = fopen(pFile,"r");
if(!fd)
{
sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);
SCWrite(pCon,pBueffel,eError);
return 0;
}
if(self->psiMode > 0){
SCWrite(pCon,"WARNING: measuring in psi mode",eWarning);
}
/* loop through space and test! */
while(fgets(pBueffel,510,fd) != NULL)
{
for(i = 0; i < 3;i++)
fHKL[i] = 0.;
if(self->psiMode > 0){
iRet = sscanf(pBueffel,"%f%f%f%f",
&fHKL[0],&fHKL[1],&fHKL[2],&fPsi);
if(iRet != 4){
snprintf(pError,255,"WARNING: skipping bad line %s",pBueffel);
SCWrite(pCon,pError,eWarning);
continue;
}
} else {
iRet = sscanf(pBueffel,"%f%f%f",&fHKL[0],&fHKL[1],&fHKL[2]);
if(iRet != 3){
snprintf(pError,255,"WARNING: skipping bad line %s",pBueffel);
SCWrite(pCon,pError,eWarning);
continue;
}
}
count++;
iRet = MesureCalculateSettings(self,fHKL,fSet,fPsi,pCon);
if(iRet == 1)
{
good++;
}
}
fclose(fd);
snprintf(pBueffel,511,"Of %d reflections on file, %d are good and %d are rotten",
count,good,count-good);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
/*------------------------------------------------------------------------*/
int MesureGenFile(pMesure self, char *pFile, int iSkip, SConnection *pCon)
{
FILE *fd = NULL;
char pBueffel[512], pTime[132];
int i, iRet, iH, iK, iL;
float fHKL[3], fSet[4];
char pDum[4];
assert(self);
assert(pCon);
/* well before doing a thing, open the list file */
fd = fopen(pFile,"r");
if(!fd)
{
sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* check that files are open, if not open */
if(self->fRefl == NULL)
{
MesureStart(self,pCon);
}
/* make a mark */
SNXFormatTime(pTime,131);
sprintf(pBueffel,"Starting at list %s at %s",pFile,pTime);
SCWrite(pCon,pBueffel,eStatus);
/* skippy! */
for(i = 0; i < iSkip; i++)
{
fgets(pBueffel,510,fd);
}
self->iCount = iSkip;
/* loop through space and measure! */
while(fgets(pBueffel,510,fd) != NULL)
{
for(i = 0; i < 3;i++)
fHKL[i] = 0.;
for(i = 0; i < 4;i++)
fSet[i] = 0.;
iRet = sscanf(pBueffel,"%4d%4d%4d%s%f%f%f%f",
&iH,&iK,&iL,pDum,
&fSet[0], &fSet[1],&fSet[2],&fSet[3]);
fHKL[0] = (float)iH;
fHKL[1] = (float)iK;
fHKL[2] = (float)iL;
self->iCount++;
iRet = MesureGenReflection(self,fHKL,fSet,pCon);
if(iRet == 0)
{
if(SCGetInterrupt(pCon) >= eAbortBatch)
{
return 0;
}
else
{
SCSetInterrupt(pCon,eContinue);
continue;
}
}
WriteReflection(self,fHKL,pCon);
}
/* we are done */
SNXFormatTime(pTime,131);
sprintf(pBueffel,"Finishing list %s at %s",pFile,pTime);
SCWrite(pCon,pBueffel,eStatus);
fclose(fd);
return 1;
}
/*--------------------------------------------------------------------------*/
int MesureSetPar(pMesure self, char *name, float fVal)
{
if(strcmp(name,"np") == 0)
{
#ifndef MESSDEBUG
self->np = (int)fVal;
if(self->lCounts)
free(self->lCounts);
self->lCounts = (long *)malloc(self->np*sizeof(long));
if(!self->lCounts)
{
return 0;
}
#else
#endif
return 1;
}
else if(strcmp(name,"step") == 0)
{
self->fStep = fVal;
return 1;
}
else if(strcmp(name,"weakthreshold") == 0)
{
self->weakThreshold = (long)nintf(fVal);
return 1;
}
else if(strcmp(name,"preset") == 0)
{
self->fPreset = fVal;
return 1;
}
else if(strcmp(name,"countmode") == 0)
{
if(fVal < 0.05)
{
self->CountMode = eTimer;
}
else
{
self->CountMode = ePreset;
}
return 1;
}
else if(strcmp(name,"compact") == 0)
{
if(fVal >= 1.)
{
self->iCompact = 1;
}
else
{
self->iCompact = 0;
}
return 1;
}
else if(strcmp(name,"weak") == 0)
{
if(fVal >= 1.)
{
self->weak = 1;
}
else
{
self->weak = 0;
}
return 1;
}
else if(strcmp(name,"fastscan") == 0)
{
if(fVal >= 1.)
{
self->fastScan = 1;
}
else
{
self->fastScan = 0;
}
return 1;
}
else if(strcmp(name,"psimode") == 0)
{
if(fVal >= 1.)
{
self->psiMode = 1;
}
else
{
self->psiMode = 0;
}
return 1;
}
else
{
return 0;
}
}
/*-------------------------------------------------------------------------*/
int MesureGetPar(pMesure self, char *name, float *fVal)
{
if(strcmp(name,"np") == 0)
{
*fVal = self->np;
return 1;
}
else if(strcmp(name,"step") == 0)
{
*fVal = self->fStep;
return 1;
}
else if(strcmp(name,"weakthreshold") == 0)
{
*fVal = (float)self->weakThreshold;
return 1;
}
else if(strcmp(name,"preset") == 0)
{
*fVal = self->fPreset;
return 1;
}
else if(strcmp(name,"countmode") == 0)
{
if(self->CountMode == eTimer)
{
*fVal = 0.;
}
else
{
*fVal = 1.0;
}
return 1;
}
else if(strcmp(name,"compact") == 0)
{
*fVal = self->iCompact;
return 1;
}
else if(strcmp(name,"fastscan") == 0)
{
*fVal = (float)self->fastScan;
return 1;
}
else if(strcmp(name,"weak") == 0)
{
*fVal = (float)self->weak;
return 1;
}
else if(strcmp(name,"psimode") == 0)
{
*fVal = self->psiMode;
return 1;
}
else
{
return 0;
}
}
/*---------------------------------------------------------------------------*/
int MesureAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
int iRet, iSkip, err;
char pBueffel[1024];
pMesure self = NULL;
double d;
float fVal, fHKL[3], start, end, step;
self = (pMesure)pData;
assert(self);
assert(pCon);
if(argc < 2)
{
sprintf(pBueffel,"ERROR: Insufficient arguments to %s",argv[0]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/*
catch table processing commands
*/
iRet = HandleFourCircleCommands(self->stepTable,pCon,argc,argv,&err);
if(iRet == 1)
{
return err;
}
strtolower(argv[1]);
/*------ start */
if(strcmp(argv[1],"start") == 0)
{
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
iRet = MesureStart(self,pCon);
if(iRet)
{
SCSendOK(pCon);
}
return iRet;
}
/*----------- list*/
else if(strcmp(argv[1],"list") == 0)
{
ListMesure(self,argv[0],pCon);
return 1;
}
/*------ file */
else if(strcmp(argv[1],"file") == 0)
{
sprintf(pBueffel,"Currently writing to: %s",self->pCurrentFile);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
/*------ nb */
else if(strcmp(argv[1],"nb") == 0)
{
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
iRet = SetNOR(self->pCryst,1);
if(!iRet)
{
SCWrite(pCon,
"ERROR: nu motor not configured at hkl, cannot do normal beam",
eError);
return 0;
}
SCSendOK(pCon);
return 1;
}
/*------ bi */
else if(strcmp(argv[1],"bi") == 0)
{
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
iRet = SetNOR(self->pCryst,0);
SCSendOK(pCon);
return 1;
}
/*--------- close */
else if(strcmp(argv[1],"close") == 0)
{
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
MesureClose(self);
return 1;
}
/*-------- reopen */
else if(strcmp(argv[1],"reopen") == 0)
{
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
if(argc < 3)
{
SCWrite(pCon,"ERROR: expected filename as parameter for reopen",eError);
return 0;
}
iRet = MesureReopen(self,argv[2],pCon);
if(iRet)
{
SCSendOK(pCon);
}
return iRet;
}
/*------- measure */
else if(strcmp(argv[1],"measure") == 0)
{
iSkip = 0;
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
if(argc < 3)
{
SCWrite(pCon,"ERROR: expected list file name as parameter for measure ",eError);
return 0;
}
if(argc >= 4)
{
iRet = Tcl_GetInt(pSics->pTcl,argv[3],&iSkip);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: expected integer, got %s",argv[3]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
}
iRet = MesureFile(self,argv[2],iSkip,pCon);
if(iRet)
{
SCSendOK(pCon);
}
return iRet;
}
/*------- calc */
else if(strcmp(argv[1],"calc") == 0)
{
if(argc < 3)
{
SCWrite(pCon,"ERROR: expected list file name as parameter for measure ",eError);
return 0;
}
iRet = TestFile(self,argv[2],pCon);
return iRet;
}
/*------- genlist */
else if(strcmp(argv[1],"genlist") == 0)
{
iSkip = 0;
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
if(argc < 3)
{
SCWrite(pCon,"ERROR: expected list file name as parameter for measure ",eError);
return 0;
}
if(argc >= 4)
{
iRet = Tcl_GetInt(pSics->pTcl,argv[3],&iSkip);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: expected integer, got %s",argv[3]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
}
iRet = MesureGenFile(self,argv[2],iSkip,pCon);
if(iRet)
{
SCSendOK(pCon);
}
return iRet;
}
/* ------ writereflection*/
else if(strcmp(argv[1],"writereflection") == 0)
{
GetCurrentHKL(self->pCryst,fHKL);
WriteReflection(self,fHKL,pCon);
SCSendOK(pCon);
return 1;
}
/* ------ count mode */
else if(strcmp(argv[1],"countmode") == 0)
{
if(argc > 2) /* set case */
{
/* check rights */
if(!SCMatchRights(pCon,usUser))
{
SCWrite(pCon,"ERROR: You are not aurhorised to do this!",eError);
return 0;
}
if(strcmp(argv[2],"timer") == 0)
{
fVal = 0.;
}
else if(strcmp(argv[2],"monitor") == 0)
{
fVal = 1.;
}
else
{
SCWrite(pCon,"ERROR: Invalid parameter for countmode",eError);
return 0;
}
MesureSetPar(self,"countmode",fVal);
SCSendOK(pCon);
return 1;
}
else /* get case */
{
MesureGetPar(self,"countmode",&fVal);
if(fVal < 0.05)
{
sprintf(pBueffel,"%s.countmode = timer",argv[0]);
}
else
{
sprintf(pBueffel,"%s.countmode = monitor", argv[0]);
}
SCWrite(pCon,pBueffel,eValue);
return 1;
}
}
/*------ can be other pars */
else
{
if(argc > 2) /* set case */
{
/* check rights */
if(!SCMatchRights(pCon,usUser))
{
SCWrite(pCon,"ERROR: You are not aurhorised to do this!",eError);
return 0;
}
iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&d);
if(iRet != TCL_OK)
{
sprintf(pBueffel,"ERROR: expected numeric value for %s but got %s",
argv[1],argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
fVal = (float)d;
iRet = MesureSetPar(self,argv[1],fVal);
if(iRet)
{
SCSendOK(pCon);
return 1;
}
else
{
sprintf(pBueffel,"ERROR: parameter %s not known",argv[1]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
}
else /* get case */
{
iRet = MesureGetPar(self,argv[1],&fVal);
if(!iRet)
{
sprintf(pBueffel,"ERROR: parameter %s not known",argv[1]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
sprintf(pBueffel,"%s.%s = %f",argv[0],argv[1],fVal);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
}
}