/*-------------------------------------------------------------------------- H K L S C A N A class for doing scans in reciprocal space for a four circle diffractometer. All the hard work is done in the scan and hkl objects. copyright: see copyright.h Mark Koennecke, June 1999 --------------------------------------------------------------------------*/ #include #include #include #include #include "fortify.h" #include "sics.h" #include "scan.h" #include "hkl.h" #include "scan.i" #include "matrix/matrix.h" #include "hkl.i" #include "hklscan.i" #include "hklscan.h" /*-----------------------------------------------------------------------*/ static void KillHklscan(void *pData) { pHklscan self = NULL; self = (pHklscan)pData; if(!self) { return; } if(self->pDes) { DeleteDescriptor(self->pDes); } free(self); } /*------------------------------------------------------------------------*/ int HklscanFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[4]) { pHklscan pNew = NULL; char pBueffel[512]; int iRet; /* check number of arguments */ if(argc < 3) { SCWrite(pCon, "ERROR: expected two arguments to MakeHklscan",eError); return 0; } /* allocate space */ pNew = (pHklscan)malloc(sizeof(sHklscan)); if(!pNew) { SCWrite(pCon,"ERROR: out of memory in MakeHklscan",eError); return 0; } memset(pNew,0,sizeof(sHklscan)); pNew->pDes = CreateDescriptor("Hklscan"); /* find scan object */ pNew->pScan = (pScanData)FindCommandData(pSics,argv[1],"ScanObject"); if(!pNew->pScan) { sprintf(pBueffel,"ERROR: %s not found or no scan object",argv[1]); SCWrite(pCon,pBueffel,eError); KillHklscan(pNew); return 0; } /* find HKL object */ pNew->pCalc = (pHKL)FindCommandData(pSics,argv[2], "4-Circle-Calculus"); if(!pNew->pCalc) { sprintf(pBueffel,"ERROR: %s not found or no HKL object",argv[2]); SCWrite(pCon,pBueffel,eError); KillHklscan(pNew); return 0; } /* alright. Install command */ iRet = AddCommand(pSics, "hklscan", HklscanAction,KillHklscan,pNew); if(!iRet) { SCWrite(pCon,"ERROR: duplicate command hklscan NOT created",eError); KillHklscan(pNew); return 0; } return 1; } /*------------------------------------------------------------------------*/ static int HklscanDrive(pScanData pScan, int iPoint) { pHklscan self = NULL; int i, iRet; assert(pScan); self = (pHklscan)pScan->pSpecial; assert(self); /* calculate new Positions */ for(i = 0; i < 3; i++) { self->fPos[i] = self->fStart[i] + iPoint * self->fStep[i]; } iRet = DriveHKL(self->pCalc, self->fPos, 0.,0,pScan->pCon); if(!iRet) { SCWrite(pScan->pCon,"ERROR: aborting hklscan",eError); } return iRet; } /*------------------------------------------------------------------------*/ static int WriteHklscanPoint(pScanData self, int iPoint) { pHklscan pHaSca = NULL; int i, i2; char pLine[512], pItem[30], pInfo[512]; pVarEntry pVar = NULL; pCountEntry pData = NULL; void *pPtr = NULL; assert(self); pHaSca = (pHklscan)self->pSpecial; assert(pHaSca); assert(self->pCon); assert(self->pSics); if(!self->fd) { self->fd = fopen(self->pFile,"r+"); if(!self->fd) { SCWrite(self->pCon,"ERROR: failed to reopen scan file during scan",eError); return 0; } } /* jump to end of header */ fseek(self->fd,self->lPos, SEEK_SET); if(self->iChannel != 0) { fprintf(self->fd,"WARNING: Scanning monitor %d\n",self->iChannel); } /* make the data header */ sprintf(pLine,"%-5s","NP"); strcpy(pInfo,"Scanning Variables: H, K, L"); strcat(pLine,"H K L "); for(i = 0; i < self->iScanVar;i++) { DynarGet(self->pScanVar,i,&pPtr); pVar = (pVarEntry)pPtr; if(pVar) { sprintf(pItem,"%-6.6s ",pVar->Name); strcat(pLine,pItem); } } strcat(pLine,"Counts "); strcat(pLine," Monitor1 "); sprintf(pItem,"\n%d Points,",self->iNP); strcat(pInfo,pItem); if(self->iMode == eTimer) { strcat(pInfo," Mode: Timer,"); } else { strcat(pInfo," Mode: Monitor,"); } sprintf(pItem," Preset %f",self->fPreset); strcat(pInfo,pItem); fprintf(self->fd,"%s\n",pInfo); fprintf(self->fd,"%s\n",pLine); /* print an addon to the status line going to the screen */ sprintf(pLine,"NP H K L "); SCWrite(self->pCon,pLine,eWarning); sprintf(pLine,"%-5d%-8.4f%-8.4f%-8.4f ",iPoint,pHaSca->fPos[0], pHaSca->fPos[1], pHaSca->fPos[2]); SCWrite(self->pCon,pLine,eWarning); /* now the scan points */ for(i = 0; i < self->iCounts; i++) { sprintf(pLine,"%-5d",i); /* print HKL */ for(i2 = 0; i2 < 3; i2++) { sprintf(pItem,"%-8.4f",pHaSca->fStart[i2] + i * pHaSca->fStep[i2]); strcat(pLine,pItem); } /* print chi, ph, om */ for(i2 = 0; i2 < self->iScanVar; i2++) { DynarGet(self->pScanVar,i2,&pPtr); pVar = (pVarEntry)pPtr; if(pVar) { sprintf(pItem,"%-7.2f",pVar->fData[i]); strcat(pLine,pItem); } } /* print Counts & Monitor */ DynarGet(self->pCounts,i,&pPtr); pData = (pCountEntry)pPtr; if(pData) { sprintf(pItem,"%-13ld",pData->lCount); strcat(pLine,pItem); sprintf(pItem,"%-12ld",pData->Monitors[0]); strcat(pLine,pItem); } fprintf(self->fd,"%s\n",pLine); } /* done */ fprintf(self->fd,"END-OF-DATA\n"); fclose(self->fd); self->fd = NULL; return 1; } /*------------------------------------------------------------------------*/ int Hklscan(pHklscan self, SConnection *pCon, int iNP, int iMode, float fPreset) { int iRet; float fVal; assert(self); /* configure the scan thing for our bizarre purpose */ ClearScanVar(self->pScan); MotorGetPar(self->pCalc->pTheta, "softlowerlim",&fVal); fVal += .5; AddScanVar(self->pScan,pServ->pSics,pCon,self->pCalc->pTheta->name, fVal,0.); MotorGetPar(self->pCalc->pOmega, "softlowerlim",&fVal); fVal += .5; AddScanVar(self->pScan,pServ->pSics,pCon,self->pCalc->pOmega->name, fVal,0.); MotorGetPar(self->pCalc->pChi, "softlowerlim",&fVal); fVal += .5; AddScanVar(self->pScan,pServ->pSics,pCon,self->pCalc->pChi->name, fVal,0.); MotorGetPar(self->pCalc->pPhi, "softlowerlim",&fVal); fVal += .5; AddScanVar(self->pScan,pServ->pSics,pCon,self->pCalc->pPhi->name, fVal,0.); self->pScan->WriteScanPoints = WriteHklscanPoint; self->pScan->ScanDrive = HklscanDrive; self->pScan->pSpecial = self; self->pScan->PrepareScan = NonCheckPrepare; /* scan */ iRet = DoScan(self->pScan,iNP, iMode, fPreset, pServ->pSics,pCon); /* unset all */ ClearScanVar(self->pScan); ResetScanFunctions(self->pScan); self->pScan->pSpecial = NULL; return iRet; } /*-------------------------------------------------------------------------*/ int HklscanAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) { char pBueffel[512]; int iRet, iMode, iNP; pHklscan self = NULL; double dVal; float fPreset; assert(pCon); assert(pSics); assert(pData); self = (pHklscan)pData; /* check for the command word */ if(argc < 2) { SCWrite(pCon,"ERROR: Insufficient number of arguments to hklscan", eError); return 0; } /* do work according to command word */ strtolower(argv[1]); if(strcmp(argv[1],"start") == 0) { if(!SCMatchRights(pCon,usUser)) { return 0; } if(argc < 5) { SCWrite(pCon, "Insufficient number of arguments to hklscan", eError); return 0; } iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dVal); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: failed to convert %s to number", argv[2]); SCWrite(pCon,pBueffel,eError); return 0; } self->fStart[0] = (float)dVal; iRet = Tcl_GetDouble(pSics->pTcl,argv[3],&dVal); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: failed to convert %s to number", argv[3]); SCWrite(pCon,pBueffel,eError); return 0; } self->fStart[1] = (float)dVal; iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&dVal); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: failed to convert %s to number", argv[4]); SCWrite(pCon,pBueffel,eError); return 0; } self->fStart[2] = (float)dVal; SCSendOK(pCon); return 1; } else if(strcmp(argv[1],"step") == 0) { if(!SCMatchRights(pCon,usUser)) { return 0; } if(argc < 5) { SCWrite(pCon, "Insufficient number of arguments to hklscan", eError); return 0; } iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dVal); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: failed to convert %s to number", argv[2]); SCWrite(pCon,pBueffel,eError); return 0; } self->fStep[0] = (float)dVal; iRet = Tcl_GetDouble(pSics->pTcl,argv[3],&dVal); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: failed to convert %s to number", argv[3]); SCWrite(pCon,pBueffel,eError); return 0; } self->fStep[1] = (float)dVal; iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&dVal); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: failed to convert %s to number", argv[4]); SCWrite(pCon,pBueffel,eError); return 0; } self->fStep[2] = (float)dVal; SCSendOK(pCon); return 1; } else if(strcmp(argv[1],"run") == 0) { if(!SCMatchRights(pCon,usUser)) { return 0; } if(argc < 5) { SCWrite(pCon, "Insufficient number of arguments to hklscan run", eError); return 0; } iRet = Tcl_GetInt(pSics->pTcl,argv[2],&iNP); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: failed to convert %s to number", argv[2]); SCWrite(pCon,pBueffel,eError); return 0; } /* interpret Mode */ if(strcmp(argv[3],"timer") == 0) { iMode = eTimer; } else if(strcmp(argv[3],"monitor") == 0) { iMode = ePreset; } else { sprintf(pBueffel,"ERROR: %s not recognized as valid counter mode", argv[3]); SCWrite(pCon,pBueffel,eError); return 0; } /* preset */ iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&dVal); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); SCWrite(pCon,pBueffel,eError); return 0; } fPreset = (float)dVal; iRet = Hklscan(self,pCon,iNP,iMode,fPreset); if(iRet) { SCSendOK(pCon); } return iRet; } sprintf(pBueffel, "ERROR: %s not recognized as command word to hklscan",argv[1]); SCWrite(pCon,pBueffel,eError); return 0; }