/*---------------------------------------------------------------------- UB calculation routines for four circle diffraction. This is the interpreter interface to functionality implemented in fourlib.c copyright: see file COPYRIGHT Mark Koennecke, March 2005 -----------------------------------------------------------------------*/ #include #include #include #include "tcl.h" #include "fortify.h" #include "sics.h" #include "ubfour.h" #include "ubcalc.h" #include "motor.h" #include "hkl.h" /*---------------------------------------------------------------------*/ typedef struct { pObjectDescriptor pDes; lattice direct; reflection r1, r2; MATRIX UB; } UBCALC, *pUBCALC; /*----------------------------------------------------------------------*/ static void killUBCALC(void *pData){ pUBCALC self = (pUBCALC)pData; if(self == NULL){ return; } if(self->pDes != NULL){ DeleteDescriptor(self->pDes); } if(self->UB != NULL){ mat_free(self->UB); } free(self); } /*--------------------------------------------------------------------*/ static int SaveUBCalc(void *data, char *name, FILE *fd){ pUBCALC self = (pUBCALC)data; if(self == NULL){ return 0; } fprintf(fd,"%s cell %f %f %f %f %f %f\n", name, self->direct.a, self->direct.b, self->direct.c, self->direct.alpha, self->direct.beta, self->direct.gamma); fprintf(fd,"%s ref1 %f %f %f %f %f %f %f\n",name, self->r1.h, self->r1.k, self->r1.l, self->r1.s2t, self->r1.om, self->r1.chi, self->r1.phi); fprintf(fd,"%s ref2 %f %f %f %f %f %f %f\n",name, self->r2.h, self->r2.k, self->r2.l, self->r2.s2t, self->r2.om, self->r2.chi, self->r2.phi); return 1; } /*---------------------------------------------------------------------*/ static pUBCALC makeUBCALC(){ pUBCALC pNew = NULL; pNew = (pUBCALC)malloc(sizeof(UBCALC)); if(pNew == NULL){ return NULL; } memset(pNew,0,sizeof(UBCALC)); pNew->pDes = CreateDescriptor("UBcalc"); pNew->UB = mat_creat(3,3,UNIT_MATRIX); if(pNew->pDes == NULL || pNew->UB == NULL){ return NULL; } pNew->pDes->SaveStatus = SaveUBCalc; return pNew; } /*----------------------------------------------------------------------*/ int MakeUBCalc(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pUBCALC pNew = NULL; int status; pNew = makeUBCALC(); if(pNew == NULL){ SCWrite(pCon,"ERROR: out of memory creating UBCALC",eError); return 0; } if(argc > 1){ status = AddCommand(pSics,argv[1],UBCalcWrapper,killUBCALC,pNew); } else { status = AddCommand(pSics,"ubcalc",UBCalcWrapper,killUBCALC,pNew); } if(status != 1){ SCWrite(pCon,"ERROR: failed to create duplicate UBCALC module",eError); } return status; } /*---------------------------------------------------------------------*/ static int readCell(SConnection *pCon, pUBCALC self, int argc, char *argv[]){ int status; Tcl_Interp *pTcl = InterpGetTcl(pServ->pSics); char pBueffel[256]; if(argc < 8){ SCWrite(pCon,"ERROR: insufficient number of arguments to ubcalc cell", eError); return 0; } status = Tcl_GetDouble(pTcl,argv[2],&self->direct.a); if(status != TCL_OK){ snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]); SCWrite(pCon,pBueffel,eError); return 0; } status = Tcl_GetDouble(pTcl,argv[3],&self->direct.b); if(status != TCL_OK){ snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]); SCWrite(pCon,pBueffel,eError); return 0; } status = Tcl_GetDouble(pTcl,argv[4],&self->direct.c); if(status != TCL_OK){ snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[4]); SCWrite(pCon,pBueffel,eError); return 0; } status = Tcl_GetDouble(pTcl,argv[5],&self->direct.alpha); if(status != TCL_OK){ snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[5]); SCWrite(pCon,pBueffel,eError); return 0; } status = Tcl_GetDouble(pTcl,argv[6],&self->direct.beta); if(status != TCL_OK){ snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[6]); SCWrite(pCon,pBueffel,eError); return 0; } status = Tcl_GetDouble(pTcl,argv[7],&self->direct.gamma); if(status != TCL_OK){ snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[7]); SCWrite(pCon,pBueffel,eError); return 0; } SCparChange(pCon); SCSendOK(pCon); return 1; } /*--------------------------------------------------------------------*/ static int readRefMotors(SConnection *pCon, SicsInterp *pSics, reflection *r){ pMotor pMot = NULL; float val; pMot = FindMotor(pSics,"stt"); if(pMot == NULL){ SCWrite(pCon,"ERROR: cannot find stt motor",eError); return 0; } MotorGetSoftPosition(pMot,pCon,&val); r->s2t = val; pMot = FindMotor(pSics,"om"); if(pMot == NULL){ SCWrite(pCon,"ERROR: cannot find om motor",eError); return 0; } MotorGetSoftPosition(pMot,pCon,&val); r->om = val; pMot = FindMotor(pSics,"chi"); if(pMot == NULL){ SCWrite(pCon,"ERROR: cannot find chi motor",eError); return 0; } MotorGetSoftPosition(pMot,pCon,&val); r->chi = val; pMot = FindMotor(pSics,"phi"); if(pMot == NULL){ SCWrite(pCon,"ERROR: cannot find phi motor",eError); return 0; } MotorGetSoftPosition(pMot,pCon,&val); r->phi = val; SCparChange(pCon); SCSendOK(pCon); return 1; } /*---------------------------------------------------------------------*/ static int readReflection(SConnection *pCon, SicsInterp *pSics, reflection *r, int argc, char *argv[]){ char pBueffel[255]; int status; Tcl_Interp *pTcl = InterpGetTcl(pSics); if(argc < 5){ SCWrite(pCon,"ERROR: not enough arguments to ubcalc ref1,2",eError); return 0; } status = Tcl_GetDouble(pTcl,argv[2],&r->h); if(status != TCL_OK){ snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]); SCWrite(pCon,pBueffel,eError); return 0; } status = Tcl_GetDouble(pTcl,argv[3],&r->k); if(status != TCL_OK){ snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]); SCWrite(pCon,pBueffel,eError); return 0; } status = Tcl_GetDouble(pTcl,argv[4],&r->l); if(status != TCL_OK){ snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[4]); SCWrite(pCon,pBueffel,eError); return 0; } if(argc >= 9){ status = Tcl_GetDouble(pTcl,argv[5],&r->s2t); if(status != TCL_OK){ snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[5]); SCWrite(pCon,pBueffel,eError); return 0; } status = Tcl_GetDouble(pTcl,argv[6],&r->om); if(status != TCL_OK){ snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[6]); SCWrite(pCon,pBueffel,eError); return 0; } status = Tcl_GetDouble(pTcl,argv[7],&r->chi); if(status != TCL_OK){ snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[7]); SCWrite(pCon,pBueffel,eError); return 0; } status = Tcl_GetDouble(pTcl,argv[8],&r->phi); if(status != TCL_OK){ snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[8]); SCWrite(pCon,pBueffel,eError); return 0; } SCparChange(pCon); SCSendOK(pCon); return 1; } else { return readRefMotors(pCon,pSics,r); } } /*---------------------------------------------------------------------*/ static void listUB(SConnection *pCon, MATRIX UB){ Tcl_DString list; char pBueffel[255]; int i; Tcl_DStringInit(&list); if(UB == NULL){ Tcl_DStringAppend(&list,"NO UB",-1); } else { Tcl_DStringAppend(&list,"UB = ", -1); for(i = 0; i < 3; i++){ snprintf(pBueffel,255,"%f %f %f\n", UB[i][0], UB[i][1],UB[i][2]); Tcl_DStringAppend(&list,pBueffel,-1); } } SCWrite(pCon,Tcl_DStringValue(&list),eValue); Tcl_DStringFree(&list); } /*---------------------------------------------------------------------*/ static int calcUB(pUBCALC self, SConnection *pCon){ MATRIX newUB = NULL; int err = 1; newUB = calcUBFromCellAndReflections(self->direct, self->r1, self->r2, &err); if(newUB == NULL){ switch(err){ case UBNOMEMORY: SCWrite(pCon,"ERROR: out of memory while calculating UB",eError); return 0; break; case REC_NO_VOLUME: SCWrite(pCon,"ERROR: bad cell constants",eError); return 0; break; default: SCWrite(pCon,"ERROR: unknown error on UB matrix calculation",eError); return 0; } } else { if(self->UB != NULL){ mat_free(self->UB); } self->UB = newUB; SCSendOK(pCon); return 1; } } /*---------------------------------------------------------------------*/ static void listCell(SConnection *pCon, char *name, lattice direct){ char pBueffel[255]; snprintf(pBueffel,255,"%s.cell = %f %f %f %f %f %f", name,direct.a, direct.b,direct.c, direct.alpha,direct.beta,direct.gamma); SCWrite(pCon,pBueffel,eValue); } /*---------------------------------------------------------------------*/ static void listReflection(SConnection *pCon, char *name, char *refName, reflection r){ char pBueffel[255]; snprintf(pBueffel,255,"%s.%s = %f %f %f %f %f %f %f", name,refName, r.h, r.k, r.l, r.s2t, r.om, r.chi, r.phi); SCWrite(pCon,pBueffel,eValue); } /*---------------------------------------------------------------------*/ static int sendUBToHKL(SConnection *pCon, SicsInterp *pSics, char *name, MATRIX UB){ pHKL hkl = NULL; char pBueffel[256]; float ub[9]; int i; hkl = FindCommandData(pSics,name,"4-Circle-Calculus"); if(hkl == NULL){ snprintf(pBueffel,255,"ERROR: %s not found or of wrong type",name); SCWrite(pCon,pBueffel,eError); return 0; } for(i = 0; i < 3; i++){ ub[i] = UB[0][i]; ub[i+3] = UB[1][i]; ub[i+6] = UB[2][i]; } SetUB(hkl,ub); SCSendOK(pCon); return 1; } /*----------------------------------------------------------------------*/ int UBCalcWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pUBCALC self = (pUBCALC)pData; assert(self); if(argc < 2){ SCWrite(pCon,"Insuffcient number of arguments to ubcalc",eError); return 0; } strtolower(argv[1]); if(strcmp(argv[1],"cell") == 0){ return readCell(pCon, self, argc, argv); } else if(strcmp(argv[1],"ref1") == 0){ return readReflection(pCon,pSics, &self->r1,argc,argv); } else if(strcmp(argv[1],"ref2") ==0){ return readReflection(pCon,pSics, &self->r2,argc,argv); } else if(strcmp(argv[1],"listub") == 0){ listUB(pCon,self->UB); return 1; } else if(strcmp(argv[1],"calcub") == 0){ return calcUB(self,pCon); } else if(strcmp(argv[1],"listcell") == 0){ listCell(pCon,argv[0],self->direct); return 1; } else if(strcmp(argv[1],"listref1") == 0){ listReflection(pCon,argv[0],"ref1",self->r1); return 1; } else if(strcmp(argv[1],"listref2") == 0){ listReflection(pCon,argv[0],"ref2",self->r2); return 1; } else if(strcmp(argv[1],"list") == 0){ listCell(pCon,argv[0],self->direct); listReflection(pCon,argv[0],"ref1",self->r1); listReflection(pCon,argv[0],"ref2",self->r2); listUB(pCon,self->UB); return 1; } else if(strcmp(argv[1],"sendto") == 0){ if(argc < 3){ SCWrite(pCon,"ERROR: Nothing to send UB too",eError); return 0; } return sendUBToHKL(pCon,pSics,argv[2],self->UB); } return 1; }