/** * 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 * * Fixed saving of anglesheader status * * Mark Koennecke, September 2009 */ #include #include #include "reflist.h" #include "sicshipadaba.h" #include "stptok.h" #include "hdbtable.h" #define INAME "index" #define ANAME "angles" #define FLAG "flag" static char undef[] = "Undefined"; #define IDXFMT " %8.4f" #define ANGFMT " %8.2f" #define ABS(x) (x < 0 ? -(x) : (x)) int CountTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, pHdb par[], int nPar); /* from hdbtable.c */ /*----------------------------------------------------------------------*/ typedef struct { int idxCount; int angCount; int count; } RLPriv, *pRLPriv; /*-----------------------------------------------------------------------*/ int SaveRefList(void *data, char *name, FILE * fd) { pHdb node = NULL; pSICSOBJ self = (pSICSOBJ)data; node = GetHipadabaNode(self->objectNode,"anglesheader"); fprintf(fd,"%s anglesheader %s\n", name, node->value.v.text); SaveHdbTable(data,name,fd); return 1; } /*---------------------------------------------------------------------- * 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]; pHdb template, node; template = GetHipadabaNode(refl->objectNode,"template"); if(template != NULL){ DeleteHipadabaNode(template,NULL); } template = MakeHipadabaNode("template",HIPNONE, 1); AddHipadabaChild(refl->objectNode, template, NULL); SICSHdbGetPar(refl, NULL, "indexheader", &v); pPtr = v.v.text; priv->idxCount = 0; while ((pPtr = stptok(pPtr, token, 50, ",")) != NULL) { node = MakeHipadabaNode(token,HIPFLOAT,1); AddHipadabaChild(template,node,NULL); priv->idxCount++; } SICSHdbGetPar(refl, NULL, "anglesheader", &v); pPtr = v.v.text; priv->angCount = 0; while ((pPtr = stptok(pPtr, token, 50, ",")) != NULL) { node = MakeHipadabaNode(token,HIPFLOAT,1); AddHipadabaChild(template,node,NULL); priv->angCount++; } node = GetHipadabaNode(refl->objectNode,"clear"); assert(node != NULL); runObjFunction(refl,pServ->dummyCon,node); node = GetHipadabaNode(refl->objectNode,"readtemplate"); assert(node != NULL); runObjFunction(refl,pServ->dummyCon,node); } /*-----------------------------------------------------------------------*/ 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; } /*-----------------------------------------------------------------------*/ pSICSOBJ MakeReflectionListInt(char *name) { pSICSOBJ pNew = NULL; pHdb node = NULL; hdbValue v; pRLPriv priv = NULL; pNew = MakeHdbTable(name, "ReflectionList"); priv = malloc(sizeof(RLPriv)); if (pNew == NULL || priv == NULL) { return NULL; } pNew->pPrivate = priv; pNew->KillPrivate = DefaultKill; 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", usUser, v); AppendHipadabaCallback(node, MakeHipadabaCallback(CalcConfiguration, pNew, NULL)); AddHipadabaChild(pNew->objectNode, node, NULL); UpdateConfiguration(pNew); priv->angCount = 4; priv->count = 0; return pNew; } /*----------------------------------------------------------------------*/ static int AddIndexCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { char path[80]; int status, i; pHdb node = NULL, addrowNode = NULL; hdbValue v; if (nPar < 3) { SCWrite(pCon, "ERROR: need indexes as arguments", eError); return 0; } addrowNode = GetHipadabaNode(self->objectNode,"addrow"); assert(addrowNode != NULL); /* copy HKL */ node = addrowNode->child; UpdateHipadabaPar(node, par[0]->value, pCon); node = node->next; UpdateHipadabaPar(node, par[1]->value, pCon); node = node->next; UpdateHipadabaPar(node, par[2]->value, pCon); /* set angles to zero */ node = node->next; v = MakeHdbFloat(.0); while(node != NULL){ UpdateHipadabaPar(node,v,pCon); node = node->next; } return runObjFunction(self, pCon, addrowNode); } /*----------------------------------------------------------------------*/ void AddRefIdx(pSICSOBJ refl, double hkl[]) { int status; hdbValue v; pHdb node, child; node = GetHipadabaNode(refl->objectNode,"addrow"); assert(node != NULL); child = node->child; UpdateHipadabaPar(child, MakeHdbFloat(hkl[0]),NULL); child = child->next; UpdateHipadabaPar(child, MakeHdbFloat(hkl[1]),NULL); child = child->next; UpdateHipadabaPar(child, MakeHdbFloat(hkl[2]),NULL); v = MakeHdbFloat(.0); child = child->next; if(child != NULL){ UpdateHipadabaPar(child, v,NULL); } child = child->next; if(child != NULL){ UpdateHipadabaPar(child, v,NULL); } child = child->next; if(child != NULL){ UpdateHipadabaPar(child, v,NULL); } child = child->next; if(child != NULL){ UpdateHipadabaPar(child, v,NULL); } runObjFunction(refl, pServ->dummyCon, node); } /*----------------------------------------------------------------------*/ static void AddRowIntern(pSICSOBJ refl, double hkl[], double ang[], SConnection *pCon) { int status; hdbValue v; pHdb node, child; node = GetHipadabaNode(refl->objectNode,"addrow"); assert(node != NULL); child = node->child; UpdateHipadabaPar(child, MakeHdbFloat(hkl[0]),NULL); child = child->next; UpdateHipadabaPar(child, MakeHdbFloat(hkl[1]),NULL); child = child->next; UpdateHipadabaPar(child, MakeHdbFloat(hkl[2]),NULL); child = child->next; if(child != NULL){ UpdateHipadabaPar(child, MakeHdbFloat(ang[0]),NULL); } child = child->next; if(child != NULL){ UpdateHipadabaPar(child, MakeHdbFloat(ang[1]),NULL); } child = child->next; if(child != NULL){ UpdateHipadabaPar(child, MakeHdbFloat(ang[2]),NULL); } child = child->next; if(child != NULL){ UpdateHipadabaPar(child, MakeHdbFloat(ang[3]),NULL); } if(child != NULL){ child = child->next; if(child != NULL){ UpdateHipadabaPar(child, MakeHdbFloat(ang[4]),NULL); } } runObjFunction(refl, pCon, node); } /*----------------------------------------------------------------------*/ void AddRefIdxAng(pSICSOBJ refl, double hkl[], double ang[]) { AddRowIntern(refl,hkl,ang,pServ->dummyCon); } /*----------------------------------------------------------------------*/ static int AddAnglesCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { int i; double hkl[3], ang[5]; memset(hkl,0,3*sizeof(double)); memset(ang,0,4*sizeof(double)); for(i = 0; i < nPar; i++){ ang[i] = par[i]->value.v.doubleValue; } AddRowIntern(self,hkl,ang,pCon); return 1; } /*----------------------------------------------------------------------*/ static int AddIndexesAnglesCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { pHdb node = NULL, addrowNode; hdbValue v; pRLPriv priv = self->pPrivate; if (nPar < 6) { SCWrite(pCon, "ERROR: need indexes/angles as arguments", eError); return 0; } addrowNode = GetHipadabaNode(self->objectNode,"addrow"); assert(addrowNode != NULL); /* copy HKL */ node = addrowNode->child; UpdateHipadabaPar(node, par[0]->value, pCon); node = node->next; UpdateHipadabaPar(node, par[1]->value, pCon); node = node->next; UpdateHipadabaPar(node, par[2]->value, pCon); /* copy angles */ v = MakeHdbFloat(.0); node = node->next; if(node != NULL && nPar > 3){ UpdateHipadabaPar(node, par[3]->value, pCon); } else if(node != NULL) { UpdateHipadabaPar(node, v, pCon); } node = node->next; if(node != NULL && nPar > 4){ UpdateHipadabaPar(node, par[4]->value, pCon); } else if(node!= NULL) { UpdateHipadabaPar(node, v, pCon); } node = node->next; if(node != NULL && nPar > 5){ UpdateHipadabaPar(node, par[5]->value, pCon); } else if (node != NULL) { UpdateHipadabaPar(node, v, pCon); } node = node->next; if(node != NULL && nPar > 6){ UpdateHipadabaPar(node, par[6]->value, pCon); } else if(node!= NULL) { UpdateHipadabaPar(node, v, pCon); } if(node != NULL){ node = node->next; if(node != NULL && nPar > 7){ UpdateHipadabaPar(node, par[7]->value, pCon); } else if(node!= NULL) { UpdateHipadabaPar(node, v, pCon); } } return runObjFunction(self, pCon, addrowNode); } /*-----------------------------------------------------------------------*/ static int ShowCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { pHdb row = NULL, child = 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, "data/%s", par[0]->value.v.text); row = GetHipadabaNode(self->objectNode, path); if (row == NULL) { SCPrintf(pCon, eError, "ERROR: bad ID %s", par[0]->value.v.text); return 0; } child = row->child; strlcpy(data,par[0]->value.v.text,1023); strcat(data," 1"); while(child != NULL){ snprintf(num,20," %f",child->value.v.doubleValue); strcat(data,num); child = child->next; } SCWrite(pCon, data, eValue); return 1; } /*-----------------------------------------------------------------------*/ const char *FindHKL(pSICSOBJ self, double h, double k, double l) { pHdb node, idx; node = GetHipadabaNode(self->objectNode, "data"); node = node->child; while(node != NULL){ idx = node->child; if(ABS(idx->value.v.doubleValue-h) > .1){ node = node->next; continue; } idx = idx->next; if(ABS(idx->value.v.doubleValue-k) > .1){ node = node->next; continue; } idx = idx->next; if(ABS(idx->value.v.doubleValue-l) < .1){ return node->name; } node = node->next; } return NULL; } /*-----------------------------------------------------------------------*/ static int NamesCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { char buffer[132]; pHdb node = NULL; pDynString txt; txt = CreateDynString(256,256); if(txt == NULL){ SCWrite(pCon,"ERROR: out of memory listing names", eError); return 0; } node = GetHipadabaNode(self->objectNode, "data"); node = node->child; while (node != NULL) { snprintf(buffer, 132, "%s", node->name); DynStringConcatLine(txt,buffer); node = node->next; } SCWrite(pCon, GetCharArray(txt), eValue); DeleteDynString(txt); return 1; } /*----------------------------------------------------------------------*/ static int RelabelCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { char buffer[10]; pHdb node = NULL; int count = 0; node = GetHipadabaNode(self->objectNode, "data"); node = node->child; while (node != NULL) { snprintf(buffer,sizeof(buffer),"%4.4d", count); if(node->name != NULL){ free(node->name); node->name = strdup(buffer); } count++; node = node->next; } return 1; } /*----------------------------------------------------------------------*/ static int SetIndexCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { char path[80]; int i; pHdb row = NULL, child; if (nPar < 4) { SCWrite(pCon, "ERROR: need id and indexes as arguments", eError); return 0; } snprintf(path,80,"data/%s", par[0]->value.v.text); row = GetHipadabaNode(self->objectNode, path); if(row == NULL){ SCPrintf(pCon,eError, "ERROR: reflection with ID %s not found", par[0]->value.v.text); return 0; } child = row->child; for(i = 0; i < 3; i++, child = child->next){ if(child != NULL){ UpdateHipadabaPar(child, par[i+1]->value, pCon); } } SCSendOK(pCon); return 1; } /*----------------------------------------------------------------------*/ static int SetAnglesCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { char path[80]; int i; pHdb row = NULL, child; hdbValue v; if (nPar < 4) { SCWrite(pCon, "ERROR: need id and angles as arguments", eError); return 0; } snprintf(path,80,"data/%s", par[0]->value.v.text); row = GetHipadabaNode(self->objectNode, path); if(row == NULL){ SCPrintf(pCon,eError, "ERROR: reflection with ID %s not found", par[0]->value.v.text); return 0; } child = row->child; /* skip over hkl */ for(i = 0; i < 3; i++, child = child->next) {} /* do angles */ v = MakeHdbFloat(.0); for(i = 0; i < 5 && child != NULL; i++, child = child->next){ if(child != NULL){ UpdateHipadabaPar(child, par[i+1]->value, pCon); } } SCSendOK(pCon); 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; } pNew->pDes->SaveStatus = SaveRefList; AddSICSHdbPar(pNew->objectNode, "names", usUser, MakeSICSFunc(NamesCmd)); cmd = AddSICSHdbPar(pNew->objectNode, "addx", usUser, MakeSICSFunc(AddIndexCmd)); SetHdbProperty(cmd,"type","command"); SetHdbProperty(cmd,"priv","user"); AddSICSHdbPar(cmd, "h", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "k", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "l", usUser, MakeHdbFloat(.0)); cmd = AddSICSHdbPar(pNew->objectNode, "setx", usUser, MakeSICSFunc(SetIndexCmd)); SetHdbProperty(cmd,"type","command"); SetHdbProperty(cmd,"priv","user"); AddSICSHdbPar(cmd, "id", usUser, MakeHdbText("")); AddSICSHdbPar(cmd, "h", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "k", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "l", usUser, MakeHdbFloat(.0)); cmd = AddSICSHdbPar(pNew->objectNode, "adda", usUser, MakeSICSFunc(AddAnglesCmd)); SetHdbProperty(cmd,"type","command"); SetHdbProperty(cmd,"priv","user"); AddSICSHdbPar(cmd, "stt", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "om", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "chi", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "phi", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "nu", usUser, MakeHdbFloat(.0)); cmd = AddSICSHdbPar(pNew->objectNode, "seta", usUser, MakeSICSFunc(SetAnglesCmd)); SetHdbProperty(cmd,"type","command"); SetHdbProperty(cmd,"priv","user"); AddSICSHdbPar(cmd, "id", usUser, MakeHdbText("")); AddSICSHdbPar(cmd, "stt", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "om", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "chi", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "phi", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "nu", usUser, MakeHdbFloat(.0)); cmd = AddSICSHdbPar(pNew->objectNode, "addax", usUser, MakeSICSFunc(AddIndexesAnglesCmd)); SetHdbProperty(cmd,"type","command"); SetHdbProperty(cmd,"priv","user"); AddSICSHdbPar(cmd, "h", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "k", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "l", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "stt", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "om", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "chi", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "phi", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "nu", usUser, MakeHdbFloat(.0)); cmd = AddSICSHdbPar(pNew->objectNode, "show", usUser, MakeSICSFunc(ShowCmd)); SetHdbProperty(cmd,"type","command"); SetHdbProperty(cmd,"priv","user"); AddSICSHdbPar(cmd, "id", usUser, MakeHdbText("")); cmd = AddSICSHdbPar(pNew->objectNode, "count", usUser, MakeSICSFunc(CountTblCmd)); cmd = AddSICSHdbPar(pNew->objectNode, "relabel", usUser, MakeSICSFunc(RelabelCmd)); 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, "clear"); assert(node != NULL); runObjFunction(refl,pServ->dummyCon,node); priv->count = 0; } /*-------------------------------------------------------------------------*/ int ReflectionListCount(pSICSOBJ refl) { pHdb node = NULL; node = GetHipadabaNode(refl->objectNode, "data"); assert(node); return CountHdbChildren(node); } /*--------------------------------------------------------------------------*/ static pHdb findReflection(pSICSOBJ refl, int idx) { pHdb node = NULL; int count = 0; if (idx < 0) { return node; } node = GetHipadabaNode(refl->objectNode, "data"); 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, child; int i; pRLPriv priv = refl->pPrivate; node = findReflection(refl, idx); if (node != NULL) { child = node->child; for(i = 0; i < 3; i++, child = child->next){ if(child != NULL){ UpdateHipadabaPar(child, MakeHdbFloat(hkl[i]), NULL); } } return 1; } else { return 0; } } /*-----------------------------------------------------------------------------*/ int SetRefAngles(pSICSOBJ refl, int idx, double ang[]) { pHdb node = NULL, child = NULL; hdbValue v; int i; pRLPriv priv = refl->pPrivate; node = findReflection(refl, idx); if (node != NULL) { child = node->child; /* skip over hkl */ for(i = 0; i < 3; i++, child = child->next){} /* set angles */ for(i = 0; i < 5; i++, child = child->next){ if(child != NULL){ UpdateHipadabaPar(child, MakeHdbFloat(ang[i]), NULL); } } return 1; } else { return 0; } } /*-------------------------------------------------------------------------------*/ int GetRefIndex(pSICSOBJ refl, int idx, double hkl[]) { pHdb node = NULL, child; int i; pRLPriv priv = refl->pPrivate; node = findReflection(refl, idx); if (node != NULL) { child = node->child; for(i = 0; i < 3; i++, child = child->next){ hkl[i] = child->value.v.doubleValue; } return 1; } else { return 0; } } /*-------------------------------------------------------------------------------*/ int GetRefIndexID(pSICSOBJ refl, char *id, double hkl[]) { pHdb node = NULL, child; pRLPriv priv = refl->pPrivate; char path[132]; int i; snprintf(path, 132, "data/%s", id); node = GetHipadabaNode(refl->objectNode, path); if (node != NULL) { child = node->child; for(i = 0; i < 3; i++, child = child->next){ hkl[i] = child->value.v.doubleValue; } return 1; } else { return 0; } } /*-------------------------------------------------------------------------------*/ int GetRefAngles(pSICSOBJ refl, int idx, double ang[]) { pHdb node = NULL, child; pRLPriv priv = refl->pPrivate; int i; node = findReflection(refl, idx); if (node != NULL) { child = node->child; /* skip hkl */ for(i = 0; i < 3; i++, child = child->next){} /* do angles */ for(i = 0; i < 5 && child != NULL; i++, child = child->next){ ang[i] = child->value.v.doubleValue; } return 1; } else { return 0; } } /*-------------------------------------------------------------------------------*/ int GetRefAnglesID(pSICSOBJ refl, char *id, double ang[]) { pHdb node = NULL, child; pRLPriv priv = refl->pPrivate; char path[132]; int i; snprintf(path, 132, "data/%s", id); node = GetHipadabaNode(refl->objectNode, path); if (node != NULL) { child = node->child; /* skip hkl */ for(i = 0; i < 3; i++, child = child->next){} /* do angles */ for(i = 0; i < 5 && child != NULL; i++, child = child->next){ ang[i] = child->value.v.doubleValue; } return 1; } else { return 0; } } /*--------------------------------------------------------------------------------*/ char *GetRefName(pSICSOBJ refl, int idx) { pHdb node = NULL; node = findReflection(refl, idx); if (node != NULL) { return node->name; } else { return undef; } }