From 46492ca9bddc6a53075a872f420ac58f4d433313 Mon Sep 17 00:00:00 2001 From: koennecke Date: Wed, 18 May 2005 13:47:46 +0000 Subject: [PATCH] - Added scan support to new TAS syntax - First full version of new TAS --- SCinter.c | 10 +- make_gen | 4 +- ofac.c | 4 + tasscanub.c | 1135 +++++++++++++++++++++++++++++++++++++++++++++++++++ tasscanub.h | 36 ++ tasub.c | 88 +++- tasub.h | 2 + tasub.w | 4 + 8 files changed, 1265 insertions(+), 18 deletions(-) create mode 100644 tasscanub.c create mode 100644 tasscanub.h diff --git a/SCinter.c b/SCinter.c index 450751e7..98ab7358 100644 --- a/SCinter.c +++ b/SCinter.c @@ -6,7 +6,7 @@ Mark Koennecke, November 1996 - Made ListObjects moe intelligent: list objects according to interface etc. + Made ListObjects more intelligent: list objects according to interface etc. Mark Koennecke, December 2003 Copyright: @@ -585,12 +585,14 @@ static void printMatch(SicsInterp *pSics, SConnection *pCon, char *mask) static void printType(SicsInterp *pSics, SConnection *pCon, char *type) { CommandList *pCurrent; + Tcl_DString txt; char pBueffel[256]; int iNum = 0; assert(pSics); assert(pCon); + Tcl_DStringInit(&txt); pBueffel[0] = '\0'; pCurrent = pSics->pCList; while(pCurrent) @@ -615,7 +617,7 @@ static void printType(SicsInterp *pSics, SConnection *pCon, char *type) strcat(pBueffel," "); strcat(pBueffel,pCurrent->pName); strcat(pBueffel,"\r\n"); - SCWrite(pCon,pBueffel,eStatus); + Tcl_DStringAppend(&txt,pBueffel,-1); pBueffel[0]='\0'; iNum = 0; } @@ -626,9 +628,9 @@ static void printType(SicsInterp *pSics, SConnection *pCon, char *type) /* write final entries */ strcat(pBueffel,"\r\n"); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,Tcl_DStringValue(&txt),eStatus); + Tcl_DStringFree(&txt); } - /*--------------------------------------------------------------------------*/ int ListObjects(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) diff --git a/make_gen b/make_gen index 25c12e67..ad60dade 100644 --- a/make_gen +++ b/make_gen @@ -24,8 +24,8 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ hklscan.o xytable.o exebuf.o exeman.o ubfour.o ubcalc.o\ circular.o maximize.o sicscron.o scanvar.o tasublib.o\ d_sign.o d_mod.o tcldrivable.o stdscan.o diffscan.o\ - synchronize.o definealias.o oscillate.o tasdrive.o\ - hmcontrol.o userscan.o rs232controller.o lomax.o \ + synchronize.o definealias.o oscillate.o tasdrive.o \ + hmcontrol.o userscan.o rs232controller.o lomax.o tasscanub.o \ fourlib.o motreg.o motreglist.o anticollider.o \ s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) \ hmdata.o nxscript.o tclintimpl.o sicsdata.o diff --git a/ofac.c b/ofac.c index 127eb924..6f38ed8b 100644 --- a/ofac.c +++ b/ofac.c @@ -111,6 +111,7 @@ #include "hklmot.h" #include "ubcalc.h" #include "tasub.h" +#include "tasscanub.h" /*----------------------- Server options creation -------------------------*/ static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) @@ -300,6 +301,8 @@ MakeUBCalc,NULL,NULL); AddCommand(pInter,"MakeTasUB", TasUBFactory,NULL,NULL); + AddCommand(pInter,"MakeTasScan", + TASUBScanFactory,NULL,NULL); /* @@ -364,6 +367,7 @@ RemoveCommand(pSics,"MakeHKLMot"); RemoveCommand(pSics,"MakeUBCalc"); RemoveCommand(pSics,"MakeTasUB"); + RemoveCommand(pSics,"MakeTasScan"); /* remove site specific installation commands diff --git a/tasscanub.c b/tasscanub.c new file mode 100644 index 00000000..d704f23e --- /dev/null +++ b/tasscanub.c @@ -0,0 +1,1135 @@ +/*-------------------------------------------------------------------------- + This is the implementation for the TAS scan code. It mainly implements + writing of the ILL file format, which the TAS'lers adore. + + Mark Koennecke, May 2005, using code from an earlier TASAMAD emulation + core. +---------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "scanvar.h" +#include +#include +#include +#include "tasscanub.h" +/*------------------------------------------------------------------------ + a little local utility for making a line of characters + -------------------------------------------------------------------------*/ +static void charLine(char *pBueffel, char c) +{ + int i; + + for(i = 0; i < 80; i++) + { + pBueffel[i] = c; + } + pBueffel[80] = '\n'; + pBueffel[81] = '\0'; +} +/*------------------------------------------------------------------------*/ +static void strtoupper(char *pText) +{ + assert(pText); + + while(*pText != '\0') + { + *pText = toupper(*pText); + pText++; + } +} +/*-----------------------------------------------------------------------*/ +static void strcenter(char *str, char *target, int iLength) +{ + int iPtr, i; + + /* + catch the error if target is to long + */ + if(strlen(str) >= iLength) + { + strncpy(target,str,iLength); + } + + iPtr = (iLength - strlen(str))/2; + for(i = 0; i < iPtr;i++) + { + target[i] = ' '; + } + target[iPtr] = '\0'; + strcat(target,str); + for(i = iPtr + strlen(str); i < iLength - 1; i++) + { + target[i] = ' '; + } + target[iLength-1] = '\0'; +} +/*----------------------------------------------------------------------*/ +static char *GetVarText(char *name) { + pSicsVariable pVar = NULL; + + pVar = (pSicsVariable)FindCommandData(pServ->pSics,name, "SicsVariable"); + if(pVar != NULL){ + return pVar->text; + } else { + return NULL; + } +} +/*----------------------------------------------------------------------- + helper function for TASHeader + ------------------------------------------------------------------------*/ +static void writePolFile(FILE *fd, pTASdata pTAS){ + char pLine[132]; + FILE *fpol = NULL; + + assert(fd); + assert(pTAS); + + fpol = fopen(GetVarText("polfile"),"r"); + if(!fpol){ + /* + error gets reported anyway later on + */ + return; + } + + while(fgets(pLine,131,fpol) != NULL){ + if(strstr(pLine,"\n") == NULL){ + fprintf(fd,"POLAN: %s\n", pLine); + } else { + fprintf(fd,"POLAN: %s", pLine); + } + } + fclose(fpol); +} +/*-----------------------------------------------------------------------*/ +static char *findLastPoint(char *text) +{ + char *pPtr; + int i; + + pPtr = text + strlen(text) - 1; + for(i = strlen(text); i > 0; i--, pPtr--) + { + if(*pPtr == '.') + { + return pPtr; + } + } + return NULL; +} +/*----------------------------------------------------------------------- + readDrivable tries to read the value of one of the magnet currents. + All errors are ignored because most of the time currents will not be + present in the system. + -----------------------------------------------------------------------*/ +static float readDrivable(char *val, SConnection *pCon){ + pIDrivable pDriv; + CommandList *pCom; + pDummy pDum; + pMotor pMot = NULL; + float fVal; + + /* + if motor: read motor + */ + pMot = FindMotor(pServ->pSics,val); + if(pMot != NULL){ + MotorGetSoftPosition(pMot,pCon,&fVal); + return fVal; + } + + /* + else: read general drivable + */ + pCom = FindCommand(pServ->pSics,val); + if(pCom != NULL){ + pDriv = GetDrivableInterface(pCom->pData); + if(pDriv != NULL){ + return pDriv->GetValue(pCom->pData,pCon); + } + } + return -999.99; +} +/*-----------------------------------------------------------------------*/ +static float GetVarFloat(char *name){ + pSicsVariable pVar = NULL; + + pVar = (pSicsVariable)FindCommandData(pServ->pSics,name, "SicsVariable"); + if(pVar != NULL){ + return pVar->fVal; + } else { + return -999.99; + } +} +/*------------------------------------------------------------------------- + TASHeader writes the header of a TAS data file. The format is an + obscure format from ILL ( not ill but Institute Laue Langevin). No + documentation about this exists except the files themselves. This is long + and tiresome code. +---------------------------------------------------------------------------*/ +static int TASUBHeader(pScanData self) +{ + pTASdata pTAS = (pTASdata)self->pSpecial; + int i, iCount, status, iFileNO; + char pBueffel[1024], pHeader[1024], pWork[132], pWork2[60], pTen[12], *pcPtr; + time_t iDate; + struct tm *psTime; + pVarEntry pVar = NULL; + void *pPtr = NULL; + pMotor pMot; + float fVal, fVal2; + CommandList *pCom = NULL; + pDummy pDum = NULL; + pIDrivable pDrive = NULL; + pEVControl pTem = NULL; + int fx; + tasReflection r; + double kfix; + + assert(self); + assert(pTAS); + assert(self->pCon); + assert(self->pSics); + + /* open data file */ + self->fd = fopen(self->pFile,"w"); + if(!self->fd) + { + SCWrite(self->pCon,"ERROR: cannot write data file",eError); + return 0; + } + + /* + extract the file number from the name for entry into the + datafile + */ + pcPtr = findLastPoint(self->pFile); + if(pcPtr != NULL) + { + pcPtr -= 6; /* 6 digits for number */ + for(i = 0; i < 6; i++, pcPtr++) + { + pWork[i] = *pcPtr; + } + pWork[6] = '\0'; + iFileNO = atoi(pWork); + } + else + { + SCWrite(self->pCon,"WARNING: failed to decode file number",eWarning); + } + + /* the bizarre R, A, V header */ + charLine(pBueffel,'R'); + fputs(pBueffel,self->fd); + fprintf(self->fd,"%8d%8d%8d\n",iFileNO,1,0); + fputs("ILL TAS data in the new ASCII format follow after the line VV...V\n", + self->fd); + charLine(pBueffel,'A'); + fputs(pBueffel,self->fd); + fprintf(self->fd,"%8d%8d\n",42,0); + + /* + format time to TAS format + */ + iDate = time(NULL); + psTime = localtime(&iDate); + memset(pWork,0,59); + strftime(pWork,59,"%d-%b-%Y %H:%M:%S",psTime); + fprintf(self->fd,"%-10s%-12s%-s\n",GetVarText("instrument"), + GetVarText("user"),pWork); + + charLine(pBueffel,'V'); + fputs(pBueffel,self->fd); + + /* + output a plethora of parameters + */ + fprintf(self->fd,"INSTR: %s\n",GetVarText("instrument")); + fprintf(self->fd,"EXPNO: \n"); + fprintf(self->fd,"USER_: %s\n",GetVarText("user")); + fprintf(self->fd,"LOCAL: %s\n",GetVarText("local")); + fprintf(self->fd,"FILE_: %d\n",iFileNO); + fprintf(self->fd,"DATE_: %s\n",pWork); + fprintf(self->fd,"TITLE: %s\n",GetVarText("title")); + fprintf(self->fd,"COMND: %s\n",GetVarText("lastscancommand")); + fprintf(self->fd, + "POSQE: QH=%8.4f, QK=%8.4f, QL=%8.4f, EN=%8.4f, UN=MEV\n", + pTAS->ub->current.qh, + pTAS->ub->current.qk, + pTAS->ub->current.qk, + getTasPar(pTAS->ub->current,EN)); + /* + build the steps line + */ + sprintf(pBueffel,"STEPS: "); + for(i = 0; i < self->iScanVar; i++) + { + DynarGet(self->pScanVar,i,&pPtr); + pVar = (pVarEntry)pPtr; + if(pVar) + { + strncpy(pWork2,ScanVarName(pVar),59); + strtoupper(pWork2); + sprintf(pWork,"D%s=%8.4f, ",pWork2,ScanVarStep(pVar)); + strcat(pBueffel,pWork); + } + } + strcat(pBueffel,"\n"); + fputs(pBueffel,self->fd); + + /* + a lot of parameters + */ + fprintf(self->fd,"PARAM: DM=%8.4f, DA=%8.4f, SM=%2d, SS=%2d, SA=%2d\n", + pTAS->ub->machine.monochromator.dd, + pTAS->ub->machine.analyzer.dd, + pTAS->ub->machine.monochromator.ss, + pTAS->ub->machine.ss_sample, + pTAS->ub->machine.analyzer.ss); + if(pTAS->ub->tasMode == KICONST){ + fx = 2; + kfix = getTasPar(pTAS->ub->current,KI); + } else { + fx = 1; + kfix = getTasPar(pTAS->ub->current,KF); + } + + fprintf(self->fd,"PARAM: FX=%3d, KFIX=%8.4f\n", + fx, + kfix); + fprintf(self->fd,"PARAM: ALF1=%8.4f, ALF2=%8.4f, ALF3=%8.4f, ALF4=%8.4f\n", + GetVarFloat("alf1"), + GetVarFloat("alf2"), + GetVarFloat("alf3"), + GetVarFloat("alf4")); + fprintf(self->fd,"PARAM: BET1=%8.4f, BET2=%8.4f, BET3=%8.4f, BET4=%8.4f\n", + GetVarFloat("bet1"), + GetVarFloat("bet2"), + GetVarFloat("bet3"), + GetVarFloat("bet4")); + fprintf(self->fd,"PARAM: ETAM=%8.4f, ETAA=%8.4f\n", + GetVarFloat("etam"), + GetVarFloat("etaa")); + + fprintf(self->fd,"PARAM: AS=%8.4f, BS=%8.4f, CS=%8.4f\n", + pTAS->ub->cell.a, + pTAS->ub->cell.b, + pTAS->ub->cell.c); + fprintf(self->fd,"PARAM: AA=%8.4f, BB=%8.4f, CC=%8.4f\n", + pTAS->ub->cell.alpha, + pTAS->ub->cell.beta, + pTAS->ub->cell.gamma); + + findReflection(pTAS->ub->reflectionList,pTAS->ub->r1 - 1,&r); + fprintf(self->fd,"PARAM: AX=%8.4f, AY=%8.4f, AZ=%8.4f\n", + r.qe.qh, + r.qe.qk, + r.qe.ql); + + findReflection(pTAS->ub->reflectionList,pTAS->ub->r2 - 1,&r); + fprintf(self->fd,"PARAM: BX=%8.4f, BY=%8.4f, BZ=%8.4f\n", + r.qe.qh, + r.qe.qk, + r.qe.ql); + + /* + write currents if in polarisation mode + */ + if(pTAS->iPOL >= 0){ + fprintf(self->fd,"VARIA: "); + iCount = 0; + for(i = 0; i < 8; i++) + { + snprintf(pWork2,59,"i%1.1d",i); + fVal = readDrivable(pWork2,self->pCon); + strtoupper(pWork2); + fprintf(self->fd,"%-8s=%8.4f, ",pWork2,fVal); + iCount++; + } + fprintf(self->fd,"\n"); + } + + /* + write motors + */ + fprintf(self->fd,"VARIA: "); + iCount = 0; + pCom = pServ->pSics->pCList; + while(pCom != NULL) + { + pDum = (pDummy)pCom->pData; + if(pDum != NULL ) + { + if(strcmp(pDum->pDescriptor->name,"Motor") == 0) + { + fVal = readDrivable(pCom->pName,self->pCon); + if(iCount == 3) + { + iCount = 0; + fprintf(self->fd,"\nVARIA: "); + } + strcpy(pWork2,pCom->pName); + strtoupper(pWork2); + fprintf(self->fd,"%-8s=%8.4f, ",pWork2,fVal); + iCount++; + } + } + pCom = pCom->pNext; + } + fprintf(self->fd,"\n"); + + /* + write zeros + */ + fprintf(self->fd,"ZEROS: "); + iCount = 0; + pCom = pServ->pSics->pCList; + while(pCom != NULL) + { + pDum = (pDummy)pCom->pData; + if(pDum != NULL ) + { + if(strcmp(pDum->pDescriptor->name,"Motor") == 0) + { + pMot = (pMotor)pCom->pData; + if(pMot) + { + status = MotorGetPar(pMot,"softzero",&fVal); + if(!status) + { + fVal = -9999.77; + } + fVal *= -1; + if(iCount == 3) + { + iCount = 0; + fprintf(self->fd,"\nZEROS: "); + } + strcpy(pWork2,pCom->pName); + strtoupper(pWork2); + fprintf(self->fd,"%-8s=%8.4f, ",pWork2,fVal); + iCount++; + } + } + } + pCom = pCom->pNext; + } + fprintf(self->fd,"\n"); + + if(pTAS->iPOL >= 0){ + writePolFile(self->fd,pTAS); + } + + /* + write counter parameters + */ + fVal = GetCounterPreset(self->pCounterData); + if(GetCounterMode(self->pCounterData) == eTimer) + { + fprintf(self->fd,"PARAM: TI=%8.4f\n",fVal); + } + else + { + fprintf(self->fd,"PARAM: MN=%8f\n",fVal); + } + + /* + write temperature data + */ + pCom = FindCommand(self->pSics,"temperature"); + if(pCom) + { + pDum = (pDummy)pCom->pData; + pDrive = pDum->pDescriptor->GetInterface(pDum,DRIVEID); + if(pDrive) /* a proper environment device */ + { + fVal = pDrive->GetValue(pDum,self->pCon); + pTem = (pEVControl)pCom->pData; + EVCGetPar(pTem,"target",&fVal2); + fprintf(self->fd,"PARAM: TT=%8.4f, RT=%8.4f\n",fVal, fVal2); + } + } + + /* + build both the format and the data header line, + start with the scan variables + */ + if(pTAS->iPOL >= 0 ){ + strcpy(pBueffel,"FORMT: (I4,I4,"); + strcpy(pHeader," PNT PAL"); + } else { + strcpy(pBueffel,"FORMT: (I4,1X,"); + strcpy(pHeader," PNT "); + } + for(i = 0; i < self->iScanVar; i++) + { + DynarGet(self->pScanVar,i,&pPtr); + pVar = (pVarEntry)pPtr; + if(pVar) + { + strcat(pBueffel,"F9.4,1X,"); + strncpy(pWork2,pVar->Name,59); + strtoupper(pWork2); + strcenter(pWork2,pTen,11); + strcat(pHeader,pTen); + } + } + /* + put the standard counter things + */ + strcat(pBueffel,"F8.0,1X,F8.0,1X,F9.2,1X,F8.0,1X,F8.0,1X,"); + strcat(pHeader," M1 M2 TIME CNTS M3 "); + /* + now the additional variables + */ + for(i = 0; i < pTAS->addCount; i++) + { + if(i == pTAS->addCount -1){ + strcat(pBueffel,"F9.4"); + } else { + strcat(pBueffel,"F9.4,1X,"); + } + strcpy(pWork2,pTAS->out[i]); + strtoupper(pWork2); + strcenter(pWork2,pTen,11); + strcat(pHeader,pTen); + } + strcat(pBueffel,")"); + + /* + write the final bit + */ + fprintf(self->fd,"%s\nDATA_:\n%s\n",pBueffel,pHeader); + + /* + write header to screen as well + */ + SCWrite(self->pCon,pHeader,eWarning); + + /* + close the file, we will reopen later with append for the data + */ + fclose(self->fd); + self->fd = NULL; + return 1; +} +/*-------------------------------------------------------------------------- + TASScanPoint writes the data at each ScanPoint +---------------------------------------------------------------------------*/ +static int TASUBScanPoint(pScanData self, int iPoint) +{ + pTASdata pTAS = (pTASdata)self->pSpecial; + pVarEntry pVar = NULL; + void *pPtr = NULL; + int i, status, iPtr; + float fVal; + pMotor pMot = NULL; + long m1, m2, m3, cnts; + char pBueffel[1024], pWork[80], pError[132]; + + /* + after polarisation analysis, this has to be ignored as it is called + another time from the ScanLoop + */ + if(pTAS->iIgnore){ + return 1; + } + + /* + reopen file for appending + */ + self->fd = fopen(self->pFile,"a"); + if(!self->fd) + { + SCWrite(self->pCon,"ERROR: cannot append to data file",eError); + return 0; + } + + /* + write point number + */ + if(pTAS->iPOL >= 0) + { + sprintf(pBueffel,"%3d %3d",iPoint+1,pTAS->iPOL); + } + else + { + sprintf(pBueffel,"%4d ", iPoint+1); + } + + /* + write the scan variables + */ + for(i = 0; i < self->iScanVar; i++) + { + DynarGet(self->pScanVar,i,&pPtr); + pVar = (pVarEntry)pPtr; + if(pVar) + { + fVal = readDrivable(ScanVarName(pVar),self->pCon); + } + sprintf(pWork,"%9.4f ", fVal); + strcat(pBueffel,pWork); + } + + /* + write monitors and counters + */ + m1 = GetMonitor(self->pCounterData,1,self->pCon); + m2 = GetMonitor(self->pCounterData,2,self->pCon); + m3 = GetMonitor(self->pCounterData,3,self->pCon); + cnts = GetCounts(self->pCounterData,self->pCon); + fVal = GetCountTime(self->pCounterData, self->pCon); + sprintf(pWork,"%8ld %8ld %9.2f %8ld %8ld ",m1,m2,fVal, cnts, m3); + strcat(pBueffel,pWork); + + /* + write additional parameters + */ + for(i = 0; i < pTAS->addCount; i++) + { + fVal = -999.99; + fVal = readDrivable(pTAS->out[i],self->pCon); + if(fVal < -990.){ + snprintf(pError,131,"WARNING: problem reading %s", + pTAS->out[i]); + SCWrite(self->pCon, pError,eWarning); + } + sprintf(pWork,"%9.4f ", fVal); + strcat(pBueffel,pWork); + } + + /* + write both to file and onto screen + */ + fprintf(self->fd,"%s\n",pBueffel); + SCWrite(self->pCon,pBueffel,eWarning); + + /* + close the file + */ + fclose(self->fd); + self->fd = NULL; + return 1; + +} +/*------------------------------------------------------------------------ + TASScanDrive starts all the motors necessary to drive to a new scan + position. It thereby takes care of the TAS calculation if necessary. + -------------------------------------------------------------------------*/ +static int TASUBScanDrive(pScanData self, int iPoint) +{ + pTASdata pTAS = (pTASdata)self->pSpecial; + pVarEntry pVar = NULL; + void *pPtr = NULL; + int i, status, iPtr; + int iTAS = 0; + pMotor pMot; + + /* + loop through all the scan variables + */ + for(i = 0; i < self->iScanVar; i++) + { + DynarGet(self->pScanVar,i,&pPtr); + pVar = (pVarEntry)pPtr; + if(pVar) + { + StartMotor(pServ->pExecutor,self->pSics, self->pCon, pVar->Name, + pVar->fStart + iPoint * pVar->fStep); + /* + Ignore errors. TAS scans continues when a motor runs into + a limit. + */ + } + } + + /* + now wait for our motors to arrive, thereby ignoring any error + returns. DO NOT WAIT if fast scan! + */ + if(pTAS->iFast) + { + return 1; + } + else + { + status = Wait4Success(GetExecutor()); + } + return 1; +} +/*----------------------------------------------------------------------- + RunPolScan does a polarized scan + ------------------------------------------------------------------------*/ +static int RunPolScan(pScanData self, int iPoint) +{ + FILE *fd = NULL; + char buffer[132]; + pTASdata pTAS = (pTASdata)self->pSpecial; + + fd = fopen(GetVarText("polfile"),"r"); + if(!fd){ + SCWrite(self->pCon,"ERROR: failed to open polarisation analysis file", + eError); + return 0; + } + pTAS->iPOL = 0; + while(fgets(buffer,131,fd) != NULL){ + /* + ignore all errors here + */ + InterpExecute(self->pSics,self->pCon,buffer); + strtolower(buffer); + if(strstr(buffer,"co") != NULL){ + pTAS->iPOL++; + self->WriteScanPoints(self,iPoint); + } + /* + but allow for interrupts + */ + if(SCGetInterrupt(self->pCon) != eContinue){ + break; + } + } + pTAS->iIgnore = 1; + fclose(fd); + pTAS->iPOL = 1; + + return 1; +} +/*--------------------------------------------------------------------------- + TASScanCount starts the counter for a TAS scan or runs the polarization + analysis. +---------------------------------------------------------------------------*/ +static int TASUBScanCount(pScanData self, int iPoint) +{ + pTASdata pTAS = (pTASdata)self->pSpecial; + float fVal; + int status, iRet; + Status eOld; + + pTAS->iIgnore = 0; + /* + call the polarisation scan function if necessary + */ + if(pTAS->iPOL >= 0) + { + return RunPolScan(self, iPoint); + } + + /* + this is easy, just an ordinary scan, start a counter + */ + fVal = GetCounterPreset(self->pCounterData); + eOld = GetStatus(); + status = DoCount(self->pCounterData,fVal,self->pCon,0); + iRet = Wait4Success(GetExecutor()); + if(iRet == DEVINT) + { + SCWrite(self->pCon,"Counting aborted due to Interrupt",eStatus); + status = 0; + } + else if(iRet == DEVERROR) + { + SCWrite(self->pCon,"Counting finished with Problems",eStatus); + status = 0; + } + else + { + status = 1; + } + SetStatus(eOld); + + return status; +} +/*-------------------------------------------------------------------------- + TAS stores the scan data. This is necessary in order to support things + like peak or center which require the scan data for operation + --------------------------------------------------------------------------*/ + static int TASUBCollect(pScanData self, int iPoint) + { + pVarEntry pVar = NULL; + void *pDings; + int i, iRet, status, iPtr; + float fVal; + CountEntry sCount; + char *pAns = NULL, *pPtr = NULL ; + pTASdata pTAS = (pTASdata)self->pSpecial; + pMotor pMot; + char pError[132]; + + assert(self); + assert(self->pCon); + + /* loop over all scan variables */ + status = 1; + for(i = 0; i < self->iScanVar; i++) + { + DynarGet(self->pScanVar,i,&pDings); + pVar = (pVarEntry)pDings; + fVal = readDrivable(ScanVarName(pVar),self->pCon); + if(fVal < -990) + { + snprintf(pError,131,"WARNING: failed to read %s", + ScanVarName(pVar)); + SCWrite(self->pCon,pError,eWarning); + } + AppendScanVar(pVar,fVal); + } + + /* store counter data */ + /* monitors */ + for(i = 1; i < 10; i++) + { + sCount.Monitors[i-1] = GetMonitor((pCounter)self->pCounterData,i, + self->pCon); + } + if( self->iChannel != 0 && self->iChannel != -10 ) + { + sCount.Monitors[self->iChannel - 1] = + GetCounts((pCounter)self->pCounterData, + self->pCon); + } + + /* counts, depending on iChannel */ + if(self->iChannel == 0) + { + sCount.lCount = GetCounts((pCounter)self->pCounterData,self->pCon); + } + else + { + sCount.lCount = GetMonitor((pCounter)self->pCounterData, + self->iChannel, self->pCon); + } + + /* get time */ + sCount.fTime = GetCountTime((pCounter)self->pCounterData, + self->pCon); + /* stow away */ + DynarReplace(self->pCounts,self->iCounts,&sCount,sizeof(CountEntry)); + self->iCounts++; + return 1; + } +/*----------------------------------------------------------------------- +prepare2Parse removes all unnecessary delimiters from the parse string. +These are: ' = +----------------------------------------------------------------------*/ +static void prepare2Parse(char *line) +{ + int i, iLang; + + iLang = strlen(line); + for(i = 0; i < iLang; i++) + { + if(line[i] == ',' || line[i] == '=') + { + line[i] = ' '; + } + } +} +/*----------------------------------------------------------------*/ +extern char *stptok(const char *s, char *t, int len, char *brk); +extern char*trim(char *txt); +/*----------------------------------------------------------------------- + During a TAS scan additional output variables can be printed. These are + defined in a text variable called ouput. ParseOutput now parses this + variable and enters the variables found in there into the TAS data + structure so that they can be printed during the scan. + ------------------------------------------------------------------------*/ +static void ParseOutput(pTASdata pTAS, SConnection *pCon) +{ + char *pText = NULL, *pPtr, pToken[20], pWarn[256]; + int iPtr; + + /* + get a copy of output + */ + pText = (char *)malloc(strlen(GetVarText("output"))*sizeof(char)); + if(!pText) + { + SCWrite(pCon,"WARNING: out of memory while parsing output variable", + eWarning); + return; + } + strcpy(pText,GetVarText("output")); + + /* + wash it + */ + prepare2Parse(pText); + + /* + parse + */ + pTAS->addCount = 0; + pPtr = pText; + while(pPtr != NULL) + { + pPtr = stptok(pPtr,pToken,20," ,="); + if(strlen(pToken) < 1 || pPtr == NULL) + continue; + + if(FindCommand(pServ->pSics,trim(pToken))) + { + strncpy(pTAS->out[pTAS->addCount],trim(pToken),10); + pTAS->addCount++; + } + else + { + sprintf(pWarn,"WARNING: ignored invalid token > %s < in output", + pToken); + SCWrite(pCon,pWarn,eWarning); + } + } + free(pText); +} +/*----------------------------------------------------------------------*/ +int TASUBPrepare(pScanData self) +{ + int status; + pTASdata pTAS = (pTASdata)self->pSpecial; + time_t iDate; + struct tm *psTime; + char pWork[70]; + char pLine[1024]; + + status = NonCheckPrepare(self); + + ParseOutput(pTAS,self->pCon); + + /* + print some status information for the looser + */ + iDate = time(NULL); + psTime = localtime(&iDate); + memset(pWork,0,69); + strftime(pWork,69,"%d-%b-%Y %H:%M:%S",psTime); + snprintf(pLine,1023,"%8s %3d Points Scan %3d Scanned Variable(s) %s", + GetVarText("instrument"), + pTAS->pScan->iNP, pTAS->pScan->iScanVar, + pWork); + SCWrite(self->pCon,pLine,eWarning); + + if(GetCounterMode(pTAS->pScan->pCounterData) == eTimer) + { + sprintf(pLine," %8f Seconds per point", + GetCounterPreset(pTAS->pScan->pCounterData)); + } + else + { + sprintf(pLine," %8f Monitor Counts per point", + GetCounterPreset(pTAS->pScan->pCounterData)); + + } + SCWrite(self->pCon,pLine,eWarning); + SCWrite(self->pCon," ",eWarning); + SCWrite(self->pCon," ",eWarning); + + /* + snprintf(pLine,1023, + " %12s %6s HKLE: %5.2f %5.2f %5.2f %8.4f %6.3f %6.3f %6.3f %6.3f", + GetVarText("title"), + GetVarText("user"), + pTAS->tasPar[QH]->fVal - (pTAS->pScan->iNP/2)*pTAS->tasPar[DQH]->fVal, + pTAS->tasPar[QK]->fVal - (pTAS->pScan->iNP/2)*pTAS->tasPar[DQL]->fVal, + pTAS->tasPar[QL]->fVal - (pTAS->pScan->iNP/2)*pTAS->tasPar[DQK]->fVal, + pTAS->tasPar[EN]->fVal - (pTAS->pScan->iNP/2)*pTAS->tasPar[DEN]->fVal, + pTAS->tasPar[DQH]->fVal, + pTAS->tasPar[DQK]->fVal, + pTAS->tasPar[DQL]->fVal, + pTAS->tasPar[DEN]->fVal); + SCWrite(pCon,pLine,eWarning); + */ + if(pTAS->ub->tasMode == KICONST) + { + snprintf(pLine,1023," Constant KI Scan: KI= %7.4f Angs-1; EI= %9.4f", + getTasPar(pTAS->ub->current,KI), + getTasPar(pTAS->ub->current,EI)); + } + else + { + snprintf(pLine,1023," Constant KF Scan: KF= %7.4f Angs-1; EF= %9.4f", + getTasPar(pTAS->ub->current,KF), + getTasPar(pTAS->ub->current,EF)); + } + SCWrite(self->pCon,pLine,eWarning); + + return status; +} +/*----------------------------------------------------------------------*/ +int TASUBScan(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]){ + pTASdata self = NULL; + char pBueffel[256]; + int np; + + self = (pTASdata)pData; + assert(self); + + self->pScan->pSpecial = self; + + if(argc < 2) { + SCWrite(pCon,"ERROR: not enough arguments to tasscan",eError); + return 0; + } + strtolower(argv[1]); + + if(strcmp(argv[1],"pol") == 0){ + if(argc > 2){ + if(!SCMatchRights(pCon,usUser)){ + return 0; + } + self->iPOL = atoi(argv[2]); + SCSendOK(pCon); + return 1; + } else { + snprintf(pBueffel,255,"%s.pol = %d",argv[0],self->iPOL); + SCWrite(pCon,pBueffel,eValue); + return 1; + } + }else if(strcmp(argv[1],"fast") == 0){ + if(argc > 2){ + if(!SCMatchRights(pCon,usUser)){ + return 0; + } + self->iFast = atoi(argv[2]); + SCSendOK(pCon); + return 1; + } else { + snprintf(pBueffel,255,"%s.fast = %d",argv[0],self->iFast); + SCWrite(pCon,pBueffel,eValue); + return 1; + } + } else if(strcmp(argv[1],"prepare") == 0){ + return TASUBPrepare(self->pScan); + } else if(strcmp(argv[1],"drive") == 0){ + if(argc < 5) { + SCWrite(pCon,"ERROR: insufficient number of arguments to tasscan drive", + eError); + return 0; + } + np = atoi(argv[4]); + return TASUBScanDrive(self->pScan,np); + } else if(strcmp(argv[1],"header") == 0){ + return TASUBHeader(self->pScan); + } else if(strcmp(argv[1],"count") == 0){ + if(argc < 7) { + SCWrite(pCon,"ERROR: insufficient number of arguments to tasscan count", + eError); + return 0; + } + np = atoi(argv[4]); + return TASUBScanCount(self->pScan,np); + } else if(strcmp(argv[1],"collect") == 0){ + if(argc < 5) { + SCWrite(pCon, + "ERROR: insufficient number of arguments to tasscan collect", + eError); + return 0; + } + np = atoi(argv[4]); + return TASUBCollect(self->pScan,np); + } else if(strcmp(argv[1],"writepoint") == 0){ + if(argc < 5) { + SCWrite(pCon, + "ERROR: insufficient number of arguments to tasscan writepoint", + eError); + return 0; + } + np = atoi(argv[4]); + return TASUBScanPoint(self->pScan,np); + } else { + SCWrite(pCon,"ERROR: subcommand to tasscan not understood",eError); + return 0; + } + + return 1; +} +/*---------------------------------------------------------------------*/ +static void KillTAS(void *pData){ + pTASdata self = (pTASdata)pData; + if(self == NULL){ + return; + } + if(self->pDes != NULL){ + DeleteDescriptor(self->pDes); + } + free(self); +} +/*----------------------------------------------------------------------*/ +int TASUBScanFactory(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]){ + pTASdata pNew = NULL; + char pBueffel[512]; + int i; + char *pVar[] = { + "polfile", + "instrument", + "user", + "local", + "title", + "lastscancommand", + "output", + NULL + }; + + + if(argc < 3){ + SCWrite(pCon,"ERROR: not enough arguments to TASUBScanFactory",eError); + return 0; + } + + pNew = (pTASdata)malloc(sizeof(TASdata)); + if(!pNew){ + SCWrite(pCon,"ERROR: out of memory creating tasscan object",eError); + return 0; + } + memset(pNew,0,sizeof(TASdata)); + pNew->pDes = CreateDescriptor("TAS Scan Stuff"); + if(!pNew->pDes){ + SCWrite(pCon,"ERROR: out of memory creating tasscan object",eError); + free(pNew); + return 0; + } + + pNew->pScan = (pScanData)FindCommandData(pSics,argv[1],"ScanObject"); + if(!pNew->pScan){ + snprintf(pBueffel,511,"ERROR: cannot locate scan object %s", argv[1]); + free(pNew); + SCWrite(pCon,pBueffel,eError); + return 0; + } + pNew->counter = (pCounter)pNew->pScan->pCounterData; + + pNew->ub = (ptasUB)FindCommandData(pSics,argv[2],"TAS-UB"); + if(!pNew->ub){ + snprintf(pBueffel,511,"ERROR: cannot locate TAS-UB object %s", argv[2]); + free(pNew); + SCWrite(pCon,pBueffel,eError); + return 0; + } + + i = 0; + while(pVar[i] != NULL){ + if(FindCommandData(pSics,pVar[i],"SicsVariable") == NULL){ + snprintf(pBueffel,511,"ERROR: variable %s missing", pVar[i]); + SCWrite(pCon,pBueffel,eError); + free(pNew); + return 0; + } + i++; + } + return AddCommand(pSics,"tasscan",TASUBScan,KillTAS,pNew); +} diff --git a/tasscanub.h b/tasscanub.h new file mode 100644 index 00000000..571fc74e --- /dev/null +++ b/tasscanub.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------------------- + This is the header file for the TAS scan code. It mainly implements + writing of the ILL file format, which the TAS'lers adore. + + Mark Koennecke, May 2005, using code from an earlier TASAMAD emulation + core. +------------------------------------------------------------------------*/ +#ifndef SICUBSTAS +#define SICSUBTAS +#include +#include "tasub.h" +/* --------------------- data structure -------------------------------*/ +#define MAXADD 20 +typedef struct { + pObjectDescriptor pDes; + pCounter counter; + pScanData pScan; + ptasUB ub; + int iPOL; + int iIgnore; /* in order to ignore writing scan points again + in polarisation mode; + */ + char out[MAXADD][10]; + int addCount; + int iFileNO; + int iFast; + char scanVar[80]; + }TASdata, *pTASdata; +/*---------------------- interface ----------------------------------*/ + + int TASUBScanFactory(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); + int TASUBScan(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); + +#endif diff --git a/tasub.c b/tasub.c index 58f62284..6c7190f0 100644 --- a/tasub.c +++ b/tasub.c @@ -83,6 +83,8 @@ static int tasUBSave(void *pData, char *name, FILE *fd){ name, self->target.qh, self->target.qk, self->target.ql, self->target.qm, self->target.ki, self->target.kf); + fprintf(fd,"%s setidx %d %d\n", + name, self->r1, self->r2); fprintf(fd,"%s update\n", name); return 1; } @@ -475,6 +477,8 @@ static void clearReflections(ptasUB self){ LLDnodeDelete(self->reflectionList); status = LLDnodePtr2Next(self->reflectionList); } + self->r1 = -1; + self->r2 = -1; } /*------------------------------------------------------------------*/ static void listReflections(ptasUB self, SConnection *pCon){ @@ -612,7 +616,7 @@ static int addReflection(ptasUB self, SicsInterp *pSics, return 1; } /*-----------------------------------------------------------------*/ -static int findReflection(int list, int idx, ptasReflection r){ +int findReflection(int list, int idx, ptasReflection r){ int count = 0; int status; @@ -628,26 +632,29 @@ static int findReflection(int list, int idx, ptasReflection r){ return 0; } /*------------------------------------------------------------------*/ -static void listUB(MATRIX UB, SConnection *pCon){ +static void listUB(ptasUB self , SConnection *pCon){ Tcl_DString list; char pBueffel[255]; int i; Tcl_DStringInit(&list); - if(UB == NULL){ + if(self->machine.UB == NULL){ Tcl_DStringAppend(&list,"NO UB",-1); - } else { + } else { Tcl_DStringAppend(&list,"UB = ", -1); - snprintf(pBueffel,255,"%f %f %f\n", UB[0][0], - UB[0][1],UB[0][2]); + snprintf(pBueffel,255,"%f %f %f\n", self->machine.UB[0][0], + self->machine.UB[0][1],self->machine.UB[0][2]); Tcl_DStringAppend(&list,pBueffel,-1); for(i = 1; i < 3; i++){ - snprintf(pBueffel,255," %f %f %f\n", UB[i][0], - UB[i][1],UB[i][2]); + snprintf(pBueffel,255," %f %f %f\n", self->machine.UB[i][0], + self->machine.UB[i][1],self->machine.UB[i][2]); Tcl_DStringAppend(&list,pBueffel,-1); } } + snprintf(pBueffel,255,"UB generated from reflections %d and %d in list\n", + self->r1, self->r2); + Tcl_DStringAppend(&list,pBueffel,-1); SCWrite(pCon,Tcl_DStringValue(&list),eValue); Tcl_DStringFree(&list); } @@ -691,7 +698,7 @@ static void printReflectionDiagnostik(ptasUB self, SConnection *pCon, qe.qh, qe.qk, qe.ql, angles.a3, angles.sample_two_theta, angles.sgu, angles.sgl, qe.ki, qe.kf); Tcl_DStringAppend(&list,line,-1); - SCWrite(pCon,Tcl_DStringValue(&list),eValue); + SCWrite(pCon,Tcl_DStringValue(&list),eWarning); Tcl_DStringFree(&list); } /*------------------------------------------------------------------*/ @@ -737,6 +744,7 @@ static int calcUB(ptasUB self, SConnection *pCon, SicsInterp *pSics, SCWrite(pCon,pBueffel,eError); return 0; } + self->r1 = idx; status = Tcl_GetInt(InterpGetTcl(pSics),argv[3],&idx); if(status != TCL_OK){ snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]); @@ -749,6 +757,7 @@ static int calcUB(ptasUB self, SConnection *pCon, SicsInterp *pSics, SCWrite(pCon,pBueffel,eError); return 0; } + self->r2 = idx; UB = calcTasUBFromTwoReflections(self->cell,r1,r2,&status); if(UB == NULL){ @@ -770,7 +779,7 @@ static int calcUB(ptasUB self, SConnection *pCon, SicsInterp *pSics, } self->machine.UB = UB; self->machine.planeNormal = calcPlaneNormal(r1,r2); - listUB(UB,pCon); + listUB(self,pCon); listDiagnostik(self,pCon); SCparChange(pCon); return 1; @@ -943,6 +952,22 @@ static int setUB(SConnection *pCon, SicsInterp *pSics, ptasUB self, return 1; } /*------------------------------------------------------------------*/ +static int setIDX(SConnection *pCon, SicsInterp *pSics, ptasUB self, + int argc, char *argv[]){ + if(argc < 4) { + SCWrite(pCon,"ERROR: not enough arguments to setidx", eError); + return 0; + } + + if(!SCMatchRights(pCon,usMugger)){ + return 0; + } + self->r1 = atoi(argv[2]); + self->r2 = atoi(argv[3]); + SCSendOK(pCon); + return 1; +} +/*------------------------------------------------------------------*/ static int setNormal(SConnection *pCon, SicsInterp *pSics, ptasUB self, int argc, char *argv[]){ double value; @@ -1066,6 +1091,40 @@ static int tasUpdate(SConnection *pCon, ptasUB self){ SCSendOK(pCon); return 1; } +/*------------------------------------------------------------------*/ +static int deleteReflection(SConnection *pCon, SicsInterp *pSics, + ptasUB self, int argc, char *argv[]){ + int idx, count = 0, status; + char pBueffel[256]; + + if(argc < 3){ + SCWrite(pCon,"ERROR: need number of reflection to delete",eError); + return 0; + } + status = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&idx); + if(status != TCL_OK){ + snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]); + SCWrite(pCon,pBueffel,eError); + return 0; + } + if(idx == self->r1 || idx == self->r2) { + SCWrite(pCon,"ERROR: I refuse to delete reflections used for current UB", + eError); + return 0; + } + idx--; + status = LLDnodePtr2First(self->reflectionList); + while(status == 1){ + if(count == idx){ + LLDnodeDelete(self->reflectionList); + break; + } + status = LLDnodePtr2Next(self->reflectionList); + count++; + } + SCSendOK(pCon); + return 1; +} /*-------------------------------------------------------------------*/ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData, int argc, char *argv[]){ @@ -1104,7 +1163,7 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData, } else if(strcmp(argv[1],"addref") == 0){ return addReflection(self,pSics,pCon,argc,argv); } else if(strcmp(argv[1],"listub") == 0){ - listUB(self->machine.UB,pCon); + listUB(self,pCon); return 1; } else if(strcmp(argv[1],"makeub") == 0){ return calcUB(self,pCon,pSics,argc,argv); @@ -1114,10 +1173,14 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData, return setUB(pCon,pSics,self,argc,argv); } else if(strcmp(argv[1],"setnormal") == 0){ return setNormal(pCon,pSics,self,argc,argv); + } else if(strcmp(argv[1],"setidx") == 0){ + return setIDX(pCon,pSics,self,argc,argv); } else if(strcmp(argv[1],"settarget") == 0){ return setTarget(pCon,pSics,self,argc,argv); } else if(strcmp(argv[1],"update") == 0){ return tasUpdate(pCon,self); + } else if(strcmp(argv[1],"del") == 0){ + return deleteReflection(pCon,pSics,self,argc,argv); } else if(strcmp(argv[1],"const") == 0){ if(argc > 2){ strtolower(argv[2]); @@ -1129,7 +1192,8 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData, } else if(strcmp(argv[2],"kf") == 0){ self->tasMode = KFCONST; } else { - SCWrite(pCon,"ERROR: unknown triple axis mode, accepted are ki, kf",eError); + SCWrite(pCon,"ERROR: unknown triple axis mode, accepted are ki, kf", + eError); return 0; } SCSendOK(pCon); diff --git a/tasub.h b/tasub.h index 8086b0f0..b703e863 100644 --- a/tasub.h +++ b/tasub.h @@ -27,6 +27,7 @@ int mustRecalculate; int mustDrive; pMotor motors[12]; + int r1, r2; }tasUB, *ptasUB; @@ -46,4 +47,5 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData, int argc, char *argv[]); +int findReflection(int list, int idx, ptasReflection r); #endif diff --git a/tasub.w b/tasub.w index 04de0974..02fb433e 100644 --- a/tasub.w +++ b/tasub.w @@ -29,6 +29,7 @@ A data structure: int mustRecalculate; int mustDrive; pMotor motors[12]; + int r1, r2; }tasUB, *ptasUB; @} \begin{description} @@ -49,6 +50,8 @@ A data structure: \item[motors] The TAS motors: A1, A2, MCV (vertical curvature), MCH (horizontal curvature), A3, A4, SGU, SGL, A5, A6, ACV, ACH. The curvature motors may be NULL at runtime. +\item[r1,r2] The indexs of the reflections used for calculating the orientation + matrix. \end{description} For the virtual motors, there must be a data structure, too: @@ -97,6 +100,7 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData, @ /*--------------------------------------------------------------------*/ @ +int findReflection(int list, int idx, ptasReflection r); #endif @} @o tasdrive.h @{