/*------------------------------------------------------------------------- N E X T R I C S NeXus file writing for the four circle diffractometer TRICS at Sinq, PSI. This object uses the NXDICT-API. A further speciality is that objects which are constantly written are kept in cache. This means, on initialisation pointers to all relevant objects which have to be stored with a data frame are searched and kept in the objects data structure. copyright: see copyright.h Mark Koennecke, April 1998 ----------------------------------------------------------------------------*/ #include #include #include #include "fortify.h" #include "sics.h" #include "sicsvar.h" #include "motor.h" #include "countdriv.h" #include "counter.h" #include "HistMem.h" #include "danu.h" #include "nxdict.h" #include "nxutil.h" #include "hkl.h" #include "udpquieck.h" #include "nextrics.h" #define DET1X 128 /* x -length of detector 1 */ #define DET1Y 128 /* y-length of detector 1 */ #define DET1XS 2 /* pixel size in x of detector 1 */ #define DET1YS 2 /* pixel size in y of detector 1 */ #define DET1DESC "Non existent Detector" #define DETAMAX 128 /* maximum length of pixelsize array */ /*------------------------ the data structure ----------------------------*/ typedef struct __NexTrics { pObjectDescriptor pDes; char *pCurrentFile; char *pFileRoot; pDataNumber pDanu; NXdict pDict; pHistMem pHistogram; int iFirst; } NexTrics; /*----------------------------------------------------------------------*/ pNexTrics CreateNexTrics(pDataNumber pNum, char *pRoot, char *pDict, SicsInterp *pSics) { pNexTrics pNew = NULL; int iRet; CommandList *pCom = NULL; /* allocate memory */ pNew = (pNexTrics)malloc(sizeof(NexTrics)); if(!pNew) { return NULL; } memset(pNew,0,sizeof(NexTrics)); /* new object descriptor */ pNew->pDes = CreateDescriptor("NexTrics"); if(!pNew->pDes) { free(pNew); return NULL; } /* initialize dictionary */ iRet = NXDinitfromfile(pDict,&pNew->pDict); if(iRet != NX_OK) { DeleteNexTrics(pNew); return NULL; } pNew->pFileRoot = strdup(pRoot); pNew->pDanu = pNum; /* find things in interpreter */ pCom = FindCommand(pSics,"banana"); if(!pCom) { DeleteNexTrics(pNew); return NULL; } pNew->pHistogram = (pHistMem)pCom->pData; pNew->iFirst = 1; return pNew; } /*-------------------------------------------------------------------------*/ void DeleteNexTrics(void *pData) { pNexTrics self = NULL; self = (pNexTrics)pData; if(!self) return; if(self->pDes) DeleteDescriptor(self->pDes); if(self->pCurrentFile) free(self->pCurrentFile); if(self->pFileRoot) free(self->pFileRoot); if(self->pDict) NXDclose(self->pDict,NULL); free(self); } /*---------------------- a neXus error handler ---------------------------*/ static void SNError(void *pData, char *text) { SConnection *pCon; assert(pData); pCon = (SConnection *)pData; SCWrite(pCon,text,eError); } /*--------------------------------------------------------------------------*/ int NexTricsFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) { pNexTrics pNew = NULL; pDataNumber pDanu = NULL; CommandList *pCom; char pBueffel[512]; int iRet; pDummy pDum; if(argc < 4) { SCWrite(pCon, "ERROR: Insufficient number of arguments to NexTricsFactory",eError); return 0; } /* first item must be the name of a datanumber variable */ pCom = FindCommand(pSics,argv[1]); if(pCom) { pDanu = (pDataNumber)pCom->pData; } if( (!pCom) || (!pDanu)) { SCWrite(pCon,"ERROR: DataNumber object NOT found",eError); return 0; } pDum = (pDummy)pDanu; if(strcmp(pDum->pDescriptor->name,"DataNumber") != 0) { sprintf(pBueffel,"ERROR: %s is no DataNumber object",argv[1]); SCWrite(pCon,pBueffel,eError); return 0; } /* install an error handler */ NXMSetError((void *)pCon,SNError); pNew = CreateNexTrics(pDanu,argv[2],argv[3],pSics); if(!pNew) { SCWrite(pCon,"ERROR: cannot create nexTrics, invalid dictionary file",eError); SCWrite(pCon,"ERROR: or system objects missing.",eError); return 0; } /* create the command */ iRet = AddCommand(pSics,"nexus",NexTricsAction,DeleteNexTrics, pNew); if(!iRet) { SCWrite(pCon,"ERROR: duplicate command nexus not created",eError); } return iRet; } /*-------------------------------------------------------------------------*/ static int DumpData(pNexTrics self, SConnection *pCon, NXhandle hfil, int iFrameNum) { int iRet; char pBueffel[512]; CounterMode eMode; HistInt lData[DET1X*DET1Y], i, lVal; int32 iVal; float fVal; /* write motors */ SNXSPutMotor(pServ->pSics,pCon,hfil,self->pDict, "framechi","CHI"); SNXSPutMotor(pServ->pSics,pCon,hfil,self->pDict, "framephi","PHI"); SNXSPutMotor(pServ->pSics,pCon,hfil,self->pDict, "frameomega","OM"); SNXSPutMotor(pServ->pSics,pCon,hfil,self->pDict, "frame2theta","stt"); SNXSPutMotor(pServ->pSics,pCon,hfil,self->pDict, "frametilt","DG1"); /* write frame time */ SNXFormatTime(pBueffel,512); iRet = NXDputalias(hfil,self->pDict,"etime",pBueffel); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: cannot write frame time",eError); } /* write counting parameters */ eMode = GetHistCountMode(self->pHistogram); if(eMode == eTimer) { strcpy(pBueffel,"Timer"); } else { strcpy(pBueffel,"Monitor"); } NXDputalias(hfil,self->pDict,"framemode",pBueffel); fVal = GetHistPreset(self->pHistogram); NXDputalias(hfil,self->pDict,"framepreset",&fVal); lVal = GetHistMonitor(self->pHistogram,1,pCon); iVal = (int32)lVal; NXDputalias(hfil,self->pDict,"framemonitor",&iVal); /* write detector1 histogram */ GetHistogram(self->pHistogram,pCon,0,0,DET1X*DET1Y,lData,DET1X*DET1Y*sizeof(HistInt)); NXDputalias(hfil,self->pDict,"framecounts",lData); /* the NXdata links */ NXDaliaslink(hfil,self->pDict,"frame","detectorx"); NXDaliaslink(hfil,self->pDict,"frame","detectory"); NXDaliaslink(hfil,self->pDict,"frame","framecounts"); /* temperature */ SNXSPutEVVar(hfil,self->pDict,"temperature", pCon, "frametemp", "framestdev"); /* close and done */ sprintf(pBueffel,"Frame %d succesfully written",iFrameNum-1); SCWrite(pCon,pBueffel,eStatus); return 1; } /*--------------------------------------------------------------------------*/ static int WriteFirstFrame(pNexTrics self, SConnection *pCon) { char pBueffel[1024]; NXhandle hfil; int iRet, iYear, i; pSicsVariable pVar; char *pText; CommandList *pCom = NULL; pHKL pCryst = NULL; float fVal, fPix[DETAMAX]; iRet = NXopen(self->pCurrentFile,NXACC_RDWR,&hfil); if(iRet != NX_OK) { sprintf(pBueffel,"ERROR: cannot open %s",self->pCurrentFile); SCWrite(pCon,pBueffel,eError); return 0; } /* make sure: first frame */ NXDupdate(self->pDict,"framename","frame0000"); /* title */ pVar = NULL; pVar = FindVariable(pServ->pSics,"title"); if(pVar) { pText = pVar->text; } else { SCWrite(pCon,"ERROR: Variable title not found ",eError); pText = pBueffel; } iRet = NXDputalias(hfil,self->pDict,"etitle",pText); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write title",eError); } /* start time */ SNXFormatTime(pBueffel,1023); iRet = NXDputalias(hfil,self->pDict,"etime",pBueffel); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write start time",eError); } /* source info */ strcpy(pBueffel,"SINQ at Paul Scherrer Institut, Villigen"); iRet = NXDputalias(hfil,self->pDict,"sname",pBueffel); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write source name",eError); } strcpy(pBueffel,"Continous flux spallation source"); iRet = NXDputalias(hfil,self->pDict,"stype",pBueffel); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write source type",eError); } /* instrument name */ strcpy(pBueffel,"TRICS at SINQ, Paul Scherrer Institut, Switzerland"); iRet = NXDputalias(hfil,self->pDict,"iname0",pBueffel); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write instrument name",eError); } /* Monochromator */ pVar = NULL; strcpy(pBueffel,"UNKNOWN"); pVar = FindVariable(pServ->pSics,"monodescription"); if(pVar) { pText = pVar->text; } else { SCWrite(pCon,"ERROR: Variable monodescription not found ",eError); pText = pBueffel; } iRet = NXDputalias(hfil,self->pDict,"monodes",pText); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write monodescription",eError); } /* lambda */ pCom = FindCommand(pServ->pSics,"HKL"); if(pCom) { pCryst = (pHKL)pCom->pData; } if(!pCryst) { SCWrite(pCon,"ERROR: HKL not found, cannot write lambda",eError); } else { GetLambda(pCryst,&fVal); iRet = NXDputalias(hfil,self->pDict,"monolambda",&fVal); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write lambda",eError); } } /* two theta */ pVar = NULL; strcpy(pBueffel,"UNKNOWN"); pVar = FindVariable(pServ->pSics,"mono2theta"); if(pVar) { fVal = pVar->fVal; } else { SCWrite(pCon,"ERROR: Variable mono2theta not found ",eError); fVal = -2188.99; } iRet = NXDputalias(hfil,self->pDict,"mono2theta",&fVal); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write monochromator 2 Theta",eError); } /* theta, needs work when lift operational */ SNXSPutMotor(pServ->pSics,pCon,hfil,self->pDict, "monotheta","MUCA"); /* detector data */ /* first set detector variables in dictionary */ strcpy(pBueffel,"detector1"); NXDupdate(self->pDict,"dnumber",pBueffel); sprintf(pBueffel,"%d",DET1X); NXDupdate(self->pDict,"framedim1",pBueffel); sprintf(pBueffel,"%d",DET1Y); NXDupdate(self->pDict,"framedim2",pBueffel); strcpy(pBueffel,DET1DESC); iRet = NXDputalias(hfil,self->pDict,"ddescription",pBueffel); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write detector1 description",eError); } for(i = 0; i < DET1X; i++) { fPix[i] = i * DET1XS; } iRet = NXDputalias(hfil,self->pDict,"detectorx",fPix); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write detector1 x-axis description",eError); } for(i = 0; i < DET1Y; i++) { fPix[i] = i * DET1YS; } iRet = NXDputalias(hfil,self->pDict,"detectory",fPix); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write detector1 y-axis description",eError); } pVar = NULL; pVar = FindVariable(pServ->pSics,"det1zerox"); if(pVar) { fVal = pVar->fVal; } else { SCWrite(pCon,"ERROR: Variable detector x zero point not found ",eError); fVal = -2188.99; } iRet = NXDputalias(hfil,self->pDict,"detzerox",&fVal); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write detecor x zero point",eError); } pVar = NULL; pVar = FindVariable(pServ->pSics,"det1zeroy"); if(pVar) { fVal = pVar->fVal; } else { SCWrite(pCon,"ERROR: Variable detector y zero point not found ",eError); fVal = -2188.99; } iRet = NXDputalias(hfil,self->pDict,"detzeroy",&fVal); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write detecor y zero point",eError); } pVar = NULL; pVar = FindVariable(pServ->pSics,"det1dist"); if(pVar) { fVal = pVar->fVal; } else { SCWrite(pCon,"ERROR: Variable detector distance not found ",eError); fVal = -2188.99; } iRet = NXDputalias(hfil,self->pDict,"detdist",&fVal); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write detecor y zero point",eError); } iRet = 1; iRet = NXDputalias(hfil,self->pDict,"detvalid",&iRet); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write frame validity",eError); } /* do sample information */ strcpy(pBueffel,"UNKNOWN"); pVar = FindVariable(pServ->pSics,"sample"); if(pVar) { pText = pVar->text; } else { SCWrite(pCon,"ERROR: Variable sample not found ",eError); pText = pBueffel; } iRet = NXDputalias(hfil,self->pDict,"samplename",pText); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write sample name",eError); } /* put the frame number */ iRet = 0; iRet = NXDputalias(hfil,self->pDict,"fnum",&iRet); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write initial frame number",eError); } /* write actual data */ iRet = DumpData(self,pCon,hfil,1); /* put the frame number */ iRet = 1; iRet = NXDputalias(hfil,self->pDict,"fnum",&iRet); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write initial frame number",eError); } self->iFirst = 0; /* close the file and go */ NXclose(&hfil); SendQuieck(QUIECK,self->pCurrentFile); return iRet; } /*-------------------------------------------------------------------------*/ static int ContinueFile(pNexTrics self, SConnection *pCon) { int iFrameNum, iRet; char pBueffel[1024]; float fVal; NXhandle hfil; assert(self); assert(pCon); assert(self->iFirst == 0); /* let's start by opening the file*/ iRet = NXopen(self->pCurrentFile,NXACC_RDWR,&hfil); if(iRet != NX_OK) { sprintf(pBueffel,"ERROR: cannot reopen %s, NO data written", self->pCurrentFile); SCWrite(pCon,pBueffel,eError); return 0; } /* read the frame number, set the framename for further reading, increment and write back again */ iRet = NXDgetalias(hfil,self->pDict,"fnum",&iFrameNum); if(iRet != NX_OK) { SCWrite(pCon,"EERROR: cannot read old framenumber, NO data written",eError); return 0; } sprintf(pBueffel,"frame%4.4d", iFrameNum); NXDupdate(self->pDict,"framename",pBueffel); iFrameNum++; iRet = NXDputalias(hfil,self->pDict,"fnum",&iFrameNum); if(iRet != NX_OK) { SCWrite(pCon,"EERROR: cannot write new framenumber, NO data written",eError); return 0; } /* put in links to duplicates: entry */ iRet = NXDaliaslink(hfil,self->pDict,"entry","etitle0"); if(iRet != NX_OK) { SCWrite(pCon,"WARNING: cannot link against title",eWarning); } /* links to instrument */ iRet = NXDaliaslink(hfil,self->pDict,"inst0","iname0"); if(iRet != NX_OK) { SCWrite(pCon,"WARNING: cannot link against instrument name",eWarning); } iRet = NXDaliaslink(hfil,self->pDict,"inst0","source0"); if(iRet != NX_OK) { SCWrite(pCon,"WARNING: cannot link against source group",eWarning); } iRet = NXDaliaslink(hfil,self->pDict,"inst0","mono0"); if(iRet != NX_OK) { SCWrite(pCon,"WARNING: cannot link against monochromator group",eWarning); } /* links in detector group */ iRet = NXDaliaslink(hfil,self->pDict,"det1","ddescription"); if(iRet != NX_OK) { SCWrite(pCon,"WARNING: cannot link against detector description",eWarning); } iRet = NXDaliaslink(hfil,self->pDict,"det1","detectorx"); if(iRet != NX_OK) { SCWrite(pCon,"WARNING: cannot link against detector x-axis",eWarning); } iRet = NXDaliaslink(hfil,self->pDict,"det1","detectory"); if(iRet != NX_OK) { SCWrite(pCon,"WARNING: cannot link against detector y-axis",eWarning); } iRet = NXDaliaslink(hfil,self->pDict,"det1","detzerox"); if(iRet != NX_OK) { SCWrite(pCon,"WARNING: cannot link against detector x zero ",eWarning); } iRet = NXDaliaslink(hfil,self->pDict,"det1","detzeroy"); if(iRet != NX_OK) { SCWrite(pCon,"WARNING: cannot link against detector y zero",eWarning); } iRet = NXDaliaslink(hfil,self->pDict,"det1","detdist"); if(iRet != NX_OK) { SCWrite(pCon,"WARNING: cannot link against detector distance",eWarning); } iRet = 1; iRet = NXDputalias(hfil,self->pDict,"detvalid",&iRet); if(iRet != NX_OK) { SCWrite(pCon,"ERROR: failed to write frame validity",eError); } /* links in sample group */ iRet = NXDaliaslink(hfil,self->pDict,"samplev","samplename"); if(iRet != NX_OK) { SCWrite(pCon,"WARNING: cannot link against sample name",eWarning); } /* write actual data */ iRet = DumpData(self,pCon,hfil,iFrameNum); /* close the file and go */ NXclose(&hfil); SendQuieck(QUIECK,self->pCurrentFile); return iRet; } /*--------------------------------------------------------------------------*/ int StartFile(pNexTrics self, SConnection *pCon) { char pBueffel[1024]; NXhandle hfil; int iRet, iYear, i; pSicsVariable pVar; char *pText; CommandList *pCom = NULL; pHKL pCryst = NULL; float fVal, fPix[DETAMAX]; /* make a filename and open it */ if(self->pCurrentFile) free(self->pCurrentFile); iRet = IncrementDataNumber(self->pDanu,&iYear); sprintf(pBueffel,"%s/trics%4.4d%4.4d.hdf",self->pFileRoot,iRet, iYear); self->pCurrentFile = strdup(pBueffel); iRet = NXopen(self->pCurrentFile,NXACC_CREATE,&hfil); if(iRet != NX_OK) { sprintf(pBueffel,"ERROR: cannot open %s",self->pCurrentFile); SCWrite(pCon,pBueffel,eError); return 0; } /* tell user what we are doing */ sprintf(pBueffel,"Initialising file %s ......", self->pCurrentFile); SCWrite(pCon,pBueffel,eWarning); /* Write header data */ SNXSPutGlobals(hfil,self->pCurrentFile, "TRICS at SinQ, Paul Scherrer Institut, Switzerland", pCon); self->iFirst = 1; /* close the file and go */ NXclose(&hfil); return 1; } /*-------------------------------------------------------------------------*/ int ReopenFile(pNexTrics self, char *filename) { char pBueffel[1024]; NXhandle hfil; int iRet, iFrameNum; assert(self); /* concat with data root and check for existence */ sprintf(pBueffel,"%s/%s",self->pFileRoot,filename); iRet = NXopen(pBueffel,NXACC_RDWR,&hfil); NXclose(&hfil); if(iRet != NX_OK) { return 0; } else { if(self->pCurrentFile) free(self->pCurrentFile); self->pCurrentFile = strdup(pBueffel); } /* check the framenumber, if already data written */ iRet = NXDgetalias(hfil,self->pDict,"fnum",&iFrameNum); if(iRet != NX_OK) { self->iFirst = 1; } else { self->iFirst = 0; } return 1; } /*--------------------------------------------------------------------------*/ int DumpFrame(pNexTrics self, SConnection *pCon) { int iRet; assert(self); assert(pCon); if(self->iFirst == 1) { iRet = WriteFirstFrame(self,pCon); } else { iRet = ContinueFile(self,pCon); } return iRet; } /*---------------------------------------------------------------------------*/ int NexTricsAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) { pNexTrics self; char pBueffel[1024]; int iRet; self = (pNexTrics)pData; assert(self); assert(pCon); /* check for subcommands */ if(argc < 2) { sprintf(pBueffel,"ERROR: no subcommand found for %s",argv[0]); SCWrite(pCon,pBueffel,eError); return 0; } /* install an error handler */ NXMSetError((void *)pCon,SNError); strtolower(argv[1]); if(strcmp(argv[1],"start") == 0) { if(!SCMatchRights(pCon,usUser)) { return 0; } iRet = StartFile(self,pCon); if(iRet) { SCSendOK(pCon); } return iRet; } else if(strcmp(argv[1],"file") == 0) { sprintf(pBueffel,"Currently writing to: %s",self->pCurrentFile); SCWrite(pCon,pBueffel,eValue); return 1; } else if(strcmp(argv[1],"dumpframe") == 0) { if(!SCMatchRights(pCon,usUser)) { return 0; } iRet = DumpFrame(self,pCon); if(iRet) { SCSendOK(pCon); } return iRet; } else if(strcmp(argv[1],"reopen") == 0) { if(!SCMatchRights(pCon,usUser)) { return 0; } if(argc < 3) { SCWrite(pCon,"ERROR: expected filename as parameter for reopen",eError); return 0; } iRet = ReopenFile(self,argv[2]); if(iRet) { SCSendOK(pCon); } return iRet; } sprintf(pBueffel,"ERROR: subcommand %s not recognized",argv[1]); SCWrite(pCon,pBueffel,eError); return 0; }