Files
sics/mcreader.c

480 lines
13 KiB
C

/*-----------------------------------------------------------------------------
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 <assert.h>
#include <ctype.h>
#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;
}