/** * 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 -1; } /*---------------------------------------------------------------------------*/ 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 < 0) { 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 < 0) { 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 < 0) { 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", 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 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, 512, "%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; 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; } }