/** * Reflection list: a configurable list of reflections and * their setting angles. To be used for four circle and possibly * TAS diffraction. * * copyright: see file COPYRIGHT * * Mark Koennecke, July 2008 */ #include #include #include "reflist.h" #include "sicshipadaba.h" #include "stptok.h" #define INAME "index" #define ANAME "angles" #define FLAG "flag" static char undef[] = "Undefined"; #define IDXFMT " %8.4f" #define ANGFMT " %8.2f" /*----------------------------------------------------------------------*/ typedef struct { int idxCount; int angCount; int count; } RLPriv, *pRLPriv; /*---------------------------------------------------------------------- * The point of the code below and the callback is to update the * configuration counts whenever the corresponding parameters * are changed. * ---------------------------------------------------------------------*/ static void UpdateConfiguration(pSICSOBJ refl) { pRLPriv priv = refl->pPrivate; hdbValue v; char *pPtr = NULL, token[50]; SICSHdbGetPar(refl, NULL, "indexheader", &v); pPtr = v.v.text; priv->idxCount = 0; while ((pPtr = stptok(pPtr, token, 50, ",")) != NULL) { priv->idxCount++; } SICSHdbGetPar(refl, NULL, "anglesheader", &v); pPtr = v.v.text; priv->angCount = 0; while ((pPtr = stptok(pPtr, token, 50, ",")) != NULL) { priv->angCount++; } ClearReflectionList(refl); } /*-----------------------------------------------------------------------*/ static hdbCallbackReturn CalcConfiguration(pHdb node, void *userData, pHdbMessage mm) { if (GetHdbSetMessage(mm) != NULL) { /* * This is after the normal SICS parameter SetUpdateCallback * which already updated the node */ UpdateConfiguration((pSICSOBJ) userData); } return hdbContinue; } /*-----------------------------------------------------------------------*/ static int SaveRefList(void *data, char *name, FILE * fd) { int i; double ang[4], hkl[3]; pSICSOBJ self = data; SaveSICSOBJ(data, name, fd); for (i = 0; i < ReflectionListCount(self); i++) { memset(hkl, 0, 3 * sizeof(double)); memset(ang, 0, 4 * sizeof(double)); GetRefIndex(self, i, hkl); GetRefAngles(self, i, ang); fprintf(fd, "%s addax %f %f %f %f %f %f %f\n", name, hkl[0], hkl[1], hkl[2], ang[0], ang[1], ang[2], ang[3]); } return 1; } /*-----------------------------------------------------------------------*/ pSICSOBJ MakeReflectionListInt(char *name) { pSICSOBJ pNew = NULL; pHdb node = NULL; hdbValue v; pRLPriv priv = NULL; pNew = MakeSICSOBJ(name, "ReflectionList"); priv = malloc(sizeof(RLPriv)); if (pNew == NULL || priv == NULL) { return NULL; } pNew->pPrivate = priv; pNew->KillPrivate = DefaultKill; pNew->pDes->SaveStatus = SaveRefList; v = MakeHdbText("h,k,l"); node = MakeSICSHdbPar("indexheader", usMugger, v); AppendHipadabaCallback(node, MakeHipadabaCallback(CalcConfiguration, pNew, NULL)); AddHipadabaChild(pNew->objectNode, node, NULL); priv->idxCount = 3; v = MakeHdbText("stt,om,chi,phi"); node = MakeSICSHdbPar("anglesheader", usMugger, v); AppendHipadabaCallback(node, MakeHipadabaCallback(CalcConfiguration, pNew, NULL)); AddHipadabaChild(pNew->objectNode, node, NULL); priv->angCount = 4; priv->count = 0; v = makeHdbValue(HIPNONE, 0); node = MakeSICSHdbPar("list", usMugger, v); AddHipadabaChild(pNew->objectNode, node, NULL); return pNew; } /*-----------------------------------------------------------------------*/ static int MakeCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { int status; status = NewListReflection(self); if (status >= 0) { SCPrintf(pCon, eValue, "newref = %4.4d", status); return 1; } else { SCWrite(pCon, "ERROR: failed to create reflection", eError); return 0; } return 0; } /*-----------------------------------------------------------------------*/ static int ClearCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { ClearReflectionList(self); return 1; } /*----------------------------------------------------------------------*/ static int AddIndexCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { char path[80]; int status; pHdb node = NULL; hdbValue v; if (nPar < 1) { SCWrite(pCon, "ERROR: need indexes as arguments", eError); return 0; } status = NewListReflection(self); snprintf(path, 80, "list/%4.4d/%s", status, INAME); node = GetHipadabaNode(self->objectNode, path); assert(node != NULL); cloneHdbValue(&node->value, &v); if (!readHdbValue(&v, par[0]->value.v.text, path, 80)) { SCPrintf(pCon, eError, "ERROR: failed to convert %s to indices", par[0]->value.v.text); return 0; } SetHipadabaPar(node, v, pCon); ReleaseHdbValue(&v); return 1; } /*----------------------------------------------------------------------*/ void AddRefIdx(pSICSOBJ refl, double hkl[]) { int status; hdbValue v; char path[80]; pHdb node; status = NewListReflection(refl); snprintf(path, 80, "list/%4.4d/%s", status, INAME); node = GetHipadabaNode(refl->objectNode, path); assert(node != NULL); v = MakeHdbFloatArray(3, hkl); SetHipadabaPar(node, v, NULL); } /*----------------------------------------------------------------------*/ void AddRefIdxAng(pSICSOBJ refl, double hkl[], double ang[]) { int status; hdbValue v; char path[80]; pHdb node; status = NewListReflection(refl); snprintf(path, 80, "list/%4.4d/%s", status, INAME); node = GetHipadabaNode(refl->objectNode, path); assert(node != NULL); v = MakeHdbFloatArray(3, hkl); SetHipadabaPar(node, v, NULL); snprintf(path, 80, "list/%4.4d/%s", status, ANAME); node = GetHipadabaNode(refl->objectNode, path); assert(node != NULL); v = MakeHdbFloatArray(3, ang); SetHipadabaPar(node, v, NULL); } /*----------------------------------------------------------------------*/ static int AddAnglesCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { char path[80]; int status; pHdb node = NULL; hdbValue v; if (nPar < 1) { SCWrite(pCon, "ERROR: need angles as arguments", eError); return 0; } status = NewListReflection(self); snprintf(path, 80, "list/%4.4d/%s", status, ANAME); node = GetHipadabaNode(self->objectNode, path); assert(node != NULL); cloneHdbValue(&node->value, &v); if (!readHdbValue(&v, par[0]->value.v.text, path, 80)) { SCPrintf(pCon, eError, "ERROR: failed to convert %s to angles", par[0]->value.v.text); return 0; } SetHipadabaPar(node, v, pCon); ReleaseHdbValue(&v); return 1; } /*----------------------------------------------------------------------*/ static int AddIndexesAnglesCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { char path[80]; int status, i; pHdb node = NULL; hdbValue v; char *pPtr = NULL; pRLPriv priv = self->pPrivate; if (nPar < 1) { SCWrite(pCon, "ERROR: need indexes/angles as arguments", eError); return 0; } status = NewListReflection(self); snprintf(path, 80, "list/%4.4d/%s", status, INAME); node = GetHipadabaNode(self->objectNode, path); assert(node != NULL); cloneHdbValue(&node->value, &v); if (!readHdbValue(&v, par[0]->value.v.text, path, 80)) { SCPrintf(pCon, eError, "ERROR: failed to convert %s to indices", par[0]->value.v.text); return 0; } SetHipadabaPar(node, v, pCon); ReleaseHdbValue(&v); /* advance pointer beyond indices */ pPtr = par[0]->value.v.text; for (i = 0; i < priv->idxCount; i++) { pPtr = stptok(pPtr, path, 80, " "); } snprintf(path, 80, "list/%4.4d/%s", status, ANAME); node = GetHipadabaNode(self->objectNode, path); assert(node != NULL); cloneHdbValue(&node->value, &v); if (!readHdbValue(&v, pPtr, path, 80)) { SCPrintf(pCon, eError, "ERROR: failed to convert %s to angles", par[0]->value.v.text); return 0; } SetHipadabaPar(node, v, pCon); ReleaseHdbValue(&v); return 1; } /*-----------------------------------------------------------------------*/ static int DelCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { pHdb node = NULL; char path[132]; if (nPar < 1) { SCWrite(pCon, "ERROR: need id to delete as argument", eError); return 0; } snprintf(path, 132, "list/%s", par[0]->value.v.text); node = GetHipadabaNode(self->objectNode, path); if (node != NULL) { DeleteHipadabaNode(node, pCon); return 1; } SCWrite(pCon, "ERROR: reflection not found", eError); return 0; } /*-----------------------------------------------------------------------*/ static int FlagCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { pHdb node = NULL; char path[132]; if (nPar < 1) { SCWrite(pCon, "ERROR: need id to flag for", eError); return 0; } snprintf(path, 132, "list/%s/%s", par[0]->value.v.text, FLAG); node = GetHipadabaNode(self->objectNode, path); if (node == NULL) { SCPrintf(pCon, eError, "ERROR: bad ID %s", par[0]->value.v.text); return 0; } if (nPar < 2) { SCPrintf(pCon, eValue, "%s.%s.flag = %d", self->pDes->name, par[0]->value.v.text, node->value.v.intValue); return 1; } else { SetHipadabaPar(node, par[1]->value, pCon); return 1; } return 0; } /*-----------------------------------------------------------------------*/ static int ShowCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { pHdb node = NULL; char path[132], num[20]; char data[1024]; hdbValue v; int i; if (nPar < 1) { SCWrite(pCon, "ERROR: need id for reflection to show", eError); return 0; } snprintf(path, 132, "list/%s/%s", par[0]->value.v.text, FLAG); node = GetHipadabaNode(self->objectNode, path); if (node == NULL) { SCPrintf(pCon, eError, "ERROR: bad ID %s", par[0]->value.v.text); return 0; } GetHipadabaPar(node, &v, pCon); snprintf(data, 1024, "%s %d", par[0]->value.v.text, v.v.intValue); snprintf(path, 132, "list/%s/%s", par[0]->value.v.text, INAME); node = GetHipadabaNode(self->objectNode, path); assert(node != NULL); GetHipadabaPar(node, &v, pCon); for (i = 0; i < v.arrayLength; i++) { snprintf(num, 20, " %f", v.v.floatArray[i]); strncat(data, num, 1024); } snprintf(path, 132, "list/%s/%s", par[0]->value.v.text, ANAME); node = GetHipadabaNode(self->objectNode, path); assert(node != NULL); GetHipadabaPar(node, &v, pCon); for (i = 0; i < v.arrayLength; i++) { snprintf(num, 20, " %f", v.v.floatArray[i]); strncat(data, num, 1024); } SCWrite(pCon, data, eValue); return 1; } /*-----------------------------------------------------------------------*/ static int ListCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { char buffer[132], path[132], *pPtr, token[20], entry[20]; pRLPriv priv = self->pPrivate; int i; pHdb node = NULL, data; pDynString txt; SCStartBuffering(pCon); /* * build header */ strcpy(buffer, " ID FLAG"); node = GetHipadabaNode(self->objectNode, "indexheader"); assert(node != NULL); pPtr = node->value.v.text; while ((pPtr = stptok(pPtr, token, 20, ",")) != NULL) { snprintf(entry, 20, " %8s", token); strncat(buffer, entry, 132); } node = GetHipadabaNode(self->objectNode, "anglesheader"); assert(node != NULL); pPtr = node->value.v.text; while ((pPtr = stptok(pPtr, token, 20, ",")) != NULL) { snprintf(entry, 20, " %8s", token); strncat(buffer, entry, 132); } SCWrite(pCon, buffer, eValue); node = GetHipadabaNode(self->objectNode, "list"); node = node->child; while (node != NULL) { data = GetHipadabaNode(node, FLAG); assert(data != NULL); snprintf(buffer, 132, " %5s %4d", node->name, data->value.v.intValue); data = GetHipadabaNode(node, INAME); for (i = 0; i < priv->idxCount; i++) { sprintf(entry, IDXFMT, data->value.v.floatArray[i]); strncat(buffer, entry, 132); } data = GetHipadabaNode(node, ANAME); for (i = 0; i < priv->angCount; i++) { sprintf(entry, ANGFMT, data->value.v.floatArray[i]); strncat(buffer, entry, 132); } SCWrite(pCon, buffer, eValue); node = node->next; } txt = SCEndBuffering(pCon); SCWrite(pCon, GetCharArray(txt), eValue); return 1; } /*-----------------------------------------------------------------------*/ static int NamesCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { char buffer[132]; pHdb node = NULL; pDynString txt; SCStartBuffering(pCon); node = GetHipadabaNode(self->objectNode, "list"); node = node->child; while (node != NULL) { snprintf(buffer, 132, "%s", node->name); SCWrite(pCon, buffer, eValue); node = node->next; } txt = SCEndBuffering(pCon); SCWrite(pCon, GetCharArray(txt), eValue); return 1; } /*----------------------------------------------------------------------*/ static int SetIndexCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { char path[80]; int status; pHdb node = NULL; hdbValue v; char *pPtr = NULL, refl[20]; if (nPar < 1) { SCWrite(pCon, "ERROR: need id and indexes as arguments", eError); return 0; } pPtr = par[0]->value.v.text; pPtr = stptok(pPtr, refl, 20, " "); snprintf(path, 80, "list/%s/%s", refl, INAME); node = GetHipadabaNode(self->objectNode, path); assert(node != NULL); cloneHdbValue(&node->value, &v); if (!readHdbValue(&v, pPtr, path, 80)) { SCPrintf(pCon, eError, "ERROR: failed to convert %s to indices", par[0]->value.v.text); return 0; } SetHipadabaPar(node, v, pCon); ReleaseHdbValue(&v); return 1; } /*----------------------------------------------------------------------*/ static int SetAnglesCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { char path[80]; int status; pHdb node = NULL; hdbValue v; char *pPtr = NULL, refl[20]; if (nPar < 1) { SCWrite(pCon, "ERROR: need id and angles as arguments", eError); return 0; } pPtr = par[0]->value.v.text; pPtr = stptok(pPtr, refl, 20, " "); snprintf(path, 80, "list/%s/%s", refl, ANAME); node = GetHipadabaNode(self->objectNode, path); if (node == NULL) { SCPrintf(pCon, eError, "ERROR: reflection with ID %s not found", refl); return 0; } cloneHdbValue(&node->value, &v); if (!readHdbValue(&v, pPtr, path, 80)) { SCPrintf(pCon, eError, "ERROR: failed to convert %s to angles", par[0]->value.v.text); return 0; } SetHipadabaPar(node, v, pCon); ReleaseHdbValue(&v); return 1; } /*-----------------------------------------------------------------------*/ int MakeReflectionList(SConnection * pCon, SicsInterp * pSics, void *data, int argc, char *argv[]) { pSICSOBJ pNew = NULL; pHdb cmd; if (argc < 2) { SCWrite(pCon, "ERROR: need name of reflection list", eError); return 0; } pNew = CreateReflectionList(pCon, pSics, argv[1]); if (pNew == NULL) { return 0; } return 1; } /*------------------------------------------------------------------------*/ pSICSOBJ CreateReflectionList(SConnection * pCon, SicsInterp * pSics, char *name) { pSICSOBJ pNew = NULL; pHdb cmd; pNew = MakeReflectionListInt(name); if (pNew == NULL) { SCWrite(pCon, "ERROR: failed to create reflection list", eError); return 0; } /* command initialization */ AddSICSHdbPar(pNew->objectNode, "make", usUser, MakeSICSFunc(MakeCmd)); AddSICSHdbPar(pNew->objectNode, "clear", usUser, MakeSICSFunc(ClearCmd)); AddSICSHdbPar(pNew->objectNode, "print", usUser, MakeSICSFunc(ListCmd)); AddSICSHdbPar(pNew->objectNode, "names", usUser, MakeSICSFunc(NamesCmd)); cmd = AddSICSHdbPar(pNew->objectNode, "del", usUser, MakeSICSFunc(DelCmd)); AddSICSHdbPar(cmd, "id", usUser, MakeHdbText("")); cmd = AddSICSHdbPar(pNew->objectNode, "addx", usUser, MakeSICSFunc(AddIndexCmd)); AddSICSHdbPar(cmd, "args", usUser, MakeHdbText("")); cmd = AddSICSHdbPar(pNew->objectNode, "setx", usUser, MakeSICSFunc(SetIndexCmd)); AddSICSHdbPar(cmd, "args", usUser, MakeHdbText("")); cmd = AddSICSHdbPar(pNew->objectNode, "adda", usUser, MakeSICSFunc(AddAnglesCmd)); AddSICSHdbPar(cmd, "args", usUser, MakeHdbText("")); cmd = AddSICSHdbPar(pNew->objectNode, "seta", usUser, MakeSICSFunc(SetAnglesCmd)); AddSICSHdbPar(cmd, "args", usUser, MakeHdbText("")); cmd = AddSICSHdbPar(pNew->objectNode, "addax", usUser, MakeSICSFunc(AddIndexesAnglesCmd)); AddSICSHdbPar(cmd, "args", usUser, MakeHdbText("")); cmd = AddSICSHdbPar(pNew->objectNode, "flag", usUser, MakeSICSFunc(FlagCmd)); AddSICSHdbPar(cmd, "id", usUser, MakeHdbText("")); AddSICSHdbPar(cmd, "value", usUser, MakeHdbInt(0)); cmd = AddSICSHdbPar(pNew->objectNode, "show", usUser, MakeSICSFunc(ShowCmd)); AddSICSHdbPar(cmd, "id", usUser, MakeHdbText("")); AddCommand(pSics, name, InterInvokeSICSOBJ, KillSICSOBJ, pNew); return pNew; } /*------------------------------------------------------------------------*/ void ClearReflectionList(pSICSOBJ refl) { pHdb node = NULL; hdbValue v; pRLPriv priv = refl->pPrivate; node = GetHipadabaNode(refl->objectNode, "list"); assert(node); DeleteHipadabaNode(node, NULL); v = makeHdbValue(HIPNONE, 0); node = MakeSICSHdbPar("list", usMugger, v); AddHipadabaChild(refl->objectNode, node, NULL); priv->count = 0; } /*-------------------------------------------------------------------------*/ int ReflectionListCount(pSICSOBJ refl) { pHdb node = NULL; node = GetHipadabaNode(refl->objectNode, "list"); assert(node); return CountHdbChildren(node); } /*-------------------------------------------------------------------------*/ int NewListReflection(pSICSOBJ refl) { int count; char path[20]; pHdb listNode = NULL, node = NULL, refNode = NULL; hdbValue v; pRLPriv priv = refl->pPrivate; listNode = GetHipadabaNode(refl->objectNode, "list"); assert(listNode); count = priv->count; priv->count++; snprintf(path, 20, "%4.4d", count); node = MakeHipadabaNode(path, HIPNONE, 0); AddHipadabaChild(listNode, node, NULL); v = makeHdbValue(HIPFLOATAR, priv->idxCount); AddSICSHdbPar(node, INAME, usUser, v); v = makeHdbValue(HIPFLOATAR, priv->angCount); AddSICSHdbPar(node, ANAME, usUser, v); v = makeHdbValue(HIPINT, 0); AddSICSHdbPar(node, FLAG, usUser, v); return count; } /*--------------------------------------------------------------------------*/ static pHdb findReflection(pSICSOBJ refl, int idx) { pHdb node = NULL; int count = 0; if (idx < 0) { return node; } node = GetHipadabaNode(refl->objectNode, "list"); assert(node); node = node->child; while (node != NULL && count != idx) { count++; node = node->next; } return node; } /*---------------------------------------------------------------------------*/ void DelListReflection(pSICSOBJ refl, int idx) { pHdb node = NULL; node = findReflection(refl, idx); if (node != NULL) { DeleteHipadabaNode(node, NULL); } } /*-----------------------------------------------------------------------------*/ int SetRefIndex(pSICSOBJ refl, int idx, double hkl[]) { pHdb node = NULL; hdbValue v; pRLPriv priv = refl->pPrivate; node = findReflection(refl, idx); if (node != NULL) { node = GetHipadabaNode(node, INAME); assert(node); v = MakeHdbFloatArray(priv->idxCount, hkl); SetHipadabaPar(node, v, NULL); return 1; } else { return 0; } } /*-----------------------------------------------------------------------------*/ int SetRefAngles(pSICSOBJ refl, int idx, double ang[]) { pHdb node = NULL; hdbValue v; pRLPriv priv = refl->pPrivate; node = findReflection(refl, idx); if (node != NULL) { node = GetHipadabaNode(node, ANAME); assert(node); v = MakeHdbFloatArray(priv->angCount, ang); SetHipadabaPar(node, v, NULL); return 1; } else { return 0; } } /*-----------------------------------------------------------------------------*/ int SetRefFlag(pSICSOBJ refl, int idx, int val) { pHdb node = NULL; hdbValue v; pRLPriv priv = refl->pPrivate; node = findReflection(refl, idx); if (node != NULL) { node = GetHipadabaNode(node, FLAG); assert(node); v = MakeHdbInt(val); SetHipadabaPar(node, v, NULL); return 1; } else { return 0; } } /*-------------------------------------------------------------------------------*/ int GetRefIndex(pSICSOBJ refl, int idx, double hkl[]) { pHdb node = NULL; pRLPriv priv = refl->pPrivate; node = findReflection(refl, idx); if (node != NULL) { node = GetHipadabaNode(node, INAME); assert(node); memcpy(hkl, node->value.v.floatArray, priv->idxCount * sizeof(double)); return 1; } else { return 0; } } /*-------------------------------------------------------------------------------*/ int GetRefIndexID(pSICSOBJ refl, char *id, double hkl[]) { pHdb node = NULL; pRLPriv priv = refl->pPrivate; char path[132]; snprintf(path, 132, "list/%s", id); node = GetHipadabaNode(refl->objectNode, path); if (node != NULL) { node = GetHipadabaNode(node, INAME); assert(node); memcpy(hkl, node->value.v.floatArray, priv->idxCount * sizeof(double)); return 1; } else { return 0; } } /*-------------------------------------------------------------------------------*/ int GetRefAngles(pSICSOBJ refl, int idx, double ang[]) { pHdb node = NULL; pRLPriv priv = refl->pPrivate; node = findReflection(refl, idx); if (node != NULL) { node = GetHipadabaNode(node, ANAME); assert(node); memcpy(ang, node->value.v.floatArray, priv->angCount * sizeof(double)); return 1; } else { return 0; } } /*-------------------------------------------------------------------------------*/ int GetRefAnglesID(pSICSOBJ refl, char *id, double hkl[]) { pHdb node = NULL; pRLPriv priv = refl->pPrivate; char path[132]; snprintf(path, 132, "list/%s", id); node = GetHipadabaNode(refl->objectNode, path); if (node != NULL) { node = GetHipadabaNode(node, ANAME); assert(node); memcpy(hkl, node->value.v.floatArray, priv->angCount * sizeof(double)); return 1; } else { return 0; } } /*-------------------------------------------------------------------------------*/ int GetRefFlag(pSICSOBJ refl, int idx) { pHdb node = NULL; pRLPriv priv = refl->pPrivate; node = findReflection(refl, idx); if (node != NULL) { node = GetHipadabaNode(node, FLAG); assert(node); return node->value.v.intValue; } else { return -1; } } /*--------------------------------------------------------------------------------*/ char *GetRefName(pSICSOBJ refl, int idx) { pHdb node = NULL; node = findReflection(refl, idx); if (node != NULL) { return node->name; } else { return undef; } }