
This is our new RELEASE-4_0 branch which was taken from ansto/93d9a7c Conflicts: .gitignore SICSmain.c asynnet.c confvirtualmot.c counter.c devexec.c drive.c event.h exebuf.c exeman.c histmem.c interface.h motor.c motorlist.c motorsec.c multicounter.c napi.c napi.h napi4.c network.c nwatch.c nxscript.c nxxml.c nxxml.h ofac.c reflist.c scan.c sicshipadaba.c sicsobj.c site_ansto/docs/Copyright.txt site_ansto/instrument/lyrebird/config/tasmad/sicscommon/nxsupport.tcl site_ansto/instrument/lyrebird/config/tasmad/taspub_sics/tasscript.tcl statusfile.c tasdrive.c tasub.c tasub.h tasublib.c tasublib.h
2173 lines
64 KiB
C
2173 lines
64 KiB
C
/*----------------------------------------------------------------------
|
|
SICS interface to the triple axis spectrometer calculation
|
|
module.
|
|
|
|
copyright: see file COPYRIGHT
|
|
|
|
Mark Koennecke, April-May 2005
|
|
|
|
Reworked to support an updater script for Integration into Hipadaba
|
|
|
|
Mark Koennecke, July 2009
|
|
|
|
Modified to use drivables rather then motors
|
|
|
|
Mark Koennecke, September 2011
|
|
----------------------------------------------------------------------*/
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include "sics.h"
|
|
#include "lld.h"
|
|
#include "SCinter.h"
|
|
#include "trigd.h"
|
|
#include "tasub.h"
|
|
#include "tasdrive.h"
|
|
#include "vector.h"
|
|
#include "tasmono.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 invokeUpdate(ptasUB self, SConnection *pCon, char *key)
|
|
{
|
|
char buffer[1024];
|
|
|
|
if(self->updater != NULL){
|
|
snprintf(buffer,1024,"%s %s", self->updater, key);
|
|
InterpExecute(pServ->pSics,pCon,buffer);
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------*/
|
|
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.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3,
|
|
r.angles.sample_two_theta, r.angles.sgu, r.angles.sgl,
|
|
KtoEnergy(r.qe.ki), KtoEnergy(r.qe.kf));
|
|
status = LLDnodePtr2Next(self->reflectionList);
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
static int tasUBSave(void *pData, char *name, FILE * fd)
|
|
{
|
|
ptasUB self = (ptasUB) pData;
|
|
tasReflection r;
|
|
|
|
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);
|
|
fprintf(fd, "%s outofplane %d\n", name, self->outOfPlaneAllowed);
|
|
if (self->tasMode == KICONST) {
|
|
fprintf(fd, "%s const ki\n", name);
|
|
} else if (self->tasMode == ELASTIC) {
|
|
fprintf(fd, "%s const elastic\n", name);
|
|
} else {
|
|
fprintf(fd, "%s const kf\n", name);
|
|
}
|
|
fprintf(fd, "%s ss %d\n", name, self->machine.ss_sample);
|
|
fprintf(fd, " %s setub %f %f %f %f %f %f %f %f %f\n",
|
|
name,
|
|
self->machine.UB[0][0], self->machine.UB[0][1],
|
|
self->machine.UB[0][2], self->machine.UB[1][0],
|
|
self->machine.UB[1][1], self->machine.UB[1][2],
|
|
self->machine.UB[2][0], self->machine.UB[2][1],
|
|
self->machine.UB[2][2]);
|
|
fprintf(fd, " %s setnormal %f %f %f\n", name,
|
|
self->machine.planeNormal[0][0], self->machine.planeNormal[1][0],
|
|
self->machine.planeNormal[2][0]);
|
|
fprintf(fd, "%s settarget %f %f %f %f %f %f\n", name, self->target.qh,
|
|
self->target.qk, self->target.ql, self->target.qm,
|
|
self->target.ki, self->target.kf);
|
|
r = self->r1;
|
|
fprintf(fd,
|
|
"%s r1 %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n",
|
|
name, r.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3,
|
|
r.angles.sample_two_theta, r.angles.sgu, r.angles.sgl,
|
|
KtoEnergy(r.qe.ki), KtoEnergy(r.qe.kf));
|
|
r = self->r2;
|
|
fprintf(fd,
|
|
"%s r2 %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n",
|
|
name, r.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3,
|
|
r.angles.sample_two_theta, r.angles.sgu, r.angles.sgl,
|
|
KtoEnergy(r.qe.ki), KtoEnergy(r.qe.kf));
|
|
fprintf(fd, "%s update\n", name);
|
|
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->machine.planeNormal[2][0] = 1.;
|
|
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->outOfPlaneAllowed = 1;
|
|
pNew->mustRecalculate = 1;
|
|
pNew->mono = MakeTasMono();
|
|
pNew->monoData = pNew;
|
|
|
|
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);
|
|
}
|
|
if(self->updater != NULL){
|
|
free(self->updater);
|
|
}
|
|
if(self->mono != NULL){
|
|
free(self->mono);
|
|
}
|
|
free(self);
|
|
}
|
|
|
|
/*==================== 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;
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
static void updateTargets(ptasUB pNew, SConnection * pCon)
|
|
{
|
|
tasAngles ang;
|
|
|
|
readTASMotAngles(pNew, pCon, &ang);
|
|
calcTasQEPosition(&pNew->machine, ang, &pNew->target);
|
|
}
|
|
/*--------------------------------------------------------------------*/
|
|
static pMotor TasFindMotor(SicsInterp *pSics, char *name)
|
|
{
|
|
pMotor mot = NULL;
|
|
CommandList *pCom = NULL;
|
|
|
|
mot = FindMotor(pSics,name);
|
|
if(mot == NULL){
|
|
pCom = FindCommand(pSics,name);
|
|
if(pCom != NULL && GetDrivableInterface(pCom->pData) != NULL){
|
|
mot = (pMotor)pCom->pData;
|
|
}
|
|
}
|
|
return mot;
|
|
}
|
|
/*--------------------------------------------------------------------*/
|
|
int TasUBFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
ptasUB pNew = NULL;
|
|
int status = 0, i;
|
|
char pBueffel[132];
|
|
char names[][3] = { "ei", "ki",
|
|
"qh", "qk", "ql",
|
|
"ef", "kf",
|
|
"en"
|
|
};
|
|
char *defltMot[] = {"a1", "a2", "mcv", "mch", "a3", "a4", "sgu", "sgl", "a5", "a6", "acv", "ach"};
|
|
|
|
if (argc < 2) {
|
|
SCWrite(pCon, "ERROR: need name to install tasUB", eError);
|
|
return 0;
|
|
}
|
|
if (argc > 2 && argc < 14) {
|
|
SCWrite(pCon, "ERROR: not enough motor names specified for MakeTasUB",
|
|
eError);
|
|
return 0;
|
|
}
|
|
pNew = MakeTasUB();
|
|
if (pNew == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory creating tasUB", eError);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
assign motors
|
|
*/
|
|
if (argc < 14) {
|
|
/*
|
|
* default names and assignement
|
|
*/
|
|
pNew->motors[0] = TasFindMotor(pSics, "a1");
|
|
pNew->motors[1] = TasFindMotor(pSics, "a2");
|
|
pNew->motors[2] = TasFindMotor(pSics, "mcv");
|
|
pNew->motors[3] = TasFindMotor(pSics, "mch");
|
|
pNew->motors[4] = TasFindMotor(pSics, "a3");
|
|
pNew->motors[5] = TasFindMotor(pSics, "a4");
|
|
pNew->motors[6] = TasFindMotor(pSics, "sgu");
|
|
pNew->motors[7] = TasFindMotor(pSics, "sgl");
|
|
pNew->motors[8] = TasFindMotor(pSics, "a5");
|
|
pNew->motors[9] = TasFindMotor(pSics, "a6");
|
|
pNew->motors[10] = TasFindMotor(pSics, "acv");
|
|
pNew->motors[11] = TasFindMotor(pSics, "ach");
|
|
for (i=0; i < 12; i++) {
|
|
strcpy(pNew->motname[i], defltMot[i]);
|
|
}
|
|
|
|
} else {
|
|
/*
|
|
* user defined names
|
|
*/
|
|
pNew->motors[0] = TasFindMotor(pSics, argv[2]);
|
|
pNew->motors[1] = TasFindMotor(pSics, argv[3]);
|
|
pNew->motors[2] = TasFindMotor(pSics, argv[4]);
|
|
pNew->motors[3] = TasFindMotor(pSics, argv[5]);
|
|
pNew->motors[4] = TasFindMotor(pSics, argv[6]);
|
|
pNew->motors[5] = TasFindMotor(pSics, argv[7]);
|
|
pNew->motors[6] = TasFindMotor(pSics, argv[8]);
|
|
pNew->motors[7] = TasFindMotor(pSics, argv[9]);
|
|
pNew->motors[8] = TasFindMotor(pSics, argv[10]);
|
|
pNew->motors[9] = TasFindMotor(pSics, argv[11]);
|
|
pNew->motors[10] = TasFindMotor(pSics, argv[12]);
|
|
pNew->motors[11] = TasFindMotor(pSics, argv[13]);
|
|
for (i=0; i < 12; i++) {
|
|
strcpy(pNew->motname[i], argv[i+2]);
|
|
}
|
|
}
|
|
/*
|
|
curvature motors may be missing, anything else is a serious problem
|
|
*/
|
|
status += testMotor(pNew, pCon, pNew->motname[A1], A1);
|
|
status += testMotor(pNew, pCon, pNew->motname[A2], A2);
|
|
status += testMotor(pNew, pCon, pNew->motname[A3], A3);
|
|
status += testMotor(pNew, pCon, pNew->motname[A4], A4);
|
|
status += testMotor(pNew, pCon, pNew->motname[SGU], SGU);
|
|
status += testMotor(pNew, pCon, pNew->motname[SGL], SGL);
|
|
status += testMotor(pNew, pCon, pNew->motname[A5], A5);
|
|
status += testMotor(pNew, pCon, pNew->motname[A6], A6);
|
|
if (status != 8) {
|
|
SCWrite(pCon, "ERROR: a required motor is missing, tasub NOT installed",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
status = AddCommand(pSics, argv[1], TasUBWrapper, KillTasUB, pNew);
|
|
if (status != 1) {
|
|
SCWrite(pCon, "ERROR: duplicate tasUB command not created", eError);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
install virtual motors
|
|
*/
|
|
for (i = 0; i < 8; i++) {
|
|
status = InstallTasMotor(pSics, pNew, i + 1, names[i]);
|
|
if (status != 1) {
|
|
snprintf(pBueffel, 131, "ERROR: failed to create TAS motor %s",
|
|
names[i]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
}
|
|
}
|
|
status = InstallTasQMMotor(pSics, pNew);
|
|
if (status != 1) {
|
|
snprintf(pBueffel, 131, "ERROR: failed to create TAS motor qm");
|
|
SCWrite(pCon, pBueffel, eError);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
return 0;
|
|
}
|
|
|
|
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) {
|
|
status = (int)d;
|
|
if (status == 1) {
|
|
crystal->ss = 1;
|
|
} else if(status == -1) {
|
|
crystal->ss = -1;
|
|
} else {
|
|
SCPrintf(pCon,eError,
|
|
"ERROR: %f not allowed for scattering sense, only 1,-1", d);
|
|
return 0;
|
|
}
|
|
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->VB2);
|
|
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;
|
|
}
|
|
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
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;
|
|
}
|
|
self->ubValid = 0;
|
|
SCWrite(pCon, "WARNING: UB is now invalid", eWarning);
|
|
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)
|
|
{
|
|
LLDdelete(self->reflectionList);
|
|
self->reflectionList = LLDcreate(sizeof(tasReflection));
|
|
self->ubValid = 0;
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
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 %s %s %s %s EI EF\n",
|
|
self->motname[A3], self->motname[A4], self->motname[SGU],
|
|
self->motname[SGL]);
|
|
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.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3,
|
|
r.angles.sample_two_theta, r.angles.sgu, r.angles.sgl,
|
|
KtoEnergy(r.qe.ki), KtoEnergy(r.qe.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);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
#define ABS(x) (x < 0 ? -(x) : (x))
|
|
/*-------------------------------------------------------------------*/
|
|
static int addReflection(ptasUB self, SicsInterp * pSics,
|
|
SConnection * pCon, int argc, char *argv[])
|
|
{
|
|
tasReflection r;
|
|
int status, count = 11;
|
|
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;
|
|
}
|
|
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[2], &r.qe.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], &r.qe.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], &r.qe.ql);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[4]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
if (self->tasMode == ELASTIC) {
|
|
count = 10;
|
|
}
|
|
if (argc >= count) {
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[5], &r.angles.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.angles.sample_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.angles.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.angles.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.qe.ki);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[9]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
r.qe.ki = energyToK(r.qe.ki);
|
|
if (self->tasMode != ELASTIC) {
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[10], &r.qe.kf);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[10]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
r.qe.kf = energyToK(r.qe.kf);
|
|
} else {
|
|
r.qe.kf = r.qe.ki;
|
|
}
|
|
} else {
|
|
if (argc > 5) {
|
|
SCWrite(pCon,
|
|
"WARNING: not all angles given on command line, using positions instead",
|
|
eWarning);
|
|
}
|
|
status = readTASMotAngles(self, pCon, &r.angles);
|
|
if (status != 1) {
|
|
return status;
|
|
}
|
|
r.qe.ki =
|
|
maCalcK(self->machine.monochromator,
|
|
r.angles.monochromator_two_theta);
|
|
r.qe.kf = maCalcK(self->machine.analyzer, r.angles.analyzer_two_theta);
|
|
}
|
|
if (self->tasMode == ELASTIC) {
|
|
r.qe.kf = r.qe.ki;
|
|
}
|
|
if (ABS(r.qe.ki - r.qe.kf) > .01) {
|
|
SCWrite(pCon, "WARNING: KI != KF!", eWarning);
|
|
}
|
|
LLDnodeAppend(self->reflectionList, &r);
|
|
Tcl_DStringInit(&list);
|
|
snprintf(pBueffel, 255,
|
|
" QH QK QL %s %s %s %s EI EF\n",
|
|
self->motname[A3], self->motname[A4], self->motname[SGU],
|
|
self->motname[SGL]);
|
|
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.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3,
|
|
r.angles.sample_two_theta, r.angles.sgu, r.angles.sgl,
|
|
KtoEnergy(r.qe.ki), KtoEnergy(r.qe.kf));
|
|
Tcl_DStringAppend(&list, pBueffel, -1);
|
|
SCWrite(pCon, Tcl_DStringValue(&list), eValue);
|
|
Tcl_DStringFree(&list);
|
|
SCparChange(pCon);
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------------*/
|
|
static int readReflection(SConnection * pCon, SicsInterp * pSics,
|
|
ptasReflection res, int argc, char *argv[])
|
|
{
|
|
tasReflection r;
|
|
int status;
|
|
char pBueffel[256];
|
|
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
|
|
if (argc < 11) {
|
|
SCWrite(pCon, "ERROR: not enough parameters to read reflection",
|
|
eError);
|
|
return 0;
|
|
}
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[2], &r.qe.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], &r.qe.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], &r.qe.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], &r.angles.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.angles.sample_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.angles.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.angles.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.qe.ki);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[9]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
r.qe.ki = energyToK(r.qe.ki);
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[10], &r.qe.kf);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[10]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
r.qe.kf = energyToK(r.qe.kf);
|
|
if (ABS(r.qe.ki - r.qe.kf) > .01) {
|
|
SCWrite(pCon, "WARNING: KI != KF!", eWarning);
|
|
}
|
|
*res = r;
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------*/
|
|
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;
|
|
}
|
|
/*-----------------------------------------------------------------*/
|
|
void setStopFixed(ptasUB self, int val)
|
|
{
|
|
if(val == 0 || val ==1) {
|
|
self->stopFixed = val;
|
|
}
|
|
}
|
|
/*------------------------------------------------------------------*/
|
|
static void listUB(ptasUB self, SConnection * pCon)
|
|
{
|
|
Tcl_DString list;
|
|
char pBueffel[255];
|
|
int i;
|
|
tasReflection r;
|
|
|
|
Tcl_DStringInit(&list);
|
|
if (self->machine.UB == NULL) {
|
|
Tcl_DStringAppend(&list, "NO UB", -1);
|
|
} else {
|
|
Tcl_DStringAppend(&list, "UB = ", -1);
|
|
snprintf(pBueffel, 255, "%f %f %f\n", self->machine.UB[0][0],
|
|
self->machine.UB[0][1], self->machine.UB[0][2]);
|
|
Tcl_DStringAppend(&list, pBueffel, -1);
|
|
for (i = 1; i < 3; i++) {
|
|
snprintf(pBueffel, 255, " %f %f %f\n", self->machine.UB[i][0],
|
|
self->machine.UB[i][1], self->machine.UB[i][2]);
|
|
Tcl_DStringAppend(&list, pBueffel, -1);
|
|
}
|
|
}
|
|
snprintf(pBueffel, 255, "UB generated from reflections:\n");
|
|
Tcl_DStringAppend(&list, pBueffel, -1);
|
|
snprintf(pBueffel, 255,
|
|
" QH QK QL %s %s %s %s EI EF\n",
|
|
self->motname[A3], self->motname[A4], self->motname[SGU],
|
|
self->motname[SGL]);
|
|
Tcl_DStringAppend(&list, pBueffel, -1);
|
|
r = self->r1;
|
|
snprintf(pBueffel, 255,
|
|
" %8.4f %8.4f %8.4f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
|
|
r.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3,
|
|
r.angles.sample_two_theta, r.angles.sgu, r.angles.sgl,
|
|
KtoEnergy(r.qe.ki), KtoEnergy(r.qe.kf));
|
|
Tcl_DStringAppend(&list, pBueffel, -1);
|
|
r = self->r2;
|
|
snprintf(pBueffel, 255,
|
|
" %8.4f %8.4f %8.4f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
|
|
r.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3,
|
|
r.angles.sample_two_theta, r.angles.sgu, r.angles.sgl,
|
|
KtoEnergy(r.qe.ki), KtoEnergy(r.qe.kf));
|
|
Tcl_DStringAppend(&list, pBueffel, -1);
|
|
snprintf(pBueffel, 255, "Plane Normal: %8.4f %8.4f %8.4f\n",
|
|
self->machine.planeNormal[0][0],
|
|
self->machine.planeNormal[1][0],
|
|
self->machine.planeNormal[2][0]);
|
|
Tcl_DStringAppend(&list, pBueffel, -1);
|
|
if (self->ubValid == 0) {
|
|
Tcl_DStringAppend(&list, "WARNING: UB matrix is invalid\n", -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 %s %s %s %s EI EF\n",
|
|
self->motname[A3], self->motname[A4], self->motname[SGU],
|
|
self->motname[SGL]);
|
|
Tcl_DStringAppend(&list, line, -1);
|
|
snprintf(line, 255,
|
|
"INPUT %8.4f %8.4f %8.4f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
|
|
r.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3,
|
|
r.angles.sample_two_theta, r.angles.sgu, r.angles.sgl,
|
|
KtoEnergy(r.qe.ki), KtoEnergy(r.qe.kf));
|
|
Tcl_DStringAppend(&list, line, -1);
|
|
qe.ki = r.qe.ki;
|
|
qe.kf = r.qe.kf;
|
|
qe.qh = r.qe.qh;
|
|
qe.qk = r.qe.qk;
|
|
qe.ql = r.qe.ql;
|
|
calcAllTasAngles(&self->machine, qe, &angles);
|
|
snprintf(line, 255,
|
|
"QE->ANG %8.4f %8.4f %8.4f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
|
|
r.qe.qh, r.qe.qk, r.qe.ql,
|
|
angles.a3, angles.sample_two_theta,
|
|
angles.sgu, angles.sgl, KtoEnergy(r.qe.ki), KtoEnergy(r.qe.kf));
|
|
Tcl_DStringAppend(&list, line, -1);
|
|
angles.a3 = r.angles.a3;
|
|
angles.sample_two_theta = r.angles.sample_two_theta;
|
|
angles.sgu = r.angles.sgu;
|
|
angles.sgl = r.angles.sgl;
|
|
calcTasQEPosition(&self->machine, angles, &qe);
|
|
snprintf(line, 255,
|
|
"ANG->QE %8.4f %8.4f %8.4f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
|
|
qe.qh, qe.qk, qe.ql, angles.a3, angles.sample_two_theta,
|
|
angles.sgu, angles.sgl, KtoEnergy(qe.ki), KtoEnergy(qe.kf));
|
|
Tcl_DStringAppend(&list, line, -1);
|
|
SCWrite(pCon, Tcl_DStringValue(&list), eWarning);
|
|
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 addAuxReflection(ptasUB self, SConnection * pCon,
|
|
SicsInterp * pSics, int argc, char *argv[])
|
|
{
|
|
int status, ss;
|
|
tasReflection r1, r2;
|
|
float value = -999.99;
|
|
char pBueffel[256];
|
|
MATRIX UB = NULL, B = NULL;
|
|
|
|
if (argc < 5) {
|
|
SCWrite(pCon,
|
|
"ERROR: not enough arguments auxiliary reflection, need HKL",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[2], &r2.qe.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], &r2.qe.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], &r2.qe.ql);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[4]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
B = mat_creat(3, 3, ZERO_MATRIX);
|
|
if (B == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory creating B matrix", eError);
|
|
return 0;
|
|
}
|
|
status = calculateBMatrix(self->cell, B);
|
|
if (status < 0) {
|
|
SCWrite(pCon, "ERROR: bad cell constants, no volume", eError);
|
|
mat_free(B);
|
|
return 0;
|
|
}
|
|
|
|
status = findReflection(self->reflectionList, 0, &r1);
|
|
if (status != 1) {
|
|
r2.qe.kf = self->current.kf;
|
|
r2.qe.ki = self->current.ki;
|
|
GetDrivablePosition(self->motors[A3], pCon, &value);
|
|
ss = self->machine.ss_sample;
|
|
r2.angles.a3 = fmod(value + ss*180.,360.) - ss*180.;
|
|
r2.angles.sgu = .0;
|
|
r2.angles.sgl = .0;
|
|
calcTwoTheta(B, r2.qe, self->machine.ss_sample,
|
|
&r2.angles.sample_two_theta);
|
|
r1 = r2;
|
|
}
|
|
|
|
status = makeAuxReflection(B, r1, &r2, self->machine.ss_sample);
|
|
mat_free(B);
|
|
if (status < 0) {
|
|
SCWrite(pCon,
|
|
"ERROR: out of memory in makeAuxUB or scattering angle not closed",
|
|
eError);
|
|
return 0;
|
|
}
|
|
LLDnodeAppend(self->reflectionList, &r2);
|
|
SCSendOK(pCon);
|
|
invokeUpdate(self,pCon,"ref");
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
static int calcAuxUB(ptasUB self, SConnection * pCon, SicsInterp * pSics,
|
|
int argc, char *argv[])
|
|
{
|
|
int status;
|
|
tasReflection r1, r2;
|
|
char pBueffel[256];
|
|
MATRIX UB = NULL, B = NULL;
|
|
|
|
if (argc < 5) {
|
|
SCWrite(pCon,
|
|
"ERROR: not enough arguments for UB calculation, need HKL of second plane vector",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[2], &r2.qe.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], &r2.qe.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], &r2.qe.ql);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[4]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
status = findReflection(self->reflectionList, 0, &r1);
|
|
if (status != 1) {
|
|
snprintf(pBueffel, 255, "ERROR: cannot find first reflection");
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
B = mat_creat(3, 3, ZERO_MATRIX);
|
|
if (B == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory creating B matrix", eError);
|
|
return 0;
|
|
}
|
|
status = calculateBMatrix(self->cell, B);
|
|
if (status < 0) {
|
|
SCWrite(pCon, "ERROR: bad cell constants, no volume", eError);
|
|
mat_free(B);
|
|
return 0;
|
|
}
|
|
|
|
status = makeAuxReflection(B, r1, &r2, self->machine.ss_sample);
|
|
mat_free(B);
|
|
if (status < 0) {
|
|
SCWrite(pCon, "ERROR: out of memory in makeAuxUB", 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 (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);
|
|
}
|
|
if (self->machine.planeNormal != NULL) {
|
|
mat_free(self->machine.planeNormal);
|
|
}
|
|
self->machine.UB = UB;
|
|
self->machine.planeNormal = makeVector();
|
|
self->machine.planeNormal[2][0] = 1.;
|
|
/* self->machine.planeNormal = calcPlaneNormal(r1, r2); */
|
|
self->ubValid = 1;
|
|
SCparChange(pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
static int calcUB(ptasUB self, SConnection * pCon, SicsInterp * pSics,
|
|
int argc, char *argv[])
|
|
{
|
|
int idx1, idx2, 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;
|
|
}
|
|
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
|
|
status = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &idx1);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
idx1--;
|
|
status = findReflection(self->reflectionList, idx1, &r1);
|
|
if (status != 1) {
|
|
snprintf(pBueffel, 255, "ERROR: cannot find reflection with index %d",
|
|
idx1 + 1);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
status = Tcl_GetInt(InterpGetTcl(pSics), argv[3], &idx2);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[3]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
idx2--;
|
|
status = findReflection(self->reflectionList, idx2, &r2);
|
|
if (status != 1) {
|
|
snprintf(pBueffel, 255, "ERROR: cannot find reflection with index %d",
|
|
idx2 + 1);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
if(!self->outOfPlaneAllowed){
|
|
r1.angles.sgu = .0;
|
|
r1.angles.sgl = .0;
|
|
r2.angles.sgu = .0;
|
|
r2.angles.sgl = .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 (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);
|
|
}
|
|
if (self->machine.planeNormal != NULL) {
|
|
mat_free(self->machine.planeNormal);
|
|
}
|
|
self->machine.UB = UB;
|
|
/* self->machine.planeNormal = calcPlaneNormalQ(UB,r1, r2);*/
|
|
self->machine.planeNormal = makeVector();
|
|
self->machine.planeNormal[2][0] = 1.;
|
|
self->r1 = r1;
|
|
self->r2 = r2;
|
|
self->ubValid = 1;
|
|
listUB(self, pCon);
|
|
listDiagnostik(self, pCon);
|
|
invokeUpdate(self,pCon,"main");
|
|
SCparChange(pCon);
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------*/
|
|
static int calcUBFromCell(ptasUB self, SConnection * pCon)
|
|
{
|
|
MATRIX B, U, UB;
|
|
tasReflection r1;
|
|
int status;
|
|
|
|
B = mat_creat(3, 3, UNIT_MATRIX);
|
|
U = mat_creat(3, 3, UNIT_MATRIX);
|
|
status = findReflection(self->reflectionList, 0, &r1);
|
|
if (status == 1) {
|
|
/*
|
|
U[0][0] = Cosd(r1.angles.a3);
|
|
U[0][1] = -Sind(r1.angles.a3);
|
|
U[1][0] = Sind(r1.angles.a3);
|
|
U[1][1] = Cosd(r1.angles.a3);
|
|
*/
|
|
}
|
|
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 cell", 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);
|
|
invokeUpdate(self,pCon,"main");
|
|
mat_free(U);
|
|
mat_free(B);
|
|
return 1;
|
|
}
|
|
/*-----------------------------------------------------------------*/
|
|
static int calcTestUBWrap(ptasUB self, SConnection *pCon,
|
|
int argc, char *argv[])
|
|
{
|
|
MATRIX UB;
|
|
double om, sgu, sgl;
|
|
tasReflection r1, r2;
|
|
|
|
|
|
if(argc < 5) {
|
|
SCWrite(pCon,"ERROR: not enough arguments to test UB", eError);
|
|
return 0;
|
|
}
|
|
|
|
om = atof(argv[2]);
|
|
sgu = atof(argv[3]);
|
|
sgl = atof(argv[4]);
|
|
|
|
UB = calcTestUB(self->cell, om, sgu, sgl);
|
|
if(UB == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory or invalid cell in test UB", eError);
|
|
return 0;
|
|
}
|
|
mat_free(self->machine.UB);
|
|
self->machine.UB = UB;
|
|
|
|
/*
|
|
r1.qe.qh = 1.0;
|
|
r1.qe.qk = .0;
|
|
r1.qe.ql = .0;
|
|
|
|
r2.qe.qh = .0;
|
|
r2.qe.qk = 1.0;
|
|
r2.qe.ql = .0;
|
|
|
|
self->machine.planeNormal = calcPlaneNormalQ(UB,r1,r2);
|
|
self->machine.planeNormal[0][0] = -Sind(sgl);
|
|
self->machine.planeNormal[1][0] = Cosd(sgl)*Sind(sgu);
|
|
self->machine.planeNormal[2][0] = Cosd(sgl)*Cosd(sgu);
|
|
SCPrintf(pCon,eValue,"Normal = %f,%f,%f\n", self->machine.planeNormal[0][0],
|
|
self->machine.planeNormal[1][0],
|
|
self->machine.planeNormal[2][0]);
|
|
|
|
self->machine.planeNormal = calcTestNormal(sgu,sgl);
|
|
SCPrintf(pCon,eValue,"Alternative normal = %f,%f,%f\n", self->machine.planeNormal[0][0],
|
|
self->machine.planeNormal[1][0],
|
|
self->machine.planeNormal[2][0]);
|
|
*/
|
|
self->machine.planeNormal[0][0] = .0;
|
|
self->machine.planeNormal[1][0] = .0;
|
|
self->machine.planeNormal[2][0] = 1.0;
|
|
|
|
|
|
SCSendOK(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 (self->tasMode == ELASTIC) {
|
|
if (argc < 6) {
|
|
SCWrite(pCon, "ERROR: need Qh, Qk, Ql, EI for calculation", eError);
|
|
return 0;
|
|
}
|
|
} else {
|
|
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;
|
|
}
|
|
if (self->tasMode != ELASTIC) {
|
|
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;
|
|
}
|
|
} else {
|
|
q.kf = q.ki;
|
|
}
|
|
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 BADRMATRIX:
|
|
SCWrite(pCon, "ERROR: bad crystallographic parameters or bad UB",
|
|
eError);
|
|
return 0;
|
|
break;
|
|
case TRIANGLENOTCLOSED:
|
|
SCWrite(pCon, "ERROR: scattering triangle not closed", eError);
|
|
return 0;
|
|
break;
|
|
}
|
|
if (self->tasMode != ELASTIC) {
|
|
snprintf(pBueffel, 255, " %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f",
|
|
angles.monochromator_two_theta,
|
|
angles.a3, angles.sample_two_theta,
|
|
angles.sgu, angles.sgl, angles.analyzer_two_theta);
|
|
} else {
|
|
snprintf(pBueffel, 255, " %8.2f %8.2f %8.2f %8.2f %8.2f",
|
|
angles.monochromator_two_theta,
|
|
angles.a3, angles.sample_two_theta, angles.sgl, angles.sgu);
|
|
}
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
static int calcQFromAngles(ptasUB self, SConnection * pCon,
|
|
SicsInterp * pSics, int argc, char *argv[])
|
|
{
|
|
tasQEPosition q;
|
|
tasAngles angles;
|
|
char pBueffel[256];
|
|
int status;
|
|
|
|
if (self->tasMode != ELASTIC) {
|
|
if (argc < 8) {
|
|
SCWrite(pCon, "ERROR: need a2, a3, a4, sgu, sgl, a6 for calculation",
|
|
eError);
|
|
return 0;
|
|
}
|
|
} else {
|
|
if (argc < 7) {
|
|
SCWrite(pCon, "ERROR: need a2, a3, a4, sgu, sgl for calculation",
|
|
eError);
|
|
return 0;
|
|
}
|
|
}
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[2],
|
|
&angles.monochromator_two_theta);
|
|
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], &angles.a3);
|
|
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],
|
|
&angles.sample_two_theta);
|
|
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], &angles.sgu);
|
|
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], &angles.sgl);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[6]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
if (self->tasMode != ELASTIC) {
|
|
status =
|
|
Tcl_GetDouble(InterpGetTcl(pSics), argv[7],
|
|
&angles.analyzer_two_theta);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[7]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
} else {
|
|
angles.analyzer_two_theta = angles.monochromator_two_theta;
|
|
}
|
|
status = calcTasQEPosition(&self->machine, angles, &q);
|
|
switch (status) {
|
|
case UBNOMEMORY:
|
|
SCWrite(pCon, "ERROR: Out of memory calculating angles", eError);
|
|
return 0;
|
|
break;
|
|
}
|
|
|
|
if (self->tasMode == ELASTIC) {
|
|
q.kf = q.ki;
|
|
}
|
|
snprintf(pBueffel, 255, "%8.4f %8.4f %8.4f %8.4f %8.4f",
|
|
q.qh, q.qk, q.ql, KtoEnergy(q.ki), KtoEnergy(q.kf));
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
static int setUB(SConnection * pCon, SicsInterp * pSics, ptasUB self,
|
|
int argc, char *argv[])
|
|
{
|
|
double value;
|
|
char pBueffel[256];
|
|
int status;
|
|
|
|
if (argc < 11) {
|
|
SCWrite(pCon, "ERROR: not enough arguments for setting UB", eError);
|
|
return 0;
|
|
}
|
|
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[2], &value);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
self->machine.UB[0][0] = value;
|
|
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[3], &value);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[3]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
self->machine.UB[0][1] = value;
|
|
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[4], &value);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[4]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
self->machine.UB[0][2] = value;
|
|
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[5], &value);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[5]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
self->machine.UB[1][0] = value;
|
|
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[6], &value);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[6]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
self->machine.UB[1][1] = value;
|
|
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[7], &value);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[7]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
self->machine.UB[1][2] = value;
|
|
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[8], &value);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[8]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
self->machine.UB[2][0] = value;
|
|
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[9], &value);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[9]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
self->machine.UB[2][1] = value;
|
|
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[10], &value);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[10]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
self->machine.UB[2][2] = value;
|
|
self->ubValid = 1;
|
|
SCSendOK(pCon);
|
|
SCparChange(pCon);
|
|
invokeUpdate(self,pCon,"main");
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
static int getUB(SConnection * pCon, SicsInterp * pSics, ptasUB self,
|
|
int argc, char *argv[])
|
|
{
|
|
double value;
|
|
char pBueffel[512];
|
|
int status;
|
|
|
|
snprintf(pBueffel, 511, "tasub.ub = %f %f %f %f %f %f %f %f %f",
|
|
self->machine.UB[0][0], self->machine.UB[0][1],
|
|
self->machine.UB[0][2], self->machine.UB[1][0],
|
|
self->machine.UB[1][1], self->machine.UB[1][2],
|
|
self->machine.UB[2][0], self->machine.UB[2][1],
|
|
self->machine.UB[2][2]);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
static int setNormal(SConnection * pCon, SicsInterp * pSics, ptasUB self,
|
|
int argc, char *argv[])
|
|
{
|
|
double value;
|
|
char pBueffel[256];
|
|
int status;
|
|
|
|
if (argc < 5) {
|
|
SCWrite(pCon, "ERROR: not enough arguments for setting plane normal",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[2], &value);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
self->machine.planeNormal[0][0] = value;
|
|
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[3], &value);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[3]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
self->machine.planeNormal[1][0] = value;
|
|
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[4], &value);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[4]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
self->machine.planeNormal[2][0] = value;
|
|
SCSendOK(pCon);
|
|
SCparChange(pCon);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
static int getNormal(SConnection * pCon, SicsInterp * pSics, ptasUB self,
|
|
int argc, char *argv[])
|
|
{
|
|
double value;
|
|
char pBueffel[512];
|
|
int status;
|
|
|
|
snprintf(pBueffel, 511, "tasub.normal = %f %f %f",
|
|
self->machine.planeNormal[0][0], self->machine.planeNormal[1][0],
|
|
self->machine.planeNormal[2][0]);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
static int setTarget(SConnection * pCon, SicsInterp * pSics, ptasUB self,
|
|
int argc, char *argv[])
|
|
{
|
|
double value;
|
|
char pBueffel[256];
|
|
int status;
|
|
|
|
if (argc < 8) {
|
|
SCWrite(pCon, "ERROR: not enough arguments for setting qe target",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[2], &self->target.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], &self->target.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], &self->target.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], &self->target.qm);
|
|
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], &self->target.ki);
|
|
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], &self->target.kf);
|
|
if (status != TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: failed to convert %s to number",
|
|
argv[7]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
SCSendOK(pCon);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
int tasUpdate(SConnection * pCon, ptasUB self)
|
|
{
|
|
int status;
|
|
tasAngles angles;
|
|
|
|
status = readTASMotAngles(self, pCon, &angles);
|
|
if (status != 1) {
|
|
return status;
|
|
}
|
|
status = calcTasQEPosition(&self->machine, angles, &self->current);
|
|
if (status < 0) {
|
|
SCWrite(pCon, "ERROR: out of memory calculating Q-E variables",
|
|
eError);
|
|
return 0;
|
|
}
|
|
if (self->tasMode == ELASTIC) {
|
|
self->current.kf = self->current.ki;
|
|
}
|
|
self->mustRecalculate = 0;
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
static int deleteReflection(SConnection * pCon, SicsInterp * pSics,
|
|
ptasUB self, int argc, char *argv[])
|
|
{
|
|
int idx, count = 0, status;
|
|
char pBueffel[256];
|
|
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: need number of reflection to delete", 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;
|
|
}
|
|
idx--;
|
|
status = LLDnodePtr2First(self->reflectionList);
|
|
while (status == 1) {
|
|
if (count == idx) {
|
|
LLDnodeDelete(self->reflectionList);
|
|
break;
|
|
}
|
|
status = LLDnodePtr2Next(self->reflectionList);
|
|
count++;
|
|
}
|
|
SCSendOK(pCon);
|
|
invokeUpdate(self,pCon,"ref");
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
static int replaceReflection(SConnection * pCon, SicsInterp * pSics,
|
|
ptasUB self, int argc, char *argv[])
|
|
{
|
|
int idx, count = 0, status;
|
|
char pBueffel[256];
|
|
tasReflection r;
|
|
|
|
if (argc < 12) {
|
|
SCWrite(pCon, "ERROR: need id and new values to replace", 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;
|
|
}
|
|
idx--;
|
|
status = LLDnodePtr2First(self->reflectionList);
|
|
while (status == 1) {
|
|
if (count == idx) {
|
|
LLDnodeDataTo(self->reflectionList,&r);
|
|
r.qe.qh = atof(argv[3]);
|
|
r.qe.qk = atof(argv[4]);
|
|
r.qe.ql = atof(argv[5]);
|
|
r.angles.a3 = atof(argv[6]);
|
|
r.angles.sample_two_theta = atof(argv[7]);
|
|
r.angles.sgu = atof(argv[8]);
|
|
r.angles.sgl = atof(argv[9]);
|
|
r.qe.ki = energyToK(atof(argv[10]));
|
|
r.qe.kf = energyToK(atof(argv[11]));
|
|
LLDnodeDataFrom(self->reflectionList,&r);
|
|
break;
|
|
}
|
|
status = LLDnodePtr2Next(self->reflectionList);
|
|
count++;
|
|
}
|
|
SCSendOK(pCon);
|
|
invokeUpdate(self,pCon,"ref");
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
int TasUBWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
ptasUB self = NULL;
|
|
char pBueffel[131];
|
|
int status, newSS;
|
|
double misalign = .0, a3offset;
|
|
|
|
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) {
|
|
status =
|
|
handleCrystalCommands(&self->machine.monochromator, pCon, argc,
|
|
argv);
|
|
if(argc > 3){
|
|
invokeUpdate(self,pCon,"mono");
|
|
}
|
|
self->mustRecalculate = 1;
|
|
return status;
|
|
} else if (strcmp(argv[1], "ana") == 0) {
|
|
status =
|
|
handleCrystalCommands(&self->machine.analyzer, pCon, argc, argv);
|
|
self->mustRecalculate = 1;
|
|
if(argc > 3){
|
|
invokeUpdate(self,pCon,"ana");
|
|
}
|
|
return status;
|
|
} else if (strcmp(argv[1], "cell") == 0) {
|
|
if (argc > 2) {
|
|
status = tasReadCell(pCon, self, argc, argv);
|
|
invokeUpdate(self,pCon,"main");
|
|
return status;
|
|
} else {
|
|
tasListCell(pCon, argv[0], self->cell);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "clear") == 0) {
|
|
clearReflections(self);
|
|
clearReflections(self);
|
|
SCWrite(pCon, "WARNING: UB is now invalid", eWarning);
|
|
invokeUpdate(self,pCon,"ref");
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "listref") == 0) {
|
|
listReflections(self, pCon);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "addref") == 0) {
|
|
status = addReflection(self, pSics, pCon, argc, argv);
|
|
invokeUpdate(self, pCon,"ref");
|
|
return status;
|
|
} else if (strcmp(argv[1], "repref") == 0) {
|
|
status = replaceReflection(pCon, pSics, self, argc, argv);
|
|
return status;
|
|
} else if (strcmp(argv[1], "listub") == 0) {
|
|
listUB(self, pCon);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "makeub") == 0) {
|
|
return calcUB(self, pCon, pSics, argc, argv);
|
|
} else if (strcmp(argv[1], "makeauxub") == 0) {
|
|
return calcAuxUB(self, pCon, pSics, argc, argv);
|
|
} else if (strcmp(argv[1], "addauxref") == 0) {
|
|
return addAuxReflection(self, pCon, pSics, argc, argv);
|
|
} else if (strcmp(argv[1], "makeubfromcell") == 0) {
|
|
return calcUBFromCell(self, pCon);
|
|
} else if (strcmp(argv[1], "maketestub") == 0) {
|
|
return calcTestUBWrap(self, pCon, argc, argv);
|
|
} else if (strcmp(argv[1], "calcang") == 0) {
|
|
return calcRefAngles(self, pCon, pSics, argc, argv);
|
|
} else if (strcmp(argv[1], "calcqe") == 0) {
|
|
return calcQFromAngles(self, pCon, pSics, argc, argv);
|
|
} else if (strcmp(argv[1], "setub") == 0) {
|
|
return setUB(pCon, pSics, self, argc, argv);
|
|
} else if (strcmp(argv[1], "getub") == 0) {
|
|
return getUB(pCon, pSics, self, argc, argv);
|
|
} else if (strcmp(argv[1], "setnormal") == 0) {
|
|
return setNormal(pCon, pSics, self, argc, argv);
|
|
} else if (strcmp(argv[1], "getnormal") == 0) {
|
|
return getNormal(pCon, pSics, self, argc, argv);
|
|
} else if (strcmp(argv[1], "settarget") == 0) {
|
|
return setTarget(pCon, pSics, self, argc, argv);
|
|
} else if (strcmp(argv[1], "update") == 0) {
|
|
return tasUpdate(pCon, self);
|
|
} else if (strcmp(argv[1], "del") == 0) {
|
|
return deleteReflection(pCon, pSics, self, argc, argv);
|
|
} else if (strcmp(argv[1], "r1") == 0) {
|
|
return readReflection(pCon, pSics, &self->r1, argc, argv);
|
|
} else if (strcmp(argv[1], "r2") == 0) {
|
|
return readReflection(pCon, pSics, &self->r2, argc, argv);
|
|
} else if (strcmp(argv[1], "updatetargets") == 0) {
|
|
updateTargets(self, pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} 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 if (strcmp(argv[2], "elastic") == 0) {
|
|
self->tasMode = ELASTIC;
|
|
} else {
|
|
SCWrite(pCon,
|
|
"ERROR: unknown triple axis mode, accepted are ki, kf, elastic",
|
|
eError);
|
|
return 0;
|
|
}
|
|
invokeUpdate(self,pCon,"main");
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
if (self->tasMode == KICONST) {
|
|
snprintf(pBueffel, 131, "%s.const = ki", argv[0]);
|
|
} else if (self->tasMode == ELASTIC) {
|
|
snprintf(pBueffel, 131, "%s.const = elastic", 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;
|
|
tasUpdate(pCon, self);
|
|
invokeUpdate(self,pCon,"main");
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
snprintf(pBueffel, 131, "%s.ss = %d", argv[0],
|
|
self->machine.ss_sample);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
} else if(strcmp(argv[1],"misalign") == 0){
|
|
status = calcTasMisalignment(&self->machine, self->current,&misalign);
|
|
if(status != 1){
|
|
SCWrite(pCon,"ERROR: failed to calculate misalignment, fix UB", eError);
|
|
return 0;
|
|
}
|
|
SCPrintf(pCon,eValue,"tasub.misalign = %f", misalign );
|
|
return 1;
|
|
} else if (strcmp(argv[1], "outofplane") == 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;
|
|
}
|
|
self->outOfPlaneAllowed = newSS;
|
|
invokeUpdate(self,pCon,"main");
|
|
SCWrite(pCon,"WARNING: You have to recalculate the UB matrix after swapping outofplane mode",
|
|
eWarning);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
snprintf(pBueffel, 131, "%s.outofplane = %d", argv[0],
|
|
self->outOfPlaneAllowed);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "a3offset") == 0) {
|
|
if (argc > 2) {
|
|
strtolower(argv[2]);
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
return 0;
|
|
}
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics), argv[2], &a3offset);
|
|
if (status != TCL_OK) {
|
|
SCWrite(pCon, "ERROR: failed to convert argument to number",
|
|
eError);
|
|
return 0;
|
|
}
|
|
self->machine.a3offset = a3offset;
|
|
invokeUpdate(self,pCon,"main");
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
snprintf(pBueffel, 131, "%s.a3offset = %lf", argv[0],
|
|
self->machine.a3offset);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "silent") == 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;
|
|
}
|
|
self->silent = newSS;
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
snprintf(pBueffel, 131, "%s.silent = %d", argv[0], self->silent);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "updater") == 0) {
|
|
if (argc > 2) {
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
return 0;
|
|
}
|
|
self->updater = strdup(argv[2]);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
snprintf(pBueffel, 131, "%s.updater = %s", argv[0], self->updater);
|
|
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;
|
|
}
|