Files
sics/singlex.c

965 lines
27 KiB
C

/**
* This is the implementation file for the single crystal diffraction module within SICS.
* This is a master module which initializes all the other ones and holds
* data structures and entities particular to single crystal diffraction.
*
* The configuration of lambda is a bit tricky: it can either be a
* drivable (connected to a monochromator) or a SICS variable or we
* use an internal Hdb node.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, July 2008
*
* Added SymRef command, Mark Koennecke, November 2008
*/
#include "singlex.h"
#include "sicshipadaba.h"
#include "sicsvar.h"
#include "hkl.h"
#include "hklmot.h"
#include "ubcalc.h"
#include "fourmess.h"
#include "cone.h"
#include "singlediff.h"
#include "singelbi.h"
#include "singlenb.h"
#include "singletas.h"
#include "singlebinb.h"
#include "lld.h"
#include "fourlib.h"
extern void InitSimpleIndex(SConnection * pCon, SicsInterp * pSics); /* from simindex.c */
/* There can be only one singlex module in any instance of SICS */
static pSICSOBJ singlex = NULL;
/*-------------------------------------------------------------------------*/
typedef struct {
pMotor stt;
pMotor om;
pMotor chi;
pMotor phi;
pMotor nu;
pMotor sgu;
pMotor sgl;
pSICSOBJ refl;
double ub[9];
double cell[6];
SingleXModes mode;
pIDrivable lambdaDriv;
void *lambdaVar;
T_SgInfo *spaceGroup;
pSingleDiff diffractometer;
} SingleX, *pSingleX;
/*--------------------------------------------------------------------------*/
static MotorFunction TextToFunc(char *txt)
{
static char *map[] = { "stt",
"om",
"chi",
"phi",
"nu",
"sgl",
"sgu",
NULL,
};
int count = 0;
while (map[count] != NULL) {
if (strcmp(map[count], txt) == 0) {
return count;
}
count++;
}
return None;
}
/*---------------------------------------------------------------------------*/
static int ConfigureCmd(pSICSOBJ self, SConnection * pCon,
pHdb commandNode, pHdb par[], int nPar)
{
pSingleX priv = self->pPrivate;
hdbValue v;
MotorFunction mf;
pMotor mot = NULL;
pDummy pDum = NULL;
CommandList *pCom = NULL;
assert(priv != NULL);
if (nPar < 2) {
SCWrite(pCon, "ERROR: need two parameters to configure", eError);
return 0;
}
GetHipadabaPar(par[0], &v, pCon);
if (strcmp(v.v.text, "lambda") == 0) {
GetHipadabaPar(par[1], &v, pCon);
pCom = FindCommand(pServ->pSics, v.v.text);
if (pCom != NULL) {
pDum = (pDummy) pCom->pData;
if ((priv->lambdaDriv =
pDum->pDescriptor->GetInterface(pDum, DRIVEID)) != NULL) {
priv->lambdaVar = pDum;
return 1;
}
if (strcmp(pDum->pDescriptor->name, "SicsVariable") == 0) {
priv->lambdaVar = pDum;
return 1;
}
}
SCWrite(pCon, "WARNING: creating local lambda node", eWarning);
AddSICSHdbPar(self->objectNode, "lambda", usUser, MakeHdbFloat(1.178));
return 1;
}
mf = TextToFunc(v.v.text);
if (mf == None) {
SCPrintf(pCon, eError,
"ERROR: failed to map %s to configuration parameter",
v.v.text);
return 0;
}
GetHipadabaPar(par[1], &v, pCon);
mot = (pMotor) FindCommandData(pServ->pSics, v.v.text, "Motor");
if (mot == NULL) {
SCPrintf(pCon, eLogError, "ERROR: failed to locate motor %s", v.v.text);
return 0;
}
switch (mf) {
case TwoTheta:
priv->stt = mot;
break;
case Omega:
priv->om = mot;
break;
case Chi:
priv->chi = mot;
break;
case Phi:
priv->phi = mot;
break;
case Nu:
priv->nu = mot;
break;
case Sgl:
priv->sgl = mot;
break;
case Sgu:
priv->sgu = mot;
break;
}
return 1;
}
/*---------------------------------------------------------------------------*/
static int MotorCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pSingleX priv = self->pPrivate;
MotorFunction mf;
pMotor pMot = NULL;
float fval;
if (nPar < 1) {
SCWrite(pCon, "ERROR: missing argument to motor cmd ", eError);
return 0;
}
mf = TextToFunc(par[0]->value.v.text);
if (mf == None) {
SCPrintf(pCon, eError, "ERROR: %s is not a four circle motor",
par[0]->value.v.text);
return 0;
}
pMot = SXGetMotor(mf);
if (pMot == NULL) {
SCPrintf(pCon, eError, "ERROR: %s motor is not configured",
par[0]->value.v.text);
return 0;
}
MotorGetSoftPosition(pMot, pCon, &fval);
SCPrintf(pCon, eValue, "%f", fval);
return 1;
}
/*---------------------------------------------------------------------------*/
static int MotorNamCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pSingleX priv = self->pPrivate;
MotorFunction mf;
pMotor pMot = NULL;
if (nPar < 1) {
SCWrite(pCon, "ERROR: missing argument to motor cmd ", eError);
return 0;
}
mf = TextToFunc(par[0]->value.v.text);
if (mf == None) {
SCPrintf(pCon, eError, "ERROR: %s is not a four circle motor",
par[0]->value.v.text);
return 0;
}
pMot = SXGetMotor(mf);
if (pMot == NULL) {
SCPrintf(pCon, eError, "ERROR: %s motor is not configured",
par[0]->value.v.text);
return 0;
}
SCPrintf(pCon, eValue, "%s", pMot->name);
return 1;
}
/*--------------------------------------------------------------------------
* check the validity of the mode and set our internal field to
* the right value
* ------------------------------------------------------------------------*/
extern char *trim(char *txt);
/*-------------------------------------------------------------------------*/
static int findModeIndex(char *mode)
{
static char *modes[] = {
"bi",
"nb",
"tas",
"binb",
"bio",
NULL
};
int count = 0;
while (modes[count] != NULL) {
if (strcmp(mode, modes[count]) == 0) {
return count;
}
count++;
}
return -1;
}
/*-------------------------------------------------------------------------*/
static hdbCallbackReturn SetModeCB(pHdb node, void *userData,
pHdbMessage mm)
{
pHdbDataMessage set = NULL;
pSingleX priv = (pSingleX) singlex->pPrivate;
SConnection *pCon = NULL;
char *pTest;
int modeIdx;
if ((set = GetHdbSetMessage(mm)) != NULL) {
pTest = trim(set->v->v.text);
pCon = set->callData;
modeIdx = findModeIndex(pTest);
switch (modeIdx) {
case Bisecting:
if (priv->chi == NULL || priv->om == NULL || priv->phi == NULL
|| priv->stt == NULL) {
if (pCon != NULL) {
SCWrite(pCon,
"ERROR: required motor for bisecting not configured",
eError);
}
return hdbAbort;
}
priv->mode = Bisecting;
initializeSingleBisecting(priv->diffractometer);
return hdbContinue;
break;
case BiO:
if (priv->chi == NULL || priv->om == NULL || priv->phi == NULL
|| priv->stt == NULL) {
if (pCon != NULL) {
SCWrite(pCon,
"ERROR: required motor for bisecting not configured",
eError);
}
return hdbAbort;
}
priv->mode = Bisecting;
initializeSingleBisectingOrion(priv->diffractometer);
free(set->v->v.text);
set->v->v.text = strdup("bio");
return hdbContinue;
break;
case NB:
if (priv->nu == NULL || priv->om == NULL || priv->stt == NULL) {
if (pCon != NULL) {
SCWrite(pCon,
"ERROR: required motor for normal beam not configured",
eError);
}
return hdbAbort;
}
priv->mode = NB;
initializeNormalBeam(priv->diffractometer);
return hdbContinue;
break;
case Tas:
if (priv->sgu == NULL || priv->sgl == NULL || priv->om == NULL
|| priv->stt == NULL) {
if (pCon != NULL) {
SCWrite(pCon, "ERROR: required motor for tas not configured",
eError);
}
return hdbAbort;
}
priv->mode = Tas;
initializeSingleTas(priv->diffractometer);
return hdbContinue;
case BiNB:
if (priv->stt == NULL || priv->nu == NULL || priv->om == NULL
|| priv->chi == NULL || priv->phi == NULL) {
if (pCon != NULL) {
SCWrite(pCon, "ERROR: required motor for BINB not configured",
eError);
}
return hdbAbort;
}
priv->mode = BiNB;
initializeSingleBINB(priv->diffractometer);
return hdbContinue;
default:
if (set->callData != NULL) {
pCon = set->callData;
SCPrintf(pCon, eError, "ERROR: %s is no valid singlex mode",
set->v->v.text);
}
return hdbAbort;
break;
}
}
return hdbContinue;
}
/*-------------------------------------------------------------------------*/
static hdbCallbackReturn GetLatticeCB(pHdb node, void *userData,
pHdbMessage mm)
{
pHdbDataMessage get = NULL;
pSingleX priv = (pSingleX) singlex->pPrivate;
if ((get = GetHdbGetMessage(mm)) != NULL) {
node->value.v.intValue = priv->spaceGroup->XtalSystem;
return hdbContinue;
}
return hdbContinue;
}
/*------------------------------------------------------------------------------------*/
static hdbCallbackReturn SetSpaceGroupCB(pHdb node, void *userData,
pHdbMessage mm)
{
pHdbDataMessage set = NULL;
pSingleX priv = (pSingleX) singlex->pPrivate;
SConnection *pCon = NULL;
const T_TabSgName *tsgn = NULL;
const char *sgName;
if ((set = GetHdbSetMessage(mm)) != NULL) {
pCon = set->callData;
tsgn = FindTabSgNameEntry(set->v->v.text, 'A');
if (tsgn == NULL && set->callData != NULL) {
SCPrintf(pCon, eError, "ERROR: %s is no valid singlex spacegroup",
set->v->v.text);
return hdbAbort;
}
sgName = tsgn->HallSymbol;
InitSgInfo(priv->spaceGroup);
priv->spaceGroup->TabSgName = tsgn;
ParseHallSymbol(sgName, priv->spaceGroup);
if (SgError != NULL) {
if (pCon != NULL) {
SCPrintf(pCon, eError, "ERROR: %s parsing space group symbol %s",
SgError, set->v->v.text);
}
SgError = NULL;
return hdbAbort;
}
CompleteSgInfo(priv->spaceGroup);
return hdbContinue;
}
return hdbContinue;
}
/*-------------------------------------------------------------------------*/
static hdbCallbackReturn SetUBCB(pHdb node, void *userData, pHdbMessage mm)
{
pHdbDataMessage set = NULL;
SConnection *pCon = NULL;
hdbValue v;
pHdb oldUB;
if ((set = GetHdbSetMessage(mm)) != NULL) {
oldUB = (pHdb) userData;
assert(oldUB != NULL);
GetHipadabaPar(node, &v, set->callData);
SetHipadabaPar(oldUB, v, set->callData);
return hdbContinue;
}
return hdbContinue;
}
/*-----------------------------------------------------------------------------*/
static int RecoverUBCmd(pSICSOBJ self, SConnection * pCon,
pHdb commandNode, pHdb par[], int nPar)
{
pHdb oldub, ub;
hdbValue v;
oldub = GetHipadabaNode(self->objectNode, "oldub");
ub = GetHipadabaNode(self->objectNode, "ub");
GetHipadabaPar(oldub, &v, pCon);
UpdateHipadabaPar(ub, v, pCon);
SCSendOK(pCon);
return 1;
}
/*-----------------------------------------------------------------------------*/
static int SymRefCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
pHdb par[], int nPar)
{
double hkl[3], settings[6];
char buffer[132];
pSingleX priv = (pSingleX) singlex->pPrivate;
T_Eq_hkl equiv;
int i;
if (nPar < 3) {
SCWrite(pCon, "ERROR: need start h,k,l for symref ", eError);
return 0;
}
hkl[0] = par[0]->value.v.intValue;
hkl[1] = par[1]->value.v.intValue;
hkl[2] = par[2]->value.v.intValue;
BuildEq_hkl(priv->spaceGroup, &equiv, (int) hkl[0], (int) hkl[1],
(int) hkl[2]);
for (i = 0; i < equiv.N; i++) {
hkl[0] = equiv.h[i];
hkl[1] = equiv.k[i];
hkl[2] = equiv.l[i];
if (priv->diffractometer->
calculateSettings(priv->diffractometer, hkl, settings) == 1) {
snprintf(buffer, sizeof(buffer), "%d,%d,%d", equiv.h[i], equiv.k[i],
equiv.l[i]);
SCWrite(pCon, buffer, eValue);
return 1;
}
}
SCWrite(pCon, "ERROR: no reachable symmetry equivalent found", eError);
return 0;
}
/*-----------------------------------------------------------------------------*/
static int SttUBCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
pHdb par[], int nPar)
{
double hkl[3], theta, d;
MATRIX z1 = NULL;
if (nPar < 3) {
SCWrite(pCon, "ERROR: need start h,k,l for sttUB", eError);
return 0;
}
hkl[0] = par[0]->value.v.doubleValue;
hkl[1] = par[1]->value.v.doubleValue;
hkl[2] = par[2]->value.v.doubleValue;
z1 = calculateScatteringVector(SXGetDiffractometer(), hkl);
if(z1 == NULL){
SCWrite(pCon,"ERROR: cannot calculate scattering vector", eError);
return 0;
}
if(!calcTheta(SXGetLambda(), z1, &d, &theta )){
mat_free(z1);
SCWrite(pCon,"ERROR: cannot calculate theta", eError);
return 0;
}
mat_free(z1);
SCPrintf(pCon,eValue,"%f", 2.*theta);
return 1;
}
/*-----------------------------------------------------------------------------*/
static int SingleXAction(SConnection * pCon, SicsInterp * pSics,
void *data, int argc, char *argv[])
{
pSICSOBJ self = data;
pSingleX priv = self->pPrivate;
double lambda;
assert(self != NULL);
assert(priv != NULL);
if (argc > 1) {
if (strcmp(argv[1], "lambda") == 0 && priv->lambdaVar != NULL) {
if (argc < 3) {
lambda = SXGetLambda();
SCPrintf(pCon, eValue, "singlex.lambda = %f", lambda);
return 1;
} else {
if (priv->lambdaDriv == NULL) {
VarSetFloat((pSicsVariable) priv->lambdaVar, atof(argv[2]),
SCGetRights(pCon));
return 1;
} else {
priv->lambdaDriv->SetValue(priv->lambdaVar, pCon, atof(argv[2]));
return 1;
}
}
}
}
return InterInvokeSICSOBJ(pCon, pSics, data, argc, argv);
}
/*---------------------------------------------------------------------------*/
static void SinglexKill(void *data)
{
pSingleX priv = data;
if (priv == NULL) {
return;
}
if (priv->spaceGroup->ListSeitzMx != NULL) {
free(priv->spaceGroup->ListSeitzMx);
}
if (priv->spaceGroup->ListRotMxInfo != NULL) {
free(priv->spaceGroup->ListRotMxInfo);
}
if (priv->spaceGroup != NULL) {
free(priv->spaceGroup);
}
if (priv->diffractometer != NULL) {
if (priv->diffractometer->motList > 0) {
LLDdelete(priv->diffractometer->motList);
}
if (priv->diffractometer->UB != NULL) {
mat_free(priv->diffractometer->UB);
}
}
free(priv);
}
/*---------------------------------------------------------------------------*/
int MakeSingleX(SConnection * pCon, SicsInterp * pSics,
void *data, int argc, char *argv[])
{
pSICSOBJ pNew = NULL;
pSingleX priv = NULL;
pHdb cmd = NULL, par = NULL, oldub;
pNew = MakeSICSOBJ("singlex", "SingleCrystalDiffraction");
priv = calloc(1, sizeof(SingleX));
if (pNew == NULL || priv == NULL) {
SCWrite(pCon, "ERROR: out of memory creating singlex", eError);
return 0;
}
priv->refl = CreateReflectionList(pCon, pSics, "ref");
priv->diffractometer = calloc(1, sizeof(SingleDiff));
priv->mode = Bisecting;
if (priv->refl == NULL || priv->diffractometer == NULL) {
SCWrite(pCon, "ERROR: out of memory creating singlex", eError);
return 0;
}
priv->diffractometer->motList = -1;
priv->diffractometer->UB = mat_creat(3, 3, UNIT_MATRIX);
priv->spaceGroup = calloc(1, sizeof(T_SgInfo));
if (priv->spaceGroup == NULL) {
return 0;
}
priv->spaceGroup->MaxList = 192;
priv->spaceGroup->ListSeitzMx =
malloc(192 * sizeof(*priv->spaceGroup->ListSeitzMx));
priv->spaceGroup->ListRotMxInfo =
malloc(192 * sizeof(*priv->spaceGroup->ListRotMxInfo));
if (priv->spaceGroup->ListSeitzMx == NULL
|| priv->spaceGroup->ListRotMxInfo == NULL) {
return 0;
}
InitSgInfo(priv->spaceGroup);
singlex = pNew;
pNew->pPrivate = priv;
pNew->KillPrivate = SinglexKill;
cmd =
AddSICSHdbPar(pNew->objectNode, "configure", usMugger,
MakeSICSFunc(ConfigureCmd));
AddSICSHdbPar(cmd, "device", usMugger, MakeHdbText(""));
AddSICSHdbPar(cmd, "name", usMugger, MakeHdbText(""));
cmd =
AddSICSHdbPar(pNew->objectNode, "motval", usSpy,
MakeSICSFunc(MotorCmd));
AddSICSHdbPar(cmd, "name", usMugger, MakeHdbText(""));
cmd =
AddSICSHdbPar(pNew->objectNode, "motnam", usSpy,
MakeSICSFunc(MotorNamCmd));
AddSICSHdbPar(cmd, "name", usMugger, MakeHdbText(""));
cmd =
AddSICSHdbPar(pNew->objectNode, "recoverub", usUser,
MakeSICSFunc(RecoverUBCmd));
cmd =
AddSICSHdbPar(pNew->objectNode, "cell", usUser,
makeHdbValue(HIPFLOATAR, 6));
SetHdbProperty(cmd, "__save", "true");
cmd =
AddSICSHdbPar(pNew->objectNode, "lattice", usInternal,
MakeHdbInt(0));
AppendHipadabaCallback(cmd,
MakeHipadabaCallback(GetLatticeCB, NULL, NULL));
cmd =
AddSICSHdbPar(pNew->objectNode, "oldub", usUser,
makeHdbValue(HIPFLOATAR, 9));
SetHdbProperty(cmd, "__save", "true");
oldub = cmd;
cmd =
AddSICSHdbPar(pNew->objectNode, "ub", usUser,
makeHdbValue(HIPFLOATAR, 9));
SetHdbProperty(cmd, "__save", "true");
PrependHipadabaCallback(cmd, MakeHipadabaCallback(SetUBCB, oldub, NULL));
cmd =
AddSICSHdbPar(pNew->objectNode, "planenormal", usUser,
makeHdbValue(HIPFLOATAR, 3));
SetHdbProperty(cmd, "__save", "true");
cmd = AddSICSHdbPar(pNew->objectNode, "mode", usUser, MakeHdbText("bi"));
SetHdbProperty(cmd, "__save", "true");
PrependHipadabaCallback(cmd,
MakeHipadabaCallback(SetModeCB, NULL, NULL));
cmd =
AddSICSHdbPar(pNew->objectNode, "spacegroup", usUser,
MakeHdbText("P"));
SetHdbProperty(cmd, "__save", "true");
PrependHipadabaCallback(cmd,
MakeHipadabaCallback(SetSpaceGroupCB, NULL,
NULL));
SetHipadabaPar(cmd, MakeHdbText("P"), pCon);
cmd =
AddSICSHdbPar(pNew->objectNode, "symref", usUser,
MakeSICSFunc(SymRefCmd));
AddSICSHdbPar(cmd, "h", usUser, MakeHdbInt(0));
AddSICSHdbPar(cmd, "k", usUser, MakeHdbInt(0));
AddSICSHdbPar(cmd, "l", usUser, MakeHdbInt(0));
cmd =
AddSICSHdbPar(pNew->objectNode, "sttub", usUser,
MakeSICSFunc(SttUBCmd));
AddSICSHdbPar(cmd, "h", usUser, MakeHdbFloat(.0));
AddSICSHdbPar(cmd, "k", usUser, MakeHdbFloat(.0));
AddSICSHdbPar(cmd, "l", usUser, MakeHdbFloat(.0));
cmd =
AddSICSHdbPar(pNew->objectNode, "peaksearch", usUser,
makeHdbValue(HIPNONE, 1));
SetHdbProperty(cmd, "__save", "true");
par = AddSICSHdbPar(cmd, "min2t", usUser, MakeHdbFloat(5.));
SetHdbProperty(par, "__save", "true");
par = AddSICSHdbPar(cmd, "step2t", usUser, MakeHdbFloat(1.));
SetHdbProperty(par, "__save", "true");
par = AddSICSHdbPar(cmd, "max2t", usUser, MakeHdbFloat(15.));
SetHdbProperty(par, "__save", "true");
par = AddSICSHdbPar(cmd, "stepchi", usUser, MakeHdbFloat(2.));
SetHdbProperty(par, "__save", "true");
par = AddSICSHdbPar(cmd, "stepphi", usUser, MakeHdbFloat(.5));
SetHdbProperty(par, "__save", "true");
par = AddSICSHdbPar(cmd, "stepom", usUser, MakeHdbFloat(.5));
SetHdbProperty(par, "__save", "true");
par = AddSICSHdbPar(cmd, "stepnu", usUser, MakeHdbFloat(.5));
SetHdbProperty(par, "__save", "true");
par = AddSICSHdbPar(cmd, "phimin", usUser, MakeHdbFloat(.0));
SetHdbProperty(par, "__save", "true");
par = AddSICSHdbPar(cmd, "phimax", usUser, MakeHdbFloat(180.));
SetHdbProperty(par, "__save", "true");
par = AddSICSHdbPar(cmd, "chimin", usUser, MakeHdbFloat(90.));
SetHdbProperty(par, "__save", "true");
par = AddSICSHdbPar(cmd, "chimax", usUser, MakeHdbFloat(180.));
SetHdbProperty(par, "__save", "true");
if (AddCommand(pSics, "singlex", SingleXAction, KillSICSOBJ, pNew)) {
HKLFactory(pCon, pSics, data, argc, argv);
HKLMotInstall(pCon, pSics, data, argc, argv);
CreateUBCalc(pCon, pSics, "ubcalcint", "hkl");
InstallFourMess(pCon, pSics);
MakeCone(pCon, pSics, data, argc, argv);
InitSimpleIndex(pCon, pSics);
} else {
SCWrite(pCon, "ERROR: duplicate initialization of singlex module",
eError);
return 0;
}
return 1;
}
/*---------------------------------------------------------------------------*/
pMotor SXGetMotor(MotorFunction m)
{
pSingleX priv = (pSingleX) singlex->pPrivate;
switch (m) {
case TwoTheta:
return priv->stt;
break;
case Omega:
return priv->om;
break;
case Chi:
return priv->chi;
break;
case Phi:
return priv->phi;
break;
case Nu:
return priv->nu;
break;
case Sgl:
return priv->sgl;
break;
case Sgu:
return priv->sgu;
break;
default:
return NULL;
}
return NULL;
}
/*---------------------------------------------------------------------------*/
const char *SXGetMotorName(MotorFunction m)
{
pMotor mot = SXGetMotor(m);
if (mot == NULL) {
return NULL;
} else {
return (const char *) mot->name;
}
}
/*--------------------------------------------------------------------------
* The technique used here is a bit funny. I do not wish to return something
* from a hdbValue data structure because either because it will be deleted
* in some stage or I introduce a memory leak. Thus I clean up everything here,
* make a copy in our private data structure and return that. Because that
* data structure will persist to the end of the program. Same for cell.
* -------------------------------------------------------------------------*/
const double *SXGetUB()
{
hdbValue v;
pHdb node = NULL;
pSingleX priv ;
assert(singlex != NULL);
priv= (pSingleX) singlex->pPrivate;
node = GetHipadabaNode(singlex->objectNode, "ub");
assert(node != NULL);
GetHipadabaPar(node, &v, NULL);
memcpy(priv->ub, v.v.floatArray, 9 * sizeof(double));
ReleaseHdbValue(&v);
return priv->ub;
}
/*--------------------------------------------------------------------------*/
void SXSetUB(double ub[9])
{
pHdb node = NULL;
if(singlex == NULL){
return;
}
pSingleX priv = (pSingleX) singlex->pPrivate;
node = GetHipadabaNode(singlex->objectNode, "ub");
assert(node != NULL);
SetHipadabaPar(node, MakeHdbFloatArray(9, ub), NULL);
}
/*------------------------------------------------------------------------*/
double *SXGetPlanenormal()
{
hdbValue v;
pHdb node = NULL;
pSingleX priv = (pSingleX) singlex->pPrivate;
double *normal = NULL;
node = GetHipadabaNode(singlex->objectNode, "planenormal");
assert(node != NULL);
GetHipadabaPar(node, &v, NULL);
normal = malloc(3 * sizeof(double));
if (normal == NULL) {
return NULL;
}
memcpy(normal, v.v.floatArray, 3 * sizeof(double));
ReleaseHdbValue(&v);
return normal;
}
/*--------------------------------------------------------------------------*/
void SXSetPlanenormal(double normal[3])
{
pHdb node = NULL;
pSingleX priv = (pSingleX) singlex->pPrivate;
node = GetHipadabaNode(singlex->objectNode, "planenormal");
assert(node != NULL);
SetHipadabaPar(node, MakeHdbFloatArray(3, normal), NULL);
}
/*--------------------------------------------------------------------------*/
const double *SXGetCell()
{
hdbValue v;
pHdb node = NULL;
pSingleX priv = (pSingleX) singlex->pPrivate;
node = GetHipadabaNode(singlex->objectNode, "cell");
assert(node != NULL);
GetHipadabaPar(node, &v, NULL);
memcpy(priv->cell, v.v.floatArray, 6 * sizeof(double));
ReleaseHdbValue(&v);
return priv->cell;
}
/*--------------------------------------------------------------------------*/
void SXSetCell(double cell[6])
{
pHdb node = NULL;
pSingleX priv = (pSingleX) singlex->pPrivate;
node = GetHipadabaNode(singlex->objectNode, "cell");
assert(node != NULL);
SetHipadabaPar(node, MakeHdbFloatArray(6, cell), NULL);
}
/*---------------------------------------------------------------------------*/
double SXGetLambda()
{
pSicsVariable lam = NULL;
float val;
hdbValue v;
pHdb node = NULL;
if(singlex == NULL){
return -99.9;
}
pSingleX priv = (pSingleX) singlex->pPrivate;
if (priv->lambdaDriv != NULL) {
return priv->lambdaDriv->GetValue(priv->lambdaVar, pServ->dummyCon);
} else if (priv->lambdaVar != NULL) {
lam = (pSicsVariable) priv->lambdaVar;
VarGetFloat(lam, &val);
return val;
}
node = GetHipadabaNode(singlex->objectNode, "lambda");
/* assert(node != NULL);
GetHipadabaPar(node, &v, pServ->dummyCon);
*/
if(node != NULL){
GetHipadabaPar(node, &v, pServ->dummyCon);
return v.v.doubleValue;
} else {
return 7.7;
}
}
/*---------------------------------------------------------------------------*/
pSICSOBJ SXGetReflectionList()
{
pSingleX priv = (pSingleX) singlex->pPrivate;
return priv->refl;
}
/*---------------------------------------------------------------------------*/
SingleXModes SXGetMode()
{
pSingleX priv = (pSingleX) singlex->pPrivate;
if(priv->mode == BiO){
return Bisecting;
} else {
return priv->mode;
}
}
/*---------------------------------------------------------------------------*/
T_SgInfo *SXGetSpaceGroup()
{
pSingleX priv = (pSingleX) singlex->pPrivate;
return priv->spaceGroup;
}
/*---------------------------------------------------------------------------*/
pSingleDiff SXGetDiffractometer()
{
const double *cell, *ub;
double lambda;
int i;
/* Not initialized.
* Trouble is motors need to be configured first, the we can set a diffractometer.
* If this is ever triggered, the most likely cause is that no mode was selected in the
* initialisation file.
*/
if(singlex == NULL){
return NULL;
}
pSingleX priv = (pSingleX) singlex->pPrivate;
if (priv->diffractometer->calculateSettings == NULL) {
return NULL;
}
cell = SXGetCell();
memcpy(priv->diffractometer->cell, cell, 6 * sizeof(double));
priv->diffractometer->lambda = SXGetLambda();
ub = SXGetUB();
for (i = 0; i < 3; i++) {
priv->diffractometer->UB[0][i] = ub[i];
priv->diffractometer->UB[1][i] = ub[i + 3];
priv->diffractometer->UB[2][i] = ub[i + 6];
}
return priv->diffractometer;
}
/*---------------------------------------------------------------------------*/
void SXSetMode(SingleXModes m)
{
pHdb node = NULL;
if(singlex == NULL){
return;
}
node = GetHipadabaNode(singlex->objectNode, "mode");
assert(node != NULL);
switch (m) {
case Bisecting:
SetHipadabaPar(node, MakeHdbText(strdup("bi")), NULL);
break;
case NB:
SetHipadabaPar(node, MakeHdbText(strdup("nb")), NULL);
break;
case Tas:
SetHipadabaPar(node, MakeHdbText(strdup("tas")), NULL);
break;
}
}