965 lines
27 KiB
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;
|
|
}
|
|
}
|