- First commit of the new UB based TAS calculation. A milestone has been

reached: it handles one test case correctly back and forth
- Fixed oscillation code
- Added a feature for switching off automatic updates in nxupdate
  Autoamtic updates cause problems when scanning...
This commit is contained in:
koennecke
2005-04-22 14:07:06 +00:00
parent 288c65e0bb
commit 6387994017
17 changed files with 1897 additions and 34 deletions

937
tasub.c Normal file
View File

@ -0,0 +1,937 @@
/*----------------------------------------------------------------------
SICS interface to the triple axis spectrometer calculation
module.
copyright: see file COPYRIGHT
Mark Koennecke, April-May 2005
----------------------------------------------------------------------*/
#include <assert.h>
#include "sics.h"
#include "lld.h"
#include "tasub.h"
/*------------------- motor indexes in motor data structure ---------*/
#define A1 0
#define A2 1
#define MCV 2
#define MCH 3
#define A3 4
#define A4 5
#define SGU 6
#define SGL 7
#define A5 8
#define A6 9
#define ACV 10
#define ACH 11
/*----------------- data structure management code -------------------*/
static void saveCrystal(char *objName, char *name, pmaCrystal crystal,
FILE *fd){
fprintf(fd,"%s %s dd %f\n",objName, name, crystal->dd);
fprintf(fd,"%s %s hb1 %f\n",objName, name, crystal->HB1);
fprintf(fd,"%s %s hb2 %f\n",objName, name, crystal->HB2);
fprintf(fd,"%s %s vb1 %f\n",objName, name, crystal->VB1);
fprintf(fd,"%s %s vb2 %f\n",objName, name, crystal->VB2);
fprintf(fd,"%s %s ss %d\n",objName, name, crystal->ss);
}
/*------------------------------------------------------------------*/
static void saveReflections(ptasUB self, char *name, FILE *fd){
tasReflection r;
int status;
status = LLDnodePtr2First(self->reflectionList);
fprintf(fd,"%s clear\n",name);
while(status == 1){
LLDnodeDataTo(self->reflectionList,&r);
fprintf(fd,"%s addref %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n",
name, r.h, r.k, r.l, r.a3, r.two_theta, r.sgu, r.sgl,
KtoEnergy(r.ki), KtoEnergy(r.kf));
status = LLDnodePtr2Next(self->reflectionList);
}
}
/*-------------------------------------------------------------------*/
static int tasUBSave(void *pData, char *name, FILE *fd){
ptasUB self = (ptasUB)pData;
if(self == NULL){
return 0;
}
fprintf(fd,"#---- tasUB module %s\n", name);
saveCrystal(name,"mono",&self->machine.monochromator,fd);
saveCrystal(name,"ana",&self->machine.analyzer,fd);
fprintf(fd,"%s cell %f %f %f %f %f %f\n", name, self->cell.a,
self->cell.b, self->cell.c, self->cell.alpha,
self->cell.beta, self->cell.gamma);
saveReflections(self,name,fd);
if(self->tasMode == KICONST){
fprintf(fd,"%s const ki\n",name);
} else {
fprintf(fd,"%s const kf\n",name);
}
fprintf(fd,"%s ss %d\n", name,self->machine.ss_sample);
return 1;
}
/*------------------------------------------------------------------*/
static void defaultMonochromator(pmaCrystal mono){
mono->dd = 3.35;
mono->ss = 1;
mono->HB1 = 1.;
mono->HB2 = 1.;
mono->VB1 = 1.;
mono->VB2 = 1.;
}
/*--------------------------------------------------------------------*/
static ptasUB MakeTasUB(){
ptasUB pNew = NULL;
pNew = (ptasUB)malloc(sizeof(tasUB));
if(pNew == NULL){
return NULL;
}
memset(pNew,0,sizeof(tasUB));
pNew->pDes = CreateDescriptor("TAS-UB");
pNew->machine.UB = mat_creat(3,3,UNIT_MATRIX);
pNew->machine.planeNormal = mat_creat(3,1,ZERO_MATRIX);
pNew->reflectionList = LLDcreate(sizeof(tasReflection));
if(!pNew->pDes || !pNew->machine.UB || pNew->reflectionList < 0 ||
pNew->machine.planeNormal == NULL){
free(pNew);
return NULL;
}
pNew->pDes->SaveStatus = tasUBSave;
pNew->machine.ss_sample = 1;
defaultMonochromator(&pNew->machine.monochromator);
defaultMonochromator(&pNew->machine.analyzer);
defaultCell(&pNew->cell);
pNew->tasMode = KICONST;
pNew->targetEn = .0;
pNew->actualEn = .0;
pNew->mustRecalculate = 1;
return pNew;
}
/*-------------------------------------------------------------------*/
static void KillTasUB(void *pData){
ptasUB self = (ptasUB)pData;
if(self == NULL){
return;
}
LLDdelete(self->reflectionList);
if(self->pDes != NULL){
DeleteDescriptor(self->pDes);
}
if(self->machine.UB != NULL){
mat_free(self->machine.UB);
}
if(self->machine.planeNormal != NULL){
mat_free(self->machine.planeNormal);
}
free(self);
}
/*===================== computation section =========================*/
static int readTASAngles(ptasUB self, SConnection *pCon,
ptasAngles ang){
int status;
float val;
/*
Monochromator
*/
status = MotorGetSoftPosition(self->motors[A1],pCon,&val);
if(status == 0){
return status;
}
ang->monochromator.theta = val;
status = MotorGetSoftPosition(self->motors[A2],pCon,&val);
if(status == 0){
return status;
}
ang->monochromator.two_theta = val;
if(self->motors[MCV] != NULL){
status = MotorGetSoftPosition(self->motors[MCV],pCon,&val);
if(status == 0){
return status;
}
ang->monochromator.vertical_curvature = val;
}
if(self->motors[MCH] != NULL){
status = MotorGetSoftPosition(self->motors[MCH],pCon,&val);
if(status == 0){
return status;
}
ang->monochromator.horizontal_curvature = val;
}
/*
Analyzer
*/
status = MotorGetSoftPosition(self->motors[A5],pCon,&val);
if(status == 0){
return status;
}
ang->analyzer.theta = val;
status = MotorGetSoftPosition(self->motors[A6],pCon,&val);
if(status == 0){
return status;
}
ang->analyzer.two_theta = val;
if(self->motors[ACV] != NULL){
status = MotorGetSoftPosition(self->motors[ACV],pCon,&val);
if(status == 0){
return status;
}
ang->analyzer.vertical_curvature = val;
}
if(self->motors[ACH] != NULL){
status = MotorGetSoftPosition(self->motors[ACH],pCon,&val);
if(status == 0){
return status;
}
ang->analyzer.horizontal_curvature = val;
}
/*
crystal
*/
status = MotorGetSoftPosition(self->motors[A3],pCon,&val);
if(status == 0){
return status;
}
ang->a3 = val;
status = MotorGetSoftPosition(self->motors[A4],pCon,&val);
if(status == 0){
return status;
}
ang->sample_two_theta = val;
status = MotorGetSoftPosition(self->motors[SGU],pCon,&val);
if(status == 0){
return status;
}
ang->sgu = val;
status = MotorGetSoftPosition(self->motors[SGL],pCon,&val);
if(status == 0){
return status;
}
ang->sgl = val;
return 1;
}
/*==================== interpreter interface section =================*/
static int testMotor(ptasUB pNew, SConnection *pCon, char *name, int idx){
char pBueffel[132];
if(pNew->motors[idx] == NULL){
snprintf(pBueffel,131,"ERROR: required motor %s NOT found",name);
SCWrite(pCon,pBueffel,eError);
return 0;
} else {
return 1;
}
}
/*--------------------------------------------------------------------*/
int TasUBFactory(SConnection *pCon,SicsInterp *pSics, void *pData,
int argc, char *argv[]){
ptasUB pNew = NULL;
int status = 0;
if(argc < 2) {
SCWrite(pCon,"ERROR: need name to install tasUB",eError);
return 0;
}
pNew = MakeTasUB();
if(pNew == NULL){
SCWrite(pCon,"ERROR: out of memory creating tasUB",eError);
return 0;
}
/*
assign motors
*/
pNew->motors[0] = FindMotor(pSics,"a1");
pNew->motors[1] = FindMotor(pSics,"a2");
pNew->motors[2] = FindMotor(pSics,"mcv");
pNew->motors[3] = FindMotor(pSics,"mch");
pNew->motors[4] = FindMotor(pSics,"a3");
pNew->motors[5] = FindMotor(pSics,"a4");
pNew->motors[6] = FindMotor(pSics,"sgu");
pNew->motors[7] = FindMotor(pSics,"sgl");
pNew->motors[8] = FindMotor(pSics,"a5");
pNew->motors[9] = FindMotor(pSics,"a6");
pNew->motors[10] = FindMotor(pSics,"acv");
pNew->motors[11] = FindMotor(pSics,"ach");
/*
curvature motors may be missing, anything else is a serious problem
*/
status += testMotor(pNew, pCon,"a1",A1);
status += testMotor(pNew, pCon,"a2",A2);
status += testMotor(pNew, pCon,"a3",A3);
status += testMotor(pNew, pCon,"a4",A4);
status += testMotor(pNew, pCon,"sgu",SGU);
status += testMotor(pNew, pCon,"sgl",SGL);
status += testMotor(pNew, pCon,"a5",A5);
status += testMotor(pNew, pCon,"a6",A6);
if(status != 8){
return 0;
}
status = AddCommand(pSics,argv[1],
TasUBWrapper,
KillTasUB,
pNew);
if(status != 1){
SCWrite(pCon,"ERROR: duplicate tasUB command not created",eError);
return 0;
}
/*
TODO: install all the virtual motors
*/
return 1;
}
/*-----------------------------------------------------------------*/
static int setCrystalParameters(pmaCrystal crystal, SConnection *pCon,
int argc, char *argv[]){
int status;
double d;
char pBueffel[132];
status = Tcl_GetDouble(InterpGetTcl(pServ->pSics),argv[3],&d);
if(status != TCL_OK){
snprintf(pBueffel,131,"ERROR: failed to convert %s to number",
argv[3]);
SCWrite(pCon,pBueffel,eError);
return 1;
}
strtolower(argv[2]);
if(strcmp(argv[2],"dd") == 0){
crystal->dd = d;
SCSendOK(pCon);
SCparChange(pCon);
return 1;
}else if(strcmp(argv[2],"ss") == 0){
if(d > .0){
crystal->ss = 1;
} else {
crystal->ss = -1;
}
SCSendOK(pCon);
SCparChange(pCon);
return 1;
}else if(strcmp(argv[2],"hb1") == 0){
crystal->HB1 = d;
SCSendOK(pCon);
SCparChange(pCon);
return 1;
}else if(strcmp(argv[2],"hb2") == 0){
crystal->HB2 = d;
SCSendOK(pCon);
SCparChange(pCon);
return 1;
}else if(strcmp(argv[2],"vb1") == 0){
crystal->VB1 = d;
SCSendOK(pCon);
SCparChange(pCon);
return 1;
}else if(strcmp(argv[2],"vb2") == 0){
crystal->VB2 = d;
SCSendOK(pCon);
SCparChange(pCon);
return 1;
} else {
snprintf(pBueffel,131,"ERROR: crystal parameter %s not known",
argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
}
/*-----------------------------------------------------------------*/
static int getCrystalParameters(pmaCrystal crystal, SConnection *pCon,
int argc, char *argv[]){
char pBueffel[132];
strtolower(argv[2]);
if(strcmp(argv[2],"dd") == 0){
snprintf(pBueffel,131,"%s.%s.dd = %f",argv[0],argv[1],crystal->dd);
SCWrite(pCon,pBueffel,eValue);
return 1;
}else if(strcmp(argv[2],"hb1") == 0){
snprintf(pBueffel,131,"%s.%s.hb1 = %f",argv[0],argv[1],crystal->HB1);
SCWrite(pCon,pBueffel,eValue);
return 1;
}else if(strcmp(argv[2],"hb2") == 0){
snprintf(pBueffel,131,"%s.%s.hb2 = %f",argv[0],argv[1],crystal->HB2);
SCWrite(pCon,pBueffel,eValue);
return 1;
}else if(strcmp(argv[2],"vb1") == 0){
snprintf(pBueffel,131,"%s.%s.vb1 = %f",argv[0],argv[1],crystal->VB1);
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);
SCWrite(pCon,pBueffel,eValue);
return 1;
}else if(strcmp(argv[2],"ss") == 0){
snprintf(pBueffel,131,"%s.%s.ss = %d",argv[0],argv[1],crystal->ss);
SCWrite(pCon,pBueffel,eValue);
return 1;
}else {
snprintf(pBueffel,131,"ERROR: crystal parameter %s not known",
argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
}
/*------------------------------------------------------------------*/
static int handleCrystalCommands(pmaCrystal crystal, SConnection *pCon,
int argc, char *argv[]){
char pBueffel[132];
if(argc < 3){
snprintf(pBueffel,131,"ERROR: insufficent number of arguments to %s %s",
argv[0],argv[1]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
if(argc > 3) {
return setCrystalParameters(crystal,pCon,argc,argv);
} else {
return getCrystalParameters(crystal,pCon,argc,argv);
}
}
/*---------------------------------------------------------------------*/
static int tasReadCell(SConnection *pCon, ptasUB self, int argc, char *argv[]){
int status;
Tcl_Interp *pTcl = InterpGetTcl(pServ->pSics);
char pBueffel[256];
if(argc < 8){
SCWrite(pCon,"ERROR: insufficient number of arguments to tasub cell",
eError);
return 0;
}
status = Tcl_GetDouble(pTcl,argv[2],&self->cell.a);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(pTcl,argv[3],&self->cell.b);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(pTcl,argv[4],&self->cell.c);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[4]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(pTcl,argv[5],&self->cell.alpha);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[5]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(pTcl,argv[6],&self->cell.beta);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[6]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(pTcl,argv[7],&self->cell.gamma);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[7]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
SCparChange(pCon);
SCSendOK(pCon);
return 1;
}
/*---------------------------------------------------------------------*/
static void tasListCell(SConnection *pCon, char *name, lattice direct){
char pBueffel[255];
snprintf(pBueffel,255,"%s.cell = %f %f %f %f %f %f",
name,direct.a, direct.b,direct.c,
direct.alpha,direct.beta,direct.gamma);
SCWrite(pCon,pBueffel,eValue);
}
/*--------------------------------------------------------------------*/
static void clearReflections(ptasUB self){
int status;
status = LLDnodePtr2First(self->reflectionList);
while(status != 0){
LLDnodeDelete(self->reflectionList);
status = LLDnodePtr2Next(self->reflectionList);
}
}
/*------------------------------------------------------------------*/
static void listReflections(ptasUB self, SConnection *pCon){
tasReflection r;
int status;
int count = 0;
char line[256];
Tcl_DString list;
Tcl_DStringInit(&list);
snprintf(line,255,
" NO QH QK QL A3 A4 SGU SGL KI KF\n");
Tcl_DStringAppend(&list,line,-1);
status = LLDnodePtr2First(self->reflectionList);
while(status == 1){
count++;
LLDnodeDataTo(self->reflectionList,&r);
snprintf(line,255,"%3d %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
count, r.h, r.k, r.l, r.a3, r.two_theta, r.sgu, r.sgl, r.ki, r.kf);
Tcl_DStringAppend(&list,line,-1);
status = LLDnodePtr2Next(self->reflectionList);
}
if(count == 0){
SCWrite(pCon,"Reflection list is empty",eValue);
} else {
SCWrite(pCon,Tcl_DStringValue(&list),eValue);
}
Tcl_DStringFree(&list);
}
/*-------------------------------------------------------------------*/
static int addReflection(ptasUB self, SicsInterp *pSics,
SConnection *pCon,
int argc, char *argv[]){
tasReflection r;
int status;
char pBueffel[256];
tasAngles angles;
Tcl_DString list;
if(argc < 5){
SCWrite(pCon,"ERROR: need at least miller indices to add reflection",
eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[2],&r.h);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&r.k);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&r.l);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[4]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
if(argc >= 11){
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[5],&r.a3);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[5]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[5],&r.a3);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[5]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[6],&r.two_theta);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[6]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[7],&r.sgu);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[7]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[8],&r.sgl);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[8]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[9],&r.ki);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[9]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
r.ki = energyToK(r.ki);
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[10],&r.kf);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[10]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
r.kf = energyToK(r.kf);
} else {
if(argc > 5){
SCWrite(pCon,
"WARNING: not all angles given on command line, using positions instead",
eWarning);
}
status = readTASAngles(self,pCon,&angles);
if(status != 1){
return status;
}
r.a3 = angles.a3;
r.two_theta = angles.sample_two_theta;
r.sgu = angles.sgu;
r.sgl = angles.sgl;
maCalcK(self->machine.monochromator,angles.monochromator,&r.ki);
maCalcK(self->machine.analyzer,angles.analyzer,&r.kf);
}
LLDnodeAppend(self->reflectionList,&r);
Tcl_DStringInit(&list);
snprintf(pBueffel,255,
" QH QK QL A3 A4 SGU SGL KI KF\n");
Tcl_DStringAppend(&list,pBueffel,-1);
snprintf(pBueffel,255,
" %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
r.h, r.k, r.l, r.a3, r.two_theta, r.sgu, r.sgl, r.ki, r.kf);
Tcl_DStringAppend(&list,pBueffel,-1);
SCWrite(pCon,Tcl_DStringValue(&list),eValue);
Tcl_DStringFree(&list);
return 1;
}
/*-----------------------------------------------------------------*/
static int findReflection(int list, int idx, ptasReflection r){
int count = 0;
int status;
status = LLDnodePtr2First(list);
while(status == 1){
if(count == idx){
LLDnodeDataTo(list,r);
return 1;
}
status = LLDnodePtr2Next(list);
count++;
}
return 0;
}
/*------------------------------------------------------------------*/
static void listUB(MATRIX UB, SConnection *pCon){
Tcl_DString list;
char pBueffel[255];
int i;
Tcl_DStringInit(&list);
if(UB == NULL){
Tcl_DStringAppend(&list,"NO UB",-1);
} else {
Tcl_DStringAppend(&list,"UB = ", -1);
snprintf(pBueffel,255,"%f %f %f\n", UB[0][0],
UB[0][1],UB[0][2]);
Tcl_DStringAppend(&list,pBueffel,-1);
for(i = 1; i < 3; i++){
snprintf(pBueffel,255," %f %f %f\n", UB[i][0],
UB[i][1],UB[i][2]);
Tcl_DStringAppend(&list,pBueffel,-1);
}
}
SCWrite(pCon,Tcl_DStringValue(&list),eValue);
Tcl_DStringFree(&list);
}
/*-----------------------------------------------------------------*/
static void printReflectionDiagnostik(ptasUB self, SConnection *pCon,
tasReflection r){
tasReflection r2;
Tcl_DString list;
char line[256];
tasQEPosition qe;
tasAngles angles;
Tcl_DStringInit(&list);
snprintf(line,255,
"METHOD QH QK QL A3 A4 SGU SGL KI KF\n");
Tcl_DStringAppend(&list,line,-1);
snprintf(line,255,
"INPUT %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
r.h, r.k, r.l, r.a3, r.two_theta, r.sgu, r.sgl, r.ki, r.kf);
Tcl_DStringAppend(&list,line,-1);
qe.ki = r.ki;
qe.kf = r.kf;
qe.qk = r.h;
qe.qk = r.k;
qe.ql = r.l;
calcAllTasAngles(&self->machine,qe,&angles);
snprintf(line,255,
"QE->ANG %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
r.h, r.k, r.l, angles.a3, angles.sample_two_theta,
angles.sgu, angles.sgl, r.ki, r.kf);
Tcl_DStringAppend(&list,line,-1);
angles.a3 = r.a3;
angles.sample_two_theta = r.two_theta;
angles.sgu = r.sgu;
angles.sgl = r.sgl;
calcTasQEPosition(&self->machine,angles,&qe);
snprintf(line,255,
"ANG->QE %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
qe.qh, qe.qk, qe.ql, r.a3, r.two_theta,
r.sgu, r.sgl, qe.ki, qe.kf);
Tcl_DStringAppend(&list,line,-1);
SCWrite(pCon,Tcl_DStringValue(&list),eValue);
Tcl_DStringFree(&list);
}
/*------------------------------------------------------------------*/
static void listDiagnostik(ptasUB self, SConnection *pCon){
tasReflection r;
int status;
status = LLDnodePtr2First(self->reflectionList);
while(status == 1){
LLDnodeDataTo(self->reflectionList,&r);
printReflectionDiagnostik(self,pCon,r);
status = LLDnodePtr2Next(self->reflectionList);
}
}
/*------------------------------------------------------------------*/
static int calcUB(ptasUB self, SConnection *pCon, SicsInterp *pSics,
int argc, char *argv[]){
int idx, status;
tasReflection r1, r2;
char pBueffel[256];
MATRIX UB = NULL;
if(argc < 4){
SCWrite(pCon,
"ERROR: not enough arguments for UB calculation, need index of two reflections",
eError);
return 0;
}
status = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&idx);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = findReflection(self->reflectionList, idx-1,&r1);
if(status != 1){
snprintf(pBueffel,255,"ERROR: cannot find reflection with index %d",idx);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetInt(InterpGetTcl(pSics),argv[3],&idx);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = findReflection(self->reflectionList, idx-1,&r2);
if(status != 1){
snprintf(pBueffel,255,"ERROR: cannot find reflection with index %d",idx);
SCWrite(pCon,pBueffel,eError);
return 0;
}
UB = calcTasUBFromTwoReflections(self->cell,r1,r2,&status);
if(UB == NULL){
switch(status){
case UBNOMEMORY:
SCWrite(pCon,"ERROR: out of memory calculating UB matrix",eError);
break;
case REC_NO_VOLUME:
SCWrite(pCon,"ERROR: bad cell constants, no volume",eError);
break;
}
return 0;
}
if(self->machine.UB != NULL){
mat_free(self->machine.UB);
}
if(self->machine.planeNormal != NULL){
mat_free(self->machine.planeNormal);
}
self->machine.UB = UB;
self->machine.planeNormal = calcPlaneNormal(r1,r2);
listUB(UB,pCon);
listDiagnostik(self,pCon);
return 1;
}
/*------------------------------------------------------------------*/
static int calcRefAngles(ptasUB self, SConnection *pCon,
SicsInterp *pSics,
int argc, char *argv[]){
tasQEPosition q;
tasAngles angles;
char pBueffel[256];
int status;
if(argc < 7){
SCWrite(pCon,"ERROR: need Qh, Qk, Ql, EI, EF for calculation",
eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[2],&q.qh);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&q.qk);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&q.ql);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[4]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[5],&q.ki);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[5]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[6],&q.kf);
if(status != TCL_OK){
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[6]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
q.ki = energyToK(q.ki);
q.kf = energyToK(q.kf);
status = calcAllTasAngles(&self->machine,q,&angles);
switch(status){
case ENERGYTOBIG:
SCWrite(pCon,"ERROR: energy to big",eError);
return 0;
break;
case UBNOMEMORY:
SCWrite(pCon,"ERROR: Out of memory calculating angles",eError);
return 0;
break;
case TRIANGLENOTCLOSED:
SCWrite(pCon,"ERROR: scattering triangle not closed",eError);
return 0;
break;
}
snprintf(pBueffel,255," %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f",
angles.monochromator.theta, angles.monochromator.two_theta,
angles.a3, angles.sample_two_theta,
angles.sgl, angles.sgu,
angles.analyzer.theta,angles.analyzer.two_theta);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
/*-------------------------------------------------------------------*/
int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
int argc, char *argv[]){
ptasUB self = NULL;
char pBueffel[131];
int status, newSS;
self = (ptasUB)pData;
assert(self != NULL);
if(argc < 2){
SCWrite(pCon,"ERROR: insufficient arguments to tasUB",eError);
return 0;
}
strtolower(argv[1]);
if(strcmp(argv[1],"mono") == 0){
return handleCrystalCommands(&self->machine.monochromator,pCon,argc,argv);
} else if(strcmp(argv[1],"ana") == 0){
return handleCrystalCommands(&self->machine.analyzer,pCon,argc,argv);
}else if(strcmp(argv[1],"cell") == 0){
if(argc > 2){
return tasReadCell(pCon,self,argc,argv);
} else {
tasListCell(pCon,argv[0],self->cell);
return 1;
}
} else if(strcmp(argv[1],"clear") == 0){
clearReflections(self);
clearReflections(self);
SCSendOK(pCon);
return 1;
} else if(strcmp(argv[1],"listref") == 0){
listReflections(self,pCon);
return 1;
} else if(strcmp(argv[1],"addref") == 0){
return addReflection(self,pSics,pCon,argc,argv);
} else if(strcmp(argv[1],"listub") == 0){
listUB(self->machine.UB,pCon);
return 1;
} else if(strcmp(argv[1],"makeub") == 0){
return calcUB(self,pCon,pSics,argc,argv);
} else if(strcmp(argv[1],"calcref") == 0){
return calcRefAngles(self,pCon,pSics,argc,argv);
} else if(strcmp(argv[1],"const") == 0){
if(argc > 2){
strtolower(argv[2]);
if(!SCMatchRights(pCon,usUser)){
return 0;
}
if(strcmp(argv[2],"ki") == 0){
self->tasMode = KICONST;
} else if(strcmp(argv[2],"kf") == 0){
self->tasMode = KFCONST;
} else {
SCWrite(pCon,"ERROR: unknown triple axis mode, accepted are ki, kf",eError);
return 0;
}
SCSendOK(pCon);
return 1;
} else {
if(self->tasMode == KICONST){
snprintf(pBueffel,131,"%s.const = ki",argv[0]);
} else {
snprintf(pBueffel,131,"%s.const = kf",argv[0]);
}
SCWrite(pCon,pBueffel,eValue);
return 1;
}
} else if(strcmp(argv[1],"ss") == 0){
if(argc > 2){
strtolower(argv[2]);
if(!SCMatchRights(pCon,usUser)){
return 0;
}
status = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&newSS);
if(status != TCL_OK){
SCWrite(pCon,"ERROR: failed to convert argument to number",eError);
return 0;
}
if(newSS != 1 && newSS != -1){
SCWrite(pCon,"ERROR: invalid value for scattering sense, only 1, -1 allowed",
eError);
return 0;
}
self->machine.ss_sample = newSS;
SCSendOK(pCon);
return 1;
} else {
snprintf(pBueffel,131,"%s.ss = %d",argv[0],self->machine.ss_sample);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
} else {
snprintf(pBueffel,131,"ERROR: subcommand %s to %s not defined",argv[1],
argv[0]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
return 1;
}