/*----------------------------------------------------------------------------- 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) { strlcpy(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; } memset(pBueffel, 0, 512); 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; }