776 lines
23 KiB
C
776 lines
23 KiB
C
/*--------------------------------------------------------------------------
|
|
|
|
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
|
|
Updated, Mark Koennecke, August 2001
|
|
Updated to store TOF-monitor, Mark Koennecke, September 2002
|
|
--------------------------------------------------------------------------*/
|
|
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#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"
|
|
#include "obpar.h"
|
|
#include "motor.h"
|
|
#include "status.h"
|
|
|
|
#define MAXMOT 13 /* must be same as in amor2t.c */
|
|
#include "amor2t.i"
|
|
#include "amor2t.h"
|
|
|
|
/* some defines for some names */
|
|
static char AMORDICT[1024] = "/home/amor/amor_sics/amor.dic";
|
|
#define INSTNAME "AMOR at SINQ, PSI"
|
|
#define SOURCENAME "Spallation source SINQ"
|
|
#define SOURCETYPE "Continous flux spallation source"
|
|
#define CHOPPERNAME "Dornier Chopper System"
|
|
|
|
/*
|
|
The rough size of each detector chunk to write in TOF mode
|
|
(currently 16MB)
|
|
#define TOFBLOCK 8192000
|
|
#define TOFBLOCK 16384000
|
|
*/
|
|
#define TOFBLOCK 65536000
|
|
|
|
/*
|
|
a pointer to amor2t which we need for a couple of parameters
|
|
*/
|
|
pAmor2T pAmor = NULL;
|
|
|
|
/*
|
|
if to save psd data in TOF mode or not. This is in order to save time
|
|
when measureing TOF with a single detector only.
|
|
*/
|
|
|
|
static int psdSave = 1;
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static void WriteDiaphragm(NXhandle hfil, NXdict hdict, int i,
|
|
SConnection * pCon)
|
|
{
|
|
char pThing[30];
|
|
|
|
|
|
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], pThing[80];
|
|
CounterMode eMode;
|
|
CommandList *pCom = NULL;
|
|
float fVal;
|
|
|
|
/* open files */
|
|
NXsetcache(TOFBLOCK);
|
|
iRet = NXopen(file, NXACC_CREATE5, &hfil);
|
|
if (iRet != NX_OK) {
|
|
snprintf(pBueffel, 511, "ERROR: cannot open file %s for writing",
|
|
file);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = NXDinitfromfile(AMORDICT, &hdict);
|
|
if (iRet != NX_OK) {
|
|
snprintf(pBueffel, 511, "ERROR: cannot open dictionary file %s",
|
|
AMORDICT);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
snprintf(pBueffel, 511, "Writing to: %s", file);
|
|
SCWrite(pCon, pBueffel, eWarning);
|
|
|
|
/* 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);
|
|
SNXSPutDrivable(pServ->pSics, pCon, hfil, hdict, "chopperspeed", "crot");
|
|
SNXSPutDrivable(pServ->pSics, pCon, hfil, hdict, "chopper1phase",
|
|
"cphase1");
|
|
SNXSPutDrivable(pServ->pSics, pCon, hfil, hdict, "chopper2phase",
|
|
"cphase2");
|
|
|
|
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);
|
|
sprintf(pThing, "d%1.1ddist", 1);
|
|
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, pThing, pThing);
|
|
|
|
/* 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);
|
|
sprintf(pThing, "d%1.1ddist", 2);
|
|
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, pThing, pThing);
|
|
|
|
/* third Diaphragm */
|
|
WriteDiaphragm(hfil, hdict, 3, pCon);
|
|
sprintf(pThing, "d%1.1ddist", 3);
|
|
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, pThing, pThing);
|
|
|
|
/* 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");
|
|
fVal = ObVal(pAmor->aParameter, PARDH);
|
|
NXDputalias(hfil, hdict, "baseheight", &fVal);
|
|
|
|
|
|
/* fourth Diaphragm */
|
|
WriteDiaphragm(hfil, hdict, 4, pCon);
|
|
fVal = ObVal(pAmor->aParameter, PARDD4);
|
|
NXDputalias(hfil, hdict, "d4dist", &fVal);
|
|
fVal = ObVal(pAmor->aParameter, PARD4H);
|
|
NXDputalias(hfil, hdict, "d4base", &fVal);
|
|
|
|
/* 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");
|
|
fVal = ObVal(pAmor->aParameter, PARADIS);
|
|
NXDputalias(hfil, hdict, "adis", &fVal);
|
|
fVal = ObVal(pAmor->aParameter, PARANA);
|
|
NXDputalias(hfil, hdict, "abase", &fVal);
|
|
|
|
|
|
/* fifth Diaphragm!!!!!!!!! */
|
|
WriteDiaphragm(hfil, hdict, 5, pCon);
|
|
fVal = ObVal(pAmor->aParameter, PARDD5);
|
|
NXDputalias(hfil, hdict, "d5dist", &fVal);
|
|
fVal = ObVal(pAmor->aParameter, PARD5H);
|
|
NXDputalias(hfil, hdict, "d5base", &fVal);
|
|
|
|
/* 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", file);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = NXDinitfromfile(AMORDICT, &hdict);
|
|
if (iRet != NX_OK) {
|
|
sprintf(pBueffel, "ERROR: cannot open dictionary file %s", AMORDICT);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* 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;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------
|
|
WriteTOFDetector writes the histogram memory data in TOF mode. As
|
|
the histogram memory can become quite large at AMOR, the data is
|
|
read and stored in chunks if it is to big. All this is handled
|
|
in this routine.
|
|
-------------------------------------------------------------------------*/
|
|
static int WriteTOFDetector(char *name, pHistMem pHM, int *iDim,
|
|
NXhandle hfil, NXdict hdict,
|
|
SConnection * pCon)
|
|
{
|
|
int nChunk, chunkSize, iChunk[3], i, iStart[3], nTime, iRet;
|
|
long iLength;
|
|
HistInt *lData = NULL;
|
|
char pBueffel[132];
|
|
const float *fTime;
|
|
int start;
|
|
|
|
fTime = GetHistTimeBin(pHM, &nTime);
|
|
iDim[2] = nTime;
|
|
iLength = iDim[0] * iDim[1] * iDim[2];
|
|
if ((iLength * 4) < TOFBLOCK) {
|
|
sprintf(pBueffel, " -chunk {%d,%d,%d} ", iDim[0], iDim[1], iDim[2]);
|
|
NXDupdate(hdict, "chunk", pBueffel);
|
|
lData = (HistInt *) malloc(iLength * sizeof(HistInt));
|
|
if (!lData) {
|
|
SCWrite(pCon,
|
|
"ERROR: out of memory, failed to write histogram", eError);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
return 0;
|
|
}
|
|
memset(lData, 0, iLength * sizeof(HistInt));
|
|
iRet = GetHistogramDirect(pHM, pCon,
|
|
0, 0, iLength, lData,
|
|
iLength * sizeof(HistInt));
|
|
if (!iRet) {
|
|
SCWrite(pCon, "ERROR: failed to read Hm data", eError);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
free(lData);
|
|
return 0;
|
|
}
|
|
SicsWait(2);
|
|
NXDputalias(hfil, hdict, name, lData);
|
|
NXDputalias(hfil, hdict, "detchunk", iDim);
|
|
NXDaliaslink(hfil, hdict, "dana", name);
|
|
} else {
|
|
/*
|
|
implement chunked writing. We strive to write layers in Y. The
|
|
number of chunks needs to fulfill three conditions then:
|
|
- multiple of xSize* timeBin;
|
|
- close to TOFBLOCK in size
|
|
- divide Y without remainder.
|
|
*/
|
|
iChunk[0] = iDim[0];
|
|
iChunk[2] = iDim[2];
|
|
iChunk[1] = 1;
|
|
chunkSize = iDim[0] * iDim[2];
|
|
for (i = 1; i < 64; i++) {
|
|
if ((iDim[1] % i) == 0) {
|
|
if (i * chunkSize * sizeof(HistInt) < TOFBLOCK) {
|
|
iChunk[1] = i;
|
|
}
|
|
}
|
|
}
|
|
sprintf(pBueffel, "Segmented TOF data in %d chunks",
|
|
iDim[1] / iChunk[1]);
|
|
SCWrite(pCon, pBueffel, eWarning);
|
|
/*
|
|
now we have a chunkSize, lets go and write!
|
|
*/
|
|
NXDputalias(hfil, hdict, "detchunk", iChunk);
|
|
chunkSize = iChunk[1] * iChunk[0] * iChunk[2];
|
|
sprintf(pBueffel, " -chunk {%d,%d,%d} ", iChunk[0], iChunk[1],
|
|
iChunk[2]);
|
|
NXDupdate(hdict, "chunk", pBueffel);
|
|
lData = (HistInt *) malloc(chunkSize * sizeof(HistInt));
|
|
if (!lData) {
|
|
SCWrite(pCon, "ERROR: out of memory while writing TOF data", eError);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
return 0;
|
|
}
|
|
NXDopenalias(hfil, hdict, name);
|
|
for (i = 0; i < iDim[1] / iChunk[1]; i++) {
|
|
memset(lData, 0, chunkSize * sizeof(HistInt));
|
|
iRet = GetHistogramDirect(pHM, pCon,
|
|
0, i * chunkSize, (i + 1) * chunkSize,
|
|
lData, chunkSize * sizeof(HistInt));
|
|
if (!iRet) {
|
|
SCWrite(pCon, "ERROR: failed to read HM data", eError);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
free(lData);
|
|
return 0;
|
|
}
|
|
/*
|
|
yield a little in order to allow other clients to receive a
|
|
response. Also allow for interrupting.
|
|
*/
|
|
SicsWait(2);
|
|
|
|
iStart[0] = 0;
|
|
iStart[1] = i * iChunk[1];
|
|
iStart[2] = 0;
|
|
NXputslab(hfil, lData, iStart, iChunk);
|
|
sprintf(pBueffel, "Wrote chunk %d", i);
|
|
SCWrite(pCon, pBueffel, eWarning);
|
|
/*
|
|
yield a little in order to allow other clients to receive a
|
|
response. Also allow for interrupting.
|
|
*/
|
|
SicsWait(2);
|
|
}
|
|
/*
|
|
close groups till root
|
|
*/
|
|
NXclosedata(hfil);
|
|
NXclosegroup(hfil);
|
|
NXclosegroup(hfil);
|
|
NXclosegroup(hfil);
|
|
|
|
/*
|
|
make link
|
|
*/
|
|
NXDaliaslink(hfil, hdict, "dana", name);
|
|
NXDaliaslink(hfil, hdict, "dana", "detchunk");
|
|
|
|
}
|
|
if (lData)
|
|
free(lData);
|
|
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;
|
|
int detxsize, detysize, iDim[MAXDIM];
|
|
|
|
|
|
/* open files */
|
|
iRet = NXopen(file, NXACC_RDWR, &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", AMORDICT);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* 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, 1, pCon);
|
|
NXDputalias(hfil, hdict, "cnmon1", &lVal);
|
|
lVal = GetMonitor((pCounter) pCom->pData, 4, pCon);
|
|
NXDputalias(hfil, hdict, "cnmon2", &lVal);
|
|
}
|
|
} else {
|
|
SCWrite(pCon, "WARNING: failed to find counter!", eWarning);
|
|
}
|
|
|
|
/*
|
|
find dimensions of detector
|
|
*/
|
|
GetHistDim(pHM, iDim, &iLength);
|
|
detxsize = iDim[0];
|
|
detysize = iDim[1];
|
|
/* update detector size */
|
|
sprintf(pBueffel, "%d", detxsize);
|
|
NXDupdate(hdict, "detxsize", pBueffel);
|
|
sprintf(pBueffel, "%d", detysize);
|
|
NXDupdate(hdict, "detysize", pBueffel);
|
|
|
|
|
|
/* write two axis */
|
|
if (detxsize > detysize)
|
|
iLength = detxsize;
|
|
else
|
|
iLength = detysize;
|
|
|
|
fAxis = (float *) malloc(iLength * sizeof(float));
|
|
if (!fAxis) {
|
|
SCWrite(pCon, "ERROR: out of memory in WriteAmorTOF", eError);
|
|
return 0;
|
|
}
|
|
for (i = 0; i < detxsize; i++) {
|
|
fAxis[i] = (float) i;
|
|
}
|
|
NXDputalias(hfil, hdict, "detxx", fAxis);
|
|
for (i = 0; i < detysize; i++) {
|
|
fAxis[i] = (float) i;
|
|
}
|
|
NXDputalias(hfil, hdict, "dety", fAxis);
|
|
NXDaliaslink(hfil, hdict, "dana", "detxx");
|
|
NXDaliaslink(hfil, hdict, "dana", "dety");
|
|
free(fAxis);
|
|
|
|
|
|
/* add height and distances */
|
|
fVal = ObVal(pAmor->aParameter, PARDS);
|
|
NXDputalias(hfil, hdict, "detdist", &fVal);
|
|
fVal = ObVal(pAmor->aParameter, PARDDH);
|
|
NXDputalias(hfil, hdict, "detbase", &fVal);
|
|
|
|
|
|
/* deal with time binning */
|
|
fTime = GetHistTimeBin(pHM, &iLength);
|
|
iDim[2] = 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);
|
|
NXDputalias(hfil, hdict, "singletime", fTime2);
|
|
NXDaliaslink(hfil, hdict, "dana", "dettime");
|
|
free(fTime2);
|
|
fTime2 = NULL;
|
|
} else {
|
|
SCWrite(pCon, "ERROR: out of memory while writing time binning",
|
|
eError);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
NXclose(&hfil);
|
|
NXDclose(hdict, NULL);
|
|
return 0;
|
|
}
|
|
|
|
/* finally get histogram */
|
|
if (iDim[2] == 2) { /* 2D data, no time binning on this detector */
|
|
iLength = detxsize * detysize;
|
|
lData = (HistInt *) malloc(iLength * sizeof(HistInt));
|
|
if (!lData) {
|
|
SCWrite(pCon,
|
|
"ERROR: out of memory, failed to write histogram", eError);
|
|
NXclose(&hfil);
|
|
NXDclose(hdict, NULL);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
return 0;
|
|
}
|
|
memset(lData, 0, iLength * sizeof(HistInt));
|
|
iRet = GetHistogram(pHM, pCon, 0, 0, iLength,
|
|
lData, iLength * sizeof(HistInt));
|
|
if (!iRet) {
|
|
SCWrite(pCon, "ERROR: failed to read HM", eError);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
NXclose(&hfil);
|
|
NXDclose(hdict, NULL);
|
|
return 0;
|
|
}
|
|
NXDputalias(hfil, hdict, "spinup2d", lData);
|
|
NXDaliaslink(hfil, hdict, "dana", "spinup2d");
|
|
} else {
|
|
if (psdSave) {
|
|
iRet = WriteTOFDetector("spinup", pHM, iDim, hfil, hdict, pCon);
|
|
if (!iRet) {
|
|
NXclose(&hfil);
|
|
NXDclose(hdict, NULL);
|
|
return 0;
|
|
}
|
|
} else {
|
|
SCWrite(pCon, "PSD writing supressed!", eWarning);
|
|
}
|
|
#define MAXSINGLE 3
|
|
/*
|
|
now get and write single detectors
|
|
*/
|
|
iLength = iDim[0] * iDim[1] * iDim[2];
|
|
lData = (HistInt *) malloc(MAXSINGLE * iDim[2] * sizeof(HistInt));
|
|
if (!lData) {
|
|
SCWrite(pCon, "ERROR: out of memory while writing single detectors",
|
|
eError);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
NXclose(&hfil);
|
|
NXDclose(hdict, NULL);
|
|
return 0;
|
|
} else {
|
|
memset(lData, 0, MAXSINGLE * iDim[2] * sizeof(HistInt));
|
|
iRet = GetHistogramDirect(pHM, pCon, 0, iLength,
|
|
iLength + MAXSINGLE * iDim[2],
|
|
lData,
|
|
MAXSINGLE * iDim[2] * sizeof(HistInt));
|
|
if (!iRet) {
|
|
SCWrite(pCon, "ERROR: failed to read single detector HM data",
|
|
eError);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
free(lData);
|
|
NXclose(&hfil);
|
|
NXDclose(hdict, NULL);
|
|
return 0;
|
|
}
|
|
NXDputalias(hfil, hdict, "singleup", lData);
|
|
NXDaliaslink(hfil, hdict, "singledana", "singleup");
|
|
NXDaliaslink(hfil, hdict, "singledana", "singletime");
|
|
/*
|
|
the TOF monitor
|
|
*/
|
|
NXDputalias(hfil, hdict, "singletofmon", lData + 2 * iDim[2]);
|
|
NXDaliaslink(hfil, hdict, "dana", "singletofmon");
|
|
NXDaliaslink(hfil, hdict, "singledana", "singletofmon");
|
|
}
|
|
}
|
|
|
|
/* to do: add polarizing code */
|
|
|
|
if (lData)
|
|
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, iFlag;
|
|
Status oldStatus;
|
|
|
|
/*
|
|
if arguments, check for psdsave
|
|
*/
|
|
if (argc > 1) {
|
|
strtolower(argv[1]);
|
|
if (strcmp(argv[1], "psdsave") == 0) {
|
|
if (argc > 2) {
|
|
psdSave = atof(argv[2]);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
sprintf(pBueffel, "storeamor.psdSave = %d", psdSave);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
pFile = SNXMakeFileName(pSics, pCon);
|
|
sprintf(pBueffel, "Writing file %s .....", pFile);
|
|
SCWrite(pCon, pBueffel, eWarning);
|
|
|
|
oldStatus = GetStatus();
|
|
SetStatus(eWriting);
|
|
LockDeviceExecutor(pServ->pExecutor);
|
|
iRet = WriteAmorHeader(pFile, pCon);
|
|
if (iRet) {
|
|
iRet = WriteAmorTOF(pFile, pCon, pMeme);
|
|
}
|
|
SetStatus(oldStatus);
|
|
UnlockDeviceExecutor(pServ->pExecutor);
|
|
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 < 3) {
|
|
SCWrite(pCon,
|
|
"ERROR: insufficient number of arguments to AmorStoreMake",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
/* we need a 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;
|
|
|
|
/* we need another parameter which is the name of the
|
|
2theta calculation module
|
|
*/
|
|
pCom = FindCommand(pServ->pSics, argv[2]);
|
|
if (!pCom) {
|
|
sprintf(pBueffel, "ERROR: amor2T module %s NOT found", argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
if (!pCom->pData) {
|
|
sprintf(pBueffel, "ERROR: amor2t module %s NOT found", argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
pAmor = (pAmor2T) pCom->pData;
|
|
if (argc > 3) {
|
|
strncpy(AMORDICT, argv[3], 1023);
|
|
}
|
|
|
|
|
|
/* 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;
|
|
}
|