/*----------------------------------------------------------------------------- Implementation file for the McStas reader module. This module helps transferring McStasresult data into SICS counters and histogram memories. copyright: see file COPYRIGHT Mark Koennecke, June 2005 -----------------------------------------------------------------------------*/ #include #include #include "mcreader.h" #include "counter.h" #include "HistMem.h" #include "sicsdata.h" /*-------------------------------------------------------------------------*/ static void KillMcReader(void *pData){ pMcStasReader self = (pMcStasReader)pData; if(self == NULL){ return; } if(self->pDes){ DeleteDescriptor(self->pDes); } if(self->handle != NULL){ NXclose(&self->handle); } free(self); } /*--------------------------------------------------------------------------*/ int McStasReaderFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pMcStasReader pNew = NULL; pNew = (pMcStasReader)malloc(sizeof(McStasReader)); if(pNew == NULL){ SCWrite(pCon,"ERROR: out of memory creating McStasReader",eError); return 0; } memset(pNew,0,sizeof(McStasReader)); pNew->pDes = CreateDescriptor("McStasReader"); if(pNew->pDes == NULL){ SCWrite(pCon,"ERROR: out of memory creating McStasReader",eError); free(pNew); return 0; } return AddCommand(pSics,"mcreader", McStasReaderWrapper, KillMcReader, pNew); } /*==================== interpreter interface ===============================*/ static void MCReportError(void *pData, char *txt){ pMcStasReader self = NULL; self = (pMcStasReader)pData; if(self != NULL){ strncpy(self->nexusError,txt,1024); } else { printf( "ERROR: NeXus error in McStasReader without McStasReader data structure: %s\n", txt); } } /*-------------------------------------------------------------------------*/ static int openMcStasFile(pMcStasReader self, SConnection *pCon, int argc, char *argv[]){ int status; char pBueffel[512]; if(argc < 3){ SCWrite(pCon,"ERROR: need filename argument for opening file", eError); } /* * be nice to users: if file still open, close it */ if(self->handle != NULL){ NXclose(&self->handle); self->handle = NULL; } /** * open the file */ NXMSetError(self,MCReportError); status = NXopen((const char*)argv[2],NXACC_READ,&self->handle); if(status != NX_OK){ snprintf(pBueffel,511,"ERROR: NeXus reported %s", self->nexusError); SCWrite(pCon,pBueffel,eError); return 0; } SCSendOK(pCon); return 1; } /*--------------------------------------------------------------------------*/ static int closeMcStasFile(pMcStasReader self, SConnection *pCon){ if(self->handle != NULL){ NXclose(&self->handle); self->handle = NULL; } SCSendOK(pCon); return 1; } /*-------------------------------------------------------------------*/ static char *getNextMCNumber(char *pStart, char pNumber[80]){ int charCount = 0; pNumber[0] = '\0'; /* advance to first digit */ while(isspace(*pStart) && *pStart != '\0'){ pStart++; } if(*pStart == '\0'){ return NULL; } /* copy */ while(!isspace(*pStart) && *pStart != '\0' && charCount < 78){ pNumber[charCount] = *pStart; pStart++; charCount++; } pNumber[charCount] = '\0'; return pStart; } /*--------------------------------------------------------------------------*/ static int insertMonitor(pMcStasReader self, SConnection *pCon, SicsInterp *pSics, int argc, char *argv[]){ char pBueffel[512], *pPtr, pNumber[80]; pCounter pCount = NULL; int status, mon, type, rank, iDim[NX_MAXRANK]; float monValue, scale = 1.; if(argc < 5){ SCWrite(pCon,\ "ERROR: insufficient number of arguments to mcreader insertmon", eError); return 0; } if(self->handle == NULL){ SCWrite(pCon,"ERROR: no file open to read data from",eError); return 0; } pCount = FindCommandData(pSics,argv[3],"SingleCounter"); if(pCount == NULL){ snprintf(pBueffel,511, "ERROR: %s is no counter object", argv[3]); SCWrite(pCon,pBueffel,eError); return 0; } mon = atoi(argv[4]); status = NXopenpath(self->handle,argv[2]); if(status != NX_OK){ snprintf(pBueffel,511,"ERROR: Nexus error %s while opening %s", self->nexusError, argv[2]); SCWrite(pCon,pBueffel,eError); return 0; } if(argc > 5) { scale = atof(argv[5]); } status = NXgetinfo(self->handle,&rank,iDim,&type); if(status != NX_OK){ snprintf(pBueffel,511,"ERROR: Nexus error %s while reading %s", self->nexusError, argv[2]); SCWrite(pCon,pBueffel,eError); return 0; } if(rank != 1 || type != NX_CHAR || iDim[0] > 511){ snprintf(pBueffel,511,"ERROR: %s is no valid monitor data", argv[2]); SCWrite(pCon,pBueffel,eError); return 0; } status = NXgetdata(self->handle,pBueffel); if(status != NX_OK){ snprintf(pBueffel,511,"ERROR: Nexus error %s while reading %s", self->nexusError, argv[2]); SCWrite(pCon,pBueffel,eError); return 0; } /* * the monitor value we want is the third value in the values field */ pPtr = pBueffel; memset(pNumber,0,80*sizeof(char)); pPtr = getNextMCNumber(pPtr,pNumber); pPtr = getNextMCNumber(pPtr,pNumber); pPtr = getNextMCNumber(pPtr,pNumber); monValue = atof(pNumber); monValue *= scale; if(pCount != NULL){ SetMonitorValue(pCount,mon,(long)monValue); } SCSendOK(pCon); return 1; } /*--------------------------------------------------------------------------*/ static int insertMonitorDirect(pMcStasReader self, SConnection *pCon, SicsInterp *pSics, int argc, char *argv[]){ char pBueffel[512], *pPtr, pNumber[80]; pCounter pCount = NULL; int status, mon; float monValue; if(argc < 5){ SCWrite(pCon,\ "ERROR: insufficient number of arguments to mcreader insertmondirect", eError); return 0; } pCount = FindCommandData(pSics,argv[2],"SingleCounter"); if(pCount == NULL){ snprintf(pBueffel,511, "ERROR: %s is no counter object", argv[3]); SCWrite(pCon,pBueffel,eError); return 0; } mon = atoi(argv[3]); monValue = atof(argv[4]); if(pCount != NULL){ SetMonitorValue(pCount,mon,(long)monValue); } SCSendOK(pCon); return 1; } /*--------------------------------------------------------------------------*/ static int insertHM(pMcStasReader self, SConnection *pCon, SicsInterp *pSics, int argc, char *argv[]){ char pBueffel[512], *pPtr, pNumber[80], *pData = NULL; pHistMem pHM = NULL; int status, type, rank, iDim[NX_MAXRANK]; int length, i; HistInt *lData = NULL; float scale = 1.; double val; if(argc < 4){ SCWrite(pCon,\ "ERROR: insufficient number of arguments to mcreader inserthm", eError); return 0; } if(self->handle == NULL){ SCWrite(pCon,"ERROR: no file open to read data from",eError); return 0; } pHM = FindCommandData(pSics,argv[3],"HistMem"); if(pHM == NULL){ snprintf(pBueffel,511, "ERROR: %s is no histogram memory object", argv[3]); SCWrite(pCon,pBueffel,eError); return 0; } status = NXopenpath(self->handle,argv[2]); if(status != NX_OK){ snprintf(pBueffel,511,"ERROR: Nexus error %s while opening %s", self->nexusError, argv[2]); SCWrite(pCon,pBueffel,eError); return 0; } if(argc > 4){ scale = atof(argv[4]); } status = NXgetinfo(self->handle,&rank,iDim,&type); if(status != NX_OK){ snprintf(pBueffel,511,"ERROR: Nexus error %s while reading %s", self->nexusError, argv[2]); SCWrite(pCon,pBueffel,eError); return 0; } pData = (char *)malloc((iDim[0]+1)*sizeof(char)); if(pData == NULL){ SCWrite(pCon,"ERROR: out of memory in mcreader inserthm",eError); return 0; } memset(pData,0,(iDim[0]+1)*sizeof(char)); status = NXgetdata(self->handle,pData); if(status != NX_OK){ snprintf(pBueffel,511,"ERROR: Nexus error %s while reading %s", self->nexusError, argv[2]); SCWrite(pCon,pBueffel,eError); return 0; } length = GetHistLength(pHM); lData = (HistInt *)malloc(length*sizeof(HistInt)); if(lData== NULL){ SCWrite(pCon,"ERROR: out of memory in mcreader inserthm",eError); free(pData); return 0; } memset(lData,0,length*sizeof(HistInt)); pPtr = pData; for(i = 0; i < length && pPtr != NULL; i++){ pPtr = getNextMCNumber(pPtr,pNumber); val = atof(pNumber); val *= scale; lData[i] = (HistInt)val; } SetHistogram(pHM,pCon,0,0,length,lData); free(pData); free(lData); SCSendOK(pCon); return 1; } /*--------------------------------------------------------------------------*/ static int getField(pMcStasReader self, SConnection *pCon, SicsInterp *pSics, int argc, char *argv[]){ char pBueffel[512], *pPtr, pNumber[80], *pData = NULL; int status, type, rank, iDim[NX_MAXRANK]; if(argc < 2){ SCWrite(pCon,\ "ERROR: insufficient number of arguments to mcreader getfield", eError); return 0; } if(self->handle == NULL){ SCWrite(pCon,"ERROR: no file open to read data from",eError); return 0; } status = NXopenpath(self->handle,argv[2]); if(status != NX_OK){ snprintf(pBueffel,511,"ERROR: Nexus error %s while opening %s", self->nexusError, argv[2]); SCWrite(pCon,pBueffel,eError); return 0; } status = NXgetinfo(self->handle,&rank,iDim,&type); if(status != NX_OK){ snprintf(pBueffel,511,"ERROR: Nexus error %s while reading %s", self->nexusError, argv[2]); SCWrite(pCon,pBueffel,eError); return 0; } pData = (char *)malloc((iDim[0]+1)*sizeof(char)); if(pData == NULL){ SCWrite(pCon,"ERROR: out of memory in mcreader getfield",eError); return 0; } memset(pData,0,(iDim[0]+1)*sizeof(char)); status = NXgetdata(self->handle,pData); if(status != NX_OK){ snprintf(pBueffel,511,"ERROR: Nexus error %s while reading %s", self->nexusError, argv[2]); SCWrite(pCon,pBueffel,eError); return 0; } SCWrite(pCon,pData,eValue); free(pData); return 1; } /*--------------------------------------------------------------------------*/ static int insertHMFromData(pMcStasReader self, SConnection *pCon, SicsInterp *pSics, int argc, char *argv[]){ char pBueffel[512]; pHistMem pHM = NULL; int length, i; HistInt *lData = NULL; pSICSData data = NULL; if(argc < 4){ SCWrite(pCon,\ "ERROR: insufficient number of arguments to mcreader inserthmfromdata", eError); return 0; } pHM = FindCommandData(pSics,argv[2],"HistMem"); if(pHM == NULL){ snprintf(pBueffel,511, "ERROR: %s is no histogram memory object", argv[3]); SCWrite(pCon,pBueffel,eError); return 0; } data = FindCommandData(pSics,argv[3],"SICSData"); if(data == NULL){ snprintf(pBueffel,511, "ERROR: %s is no SICSData object", argv[3]); SCWrite(pCon,pBueffel,eError); return 0; } length = GetHistLength(pHM); if(data->currentDataSize < length){ snprintf(pBueffel,511,"WARNING: data in %s to short for HM %s", argv[3],argv[2]); SCWrite(pCon,pBueffel,eWarning); } lData = (HistInt *)malloc(length*sizeof(HistInt)); if(lData== NULL){ SCWrite(pCon,"ERROR: out of memory in mcreader inserthm",eError); return 0; } memset(lData,0,length*sizeof(HistInt)); if(data->currentDataSize < length){ length = data->currentDataSize; } for(i = 0; i < length; i++){ lData[i] = (HistInt)data->data[i]; } SetHistogram(pHM,pCon,0,0,length,lData); free(lData); SCSendOK(pCon); return 1; } /*--------------------------------------------------------------------------*/ int McStasReaderWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pMcStasReader self = NULL; char pBueffel[512]; self = (pMcStasReader)pData; assert(self != NULL); if(argc < 2){ SCWrite(pCon,"ERROR: insufficient number of arguments to mcreader", eError); return 0; } strtolower(argv[1]); if(strcmp(argv[1],"open") == 0){ return openMcStasFile(self, pCon, argc, argv); } else if(strcmp(argv[1],"close") == 0){ return closeMcStasFile(self,pCon); } else if(strcmp(argv[1],"insertmon") == 0){ return insertMonitor(self,pCon, pSics,argc,argv); } else if(strcmp(argv[1],"insertmondirect") == 0){ return insertMonitorDirect(self,pCon, pSics,argc,argv); } else if(strcmp(argv[1],"inserthm") == 0){ return insertHM(self,pCon, pSics,argc,argv); } else if(strcmp(argv[1],"inserthmfromdata") == 0){ return insertHMFromData(self,pCon, pSics,argc,argv); } else if(strcmp(argv[1],"getfield") == 0){ return getField(self,pCon, pSics,argc,argv); } else { snprintf(pBueffel,511,"ERROR: invalid subcommand %s to %s", argv[1],argv[0]); SCWrite(pCon,pBueffel,eError); return 0; } return 1; }