/*-------------------------------------------------------------------------- N X A M O R Routines for writing NeXus files for the reflectometer AMOR at PSI. copyright: see copyright.h Mark Koennecke, September 1999 --------------------------------------------------------------------------*/ #include #include #include "fortify.h" #include "sics.h" #include "nxdict.h" #include "nxutil.h" #include "scan.h" #include "scan.i" #include "HistMem.h" #include "counter.h" #include "nxamor.h" /* some defines for some names */ #define AMORDICT "amor.dic" #define INSTNAME "AMOR at SINQ, PSI" #define SOURCENAME "Spallation source SINQ" #define SOURCETYPE "Continous flux spallation source" #define CHOPPERNAME "Dornier Chopper System" /* this is the real detector size, the one in the dictionary will be updated from this! */ #define DETSIZE 128 /*------------------------------------------------------------------------*/ static void WriteDiaphragm(NXhandle hfil, NXdict hdict, int i, SConnection *pCon) { char pThing[30]; sprintf(pThing,"d%1.1ddist",i); SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,pThing,pThing); sprintf(pThing,"d%1.1dt",i); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,pThing,pThing); sprintf(pThing,"d%1.1db",i); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,pThing,pThing); sprintf(pThing,"d%1.1dl",i); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,pThing,pThing); sprintf(pThing,"d%1.1dr",i); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,pThing,pThing); } /*----------------------------------------------------------------------*/ int WriteAmorHeader(char *file, SConnection *pCon) { NXhandle hfil; NXdict hdict; int iRet; char pBueffel[512]; CounterMode eMode; CommandList *pCom = NULL; float fVal; /* open files */ iRet = NXopen(file,NXACC_CREATE,&hfil); if(iRet != NX_OK) { sprintf(pBueffel,"ERROR: cannot open file %s for writing",file); SCWrite(pCon,pBueffel,eError); return 0; } iRet = NXDinitfromfile(AMORDICT,&hdict); if(iRet != NX_OK) { sprintf(pBueffel,"ERROR: cannot open dictionary file %s"); SCWrite(pCon,pBueffel,eError); return 0; } /* put some global information */ SNXSPutGlobals(hfil,file,"AMOR",pCon); SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"etitle","title"); SNXFormatTime(pBueffel,512); NXDputalias(hfil,hdict,"estart",pBueffel); /* instrument vGroup */ NXDputalias(hfil,hdict,"iname",INSTNAME); /* source */ NXDputalias(hfil,hdict,"sname",SOURCENAME); NXDputalias(hfil,hdict,"stype",SOURCETYPE); /* chopper */ NXDputalias(hfil,hdict,"cname",CHOPPERNAME); SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"crot", "chopperrotation"); /* frame overlap mirror */ SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"fomname", "fomname"); SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"fodist", "fomdist"); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"fomh","ftz"); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"fomom","fom"); /* first Diaphragm */ WriteDiaphragm(hfil,hdict,1,pCon); /* polarizing, monochromating mirror */ SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"polname", "polname"); SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"poldist", "poldist"); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"polz","moz"); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"polom","mom"); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"poly","mty"); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"polzom","mtz"); /* second Diaphragm */ WriteDiaphragm(hfil,hdict,2,pCon); /* third Diaphragm */ WriteDiaphragm(hfil,hdict,3,pCon); /* sample table */ SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"saname", "sample"); SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"stdist", "sampledist"); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"somheight","stz"); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"schi","sch"); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"somega","som"); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"stheight","soz"); /* fourth Diaphragm */ WriteDiaphragm(hfil,hdict,4,pCon); /* analyzer */ SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"anname", "ananame"); SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"andist", "anadist"); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"anoz","atz"); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"anom","aom"); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"antz","aoz"); /* fifth Diaphragm!!!!!!!!! */ WriteDiaphragm(hfil,hdict,5,pCon); /* counting data */ pCom = FindCommand(pServ->pSics,"counter"); if(pCom) { if(pCom->pData) { eMode = GetCounterMode((pCounter)pCom->pData); if(eMode == eTimer) { strcpy(pBueffel,"timer"); } else { strcpy(pBueffel,"monitor"); } NXDputalias(hfil,hdict,"cnmode",pBueffel); fVal = GetCounterPreset((pCounter)pCom->pData); NXDputalias(hfil,hdict,"cnpreset",&fVal); } } else { SCWrite(pCon,"WARNING: failed to find counter!",eWarning); } NXclose(&hfil); NXDclose(hdict,NULL); return 1; } /*------------------------------------------------------------------------*/ int WriteAmorScan(char *file, SConnection *pCon, pScanData pScan) { NXhandle hfil; NXdict hdict; int iRet, i; char pBueffel[512], pDefinition[1024]; CommandList *pCom = NULL; float fVal; float *fAxis = NULL; long *lData = NULL; int *iData = NULL; /* open files */ iRet = NXopen(file,NXACC_RDWR,&hfil); if(iRet != NX_OK) { sprintf(pBueffel,"ERROR: cannot open file %s for writing"); SCWrite(pCon,pBueffel,eError); return 0; } iRet = NXDinitfromfile(AMORDICT,&hdict); if(iRet != NX_OK) { sprintf(pBueffel,"ERROR: cannot open dictionary file %s"); SCWrite(pCon,pBueffel,eError); return 0; } /* write general detector data */ SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"sdetdist", "detectordist"); /* allocate memory for writing scan data */ fAxis = (float *)malloc(pScan->iNP*sizeof(float)); lData = (long *)malloc(pScan->iNP*sizeof(long)); iData = (int *)malloc(pScan->iNP*sizeof(int)); if( (!fAxis) || (!lData) || (!iData) ) { SCWrite(pCon,"ERROR: out of memory in WriteAmorScan",eError); return 0; } memset(fAxis,0,pScan->iNP*sizeof(float)); memset(lData,0,pScan->iNP*sizeof(long)); memset(iData,0,pScan->iNP*sizeof(int)); /* write scan variables */ for(i = 0; i < pScan->iScanVar; i++) { /* build definition string */ NXDget(hdict,"scanroot",pBueffel, 512); strcpy(pDefinition,pBueffel); strcat(pDefinition," "); GetScanVarName(pScan,i,pBueffel,512); strcat(pDefinition,pBueffel); sprintf(pBueffel," -rank 1 -dim {%d} ", pScan->iNP); strcat(pDefinition,pBueffel); if(i == 0) { strcat(pDefinition," -attr {axis,1}"); } /* get data and write */ GetScanVar(pScan,i,fAxis,pScan->iNP); NXDputdef(hfil,hdict,pDefinition,fAxis); if(i == 0) { NXDget(hdict,"sdana",pBueffel,512); NXDdeflink(hfil,hdict,pBueffel,pDefinition); } } /* Write counted data: Here there is a convention which has to be valid in amorscan as well: GetCounts gets the main detector. GetMonitor 0 the second detector, GetMonitor 1 the first detector other spin, GetMonitor 2, the second detector the other spin, getMonitor 3, the first monitor, getMonitor 4 the second monitor */ sprintf(pBueffel,"%d",pScan->iNP); NXDupdate(hdict,"scanlength",pBueffel); GetScanCounts(pScan,lData,pScan->iNP); for(i = 0; i < pScan->iNP; i++) { iData[i] = (int)lData[i]; } NXDputalias(hfil,hdict, "spinupup",iData); NXDaliaslink(hfil,hdict,"sdana","spinupup"); GetScanMonitor(pScan,0,lData,pScan->iNP); for(i = 0; i < pScan->iNP; i++) { iData[i] = (int)lData[i]; } NXDputalias(hfil,hdict, "spinuplo",iData); NXDaliaslink(hfil,hdict,"sdana","spinuplo"); /* monitors */ GetScanMonitor(pScan,3,lData,pScan->iNP); for(i = 0; i < pScan->iNP; i++) { iData[i] = (int)lData[i]; } NXDputalias(hfil,hdict, "smonitor1",iData); GetScanMonitor(pScan,4,lData,pScan->iNP); for(i = 0; i < pScan->iNP; i++) { iData[i] = (int)lData[i]; } NXDputalias(hfil,hdict, "smonitor2",iData); /* to be added: polarizing mode, possibly coz, cox, com etc. */ /* a few motors which may or may not be useful */ SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"sdetx","cox"); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"sdetom","com"); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"sdetheight","coz"); /* close and go */ NXclose(&hfil); NXDclose(hdict,NULL); free(fAxis); free(lData); free(iData); return 1; } /*-----------------------------------------------------------------------*/ int WriteAmorTOF(char *file, SConnection *pCon, pHistMem pHM) { NXhandle hfil; NXdict hdict; int iRet, i, iLength; char pBueffel[512]; float fVal, *fAxis = NULL, *fTime2 = NULL; CommandList *pCom = NULL; const float *fTime; HistInt *lData = NULL, lVal; /* open files */ iRet = NXopen(file,NXACC_RDWR,&hfil); if(iRet != NX_OK) { sprintf(pBueffel,"ERROR: cannot open file %s for writing"); SCWrite(pCon,pBueffel,eError); return 0; } iRet = NXDinitfromfile(AMORDICT,&hdict); if(iRet != NX_OK) { sprintf(pBueffel,"ERROR: cannot open dictionary file %s"); SCWrite(pCon,pBueffel,eError); return 0; } /* write general detector data */ SNXSPutVariable(pServ->pSics,pCon,hfil, hdict,"detdist", "detectordist"); /* a few motors which may or may not be useful */ SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"detx","cox"); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"detom","com"); SNXSPutMotor(pServ->pSics,pCon,hfil,hdict,"detheight","coz"); /* write counter related stuff */ pCom = FindCommand(pServ->pSics,"counter"); if(pCom) { if(pCom->pData) { fVal = GetCountTime((pCounter)pCom->pData,pCon); NXDputalias(hfil,hdict,"cntime",&fVal); /* the assignment of monitors has to be checked once the Schlumpf is done */ lVal = GetMonitor((pCounter)pCom->pData,2, pCon); NXDputalias(hfil,hdict,"cnmon1",&lVal); lVal = GetMonitor((pCounter)pCom->pData,3, pCon); NXDputalias(hfil,hdict,"cnmon2",&lVal); } } else { SCWrite(pCon,"WARNING: failed to find counter!",eWarning); } /* write two axis */ fAxis = (float *)malloc(DETSIZE*sizeof(float)); if(!fAxis) { SCWrite(pCon,"ERROR: out of memory in WriteAmorTOF",eError); return 0; } for(i = 0; i < DETSIZE; i++) { fAxis[i] = (float)i; } NXDputalias(hfil,hdict,"detxx",fAxis); NXDputalias(hfil,hdict,"dety",fAxis); NXDaliaslink(hfil,hdict,"dana","detxx"); NXDaliaslink(hfil,hdict,"dana","dety"); free(fAxis); /* update detector size */ sprintf(pBueffel,"%d",DETSIZE); NXDupdate(hdict,"detsize",pBueffel); /* deal with time binning */ fTime = GetHistTimeBin(pHM,&iLength); fTime2 = (float *)malloc(iLength*sizeof(float)); if(fTime2) { for(i = 0; i < iLength; i++) { fTime2[i] = fTime[i]/10.; } sprintf(pBueffel,"%d",iLength); NXDupdate(hdict,"timebin",pBueffel); NXDputalias(hfil,hdict,"dettime",fTime2); NXDaliaslink(hfil,hdict,"dana","dettime"); free(fTime2); fTime2 = NULL; } else { SCWrite(pCon,"ERROR: out of memory while writing time binning", eError); } /* finally get histogram */ iLength = GetHistLength(pHM); lData = (HistInt *)malloc(iLength*sizeof(HistInt)); if(!lData) { SCWrite(pCon, "ERROR: out of memory, failed to write histogram",eError); return 0; } memset(lData,0,iLength*sizeof(HistInt)); GetHistogram(pHM,pCon, 0,0,iLength,lData,iLength*sizeof(HistInt)); NXDputalias(hfil,hdict,"spinup",lData); NXDaliaslink(hfil,hdict,"dana","spinup"); /* to do: add polarizing code */ free(lData); NXclose(&hfil); NXDclose(hdict,NULL); return 1; } /*-----------------------------------------------------------------------*/ static pHistMem pMeme = NULL; int AmorStore(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) { char pBueffel[512], *pFile = NULL; int iRet; pFile = SNXMakeFileName(pSics,pCon); sprintf(pBueffel,"Writing file %s .....",pFile); SCWrite(pCon,pBueffel,eWarning); iRet = WriteAmorHeader(pFile,pCon); if(iRet) { iRet = WriteAmorTOF(pFile,pCon,pMeme); } free(pFile); SCSendOK(pCon); return iRet; } /*---------------------------------------------------------------------*/ int AmorStoreMake(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) { CommandList *pCom = NULL; char pBueffel[512]; int iRet; if(argc < 2) { SCWrite(pCon, "ERROR: insufficient number of arguments to AmorStoreMake", eError); return 0; } /* we need one parameter which is the name of the histogram memory*/ pCom = FindCommand(pServ->pSics,argv[1]); if(!pCom) { sprintf(pBueffel,"ERROR: Histogram memory %s NOT found", argv[1]); SCWrite(pCon,pBueffel,eError); return 0; } if(!pCom->pData) { sprintf(pBueffel,"ERROR: Histogram memory %s NOT found", argv[1]); SCWrite(pCon,pBueffel,eError); return 0; } pMeme = (pHistMem)pCom->pData; /* install command */ iRet = AddCommand(pSics,"storeamor", AmorStore,NULL,NULL); if(!iRet) { sprintf(pBueffel,"ERROR: duplicate command amorstore NOT created"); SCWrite(pCon,pBueffel,eError); return 0; } return 1; }