- Fixes to hkl code

- Fixes to make RITA work
- tasub extended to calculate UB from cell alone, support for elastic mode
- New MultiCounter as abstraction for counting on HM's
- regression test driver for counters
This commit is contained in:
koennecke
2006-09-13 07:12:00 +00:00
parent 87d81cf474
commit cb3bf30bbf
33 changed files with 1961 additions and 671 deletions

View File

@ -701,12 +701,21 @@ static void writeToLogFiles(SConnection *self, char *buffer)
SICSLogWrite(buffer,iOut);
/* write to commandlog if user or manager privilege */
if(SCGetRights(self) <= usUser && self->iMacro != 1)
if(SCGetRights(self) <= usUser)
{
sprintf(pBueffel,"To sock %d :",iRet);
sendingConnection = self;
WriteToCommandLog(pBueffel,buffer);
sendingConnection = NULL;
if(self->iMacro != 1)
{
sprintf(pBueffel,"To sock %d :",iRet);
WriteToCommandLog(pBueffel,buffer);
}
else
{
if(iOut == eError || iOut == eWarning)
{
sprintf(pBueffel,"To sock %d :",iRet);
WriteToCommandLog(pBueffel,buffer);
}
}
}
/* put it into the interpreter if present */
@ -1437,9 +1446,16 @@ pDynString SCEndBuffering(SConnection *pCon)
{
strcat(pBueffel,"CONT or CRON>> ");
}
sendingConnection = self;
WriteToCommandLog(pBueffel,pCommand);
sendingConnection = NULL;
/*
* This is a fix to suppress cron messages in the success
* case
*/
if(SCGetWriteFunc(self) != SCNotWrite)
{
sendingConnection = self;
WriteToCommandLog(pBueffel,pCommand);
sendingConnection = NULL;
}
}
/* invoke */

View File

@ -88,4 +88,10 @@
* file: mcstascounter.c
*/
pCounterDriver NewMcStasCounter(char *name);
/*
* for regression testing
* file: regresscter.c
*/
pCounterDriver NewRegressCounter(char *name);
#endif

View File

@ -103,9 +103,9 @@
if(iRet == OKOK)
{
self->isUpToDate = 0;
self->badStatusCount = 0;
self->badStatusCount = 0;
self->tStart = time(&tX);
InvokeCallBack(self->pCall,COUNTSTART,pCon);
InvokeCallBack(self->pCall,COUNTSTART,pCon);
return iRet;
}
else
@ -314,7 +314,7 @@
for(i = 0; i < 3; i++)
{
iRet = self->pDriv->ReadValues(self->pDriv);
if(iRet)
if(iRet == OKOK)
{
self->isUpToDate = 1;
return OKOK;
@ -529,6 +529,13 @@
}
}
/*
* test for regression testing counter
*/
if(strcmp(argv[2],"regress") == 0){
pDriv = NewRegressCounter(argv[1]);
}
/*
* test for McStas simulation counter driver
*/

View File

@ -668,7 +668,6 @@ static int errorDevice(pCheckContext pCheck){
ExeInterest(pCheck->self, pCheck->pDev, "finished with problem");
DevexecLog("STOP",pCheck->pDev->name);
DeleteDevEntry(pCheck->pDev);
LLDnodeDelete(pCheck->self->iList);
status = LLDnodePtr2Prev(pCheck->self->iList);
SCWrite(pCheck->self->pOwner, "", eFinish);
@ -676,7 +675,9 @@ static int errorDevice(pCheckContext pCheck){
if(pCheck->pDrivInt != NULL) {
pCheck->pDrivInt->iErrorCount++;
}
return checkInterrupt(pCheck,status);
status = checkInterrupt(pCheck,status);
DeleteDevEntry(pCheck->pDev);
return status;
}
/*-------------------------------------------------------------------------*/
static int testFinish(pExeList self){

View File

@ -421,6 +421,7 @@
pFit self = NULL;
int iRet;
char pBueffel[256];
pDynString buf = NULL;
self = (pFit)pData;
assert(self);
@ -470,6 +471,7 @@
}
/* print results */
SCStartBuffering(pCon);
sprintf(pBueffel,"Estimated Peak Center: %f, StdDev: %f \n",
self->fCenter,self->fStddev);
SCWrite(pCon,pBueffel,eValue);
@ -477,6 +479,10 @@
SCWrite(pCon,pBueffel,eValue);
sprintf(pBueffel,"Approximate FWHM: %f\n",self->FWHM);
SCWrite(pCon,pBueffel,eValue);
buf = SCEndBuffering(pCon);
if(buf != NULL){
SCWrite(pCon,GetCharArray(buf),eValue);
}
return 1;
}

View File

@ -625,6 +625,10 @@ int findAllowedBisecting(double lambda, MATRIX z1, float fSet[4],
return 0;
}
if(testFunc(userData, fSet, mask) == 1){
return 1;
}
for(psi = .0; psi < 360.; psi += .5){
rotatePsi(om,chi,phi,psi,&ompsi,&chipsi,&phipsi);
fTest[0] = stt;
@ -638,6 +642,26 @@ int findAllowedBisecting(double lambda, MATRIX z1, float fSet[4],
}
return 1;
}
/*
* if chi close to 0, or 180, try to wrap phi onto om
*/
if(ABS(fTest[2] - .0) < .1 || ABS(fTest[2] - 180.) < .1){
fTest[1] -= fTest[3];
fTest[3] = .0;
if(fTest[1] < 0.){
fTest[1] += 360.;
}
if(fTest[1] > 360.0){
fTest[1] -= 360.;
}
status = testFunc(userData,fTest,mask);
if(status == 1){
for(i = 0; i < 4; i++){
fSet[i] = fTest[i];
}
return 1;
}
}
if(mask[0] == 0) {
/*
* useless: when two theta problem there is no solution

View File

@ -290,6 +290,60 @@ hdbValue makeHdbValue(int datatype, int length){
}
return val;
}
/*------------------------------------------------------------------------*/
hdbValue makeHdbData(int datatype, int length, void *data){
hdbValue val;
memset(&val,0,sizeof(hdbValue));
val.dataType = datatype;
switch(datatype){
case HIPINT:
if(data != NULL){
memcpy(&val.v.intValue,data,sizeof(int));
}
break;
case HIPFLOAT:
if(data != NULL){
memcpy(&val.v.doubleValue,data,sizeof(double));
}
break;
case HIPINTAR:
case HIPINTVARAR:
val.arrayLength = length;
val.v.intArray = malloc(length*sizeof(int));
if(val.v.intArray != NULL){
memset(val.v.intArray,0,length*sizeof(int));
}
if(data != NULL){
memcpy(val.v.intArray,data,length*sizeof(int));
}
break;
case HIPFLOATAR:
case HIPFLOATVARAR:
val.arrayLength = length;
val.v.floatArray = malloc(length*sizeof(double));
if(val.v.floatArray != NULL){
memset(val.v.floatArray,0,length*sizeof(double));
}
if(data != NULL){
memcpy(val.v.floatArray,data,length*sizeof(double));
}
break;
case HIPTEXT:
if(data != NULL){
val.v.text = strdup((char *)data);
} else {
val.v.text = strdup("UNKNOWN");
}
val.arrayLength = strlen(val.v.text);
break;
case HIPOBJ:
val.v.obj = data;
break;
}
return val;
}
/*-------------------------------------------------------------------------*/
hdbValue MakeHdbInt(int initValue){
hdbValue result;
@ -411,6 +465,13 @@ int compareHdbValue(hdbValue v1, hdbValue v2){
}
return 1;
break;
case HIPOBJ:
if(v2.v.obj == v1.v.obj) {
return 1;
} else {
return 0;
}
break;
default:
assert(0);
break;
@ -424,6 +485,35 @@ int cloneHdbValue(hdbValue *source, hdbValue *clone){
clone->dataType = source->dataType;
return copyHdbValue(source, clone);
}
/*-------------------------------------------------------------------------*/
int getHdbValueLength(hdbValue v){
int length = 0;
switch(v.dataType){
case HIPNONE:
break;
case HIPINT:
length = sizeof(int);
break;
case HIPFLOAT:
length = sizeof(double);
break;
case HIPINTAR:
case HIPINTVARAR:
length = v.arrayLength * sizeof(int);
break;
case HIPFLOATAR:
case HIPFLOATVARAR:
length = v.arrayLength * sizeof(double);
break;
case HIPTEXT:
length = strlen(v.v.text);
break;
case HIPOBJ:
length = sizeof(void *);
break;
}
return length;
}
/*================= node functions ========================================*/
pHdb MakeHipadabaNode(char *name, int datatype, int length){
pHdb pNew = NULL;
@ -655,7 +745,6 @@ void AppendHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
newCB->previous = current;
}
}
/*-------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
void PrependHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
switch(type){
@ -779,6 +868,9 @@ int copyHdbValue(hdbValue *source, hdbValue *target){
target->v.floatArray[i] = source->v.floatArray[i];
}
break;
case HIPOBJ:
target->v.obj = source->v.obj;
break;
default:
/*
* unknown data type
@ -818,3 +910,117 @@ int GetHipadabaPar(pHdb node, hdbValue *v, void *callData){
copyHdbValue(&node->value,v);
return 1;
}
/*----------------------------------------------------------------------------*/
static int calcDataLength(pHdb node, int testLength){
int length = 0;
length = getHdbValueLength(node->value);
if(node->value.dataType == HIPFLOATVARAR ||
node->value.dataType == HIPINTVARAR ||
node->value.dataType == HIPTEXT){
length = testLength;
}
return length;
}
/*--------------------------------------------------------------------------*/
int SetHdbPar(pHdb node, int dataType, void *data, int length,
void *callData){
int status;
hdbValue v;
if(node->value.dataType == HIPNONE){
return 1;
}
if(dataType != node->value.dataType){
return HDBTYPEMISMATCH;
}
if(length != calcDataLength(node,length)){
return HDBLENGTHMISMATCH;
}
v = makeHdbData(dataType, length, data);
status = InvokeCallbackChain(node->writeCallbacks, node, callData, v);
if(status == 1) {
copyHdbValue(&v,&node->value);
}
return status;
}
/*--------------------------------------------------------------------------*/
int UpdateHdbPar(pHdb node, int dataType, void *data, int length,
void *callData){
int status;
hdbValue v;
if(node->value.dataType == HIPNONE){
return 1;
}
if(dataType != node->value.dataType){
return HDBTYPEMISMATCH;
}
if(length != calcDataLength(node,length)){
return HDBLENGTHMISMATCH;
}
v = makeHdbData(dataType,length,data);
status = InvokeCallbackChain(node->updateCallbacks, node, callData, v);
if(status == 1) {
copyHdbValue(&v,&node->value);
}
return status;
}
/*-----------------------------------------------------------------------------*/
int GetHdbPar(pHdb node, int dataType, void *data, int length,
void *callData){
int status, toCopy;
hdbValue v;
if(dataType != node->value.dataType){
return HDBTYPEMISMATCH;
}
if(length != calcDataLength(node,length)){
return HDBLENGTHMISMATCH;
}
status = InvokeCallbackChain(node->readCallbacks, node, callData, v);
if(status != 1 ){
return status;
}
switch(dataType){
case HIPNONE:
break;
case HIPINT:
memcpy(data,&node->value.v.intValue,sizeof(int));
break;
case HIPFLOAT:
memcpy(data,&node->value.v.doubleValue,sizeof(double));
break;
case HIPINTAR:
case HIPINTVARAR:
memcpy(data,node->value.v.intArray,
node->value.arrayLength*sizeof(int));
break;
case HIPTEXT:
toCopy = strlen(node->value.v.text);
if(toCopy > length){
toCopy = length;
}
memcpy(data,&node->value.v.text, toCopy);
break;
case HIPFLOATAR:
case HIPFLOATVARAR:
memcpy(data,node->value.v.floatArray,
node->value.arrayLength*sizeof(double));
break;
case HIPOBJ:
memcpy(data,&node->value.v.obj,sizeof(void *));
break;
default:
assert(0);
break;
}
return 1;
}

View File

@ -33,10 +33,14 @@
#define HIPFLOATAR 4
#define HIPINTVARAR 5
#define HIPFLOATVARAR 6
#define HIPOBJ 7
/* -------- callback types */
#define HCBSET 0
#define HCBUPDATE 1
#define HCBREAD 2
/*--------- error codes */
#define HDBTYPEMISMATCH -7701
#define HDBLENGTHMISMATCH -7702
/*===================== structure definitions ===================================*/
typedef struct __hdbValue {
int dataType;
@ -47,6 +51,7 @@ typedef struct __hdbValue {
char *text;
int *intArray;
double *floatArray;
void *obj;
}v;
}hdbValue;
/*------------------------------------------------------------------------------*/
@ -77,6 +82,15 @@ typedef struct __hdbcallback {
}hdbCallback, *pHdbCallback;
/*======================== Function protoypes: hdbData ========================*/
hdbValue makeHdbValue(int datatype, int length);
/**
* make a hdbValue and initailize it with the data in the void
* pointer. Do not initialise when data = NULL.
* @param dataType The datatype of the hdbValue
* @param The array length of the hdbValue
* @param data Initialisation data for hdbValue
* @return a suitably defined hdbValue
*/
hdbValue makeHdbData(int datatype, int length, void *data);
/**
* wrap an integer as an hdbValue
* @param initValue the initial value of the int
@ -147,6 +161,12 @@ int compareHdbValue(hdbValue v1, hdbValue v2);
* @return 1 on success, 0 on when out of memory
*/
int cloneHdbValue(hdbValue *source, hdbValue *clone);
/**
* get the length of the hdbValue in bytes.
* @param v The hdbValue to calculate the length for
* @return the number of data bytes
*/
int getHdbValueLength(hdbValue v);
/*========================== function protoypes: Nodes =======================*/
/**
* make a new hipadaba node
@ -156,7 +176,7 @@ int cloneHdbValue(hdbValue *source, hdbValue *clone);
*/
pHdb MakeHipadabaNode(char *name, int datatype, int length);
/**
* add a child to a node
* add a child to a node at the end of the child list.
* @param parent The node to which to add the child
* @param child The node to add
*/
@ -250,8 +270,8 @@ void InternalRemoveHipadabaCallback(pHdb root, int internalID);
*/
int SetHipadabaPar(pHdb node, hdbValue v, void *callData);
/**
* Update a hipadaba parameter. This is an internal update of a parameter, during
* driving etc.
* Update a hipadaba parameter. This is an internal update of a parameter,
* during driving etc.
* @param node The node for which to update the parameter
* @param v The new value for the node
* @param callData Additonal context data to be passed to the callback functions
@ -266,5 +286,41 @@ int UpdateHipadabaPar(pHdb node, hdbValue v, void *callData);
* @return 0 on failure, 1 on success
*/
int GetHipadabaPar(pHdb node, hdbValue *v, void *callData);
/**
* Set a hipadaba parameter. This is an external set for a parameter. It may cause
* motors to start driving etc.
* @param node The node for which to set the parameter
* param dataType The datatype the value ought to have
* @param data A pointer to the data to set.
* @param length The length of data
* @param callData Additonal context data to be passed to the callback functions
* @return 0 on failure, a negative error code on failure
*/
int SetHdbPar(pHdb node, int dataType, void *data, int length,
void *callData);
/**
* Updates a hipadaba parameter. This does not cause an active parameter to
* start driving but invokes all nitifications which may be regsitered on
* this parameter.
* @param node The node for which to set the parameter
* param dataType The datatype the value ought to have
* @param data A pointer to the data to set.
* @param length The length of data
* @param callData Additonal context data to be passed to the callback functions
* @return 0 on failure, a negative error code on failure
*/
int UpdateHdbPar(pHdb node, int dataType, void *data, int length,
void *callData);
/**
* Read a hipadaba parameter
* @param node The node for which to read the parameter
* @param dataType The expected type of the data
* @param data A pointer to which data will be copied
* @param length The length of data.
* @param callData Additonal context data to be passed to the callback functions
* @return 0 on failure, a negative error code on failures.
*/
int GetHdbPar(pHdb node, int dataType, void *data, int length,
void *callData);
#endif

View File

@ -171,7 +171,9 @@
iRet = self->pDriv->Start(self->pDriv, pCon);
if(iRet == OKOK)
{
updateHMData(self->pDriv->data);
/* send a COUNTSTART event */
InvokeCallBack(self->pCall,COUNTSTART,pCon);
updateHMData(self->pDriv->data);
return iRet;
}
else
@ -721,8 +723,6 @@ void HistDirty(pHistMem self)
{
assert(self);
/* send a COUNTSTART event */
InvokeCallBack(self->pCall,COUNTSTART,pCon);
/* start */
return StartDevice(GetExecutor(),"HistogramMemory", self->pDes, self,
@ -744,9 +744,6 @@ void HistDirty(pHistMem self)
return 0;
}
/* send a COUNTSTART event */
InvokeCallBack(self->pCall,COUNTSTART,pCon);
/* wait till end */
iRet = Wait4Success(GetExecutor());
if(iRet == DEVINT)

85
hkl.c
View File

@ -61,7 +61,6 @@
fprintf(fd,"%s hm %d\n",name, self->iHM);
fprintf(fd,"%s scantolerance %f\n", name,self->scanTolerance);
fprintf(fd,"%s nb %d\n", name, self->iNOR);
fprintf(fd,"%s phiom %d\n", name, self->iOMPHI);
return 1;
}
@ -689,7 +688,7 @@ int hklInRange(void *data, float fSet[4], int mask[4])
fSet[0] = dTheta;
/* for omega check against the limits +- SCANBORDER in order to allow for
a omega scan
a omega scan.
*/
MotorGetPar(self->pOmega,"softlowerlim",&fLimit);
if((float)fSet[1] < fLimit + self->scanTolerance){
@ -721,7 +720,7 @@ static int calculateBisecting(MATRIX z1, pHKL self, SConnection *pCon,
float fSet[4], double myPsi, int iRetry)
{
double stt, om, chi, phi, psi, ompsi, chipsi, phipsi;
int i, test;
int i, test, mask[4];
/*
just the plain angle calculation
@ -731,16 +730,31 @@ static int calculateBisecting(MATRIX z1, pHKL self, SConnection *pCon,
return 0;
}
fSet[0] = stt;
fSet[1] = om;
fSet[2] = chi;
fSet[3] = phi;
if(iRetry == 1) {
rotatePsi(om,chi,phi,psi,&ompsi,&chipsi,&phipsi);
rotatePsi(om,chi,phi,myPsi,&ompsi,&chipsi,&phipsi);
fSet[1] = ompsi;
fSet[2] = circlify(chipsi);
fSet[3] = circlify(phipsi);
return 1;
} else {
return findAllowedBisecting(self->fLambda, z1, fSet, hklInRange,self);
if(hklInRange(self,fSet, mask) == 1){
return 1;
} else {
if(tryOmegaTweak(self,z1, &stt, &om, &chi, &phi) == 1){
fSet[0] = stt;
fSet[1] = om;
fSet[2] = chi;
fSet[3] = phi;
return 1;
} else {
return findAllowedBisecting(self->fLambda, z1, fSet, hklInRange,self);
}
}
}
}
/*-----------------------------------------------------------------------*/
static int calculateNormalBeam(MATRIX z1, pHKL self, SConnection *pCon,
@ -789,7 +803,11 @@ static int calculateNormalBeam(MATRIX z1, pHKL self, SConnection *pCon,
if(checkNormalBeam(omnb, &gamma, nu,fSet,pCon,self)){
return 1;
} else {
return 0;
if(checkNormalBeam(360. - omnb, &gamma, nu, fSet,pCon,self)){
return 1;
} else {
return 0;
}
}
}
/*---------------------------------------------------------------------*/
@ -850,7 +868,7 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self,
{
if(checkNormalBeam(om, &gamma, nu,fSet,pCon,self))
{
return 1;
return 1;
}
}
return 0;
@ -903,30 +921,6 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self,
if(self->iNOR == 0)
{
status = calculateBisecting(z1,self,pCon,fSet, myPsi, iRetry);
/*
* Betrand mode: wrap phi rotation into omega
*/
if(self->iOMPHI > 0) {
if(ABS(fSet[2] - .0) < .1 || ABS(fSet[2] - 180.) < .1){
fSet[1] -= fSet[3];
/*
fSet[1] = 360. - fSet[3];
*/
fSet[3] = .0;
if(fSet[1] < 0.){
fSet[1] += 360.;
}
if(fSet[1] > 360.0){
fSet[1] -= 360.;
}
} else {
snprintf(pBueffel,511,
"ERROR: for omphi mode chi must be 0 or 180, is %f",
fSet[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
}
}
else if(self->iNOR == 1)
{
@ -1414,8 +1408,8 @@ ente:
if(strcmp(argv[1],"list") == 0 )
{
sprintf(pBueffel,
"lambda = %f Normal Beam = %d PHIOM = %d Quadrant = %d HM = %d",
self->fLambda, self->iNOR, self->iOMPHI,
"lambda = %f Normal Beam = %d Quadrant = %d HM = %d",
self->fLambda, self->iNOR,
self->iQuad,self->iHM);
SCWrite(pCon,pBueffel,eValue);
sprintf(pBueffel,"UB = { %f %f %f",
@ -1654,29 +1648,6 @@ ente:
SCSendOK(pCon);
return 1;
}
/*------------- phi omega mode (to be removed) */
else if(strcmp(argv[1],"phiom") == 0)
{
if(argc < 3)
{
snprintf(pBueffel,511,"%s.phiom = %d",argv[0],self->iOMPHI);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
if(!SCMatchRights(pCon,usUser))
{
return 0;
}
if(!isNumeric(argv[2]))
{
sprintf(pBueffel,"ERROR: %s was not recognized as a number", argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
self->iOMPHI = atoi(argv[2]);
SCSendOK(pCon);
return 1;
}
/*------------- quadrant */
else if(strcmp(argv[1],"quadrant") == 0)
{

1
hkl.i
View File

@ -15,7 +15,6 @@
int iManual;
double fLastHKL[5];
int iNOR;
int iOMPHI;
int iQuad;
int iHM;
pMotor pTheta;

View File

@ -26,7 +26,6 @@ $\langle$hkldat {\footnotesize ?}$\rangle\equiv$
\mbox{}\verb@ int iManual;@\\
\mbox{}\verb@ double fLastHKL[5];@\\
\mbox{}\verb@ int iNOR;@\\
\mbox{}\verb@ int iOMPHI;@\\
\mbox{}\verb@ int iQuad;@\\
\mbox{}\verb@ int iHM;@\\
\mbox{}\verb@ pMotor pTheta;@\\

1
hkl.w
View File

@ -21,7 +21,6 @@ The object uses the following object data structure:
int iManual;
double fLastHKL[5];
int iNOR;
int iOMPHI;
int iQuad;
int iHM;
pMotor pTheta;

View File

@ -406,10 +406,10 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
break;
case 2:
lSum = 0;
for(i = iStart[0]; i < iEnd[0]; i++){
iIndex = i*self->iDim[1];
for(i = iStart[1]; i < iEnd[1]; i++){
iIndex = i*self->iDim[0];
lRowSum = SumRow(self->localBuffer,iHistLength,
iIndex+iStart[1], iIndex+iEnd[1]);
iIndex+iStart[0], iIndex+iEnd[0]);
lSum += lRowSum;
}
break;

View File

@ -34,7 +34,7 @@
/*-------------------------- conversion routines -------------------------*/
static float ang2x(pLin2Ang self, float fAngle)
{
return self->length*sin((fAngle+self->zero)/RD);
return self->length*tan((fAngle+self->zero)/RD);
}
/*-----------------------------------------------------------------------*/
static float x2ang(pLin2Ang self, float fX)
@ -44,7 +44,7 @@
assert(self->length > 0.);
dt = fX/self->length;
return RD*asin(dt) - self->zero;
return RD*atan(dt) - self->zero;
}
/*============== functions in the interface ============================*/
static void *Lin2AngGetInterface(void *pData, int iID)

13
macro.c
View File

@ -2,7 +2,7 @@
All you need to evaluate macros with SICS
The implmentation for the macro stuff is complex and non intuitive.
The implementation for the macro stuff is complex and non intuitive.
This is the price to pay for adding the extremly powerful and
strong Tcl-interpreter to SICS. The problem is that Tcl does not
know anything about connections and our error handling. We have
@ -891,14 +891,9 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp,
if (pCommand != pBueffel) free(pCommand);
if(iRet == TCL_OK)
{
/* we do not now why, but at some time it was found that
we need a copy, and can not use pTcl->result directly
SCWrite(pCon,pTcl->result,eStatus);
let us use SCPrintf, which maked always a copy
*/
SCPrintf(pCon, eStatus, "%s", pTcl->result);
if(strlen(pTcl->result) > 0){
SCPrintf(pCon, eStatus, "%s", pTcl->result);
}
return 1;
}
else

View File

@ -31,7 +31,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.o \
mcstashm.o initializer.o remob.o tclmotdriv.o protocol.o \
sinfox.o sicslist.o cone.o hipadaba.o sicshipadaba.o statistics.o \
moregress.o
moregress.o hdbcommand.o multicounter.o regresscter.o
MOTOROBJ = motor.o simdriv.o
COUNTEROBJ = countdriv.o simcter.o counter.o

View File

@ -445,7 +445,9 @@ static int MesureCalculateSettings(pMesure self, float fHKL[3], float fSet[4],
float fPsi, SConnection *pCon)
{
int status, np;
float step, tolerance;
float step, tolerance, fHard;
char *scanvar = NULL;
char buffer[256];
SetHKLScanTolerance(self->pCryst,.0);
status = CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon);
@ -460,7 +462,26 @@ static int MesureCalculateSettings(pMesure self, float fHKL[3], float fSet[4],
np = getMesureNP(self,(double)fSet[0]);
tolerance = (step * (float)np)/2. + .2;
SetHKLScanTolerance(self->pCryst,tolerance);
return CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon);
status = CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon);
if(status != 1){
return status;
}
scanvar = GetFourCircleScanVar(self->stepTable,fSet[0]);
if(scanvar != NULL && strcmp(scanvar,"om") != 0){
tolerance *= 2.;
strcpy(buffer,"ERROR: 2theta limit problem:");
if(!MotorCheckBoundary(self->p2Theta,fSet[0]-tolerance,&fHard,
buffer,256-strlen(buffer))){
SCWrite(pCon,buffer,eWarning);
return 0;
}
if(!MotorCheckBoundary(self->p2Theta,fSet[0]+tolerance,&fHard,
buffer,256-strlen(buffer))){
SCWrite(pCon,buffer,eWarning);
return 0;
}
}
return status;
}
/*--------------------------------------------------------------------------*/
int MesureReflection(pMesure self, float fHKL[3], float fPsi,

1056
motor.c

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,7 @@
typedef struct __Motor {
pObjectDescriptor pDescriptor;
ObPar *ParArray;
pIDrivable pDrivInt;
pICallBack pCall;
char *drivername;

380
multicounter.c Normal file
View File

@ -0,0 +1,380 @@
/**
* The MultiCounter is another counter which coordinates multiple
* counting objects, counters and histogram memories. It also calls a
* script function after TransferData which collects counters and monitors.
* The purpose is to have a flexible counter abstraction for upper level
* code such as maximizers and scan functions. The script can deal with
* counting on monitors or on sums of histogram memories.
*
* This is a bit unclean. The counter driver is of no use, therefore its
* private data structure is used to hold the other counters and the name
* of the script. It would have been better to inherit from counter but
* that would have required lost of type casts. I am to lazy for this.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, September 2006
*/
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <tcl.h>
#include "multicounter.h"
#include "counter.h"
#include "HistMem.h"
#include "macro.h"
#include "splitter.h"
#define MAXSLAVE 16
/*=============== code for the driver ======================================*/
typedef struct {
void *slaveData[MAXSLAVE];
pICountable slaves[MAXSLAVE];
char *transferScript;
int nSlaves;
}MultiCounter, *pMultiCounter;
/*--------------------------------------------------------------------------*/
static void KillMultiDriver(struct __COUNTER *data){
pMultiCounter self = (pMultiCounter)data->pData;
if(self == NULL){
return;
}
if(self->transferScript != NULL){
free(self->transferScript);
}
free(self);
}
/*============== countable interface functions ============================*/
static int MMCCHalt(void *pData){
int i, retVal = OKOK, status;
pCounter pCount = NULL;
pMultiCounter self = NULL;
pCount = (pCounter)pData;
if(pCount != NULL){
self = (pMultiCounter)pCount->pDriv->pData;
}
assert(self);
for(i = 0; i < self->nSlaves; i++){
status = self->slaves[i]->Halt(self->slaveData[i]);
if(status != OKOK)
retVal = status;
}
return retVal;
}
/*-------------------------------------------------------------------------*/
static int MMCCStart(void *pData, SConnection *pCon)
{
int i, status;
pCounter pCount = NULL;
pMultiCounter self = NULL;
pCount = (pCounter)pData;
if(pCount != NULL){
self = (pMultiCounter)pCount->pDriv->pData;
}
assert(self);
for(i = 0; i < self->nSlaves; i++){
self->slaves[i]->SetCountParameters(self->slaveData[i],
pCount->pDriv->fPreset, pCount->pDriv->eMode);
status = self->slaves[i]->StartCount(self->slaveData[i],pCon);
if(status != OKOK){
MMCCHalt(pData);
return status;
}
}
pCount->isUpToDate = 0;
pCount->tStart = time(NULL);
InvokeCallBack(pCount->pCall,COUNTSTART,pCon);
return OKOK;
}
/*-------------------------------------------------------------------------*/
static int MMCCStatus(void *pData, SConnection *pCon){
int status,i;
pCounter pCount = NULL;
pMultiCounter self = NULL;
pDummy pDum = NULL;
pCount = (pCounter)pData;
if(pCount != NULL){
self = (pMultiCounter)pCount->pDriv->pData;
}
assert(self);
status = self->slaves[0]->CheckCountStatus(self->slaveData[0],pCon);
if(status == HWIdle || status == HWFault){
/*
stop counting on slaves when finished or when an error
occurred.
*/
InvokeCallBack(pCount->pCall,COUNTEND,pCon);
MMCCHalt(pCount);
}
for(i = 1; i < MAXSLAVE; i++){
if(self->slaves[i] != NULL){
pDum = (pDummy)self->slaveData[i];
if(strcmp(pDum->pDescriptor->name,"HistMem") == 0){
HistDirty((pHistMem)self->slaveData[i]);
}
}
}
return status;
}
/*-------------------------------------------------------------------------*/
static int MMCCPause(void *pData, SConnection *pCon){
int i, status;
pCounter pCount = NULL;
pMultiCounter self = NULL;
pCount = (pCounter)pData;
if(pCount != NULL){
self = (pMultiCounter)pCount->pDriv->pData;
}
assert(self);
for(i = 0; i < self->nSlaves; i++){
status = self->slaves[i]->Pause(self->slaveData[i],pCon);
if(status != OKOK){
MMCCHalt(pCount);
return status;
}
}
return OKOK;
}
/*--------------------------------------------------------------------------*/
static int MMCCContinue(void *pData, SConnection *pCon){
int i, status;
pCounter pCount = NULL;
pMultiCounter self = NULL;
pCount = (pCounter)pData;
if(pCount != NULL){
self = (pMultiCounter)pCount->pDriv->pData;
}
assert(self);
for(i = 0; i < self->nSlaves; i++){
status = self->slaves[i]->Continue(self->slaveData[i],pCon);
if(status != OKOK){
MMCCHalt(pCount);
return status;
}
}
return OKOK;
}
/*------------------------------------------------------------------------*/
static char *getNextMMCCNumber(char *pStart, char pNumber[80]){
int charCount = 0;
pNumber[0] = '\0';
/* advance to first digit */
while(isspace(*pStart) && *pStart != '\0'){
pStart++;
}
if(*pStart == '\0'){
return NULL;
}
/* copy */
while(!isspace(*pStart) && *pStart != '\0' && charCount < 78){
pNumber[charCount] = *pStart;
pStart++;
charCount++;
}
pNumber[charCount] = '\0';
return pStart;
}
/*-------------------------------------------------------------------------*/
static void loadCountData(pCounter pCount, const char *data){
char *pPtr = NULL;
char pNumber[80];
int i = 0;
pPtr = (char *)data;
pPtr = getNextMMCCNumber(pPtr,pNumber);
pCount->pDriv->fTime = atof(pNumber);
while(pPtr != NULL && i < MAXCOUNT){
pPtr = getNextMMCCNumber(pPtr,pNumber);
pCount->pDriv->lCounts[i] = atoi(pNumber);
i++;
}
}
/*--------------------------------------------------------------------------*/
static int MMCCTransfer(void *pData, SConnection *pCon){
int i, retVal = OKOK, status;
char pBueffel[132];
pCounter pCount = NULL;
pMultiCounter self = NULL;
int tclStatus;
pCount = (pCounter)pData;
if(pCount != NULL){
self = (pMultiCounter)pCount->pDriv->pData;
}
assert(self);
for(i = 0; i < self->nSlaves; i++){
status = self->slaves[i]->TransferData(self->slaveData[i], pCon);
if(status != OKOK){
retVal = status;
sprintf(pBueffel,"WARNING: slave histogram %d failed to transfer data",
i);
SCWrite(pCon,pBueffel,eWarning);
}
}
if(self->transferScript != NULL){
MacroPush(pCon);
tclStatus = Tcl_Eval(InterpGetTcl(pServ->pSics), self->transferScript);
if(tclStatus != TCL_OK){
snprintf(pBueffel,131,"ERROR: TransferScript returned: %s",
Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
SCWrite(pCon,pBueffel,eError);
MacroPop();
return HWFault;
}
MacroPop();
loadCountData(pCount,Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
}
return retVal;
}
/*-------------------------------------------------------------------------*/
static void MMCCParameter(void *pData, float fPreset, CounterMode eMode ){
int i;
pCounter pCount = NULL;
pMultiCounter self = NULL;
pCount = (pCounter)pData;
if(pCount != NULL){
self = (pMultiCounter)pCount->pDriv->pData;
}
assert(self);
for(i = 0; i < self->nSlaves; i++){
self->slaves[i]->SetCountParameters(self->slaveData[i], fPreset,
eMode);
}
}
/*=============== Interpreter Interface ================================ */
int MultiCounterAction(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[]){
pMultiCounter self = NULL;
pCounter pCount = NULL;
char buffer[256];
if(argc > 1){
strtolower(argv[1]);
if(strcmp(argv[1],"transferscript") == 0){
pCount = (pCounter)pData;
self = (pMultiCounter)pCount->pDriv->pData;
if(argc < 3){
SCPrintf(pCon,eValue,"%s.transferscript = %s",
argv[0],self->transferScript);
return 1;
} else {
if(!SCMatchRights(pCon,usUser)){
return 0;
}
if(self->transferScript != NULL){
free(self->transferScript);
}
Arg2Text(argc-2,&argv[2],buffer,255);
self->transferScript = strdup(buffer);
SCSendOK(pCon);
return 1;
}
}
}
return CountAction(pCon,pSics,pData,argc,argv);
}
/*------------------------------------------------------------------------*/
int MakeMultiCounter(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[]){
int i, status;
pCounter pNew = NULL;
char pBueffel[132];
CommandList *pCom;
pICountable pCount;
pMultiCounter self = NULL;
pCounterDriver pDriv = NULL;
/*
need at least two parameters
*/
if(argc < 3){
SCWrite(pCon,"ERROR: insufficient number of arguments to MakeMultiCounter",
eError);
return 0;
}
/*
allocate our data structure
*/
self = malloc(sizeof(MultiCounter));
pDriv = malloc(sizeof(CounterDriver));
if(self == NULL || pDriv == NULL){
SCWrite(pCon,"ERROR: out of memory in MakeMultiCounter",eError);
return 0;
}
memset(self,0,sizeof(MultiCounter));
memset(pDriv,0,sizeof(CounterDriver));
pDriv->pData = self;
pDriv->KillPrivate = KillMultiDriver;
pDriv->iNoOfMonitors = MAXCOUNT;
pNew = CreateCounter(argv[1],pDriv);
if(pNew == NULL){
SCWrite(pCon,"ERROR: out of memory in MakeMultiCounter",eError);
return 0;
}
/*
assign interface functions
*/
pNew->pCountInt->Halt = MMCCHalt;
pNew->pCountInt->StartCount = MMCCStart;
pNew->pCountInt->CheckCountStatus = MMCCStatus;
pNew->pCountInt->Pause = MMCCPause;
pNew->pCountInt->Continue = MMCCContinue;
pNew->pCountInt->TransferData = MMCCTransfer;
pNew->pCountInt->SetCountParameters = MMCCParameter;
/*
now loop through the remaining arguments, thereby entering them into
the slave list.
*/
for(i = 2; i < argc; i++){
pCom = FindCommand(pSics,argv[i]);
if(!pCom){
sprintf(pBueffel,"ERROR: object %s not found in MakeMultiCounter",
argv[i]);
SCWrite(pCon,pBueffel,eError);
continue;
}
pCount = GetCountableInterface(pCom->pData);
if(!pCount){
sprintf(pBueffel,"ERROR: object %s is NOT countable",
argv[i]);
SCWrite(pCon,pBueffel,eError);
continue;
}
self->slaves[self->nSlaves] = pCount;
self->slaveData[self->nSlaves] = pCom->pData;
self->nSlaves++;
}
/*
now install our action command and we are done
*/
status = AddCommand(pSics,argv[1],MultiCounterAction,DeleteCounter,
pNew);
if(!status){
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]);
SCWrite(pCon,pBueffel,eError);
DeleteCounter(pNew);
return 0;
}
return 1;
}

19
multicounter.h Normal file
View File

@ -0,0 +1,19 @@
/**
* The MultiCounter is another counter which coordinates multiple
* counting objects, counters and histogram memories. It also calls a
* script function after TransferData which collects counters and monitors.
* The purpose is to have a flexible counter abstraction for upper level
* code such as maximizers and scan functions. The script can deal with
* counting on monitors or on sums of histogram memories.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, September 2006
*/
#ifndef MULTICOUNTER_H_
#define MULTICOUNTER_H_
#include <sics.h>
int MakeMultiCounter(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[]);
#endif /*MULTICOUNTER_H_*/

View File

@ -1073,6 +1073,7 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData,
pNXScript self = (pNXScript)pData;
char *pFile = NULL;
int status;
char buffer[132];
/*
preliminary checks
@ -1136,6 +1137,20 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData,
return 1;
}
if(strcmp(argv[1],"isalias") == 0) {
if(argc < 3) {
SCWrite(pCon,"ERROR: need alias to test",eError);
return 1;
}
if(NXDget(self->dictHandle,argv[2],buffer,131) == NX_OK){
snprintf(buffer,131,"%s = 1", argv[2]);
} else {
snprintf(buffer,131,"%s = 0", argv[2]);
}
SCWrite(pCon,buffer,eValue);
return 1;
}
if(strcmp(argv[1],"makelink") == 0){
makeLink(pCon,pSics,self,argc,argv);
return 1;

4
ofac.c
View File

@ -119,6 +119,7 @@
#include "sicslist.h"
#include "cone.h"
#include "sicshipadaba.h"
#include "multicounter.h"
/*----------------------- Server options creation -------------------------*/
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
@ -328,6 +329,8 @@
InstallSinfox,NULL,NULL);
AddCommand(pInter,"MakeCone",
MakeCone,NULL,NULL);
AddCommand(pInter,"MakeMultiCounter",
MakeMultiCounter,NULL,NULL);
/*
install site specific commands
@ -396,6 +399,7 @@
RemoveCommand(pSics,"InstallProtocolHandler");
RemoveCommand(pSics,"InstallSinfox");
RemoveCommand(pSics,"MakeCone");
RemoveCommand(pSics,"MakeMultiCounter");
/*
remove site specific installation commands
*/

262
regresscter.c Normal file
View File

@ -0,0 +1,262 @@
/*--------------------------------------------------------------------------
This is a counter for use in automated regression tests.
copyright: see file COPYRIGHT
Mark Koennecke, September 2006
----------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <time.h>
#include "fortify.h"
#include <string.h>
#include "sics.h"
#include "countdriv.h"
/*---------------------------------- possible error types ------------------*/
#define NONE 0
#define STARTFAIL 1
#define STATUSFAIL 2
#define PAUSEFAIL 3
#define CONTFAIL 4
#define READFAIL 5
#define STATEIDLE 0
#define STATERUN 1
#define STATEPAU 2
/*--------------------------------------------------------------------------*/
typedef struct {
int errType;
int recover;
int state;
time_t endTime;
} RegressSt;
/*---------------------------------------------------------------------------*/
static int RegressGetStatus(struct __COUNTER *self, float *fControl){
RegressSt *pSim = NULL;
time_t tD, tDe;
int iRun;
assert(self);
pSim = (RegressSt *) self->pData;
assert(pSim);
if(pSim->errType == STATUSFAIL){
return HWFault;
}
if(time(NULL) > pSim->endTime){
pSim->state = STATEIDLE;
}
switch(pSim->state){
case STATEIDLE:
return HWIdle;
break;
case STATERUN:
return HWBusy;
break;
case STATEPAU:
return HWPause;
break;
}
assert(0);
return HWFault;
}
/*---------------------------------------------------------------------------*/
static int RegressStart(struct __COUNTER *self){
RegressSt *pSim = NULL;
time_t tD;
int iRun;
assert(self);
pSim = (RegressSt *) self->pData;
assert(pSim);
if(pSim->errType == STARTFAIL){
return HWFault;
}
pSim->state = STATERUN;
if(self->eMode == eTimer){
pSim->endTime = time(NULL) + (int)self->fPreset;
} else {
pSim->endTime = time(NULL) + 7;
}
return OKOK;
}
/*---------------------------------------------------------------------------*/
static int RegressPause(struct __COUNTER *self){
RegressSt *pSim = NULL;
time_t tD;
int iRun;
assert(self);
pSim = (RegressSt *) self->pData;
assert(pSim);
if(pSim->errType == PAUSEFAIL){
return HWFault;
}
pSim->state = STATEPAU;
return OKOK;
}
/*---------------------------------------------------------------------------*/
static int RegressContinue(struct __COUNTER *self){
RegressSt *pSim = NULL;
assert(self);
pSim = (RegressSt *) self->pData;
assert(pSim);
if(pSim->errType == CONTFAIL){
return HWFault;
}
pSim->state = STATERUN;
return OKOK;
}
/*--------------------------------------------------------------------------*/
static int RegressHalt(struct __COUNTER *self){
RegressSt *pSim = NULL;
assert(self);
pSim = (RegressSt *) self->pData;
assert(pSim);
pSim->state = STATEIDLE;
return OKOK;
}
/*-------------------------------------------------------------------------*/
static int RegressReadValues(struct __COUNTER *self){
RegressSt *pSim = NULL;
int i;
assert(self);
pSim = (RegressSt *) self->pData;
assert(pSim);
if(pSim->errType == READFAIL){
return HWFault;
}
for (i = 0; i < MAXCOUNT; i++) {
self->lCounts[i] = i*10+5;
}
self->lCounts[1] = self->fPreset;
self->fTime = self->fPreset;
return OKOK;
}
/*-------------------------------------------------------------------------*/
static int RegressGetError(struct __COUNTER *self, int *iCode, char *error,
int iErrLen){
strncpy(error, "Regression counter error", iErrLen);
*iCode = 1;
return 1;
}
/*--------------------------------------------------------------------------*/
static int RegressTryAndFixIt(struct __COUNTER *self, int iCode){
RegressSt *pSim = NULL;
assert(self);
pSim = (RegressSt *) self->pData;
assert(pSim);
if(pSim->recover == 1){
pSim->errType = NONE;
return COREDO;
} else {
return COTERM;
}
}
/*--------------------------------------------------------------------------*/
static int RegressSet(struct __COUNTER *self, char *name, int iCter, float FVal){
RegressSt *pSim = NULL;
assert(self);
pSim = (RegressSt *) self->pData;
assert(pSim);
if(strcmp(name,"errortype") == 0){
pSim->errType = (int)FVal;
return 1;
}
if(strcmp(name,"recover") == 0){
pSim->recover = (int)FVal;
return 1;
}
if(strcmp(name,"finish") == 0){
pSim->state = STATEIDLE;
return 1;
}
return 0;
}
/*--------------------------------------------------------------------------*/
static int RegressGet(struct __COUNTER *self, char *name,
int iCter, float *fVal){
RegressSt *pSim = NULL;
assert(self);
pSim = (RegressSt *) self->pData;
assert(pSim);
if(strcmp(name,"errortype") == 0){
*fVal = pSim->errType;
return 1;
}
if(strcmp(name,"recover") == 0){
*fVal = pSim->recover;
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------*/
static int RegressSend(struct __COUNTER *self, char *pText,
char *pReply, int iReplyLen){
strncpy(pReply, "Simulated response", iReplyLen);
return 1;
}
/*---------------------------------------------------------------------------*/
pCounterDriver NewRegressCounter(char *name){
pCounterDriver pRes = NULL;
RegressSt *pData = NULL;
int iRet;
int iC1, iC2, iC3;
char *pErr;
char pBueffel[132];
pRes = CreateCounterDriver(name, "Regress");
if (!pRes) {
return NULL;
}
pData = (RegressSt *) malloc(sizeof(RegressSt));
if (!pData) {
DeleteCounterDriver(pRes);
return NULL;
}
memset(pData,0,sizeof(RegressSt));
pRes->pData = pData;
/*
* assign functions
*/
pRes->GetStatus = RegressGetStatus;
pRes->Start = RegressStart;
pRes->Halt = RegressHalt;
pRes->ReadValues = RegressReadValues;
pRes->GetError = RegressGetError;
pRes->TryAndFixIt = RegressTryAndFixIt;
pRes->Pause = RegressPause;
pRes->Continue = RegressContinue;
pRes->Set = RegressSet;
pRes->Get = RegressGet;
pRes->Send = RegressSend;
pRes->KillPrivate = NULL;
pRes->iNoOfMonitors = 8;
return pRes;
}

33
scan.c
View File

@ -385,6 +385,7 @@ int AppendScanLine(pScanData self, char *line)
}
/*-------------------------------------------------------------------------*/
extern char *stptok(const char *s, char *t, int len, char *brk);
extern char *trim(char *txt);
int StoreScanCounts(pScanData self, char *data)
{
@ -402,7 +403,7 @@ int StoreScanCounts(pScanData self, char *data)
InitCountEntry(&sCount);
/* parse the data */
pPtr = data;
pPtr = trim(data);
pPtr = stptok(pPtr,pNumber,29," \t");
if(pPtr != NULL)
{
@ -1584,7 +1585,7 @@ static int PrintTimes(pScanData self, SConnection *pCon,
snprintf(pBueffel,59,"%s.scantimes = { ",name);
DynStringCopy(data,pBueffel);
for(i = 0; i < self->iNP; i++)
for(i = 0; i < self->iCounts; i++)
{
DynarGet(self->pCounts,i,&pPtr);
pData = (pCountEntry)pPtr;
@ -2127,12 +2128,17 @@ static int DumpScan(pScanData self, SConnection *pCon)
}
/*------------ functions */
else if(strcmp(argv[1],"function") == 0)
{
return InterpretScanFunctions(self, pCon, argc, argv);
{
return InterpretScanFunctions(self, pCon, argc, argv);
}
/*---------- scan */
else if(strcmp(argv[1],"run") == 0)
{
if (argc < 5) {
sprintf(pBueffel,"ERROR: not enough arguments for %s run",argv[0]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* get NP */
iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&lNP);
if(iRet != TCL_OK)
@ -2181,6 +2187,11 @@ static int DumpScan(pScanData self, SConnection *pCon)
/*---------- silent */
else if(strcmp(argv[1],"silent") == 0)
{
if (argc < 5) {
sprintf(pBueffel,"ERROR: not enough arguments for %s silent",argv[0]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* get NP */
iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&lNP);
if(iRet != TCL_OK)
@ -2404,6 +2415,20 @@ static int DumpScan(pScanData self, SConnection *pCon)
}
return AppendVarPos(pCon,self,i,(float)fStep);
}
else if(strcmp(argv[1],"softpos") == 0){
if(argc > 2) {
if(!SCMatchRights(pCon,usMugger)){
return 0;
}
self->posSoft = atoi(argv[2]);
SCSendOK(pCon);
return 1;
} else {
sprintf(pBueffel,"%s.softpos = %d", argv[0],self->posSoft);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
}
/*------- savecounter */
else if(strcmp(argv[1],"savecounter") == 0)
{

View File

@ -4,6 +4,8 @@
An attempt to a generic interface to SICS data for all sorts of SICS
clients.
WARNING: this code only works when ints and floats are of the same size!
copyright: see file COPYRIGHT
Mark Koennecke, June 2003
@ -60,6 +62,47 @@ pSICSData createSICSData(void){
pNew->dataUsed = 0;
return pNew;
}
/*---------------------------------------------------------------------------*/
int getSICSDataInt(pSICSData self, int pos, int *value){
if(pos >= self->dataUsed || self->dataType[pos] != INTTYPE){
return 0;
}
*value = self->data[pos];
return 1;
}
/*---------------------------------------------------------------------------*/
int getSICSDataFloat(pSICSData self, int pos, float *value){
if(pos >= self->dataUsed || self->dataType[pos] != FLOATTYPE){
return 0;
}
memcpy(value,&self->data[pos],sizeof(float));
return 1;
}
/*---------------------------------------------------------------------------*/
int setSICSDataInt(pSICSData self, int pos, int value){
int *idata = NULL;
idata = getSICSDataPointer(self,0,pos+1);
if(idata == NULL){
return 0;
}
idata[pos] = value;
self->dataType[pos] = INTTYPE;
return 1;
}
/*----------------------------------------------------------------------------*/
int setSICSDataFloat(pSICSData self, int pos, float value){
int *idata = NULL;
idata = getSICSDataPointer(self,0,pos+1);
if(idata == NULL){
return 0;
}
memcpy(&idata[pos],&value,sizeof(float));
self->dataType[pos] = FLOATTYPE;
return 1;
}
/*-------------------------------------------------------------------*/
int *getSICSDataPointer(pSICSData self, int start, int end){
int newSize;
@ -134,7 +177,7 @@ static void netEncode(pSICSData self){
}
}
/*---------------------------------------------------------------------*/
static void clearSICSData(pSICSData self){
void clearSICSData(pSICSData self){
assert(self);
self->dataUsed = 0;
@ -543,6 +586,35 @@ static int copyHM(pSICSData self, int argc, char *argv[],
SCSendOK(pCon);
return 1;
}
/*----------------------------------------------------------------------*/
static int copyData(pSICSData self,SicsInterp *pSics,
SConnection *pCon,int argc, char *argv[]){
pSICSData other = NULL;
int pos, start, end, i;
if(argc < 6){
SCWrite(pCon,"ERROR: Insufficient number of arguments to copydata",
eError);
return 0;
}
pos = atoi(argv[2]);
start = atoi(argv[4]);
end = atoi(argv[5]);
if((other = FindCommandData(pSics,argv[3],"SICSData")) == NULL){
SCWrite(pCon,"ERROR: invalid SICSData requested",eError);
return 0;
}
if(start > end || end > other->dataUsed){
SCWrite(pCon,"ERROR: invalid copy range specified",eError);
return 0;
}
getSICSDataPointer(self,pos, pos + (end -start));
memcpy(&self->data[pos],&other->data[start],(end-start)*sizeof(int));
memcpy(&self->dataType[pos],&other->dataType[start],
(end-start)*sizeof(char));
return 1;
}
/*----------------------------------------------------------------------
Look here in order to find out about commands understood
----------------------------------------------------------------------*/
@ -591,6 +663,8 @@ int SICSDataAction(SConnection *pCon, SicsInterp *pSics, void *pData,
return 0;
}
return divideSicsData(self,pSics,pCon,argv[2]);
} else if(strcmp(argv[1],"copydata") == 0){
return copyData(self,pSics,pCon,argc, argv);
} else if(strcmp(argv[1],"putint") == 0){
/*---------- putint */
return putInt(self,argc-2,&argv[2],pCon, pSics);

View File

@ -40,4 +40,11 @@
void *pData,
int argc, char *argv[]);
void clearSICSData(pSICSData self);
int getSICSDataInt(pSICSData self, int pos, int *value);
int getSICSDataFloat(pSICSData self, int pos, float *value);
int setSICSDataInt(pSICSData self, int pos, int value);
int setSICSDataFloat(pSICSData self, int pos, float value);
#endif

View File

@ -6,6 +6,8 @@ sources such as histogram memories or scans. Data assembled in this
way, for instance through scripts, can then be forwarded to clients
either in UUencoded form or as a zipped array.
WARNING: this code only works right when integers and floats are of the same size!
In a later stage this may be extended to support selected mathematical
operations as well. In another stage this may supersede the uuget and
zipget methods in the scan, histogram memory and specialized status
@ -48,6 +50,13 @@ This object exports the following functions:
int SICSDataAction(SConnection *pCon, SicsInterp *pSics,
void *pData,
int argc, char *argv[]);
void clearSICSData(pSICSData self);
int getSICSDataInt(pSICSData self, int pos, int *value);
int getSICSDataFloat(pSICSData self, int pos, float *value);
int setSICSDataInt(pSICSData self, int pos, int value);
int setSICSDataFloat(pSICSData self, int pos, float value);
@}
\begin{description}
\item[getSICSDataPointer] returns a pointer to the first element of

View File

@ -541,6 +541,12 @@ pHdb MakeSICSHdbPar(char *name, int priv, hdbValue v){
return result;
}
/*---------------------------------------------------------------------------*/
pHdb CreateSICSHdbPar(char *name, int priv, int dataType,
int length, void *data){
return MakeSICSHdbPar(name,priv,makeHdbData(dataType,
length,data));
}
/*----------------------------------------------------------------------------*/
pHdb MakeSICSHdbDriv(char *name, int priv, void *sicsObject, int dataType){
pHdb result = NULL;
@ -659,6 +665,12 @@ pHdb MakeSICSScriptPar(char *name, char *setScript, char *readScript,
return result;
}
/*-------------------------------------------------------------------------*/
pHdb CreateSICSScriptPar(char *name, char *setScript, char *readScript,
int dataType, int length, void *data){
return MakeSICSScriptPar(name,setScript,readScript,
makeHdbData(dataType, length,data));
}
/*--------------------------------------------------------------------------*/
static void removeNodeFromUpdateList(pHdb node){
pHdb current = NULL;
@ -774,14 +786,23 @@ int AddSICSHdbMemPar(pHdb node, char *name, int priv,
return 1;
}
/*==================== access suport functions ==============================*/
int SICSHdbGetFloat(pHdb parent, SConnection *pCon,
char *path, float *value){
hdbValue v;
int SICSHdbGetPar(void *obj, SConnection *pCon,
char *path, int dataType, void *data, int length){
pHdb par = NULL;
int status;
char buffer[256];
pDummy pDum;
par = GetHipadabaNode(parent,path);
pDum = (pDummy)obj;
if(pDum == NULL || pDum->pDescriptor->parNode == NULL){
if(pCon != NULL){
snprintf(buffer,255,"ERROR: parameter %s not found", path);
SCWrite(pCon,buffer,eError);
}
return SICSNOPAR;
}
par = GetHipadabaNode(pDum->pDescriptor->parNode,path);
if(par == NULL){
if(pCon != NULL){
snprintf(buffer,255,"ERROR: parameter %s not found", path);
@ -790,31 +811,31 @@ int SICSHdbGetFloat(pHdb parent, SConnection *pCon,
return SICSNOPAR;
}
status = GetHipadabaPar(par,&v,pCon);
status = GetHdbPar(par,dataType,data,length,pCon);
if(status < 0){
return status;
}
if(v.dataType == HIPFLOAT){
*value = (float)v.v.doubleValue;
} else if(v.dataType == HIPINT){
*value = (float)v.v.intValue;
} else {
/*
* it is an error to call this for array dada types
*/
assert(0);
}
return 1;
}
/*--------------------------------------------------------------------------*/
int SICSHdbSetFloat(pHdb parent, SConnection *pCon,
char *path, float value){
int SICSHdbUpdatePar(void *obj, SConnection *pCon,
char *path, int dataType,void *data, int dataLength ){
hdbValue v;
pHdb par = NULL;
int status;
char buffer[256];
pDummy pDum;
par = GetHipadabaNode(parent,path);
pDum = (pDummy)obj;
if(pDum == NULL || pDum->pDescriptor->parNode == NULL){
if(pCon != NULL){
snprintf(buffer,255,"ERROR: parameter %s not found", path);
SCWrite(pCon,buffer,eError);
}
return SICSNOPAR;
}
par = GetHipadabaNode(pDum->pDescriptor->parNode,path);
if(par == NULL){
if(pCon != NULL){
snprintf(buffer,255,"ERROR: parameter %s not found", path);
@ -823,25 +844,45 @@ int SICSHdbSetFloat(pHdb parent, SConnection *pCon,
return SICSNOPAR;
}
v.dataType = par->value.dataType;
if(v.dataType == HIPFLOAT){
v.v.doubleValue = (double)value;
} else if(v.dataType == HIPINT){
v.v.intValue = (int)value;
} else {
/*
* it is an error to call this for array dada types
*/
assert(0);
}
status = SetHipadabaPar(par,v,pCon);
status = UpdateHdbPar(par,dataType,data,dataLength,pCon);
if(status < 0){
return status;
}
return 1;
}
/*--------------------------------------------------------------------------*/
int SICSHdbSetPar(void *obj, SConnection *pCon,
char *path, int dataType,void *data, int dataLength ){
hdbValue v;
pHdb par = NULL;
int status;
char buffer[256];
pDummy pDum;
pDum = (pDummy)obj;
if(pDum == NULL || pDum->pDescriptor->parNode == NULL){
if(pCon != NULL){
snprintf(buffer,255,"ERROR: parameter %s not found", path);
SCWrite(pCon,buffer,eError);
}
return SICSNOPAR;
}
par = GetHipadabaNode(pDum->pDescriptor->parNode,path);
if(par == NULL){
if(pCon != NULL){
snprintf(buffer,255,"ERROR: parameter %s not found", path);
SCWrite(pCon,buffer,eError);
}
return SICSNOPAR;
}
status = SetHdbPar(par,dataType,data,dataLength,pCon);
if(status < 0){
return status;
}
return 1;
}
/*---------------------------------------------------------------------------*/
int InstallSICSNotify(pHdb node, SConnection *pCon, int id, int recurse){
pHdb currentChild = NULL;

View File

@ -117,6 +117,19 @@ pHdbCallback MakeMemSetCallback(float *address);
* @return A new suitably configured Hdb parameter or NULL when out of memory.
*/
pHdb MakeSICSHdbPar(char *name, int priv, hdbValue v);
/**
* make a simple SICS hdb parameter. Setting it will call update immediately. Use
* this for program parameters.
* @param name The name of the parameter
* @param priv The privilege required to change that parameter
* @param dataType The datatype for the new parameter.
* @param length The length of any arrays
* @param data Data to initalise the parameter with. Can be NULL, then
* no initialisation takes place.
* @return A new suitably configured Hdb parameter or NULL when out of memory.
*/
pHdb CreateSICSHdbPar(char *name, int priv, int dataType,
int length, void *data);
/**
* make a SICS hdb drivable parameter. Setting it will start the motor,
* virtual motor or environment parameter. This will call StartDevice
@ -153,6 +166,19 @@ pHdb MakeSICSROPar(char *name, hdbValue v);
* @return A new suitably configured Hdb parameter or NULL when out of memory.
*/
pHdb MakeSICSScriptPar(char *name, char *setScript, char *readScript, hdbValue v);
/**
* make a SICS scriptable parameter. I.e. when this parameter is set or read,
* appropriate scripts are invoked.
* @param name The name of the parameter
* @param dataType The datatype for the new parameter.
* @param length The length of any arrays
* @param data Data to initalise the parameter with. Can be NULL, then
* no initialisation takes place.
* @return A new suitably configured Hdb parameter or NULL when out of memory.
*/
pHdb CreateSICSScriptPar(char *name, char *setScript, char *readScript,
int dataType, int length, void *data);
/**
* remove a SICS paramameter node and its children. In contrast to the
* normal DeletHipadabaNode, this function also takes care of
@ -194,27 +220,41 @@ int AddSICSHdbMemPar(pHdb node, char *name, int priv,
void *data, int datalength, int type, int length);
/*============== access support functions =================================*/
/**
* SICSHdbGetFloat returns the float value of a parameter. Integers are
* automatically converted.
* @param parent The parent node where to start searching for the parameter
* SICSHdbGetPar returns the value of a parameter.
* @param obj The object for which to get a parameter.
* @param pCon The optional connection object to use for reporting errors.
* @param path The path to the parameter.
* @param value The value of the parameter
* @param dataType The datatype for the parameter.
* @param data Target pointer to which to copy data too.
* @param length The length of data
* @return 1 on success, a negative error code else.
*/
int SICSHdbGetFloat(pHdb parent, SConnection *pCon,
char *path, float *value);
int SICSHdbGetPar(void *obj, SConnection *pCon,
char *path, int dataType, void *data, int length);
/**
* SICSHdbSetFloat sets the value of a parameter. Integers are
* automatically converted.
* @param parent The parent node where to start searching for the parameter
* SICSHdbUpdatePar updates the value of a parameter.
* @param obj The object for which to get a parameter.
* @param pCon The optional connection object to use for reporting errors.
* @param path The path to the parameter.
* @param value The new value of the parameter
* @param dataType The datatype for the parameter.
* @param data Pointer from which to copy data.
* @param length The length of data
* @return 1 on success, a negative error code else.
*/
int SICSHdbSetFloat(pHdb parent, SConnection *pCon,
char *path, float value);
int SICSHdbUpdatePar(void *obj, SConnection *pCon,
char *path, int dataType, void *data, int length);
/**
* SICSHdbSetPar sets the value of a parameter.
* @param obj The object for which to get a parameter.
* @param pCon The optional connection object to use for reporting errors.
* @param path The path to the parameter.
* @param dataType The datatype for the parameter.
* @param data Pointer from which to copy data.
* @param length The length of data
* @return 1 on success, a negative error code else.
*/
int SICSHdbSetPar(void *obj, SConnection *pCon,
char *path, int dataType, void *data, int length);
/**
* query function if a parameter is read only.
* @param node The ndoe to query

View File

@ -34,6 +34,11 @@ static long TASSetValue(void *pData, SConnection *pCon,
ptasMot self = (ptasMot)pData;
assert(self);
if(self->code > 5 && self->math->tasMode == ELASTIC){
SCWrite(pCon,"ERROR: cannot drive this motor in elastic mode",
eError);
return HWFault;
}
setTasPar(&self->math->target,self->math->tasMode,self->code,value);
self->math->mustDrive = 1;
return OKOK;
@ -132,6 +137,10 @@ static float TASGetValue(void *pData, SConnection *pCon){
self->math->mustRecalculate = 0;
}
val = getTasPar(self->math->current,self->code);
if(self->code > 5 && self->math->tasMode == ELASTIC){
SCWrite(pCon,"WARNING: value for this motor is meaningless in elastic mode",
eWarning);
}
return (float)val;
}
/*-----------------------------------------------------------------*/
@ -202,6 +211,13 @@ static void writeMotPos(SConnection *pCon, int silent, char *name,
SCWrite(pCon,pBueffel,eWarning);
}
}
/*--------------------------------------------------------------------------*/
static float getMotorValue(pMotor mot, SConnection *pCon){
float val;
MotorGetSoftPosition(mot,pCon,&val);
return val;
}
/*---------------------------------------------------------------------------*/
static int startMotors(ptasMot self, tasAngles angles,
SConnection *pCon, int driveQ, int driveTilt){
@ -213,7 +229,7 @@ static int startMotors(ptasMot self, tasAngles angles,
/*
monochromator
*/
val = self->math->motors[A1]->pDrivInt->GetValue(self->math->motors[A1],pCon);
val = getMotorValue(self->math->motors[A1],pCon);
if(ABS(val - angles.monochromator_two_theta/2.) > MOTPREC){
status = self->math->motors[A1]->pDrivInt->SetValue(self->math->motors[A1],
pCon,
@ -224,7 +240,7 @@ static int startMotors(ptasMot self, tasAngles angles,
}
writeMotPos(pCon,silent,"a1",val, angles.monochromator_two_theta/2.);
val = self->math->motors[A2]->pDrivInt->GetValue(self->math->motors[A2],pCon);
val = getMotorValue(self->math->motors[A2],pCon);
if(ABS(val - angles.monochromator_two_theta) > MOTPREC){
status = self->math->motors[A2]->pDrivInt->SetValue(self->math->motors[A2],
pCon,
@ -238,7 +254,8 @@ static int startMotors(ptasMot self, tasAngles angles,
if(self->math->motors[MCV] != NULL){
curve = maCalcVerticalCurvature(self->math->machine.monochromator,
angles.monochromator_two_theta);
val = self->math->motors[MCV]->pDrivInt->GetValue(self->math->motors[MCV],pCon);
val = getMotorValue(self->math->motors[MCV],pCon);
if(ABS(val - curve) > MOTPREC){
status = self->math->motors[MCV]->pDrivInt->SetValue(self->math->motors[MCV],
pCon,
@ -253,7 +270,8 @@ static int startMotors(ptasMot self, tasAngles angles,
if(self->math->motors[MCH] != NULL){
curve = maCalcHorizontalCurvature(self->math->machine.monochromator,
angles.monochromator_two_theta);
val = self->math->motors[MCH]->pDrivInt->GetValue(self->math->motors[MCH],pCon);
val = getMotorValue(self->math->motors[MCH],pCon);
if(ABS(val - curve) > MOTPREC){
status = self->math->motors[MCH]->pDrivInt->SetValue(self->math->motors[MCH],
pCon,
@ -269,8 +287,7 @@ static int startMotors(ptasMot self, tasAngles angles,
analyzer
*/
if(self->math->tasMode != ELASTIC){
val = self->math->motors[A5]->pDrivInt->GetValue(self->math->motors[A5],
pCon);
val = getMotorValue(self->math->motors[A5],pCon);
if(ABS(val - angles.analyzer_two_theta/2.) > MOTPREC){
status = self->math->motors[A5]->pDrivInt->SetValue(self->math->motors[A5],
pCon,
@ -282,7 +299,7 @@ static int startMotors(ptasMot self, tasAngles angles,
writeMotPos(pCon,silent,self->math->motors[A5]->name,
val, angles.analyzer_two_theta/2.);
val = self->math->motors[A6]->pDrivInt->GetValue(self->math->motors[A6],pCon);
val = getMotorValue(self->math->motors[A6],pCon);
if(ABS(val - angles.analyzer_two_theta) > MOTPREC){
status = self->math->motors[A6]->pDrivInt->SetValue(self->math->motors[A6],
pCon,
@ -296,7 +313,7 @@ static int startMotors(ptasMot self, tasAngles angles,
if(self->math->motors[ACV] != NULL){
curve = maCalcVerticalCurvature(self->math->machine.analyzer,
angles.analyzer_two_theta);
val = self->math->motors[ACV]->pDrivInt->GetValue(self->math->motors[ACV],pCon);
val = getMotorValue(self->math->motors[ACV],pCon);
if(ABS(val - curve) > MOTPREC){
status = self->math->motors[ACV]->pDrivInt->SetValue(self->math->motors[ACV],
pCon,
@ -310,8 +327,7 @@ static int startMotors(ptasMot self, tasAngles angles,
if(self->math->motors[ACH] != NULL){
curve = maCalcHorizontalCurvature(self->math->machine.analyzer,
angles.analyzer_two_theta);
val = self->math->motors[ACH]->pDrivInt->GetValue(self->math->motors[ACH],
pCon);
val = getMotorValue(self->math->motors[ACH],pCon);
if(ABS(val - curve) > MOTPREC){
status = self->math->motors[ACH]->pDrivInt->SetValue(self->math->motors[ACH],
pCon,
@ -331,7 +347,7 @@ static int startMotors(ptasMot self, tasAngles angles,
/*
crystal
*/
val = self->math->motors[A3]->pDrivInt->GetValue(self->math->motors[A3],pCon);
val = getMotorValue(self->math->motors[A3],pCon);
if(ABS(val - angles.a3) > MOTPREC){
status = self->math->motors[A3]->pDrivInt->SetValue(self->math->motors[A3],
pCon,
@ -342,7 +358,7 @@ static int startMotors(ptasMot self, tasAngles angles,
}
writeMotPos(pCon,silent,"a3",val, angles.a3);
val = self->math->motors[A4]->pDrivInt->GetValue(self->math->motors[A4],pCon);
val = getMotorValue(self->math->motors[A4],pCon);
if(ABS(val - angles.sample_two_theta) > MOTPREC){
status = self->math->motors[A4]->pDrivInt->SetValue(self->math->motors[A4],
pCon,
@ -354,7 +370,7 @@ static int startMotors(ptasMot self, tasAngles angles,
writeMotPos(pCon,silent,"a4",val, angles.sample_two_theta);
if(driveTilt == 1){
val = self->math->motors[SGL]->pDrivInt->GetValue(self->math->motors[SGL],pCon);
val = getMotorValue(self->math->motors[SGL],pCon);
if(ABS(val - angles.sgl) > MOTPREC){
status = self->math->motors[SGL]->pDrivInt->SetValue(self->math->motors[SGL],
pCon,
@ -365,7 +381,7 @@ static int startMotors(ptasMot self, tasAngles angles,
}
writeMotPos(pCon,silent,"sgl",val, angles.sgl);
val = self->math->motors[SGU]->pDrivInt->GetValue(self->math->motors[SGU],pCon);
val = getMotorValue(self->math->motors[SGU],pCon);
if(ABS(val - angles.sgu) > MOTPREC){
status = self->math->motors[SGU]->pDrivInt->SetValue(self->math->motors[SGU],
pCon,

44
tasub.c
View File

@ -242,7 +242,7 @@ int TasUBFactory(SConnection *pCon,SicsInterp *pSics, void *pData,
return 0;
}
if(argc > 2 && argc < 14){
SCWrite(pCon,"ERROR: not enough motor names specified form MakeTasUB",eError);
SCWrite(pCon,"ERROR: not enough motor names specified for MakeTasUB",eError);
return 0;
}
pNew = MakeTasUB();
@ -414,7 +414,7 @@ static int getCrystalParameters(pmaCrystal crystal, SConnection *pCon,
SCWrite(pCon,pBueffel,eValue);
return 1;
}else if(strcmp(argv[2],"vb2") == 0){
snprintf(pBueffel,131,"%s.%s.vb2 = %f",argv[0],argv[1],crystal->VB1);
snprintf(pBueffel,131,"%s.%s.vb2 = %f",argv[0],argv[1],crystal->VB2);
SCWrite(pCon,pBueffel,eValue);
return 1;
}else if(strcmp(argv[2],"ss") == 0){
@ -952,6 +952,44 @@ static int calcUB(ptasUB self, SConnection *pCon, SicsInterp *pSics,
SCparChange(pCon);
return 1;
}
/*-----------------------------------------------------------------*/
static int calcUBFromCell(ptasUB self, SConnection *pCon){
MATRIX B, U, UB;
int status;
B = mat_creat(3,3,UNIT_MATRIX);
U = mat_creat(3,3,UNIT_MATRIX);
if(B == NULL || U == NULL){
SCWrite(pCon,"ERROR: out of memory in calcUBFromCell",eError);
return 0;
}
status = calculateBMatrix(self->cell,B);
if(status == REC_NO_VOLUME){
SCWrite(pCon,"ERROR: cell has no volume",eError);
return 0;
}
UB = mat_mul(U,B);
if(UB == NULL){
SCWrite(pCon,"ERROR: matrix multiplication failed",eError);
return 0;
}
if(mat_det(UB) < .000001){
SCWrite(pCon,"ERROR: invalid UB matrix, check reflections",eError);
return 0;
}
if(self->machine.UB != NULL){
mat_free(self->machine.UB);
}
self->machine.UB = UB;
self->machine.planeNormal[0][0] = .0;
self->machine.planeNormal[1][0] = .0;
self->machine.planeNormal[2][0] = 1.;
self->ubValid = 1;
SCparChange(pCon);
mat_free(U);
mat_free(B);
return 1;
}
/*------------------------------------------------------------------*/
static int calcRefAngles(ptasUB self, SConnection *pCon,
SicsInterp *pSics,
@ -1421,6 +1459,8 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
return 1;
} else if(strcmp(argv[1],"makeub") == 0){
return calcUB(self,pCon,pSics,argc,argv);
} else if(strcmp(argv[1],"makeubfromcell") == 0){
return calcUBFromCell(self,pCon);
} else if(strcmp(argv[1],"calcang") == 0){
return calcRefAngles(self,pCon,pSics,argc,argv);
} else if(strcmp(argv[1],"calcqe") == 0){