From f33ca7b0d71f0a4932958288ee7a52aba69b346b Mon Sep 17 00:00:00 2001 From: koennecke Date: Tue, 31 May 2005 10:00:18 +0000 Subject: [PATCH] - Added file checking and listings to exeman - Fixed some problems with mesure - Fixed issues with tasub --- exeman.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++ fourtable.c | 7 +- mesure.c | 49 ++++++++++--- mesure.h | 1 + mesure.w | 1 + motor.c | 2 +- nxxml.h | 73 +++++++++++++++++++ tasdrive.c | 4 ++ tasub.c | 33 +++++---- tasublib.c | 13 +++- 10 files changed, 354 insertions(+), 30 deletions(-) create mode 100644 nxxml.h diff --git a/exeman.c b/exeman.c index 7478090c..fd54c9d0 100644 --- a/exeman.c +++ b/exeman.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include "fortify.h" #include "sics.h" #include "exebuf.h" @@ -388,6 +390,45 @@ static int appendLine(pExeMan self, SConnection *pCon, return 1; } /*--------------------------------------------------------------------*/ +static int uploadForceSave(pExeMan self, SConnection *pCon, + int argc, char *argv[]){ + int status; + char pPath[256], *pPtr; + + if(SCGetRights(pCon) > usUser){ + SCWrite(pCon,"ERROR: no permission to save buffers",eError); + return 0; + } + if(argc < 3) { + SCWrite(pCon,"ERROR: no file given to save upload buffer to",eError); + return 0; + } + if(self->uploadBuffer == NULL){ + SCWrite(pCon,"ERROR: no upload buffer to save exists",eError); + return 0; + } + if(argv[2][0] != '/') { + pPtr = self->batchPath; + pPtr = stptok(pPtr,pPath,131,":"); + if(strlen(pPath) + 1 + strlen(argv[2]) <= 256){ + strcat(pPath,"/"); + strcat(pPath,argv[2]); + } else { + strncpy(pPath,argv[2],255); + } + } else { + strncpy(pPath,argv[2],131); + } + + status = exeBufSave(self->uploadBuffer,pPath); + if(status == 0){ + SCWrite(pCon,"ERROR: failed to save exe buffer, destroyed...",eError); + } + exeBufDelete(self->uploadBuffer); + self->uploadBuffer = NULL; + return status; +} +/*--------------------------------------------------------------------*/ static int uploadSave(pExeMan self, SConnection *pCon, int argc, char *argv[]){ int status; @@ -417,6 +458,11 @@ static int uploadSave(pExeMan self, SConnection *pCon, } else { strncpy(pPath,argv[2],131); } + if(fileExists(pPath)) { + SCWrite(pCon,"ERROR: file exists",eError); + return 0; + } + status = exeBufSave(self->uploadBuffer,pPath); if(status == 0){ SCWrite(pCon,"ERROR: failed to save exe buffer, destroyed...",eError); @@ -425,6 +471,141 @@ static int uploadSave(pExeMan self, SConnection *pCon, self->uploadBuffer = NULL; return status; } +/*---------------------------------------------------------------------------------*/ +/* See if a string matches a wildcard specification that uses * or ? + (like "*.txt"), and return TRUE or FALSE, depending on the result. + There's also a TRUE/FALSE parameter you use to indicate whether + the match should be case-sensitive or not. +*/ +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif +/*--------------------------------------------------------------------------------*/ +static int IsWildcardMatch (char *wildcardString, char *stringToCheck, int caseSensitive) +{ + char wcChar; + char strChar; + // use the starMatchesZero variable to determine whether an asterisk + // matches zero or more characters (TRUE) or one or more characters + // (FALSE) + int starMatchesZero = TRUE; + + + while ((strChar = *stringToCheck) && (wcChar = *wildcardString)) + { + // we only want to advance the pointers if we successfully assigned + // both of our char variables, so we'll do it here rather than in the + // loop condition itself + *stringToCheck++; + *wildcardString++; + + // if this isn't a case-sensitive match, make both chars uppercase + // (thanks to David John Fielder (Konan) at http://innuendo.ev.ca + // for pointing out an error here in the original code) + if (!caseSensitive) + { + wcChar = toupper(wcChar); + strChar = toupper(strChar); + } + + // check the wcChar against our wildcard list + switch (wcChar) + { + // an asterisk matches zero or more characters + case '*' : + // do a recursive call against the rest of the string, + // until we've either found a match or the string has + // ended + if (starMatchesZero) + *stringToCheck--; + + while (*stringToCheck) + { + if (IsWildcardMatch(wildcardString, stringToCheck++, caseSensitive)) + return TRUE; + } + + break; + + // a question mark matches any single character + case '?' : + break; + + // if we fell through, we want an exact match + default : + if (wcChar != strChar) + return FALSE; + break; + } + + } + + // if we have any asterisks left at the end of the wildcard string, we can + // advance past them if starMatchesZero is TRUE (so "blah*" will match "blah") + while ((*wildcardString) && (starMatchesZero)) + { + if (*wildcardString == '*') + wildcardString++; + else + break; + } + + // if we got to the end but there's still stuff left in either of our strings, + // return false; otherwise, we have a match + if ((*stringToCheck) || (*wildcardString)) + return FALSE; + else + return TRUE; + +} +/*----------------------------------------------------------------------------*/ +static int wwmatch(char *pattern, char *name){ + return IsWildcardMatch(pattern,name,1); +} +/*-------------------------------------------------------------------- + search the directory pPath for file matching pattern. Successfull + files will be appended to result +-----------------------------------------------------------------------*/ +static void searchDir(char *pPath, char *pattern, pDynString result){ + DIR *currentdir = NULL; + struct dirent *currentFile = NULL; + + currentdir = opendir(pPath); + if(currentdir == NULL){ + return; + } + currentFile = readdir(currentdir); + while(currentFile != NULL){ + if(wwmatch((const char *)pattern, currentFile->d_name)){ + DynStringConcat(result,currentFile->d_name); + DynStringConcatChar(result,'\n'); + } + currentFile = readdir(currentdir); + } + closedir(currentdir); +} +/*--------------------------------------------------------------------*/ +static pDynString findDirEntries(pExeMan self, char *pattern){ + pDynString result = NULL; + char pPath[132], *pPtr = NULL; + + result = CreateDynString(256,256); + if(!result){ + return NULL; + } + + pPtr = self->batchPath; + while((pPtr = stptok(pPtr,pPath,131,":")) != NULL){ + searchDir(pPath,pattern,result); + } + + pPtr = self->sysPath; + while((pPtr = stptok(pPtr,pPath,131,":")) != NULL){ + searchDir(pPath,pattern,result); + } + return result; +} /*=========================== info ===================================*/ static void printExeStack(pExeMan self, SConnection *pCon){ int i, j; @@ -730,6 +911,7 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, pExeMan self = NULL; char pBufferName[256]; int status; + pDynString dirList = NULL; self = (pExeMan)pData; assert(self != NULL); @@ -768,6 +950,12 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, SCSendOK(pCon); } return status; + }else if(strcmp(argv[1],"forcesave") == 0){ + status = uploadForceSave(self,pCon,argc,argv); + if(status){ + SCSendOK(pCon); + } + return status; }else if(strcmp(argv[1],"info") == 0){ status = infoHandler(self,pCon,argc,argv); return status; @@ -780,6 +968,19 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, SCSendOK(pCon); } return status; + } else if(strcmp(argv[1],"dir") == 0){ + if(argc <= 2){ + dirList = findDirEntries(self,"*"); + } else { + dirList = findDirEntries(self,argv[2]); + } + if(dirList != NULL){ + SCWrite(pCon,GetCharArray(dirList),eValue); + DeleteDynString(dirList); + } else { + SCWrite(pCon,"Nothing found",eValue); + } + return 1; }else if(strcmp(argv[1],"clear") == 0){ clearQueue(self); SCSendOK(pCon); diff --git a/fourtable.c b/fourtable.c index d5624bf1..e1fd281c 100644 --- a/fourtable.c +++ b/fourtable.c @@ -39,6 +39,7 @@ static void clearTable(int handle){ LLDnodeDelete(handle); status = LLDnodePtr2Next(handle); } + LLDnodeDelete(handle); } /*------------------------------------------------------------------------*/ static void printList(int handle, SConnection *pCon){ @@ -240,17 +241,15 @@ int HandleFourCircleCommands(int handle, SConnection *pCon, /*-----------------------------------------------------------------------*/ static FourTableEntry findEntry(int handle, double two_theta){ int status; - FourTableEntry entry, prevEntry; + FourTableEntry entry; status = LLDnodePtr2First(handle); - LLDnodeDataTo(handle,&prevEntry); while(status == 1) { LLDnodeDataTo(handle,&entry); if(entry.twoThetaEnd > two_theta){ - return prevEntry; + return entry; } status = LLDnodePtr2Next(handle); - prevEntry = entry; } strcpy(entry.scanVar,"NOT FOUND"); return entry; diff --git a/mesure.c b/mesure.c index 86e03313..ce68d1c8 100644 --- a/mesure.c +++ b/mesure.c @@ -53,7 +53,9 @@ pHKL pCryst; /* hkl object for crystallographic calc and reflection driving */ pMotor pOmega; /* motor for omega scans */ + pMotor p2Theta; /* motor for 2 theta scans*/ char *pCOmega; /* name of omega motor */ + char *pC2Theta; /* name of 2 theta motor */ char *pFileRoot; /* where to write files */ pDataNumber pDanu; /* where to get data file number */ FILE *fRefl; /* reflection profile file */ @@ -140,7 +142,8 @@ static void ListMesure(pMesure self, char *name, SConnection *pCon) } /*--------------------------------------------------------------------------*/ pMesure CreateMesure(pHKL pCryst, pScanData pScanner, pMotor pOmega, - char *pOm, char *pFileRoot, + char *pOm, pMotor p2Theta, char *p2t, + char *pFileRoot, pDataNumber pDanu) { pMesure pNew = NULL; @@ -172,7 +175,9 @@ static void ListMesure(pMesure self, char *name, SConnection *pCon) pNew->pScanner = pScanner; pNew->pCryst = pCryst; pNew->pOmega = pOmega; + pNew->p2Theta = p2Theta; pNew->pCOmega = strdup(pOm); + pNew->pC2Theta = strdup(p2t); pNew->pFileRoot = strdup(pFileRoot); pNew->pDanu = pDanu; pNew->iCount = 0; @@ -229,7 +234,7 @@ static void ListMesure(pMesure self, char *name, SConnection *pCon) pHKL pCryst = NULL; pScanData pScan = NULL; CommandList *pCom = NULL; - pMotor pMot = NULL; + pMotor pMot = NULL, pMot2 = NULL; pDataNumber pDanu = NULL; pSicsO2T pO2T = NULL; char pBueffel[512]; @@ -242,7 +247,7 @@ static void ListMesure(pMesure self, char *name, SConnection *pCon) /* check no of parameters inicom name hkl scan omega root danu */ - if(argc < 7) + if(argc < 8) { SCWrite(pCon, "ERROR: Insufficient number of parameters to MesureFactory",eError); @@ -297,9 +302,18 @@ static void ListMesure(pMesure self, char *name, SConnection *pCon) SCWrite(pCon,pBueffel,eError); return 0; } + + /* 2 theta */ + pMot2 = FindMotor(pSics,argv[5]); + if(!pMot2) + { + sprintf(pBueffel,"ERROR: %s is no motor object ",argv[5]); + SCWrite(pCon,pBueffel,eError); + return 0; + } /* Data Number */ - pCom = FindCommand(pSics,argv[6]); + pCom = FindCommand(pSics,argv[7]); if(pCom) { pDum = (pDummy)pCom->pData; @@ -313,13 +327,14 @@ static void ListMesure(pMesure self, char *name, SConnection *pCon) } if(!pDanu) { - sprintf(pBueffel,"ERROR: %s is no DataNumber object",argv[6]); + sprintf(pBueffel,"ERROR: %s is no DataNumber object",argv[7]); SCWrite(pCon,pBueffel,eError); return 0; } /* finally create the thing */ - pNew = CreateMesure(pCryst,pScan,pMot,argv[4],argv[5],pDanu); + pNew = CreateMesure(pCryst,pScan,pMot,argv[4], pMot2, argv[5], + argv[6],pDanu); if(!pNew) { SCWrite(pCon,"ERROR: no memory in MesureFactory",eError); @@ -415,7 +430,7 @@ static int getMesureNP(pMesure self, double twoTheta) This is supposed to be automatically set. In order to do so, I need the step width which in turn is dependent on two theta. Therefore I calculate two times: the first time with a scan tolerance of 0 to get two theta, the - second time with teh scan tolerance ste to a decent value to get the + second time with the scan tolerance ste to a decent value to get the real thing. ---------------------------------------------------------------------------*/ static int MesureCalculateSettings(pMesure self, float fHKL[3], float fSet[4], @@ -611,13 +626,29 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon) /* below is the code for a single counter scan. - TODO: (maybe) make this clearer and separte this into another subroutine + TODO: (maybe) make this clearer and separate this into another subroutine Set the scan up */ ClearScanVar(self->pScanner); - AddScanVar(self->pScanner, pServ->pSics,pCon,scanVar, + AddScanVar(self->pScanner, pServ->pSics,pCon,self->pCOmega, fStart, stepWidth); + /* + Oksana does not want o2t scans to be tightly coupled, this is why we + cannot use the normal o2t scan variable. Instead we calculate new limits and + steps for 2 theta and use it as a second scan variable + */ + if(strstr(scanVar,"o2t") != NULL){ + iRet = MotorGetSoftPosition(self->p2Theta,pCon,&fStart); + if(!iRet) + { + return iRet; + } + stepWidth *= 2.; + fStart -= (np/2.)*stepWidth; + AddScanVar(self->pScanner, pServ->pSics,pCon,self->pC2Theta, + fStart, stepWidth); + } /* as np can change, we have to reallocate enough space diff --git a/mesure.h b/mesure.h index aaad2ec7..9d89f607 100644 --- a/mesure.h +++ b/mesure.h @@ -17,6 +17,7 @@ /*--------------------- live & death --------------------------------------*/ pMesure CreateMesure(pHKL pCryst, pScanData pScanner, pMotor pOmega, char *pom, + pMotor p2Theta, char *p2t, char *pFileRoot,pDataNumber pDanu); void DeleteMesure(void *pData); diff --git a/mesure.w b/mesure.w index 4a0d9b83..3806ad08 100644 --- a/mesure.w +++ b/mesure.w @@ -25,6 +25,7 @@ The interface to this object consists of these functions: /*--------------------- live & death --------------------------------------*/ pMesure CreateMesure(pHKL pCryst, pScanData pScanner, pMotor pOmega, char *pom, + pMotor p2Theta, char *p2t, char *pFileRoot,pDataNumber pDanu); void DeleteMesure(void *pData); diff --git a/motor.c b/motor.c index e33360b8..d8346f3c 100644 --- a/motor.c +++ b/motor.c @@ -732,7 +732,7 @@ extern void KillPiPiezo(void *pData); iRet = MotorCheckBoundary(self,fNew,&fHard,pBueffel,511); if(!iRet) { - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eWarning); SCSetInterrupt(pCon,eAbortOperation); return 0; } diff --git a/nxxml.h b/nxxml.h new file mode 100644 index 00000000..a9036bb3 --- /dev/null +++ b/nxxml.h @@ -0,0 +1,73 @@ +/* + * This is the header file for the NeXus XML file driver. + * + * Copyright (C) 2004 Mark Koennecke + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information, see + */ +#ifndef NEXUSXML +#define NEXUSXML + +NX_EXTERNAL NXstatus CALLING_STYLE NXXopen(CONSTCHAR *filename, NXaccess access_method, NXhandle* pHandle); +NX_EXTERNAL NXstatus CALLING_STYLE NXXclose(NXhandle* pHandle); +NX_EXTERNAL NXstatus CALLING_STYLE NXXflush(NXhandle* pHandle); + +NXstatus CALLING_STYLE NXXmakegroup (NXhandle fid, CONSTCHAR *name, + CONSTCHAR *nxclass); +NXstatus CALLING_STYLE NXXopengroup (NXhandle fid, CONSTCHAR *name, + CONSTCHAR *nxclass); +NXstatus CALLING_STYLE NXXclosegroup (NXhandle fid); + +NXstatus CALLING_STYLE NXXcompmakedata (NXhandle fid, CONSTCHAR *name, + int datatype, + int rank, + int dimensions[], + int compress_type, int chunk_size[]); +NXstatus CALLING_STYLE NXXmakedata (NXhandle fid, + CONSTCHAR *name, int datatype, + int rank, int dimensions[]); +NXstatus CALLING_STYLE NXXopendata (NXhandle fid, CONSTCHAR *name); +NXstatus CALLING_STYLE NXXclosedata (NXhandle fid); +NXstatus CALLING_STYLE NXXputdata (NXhandle fid, void *data); +NXstatus CALLING_STYLE NXXgetdata (NXhandle fid, void *data); +NXstatus CALLING_STYLE NXXgetinfo (NXhandle fid, int *rank, + int dimension[], int *iType); +NXstatus CALLING_STYLE NXXputslab (NXhandle fid, void *data, + int iStart[], int iSize[]); +NXstatus CALLING_STYLE NXXgetslab (NXhandle fid, void *data, + int iStart[], int iSize[]); +NXstatus CALLING_STYLE NXXputattr (NXhandle fid, CONSTCHAR *name, void *data, + int datalen, int iType); +NXstatus CALLING_STYLE NXXgetattr (NXhandle fid, char *name, + void *data, int* datalen, int* iType); + +NXstatus CALLING_STYLE NXXgetnextentry (NXhandle fid,NXname name, + NXname nxclass, int *datatype); +NX_EXTERNAL NXstatus CALLING_STYLE NXXgetnextattr(NXhandle handle, + NXname pName, int *iLength, int *iType); +NX_EXTERNAL NXstatus CALLING_STYLE NXXinitgroupdir(NXhandle handle); +NX_EXTERNAL NXstatus CALLING_STYLE NXXinitattrdir(NXhandle handle); +NX_EXTERNAL NXstatus CALLING_STYLE NXXgetattrinfo (NXhandle fid, int *iN); +NX_EXTERNAL NXstatus CALLING_STYLE NXXgetgroupinfo (NXhandle fid, int *iN, + NXname pName, NXname pClass); + +NX_EXTERNAL NXstatus CALLING_STYLE NXXgetdataID (NXhandle fid, NXlink* sRes); +NX_EXTERNAL NXstatus CALLING_STYLE NXXgetgroupID (NXhandle fid, NXlink* sRes); +NX_EXTERNAL NXstatus CALLING_STYLE NXXmakelink (NXhandle fid, NXlink* sLink); +NX_EXTERNAL NXstatus CALLING_STYLE NXXsameID (NXhandle fileid, + NXlink* pFirstID, NXlink* pSecondID); +#endif diff --git a/tasdrive.c b/tasdrive.c index b0b1e7a9..4a230630 100644 --- a/tasdrive.c +++ b/tasdrive.c @@ -329,19 +329,23 @@ static int calculateAndDrive(ptasMot self, SConnection *pCon){ switch(status){ case ENERGYTOBIG: SCWrite(pCon,"ERROR: desired energy to big",eError); + self->math->mustDrive = 0; return HWFault; break; case UBNOMEMORY: SCWrite(pCon,"ERROR: out of memory calculating angles",eError); + self->math->mustDrive = 0; return HWFault; break; case BADRMATRIX: SCWrite(pCon,"ERROR: bad crystallographic parameters or bad UB",eError); + self->math->mustDrive = 0; return HWFault; break; case TRIANGLENOTCLOSED: SCWrite(pCon,"ERROR: cannot close scattering triangle",eError); + self->math->mustDrive = 0; return HWFault; break; default: diff --git a/tasub.c b/tasub.c index 6c7190f0..b54f0079 100644 --- a/tasub.c +++ b/tasub.c @@ -490,7 +490,7 @@ static void listReflections(ptasUB self, SConnection *pCon){ Tcl_DStringInit(&list); snprintf(line,255, - " NO QH QK QL A3 A4 SGU SGL KI KF\n"); + " NO QH QK QL A3 A4 SGU SGL EI EF\n"); Tcl_DStringAppend(&list,line,-1); status = LLDnodePtr2First(self->reflectionList); while(status == 1){ @@ -498,7 +498,7 @@ static void listReflections(ptasUB self, SConnection *pCon){ LLDnodeDataTo(self->reflectionList,&r); snprintf(line,255,"%3d %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n", count, r.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3, r.angles.sample_two_theta, - r.angles.sgu, r.angles.sgl, r.qe.ki, r.qe.kf); + r.angles.sgu, r.angles.sgl, KtoEnergy(r.qe.ki), KtoEnergy(r.qe.kf)); Tcl_DStringAppend(&list,line,-1); status = LLDnodePtr2Next(self->reflectionList); } @@ -510,6 +510,8 @@ static void listReflections(ptasUB self, SConnection *pCon){ Tcl_DStringFree(&list); } /*-------------------------------------------------------------------*/ +#define ABS(x) (x < 0 ? -(x) : (x)) +/*-------------------------------------------------------------------*/ static int addReflection(ptasUB self, SicsInterp *pSics, SConnection *pCon, int argc, char *argv[]){ @@ -597,18 +599,22 @@ static int addReflection(ptasUB self, SicsInterp *pSics, if(status != 1){ return status; } - r.qe.ki = maCalcK(self->machine.monochromator,angles.monochromator_two_theta); - r.qe.kf = maCalcK(self->machine.analyzer,angles.analyzer_two_theta); + r.qe.ki = maCalcK(self->machine.monochromator,r.angles.monochromator_two_theta); + r.qe.kf = maCalcK(self->machine.analyzer,r.angles.analyzer_two_theta); + } + if(ABS(r.qe.ki - r.qe.kf) > .01) { + SCWrite(pCon,"WARNING: KI != KF!",eWarning); } LLDnodeAppend(self->reflectionList,&r); Tcl_DStringInit(&list); snprintf(pBueffel,255, - " QH QK QL A3 A4 SGU SGL KI KF\n"); + " QH QK QL A3 A4 SGU SGL EI EF\n"); Tcl_DStringAppend(&list,pBueffel,-1); snprintf(pBueffel,255, " %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n", r.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3, r.angles.sample_two_theta, - r.angles.sgu, r.angles.sgl, r.qe.ki, r.qe.kf); + r.angles.sgu, r.angles.sgl, KtoEnergy(r.qe.ki), + KtoEnergy(r.qe.kf)); Tcl_DStringAppend(&list,pBueffel,-1); SCWrite(pCon,Tcl_DStringValue(&list),eValue); Tcl_DStringFree(&list); @@ -669,12 +675,13 @@ static void printReflectionDiagnostik(ptasUB self, SConnection *pCon, Tcl_DStringInit(&list); snprintf(line,255, - "METHOD QH QK QL A3 A4 SGU SGL KI KF\n"); + "METHOD QH QK QL A3 A4 SGU SGL EI EF\n"); Tcl_DStringAppend(&list,line,-1); snprintf(line,255, - "INPUT %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n", + "INPUT %8.4f %8.4f %8.4f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n", r.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3, - r.angles.sample_two_theta, r.angles.sgu, r.angles.sgl, r.qe.ki, r.qe.kf); + r.angles.sample_two_theta, r.angles.sgu, r.angles.sgl, + KtoEnergy(r.qe.ki), KtoEnergy(r.qe.kf)); Tcl_DStringAppend(&list,line,-1); qe.ki = r.qe.ki; qe.kf = r.qe.kf; @@ -683,10 +690,10 @@ static void printReflectionDiagnostik(ptasUB self, SConnection *pCon, qe.ql = r.qe.ql; calcAllTasAngles(&self->machine,qe,&angles); snprintf(line,255, - "QE->ANG %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n", + "QE->ANG %8.4f %8.4f %8.4f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n", r.qe.qh, r.qe.qk, r.qe.ql, angles.a3, angles.sample_two_theta, - angles.sgu, angles.sgl, r.qe.ki, r.qe.kf); + angles.sgu, angles.sgl, KtoEnergy(r.qe.ki), KtoEnergy(r.qe.kf)); Tcl_DStringAppend(&list,line,-1); angles.a3 = r.angles.a3; angles.sample_two_theta = r.angles.sample_two_theta; @@ -694,9 +701,9 @@ static void printReflectionDiagnostik(ptasUB self, SConnection *pCon, angles.sgl = r.angles.sgl; calcTasQEPosition(&self->machine,angles,&qe); snprintf(line,255, - "ANG->QE %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n", + "ANG->QE %8.4f %8.4f %8.4f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n", qe.qh, qe.qk, qe.ql, angles.a3, angles.sample_two_theta, - angles.sgu, angles.sgl, qe.ki, qe.kf); + angles.sgu, angles.sgl, KtoEnergy(qe.ki), KtoEnergy(qe.kf)); Tcl_DStringAppend(&list,line,-1); SCWrite(pCon,Tcl_DStringValue(&list),eWarning); Tcl_DStringFree(&list); diff --git a/tasublib.c b/tasublib.c index ab36e988..d311fb35 100644 --- a/tasublib.c +++ b/tasublib.c @@ -260,7 +260,9 @@ static MATRIX buildTVMatrix(MATRIX U1V, MATRIX U2V){ MATRIX T, T3V; int i; + normalizeVector(U2V); T3V = vectorCrossProduct(U1V,U2V); + normalizeVector(T3V); if(T3V == NULL){ return NULL; } @@ -340,13 +342,18 @@ int calcTasQAngles(MATRIX UB, MATRIX planeNormal, int ss, tasQEPosition qe, } om = Acosd(R[0][0]/sq); om -= 180.; - angles->sgl = Acosd(sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0])); + tmp = Asind(R[1][0]/sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0])); + + tmp = Acosd(sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0])); + angles->sgl = Asind(-R[2][0]); + sq = sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0]); if(ABS(sq) < .00001){ return BADRMATRIX; } angles->sgu = Asind(R[2][1]/sq); - + tmp = Acosd(R[2][2]/sqrt(R[0][0]*R[0][0]+R[1][0]*R[1][0])); + QC = tasReflectionToQC(qe,UB); if(QC == NULL){ return UBNOMEMORY; @@ -355,7 +362,7 @@ int calcTasQAngles(MATRIX UB, MATRIX planeNormal, int ss, tasQEPosition qe, q = vectorLength(QC); q = 2.*PI*vectorLength(QC); cos2t = (qe.ki*qe.ki + qe.kf*qe.kf - q*q)/(2. * ABS(qe.ki) * ABS(qe.kf)); - if(cos2t > 1.){ + if(ABS(cos2t) > 1.){ return TRIANGLENOTCLOSED; } angles->sample_two_theta = ss*Acosd(cos2t);