815 lines
23 KiB
C
815 lines
23 KiB
C
/*--------------------------------------------------------------------------
|
|
N X D A T A
|
|
|
|
This implements the data file writing for the Powder diffractometers
|
|
HRPT and DMC.
|
|
|
|
Mark Koennecke, March-April 1997
|
|
|
|
Updated and expanded: Mark Koennecke, November 1999
|
|
|
|
Copyright:
|
|
|
|
Labor fuer Neutronenstreuung
|
|
Paul Scherrer Institut
|
|
CH-5423 Villigen-PSI
|
|
|
|
|
|
The authors hereby grant permission to use, copy, modify, distribute,
|
|
and license this software and its documentation for any purpose, provided
|
|
that existing copyright notices are retained in all copies and that this
|
|
notice is included verbatim in any distributions. No written agreement,
|
|
license, or royalty fee is required for any of the authorized uses.
|
|
Modifications to this software may be copyrighted by their authors
|
|
and need not follow the licensing terms described here, provided that
|
|
the new terms are clearly indicated on the first page of each file where
|
|
they apply.
|
|
|
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
|
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
|
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
|
MODIFICATIONS.
|
|
----------------------------------------------------------------------------*/
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
#include "fortify.h"
|
|
#include "sics.h"
|
|
#include "sicsvar.h"
|
|
#include "nxdict.h"
|
|
#include "modriv.h"
|
|
#include "motor.h"
|
|
#include "nxdata.h"
|
|
#include "nxutil.h"
|
|
#include "selector.h"
|
|
#include "selvar.h"
|
|
#include "countdriv.h"
|
|
#include "counter.h"
|
|
#include "danu.h"
|
|
#include "HistMem.h"
|
|
#include "udpquieck.h"
|
|
#include "evcontroller.h"
|
|
#include "nxscript.h"
|
|
|
|
|
|
#define DMCDETNAM "DMC-BF3-Detector"
|
|
#define DMCDETOB "detector"
|
|
#define HRPTDETNAM "Cerca-Detector"
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
static void SNError(void *pData, char *text)
|
|
{
|
|
SConnection *pCon;
|
|
|
|
assert(pData);
|
|
pCon = (SConnection *) pData;
|
|
SCWrite(pCon, text, eError);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
char *SNXMakeFileName(SicsInterp * pSics, SConnection * pCon)
|
|
{
|
|
char *pPtr = NULL;
|
|
pPtr = makeFilename(pSics, pCon);
|
|
if (pPtr == NULL) {
|
|
pPtr = strdup("emergency.hdf");
|
|
}
|
|
return pPtr;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
char *SNXMakeFileNameOld(SicsInterp * pSics, SConnection * pCon)
|
|
{
|
|
pSicsVariable pPath = NULL, pPref = NULL, pEnd = NULL;
|
|
char *pRes = NULL;
|
|
int iLen, iNum, iYear;
|
|
char pNumText[10];
|
|
CommandList *pCom = NULL;
|
|
|
|
/* Try, get all the Variables */
|
|
pPath = FindVariable(pSics, "sicsdatapath");
|
|
pPref = FindVariable(pSics, "sicsdataprefix");
|
|
pCom = FindCommand(pSics, "sicsdatanumber");
|
|
pEnd = FindVariable(pSics, "sicsdatapostfix");
|
|
|
|
if ((!pPath) || (!pPref) || (!pCom) || (!pEnd)) {
|
|
SCWrite(pCon,
|
|
"ERROR: cannot read variables for automatic data file name creation",
|
|
eError);
|
|
SCWrite(pCon,
|
|
"ERROR: This is a VERY, VERY, VERY serious installation problem",
|
|
eError);
|
|
SCWrite(pCon, "ERROR: your data will be dumped into emergency.hdf",
|
|
eError);
|
|
return strdup("emergency.hdf");
|
|
}
|
|
|
|
/* find length */
|
|
iLen = strlen(pPath->text);
|
|
iLen += strlen(pPref->text);
|
|
iLen += 8; /* for number + year */
|
|
iLen += strlen(pEnd->text);
|
|
iLen += 10; /* safety margin */
|
|
|
|
/* allocate memory */
|
|
pRes = (char *) malloc(iLen * sizeof(char));
|
|
if (!pRes) {
|
|
SCWrite(pCon, "ERROR: no memory in SNXMakeFileName", eError);
|
|
return NULL;
|
|
}
|
|
memset(pRes, 0, iLen);
|
|
|
|
/* build the filename */
|
|
strcpy(pRes, pPath->text);
|
|
strcat(pRes, pPref->text);
|
|
iNum = IncrementDataNumber(pCom->pData, &iYear);
|
|
if (iNum < 0) {
|
|
SCWrite(pCon, "ERROR: cannot increment data number!", eError);
|
|
SCWrite(pCon, "ERROR: your data will be dumped to emergency.hdf",
|
|
eError);
|
|
free(pRes);
|
|
return strdup("emergency.hdf");
|
|
}
|
|
sprintf(pNumText, "%5.5d", iNum);
|
|
strcat(pRes, pNumText);
|
|
sprintf(pNumText, "%4.4d", iYear);
|
|
strcat(pRes, pNumText);
|
|
strcat(pRes, pEnd->text);
|
|
|
|
|
|
/* install an error handler */
|
|
NXMSetError((void *) pCon, SNError);
|
|
|
|
return pRes;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
NXhandle SNXStartFile(SConnection * pCon, SicsInterp * pSics)
|
|
{
|
|
NXhandle pFile = NULL;
|
|
char *filename = NULL;
|
|
pSicsVariable pVar = NULL;
|
|
int iStat;
|
|
char pBueffel[512], pTime[132];
|
|
|
|
/* get a filename */
|
|
filename = SNXMakeFileName(pSics, pCon);
|
|
if (!filename) {
|
|
return NULL;
|
|
}
|
|
|
|
/* create a Nexus file */
|
|
NXopen(filename, NXACC_CREATE, &pFile);
|
|
if (!pFile) {
|
|
SCWrite(pCon, "ERROR: cannot create data file ", eError);
|
|
free(filename);
|
|
return NULL;
|
|
}
|
|
|
|
/* tell Uwe User what we are doing */
|
|
sprintf(pBueffel, "Writing %s ......", filename);
|
|
SCWrite(pCon, pBueffel, eWarning);
|
|
|
|
/* store global attributes */
|
|
iStat = NXputattr(pFile, "file_name", filename,
|
|
strlen(filename) + 1, NX_CHAR);
|
|
if (iStat == NX_ERROR) {
|
|
SCWrite(pCon, "ERROR: writing file_name attribute to Nexus file",
|
|
eError);
|
|
}
|
|
|
|
/* filename no longer needed */
|
|
free(filename);
|
|
|
|
/* write creation time */
|
|
SNXFormatTime(pTime, 132);
|
|
iStat = NXputattr(pFile, "file_time", pTime, strlen(pTime) + 1, NX_CHAR);
|
|
if (iStat == NX_ERROR) {
|
|
SCWrite(pCon, "ERROR: writing date attribute to Nexus file", eError);
|
|
}
|
|
sprintf(pBueffel, "File created at StarDate: %s", pTime);
|
|
SCWrite(pCon, pBueffel, eWarning);
|
|
|
|
pVar = FindVariable(pSics, "instrument");
|
|
if (pVar) {
|
|
iStat = NXputattr(pFile, "instrument", pVar->text,
|
|
strlen(pVar->text) + 1, NX_CHAR);
|
|
if (iStat == NX_ERROR) {
|
|
SCWrite(pCon, "ERROR: writing instrument attribute to Nexus file",
|
|
eError);
|
|
}
|
|
}
|
|
pVar = NULL;
|
|
pVar = FindVariable(pSics, "user");
|
|
if (pVar) {
|
|
iStat = NXputattr(pFile, "owner", pVar->text,
|
|
strlen(pVar->text) + 1, NX_CHAR);
|
|
if (iStat == NX_ERROR) {
|
|
SCWrite(pCon, "ERROR: writing owner attribute to Nexus file",
|
|
eError);
|
|
}
|
|
}
|
|
|
|
pVar = NULL;
|
|
pVar = FindVariable(pSics, "address");
|
|
if (pVar) {
|
|
iStat = NXputattr(pFile, "owner_adress", pVar->text,
|
|
strlen(pVar->text) + 1, NX_CHAR);
|
|
if (iStat == NX_ERROR) {
|
|
SCWrite(pCon, "ERROR: writing owner_adress attribute to Nexus file",
|
|
eError);
|
|
}
|
|
}
|
|
pVar = NULL;
|
|
pVar = FindVariable(pSics, "phone");
|
|
if (pVar) {
|
|
iStat = NXputattr(pFile, "owner_telephone_number", pVar->text,
|
|
strlen(pVar->text) + 1, NX_CHAR);
|
|
if (iStat == NX_ERROR) {
|
|
SCWrite(pCon,
|
|
"ERROR: writing owner_telephone_number attribute to Nexus file",
|
|
eError);
|
|
}
|
|
}
|
|
pVar = NULL;
|
|
pVar = FindVariable(pSics, "fax");
|
|
if (pVar) {
|
|
iStat = NXputattr(pFile, "owner_fax_number", pVar->text,
|
|
strlen(pVar->text) + 1, NX_CHAR);
|
|
if (iStat == NX_ERROR) {
|
|
SCWrite(pCon,
|
|
"ERROR: writing owner_fax_number attribute to Nexus file",
|
|
eError);
|
|
}
|
|
}
|
|
pVar = NULL;
|
|
pVar = FindVariable(pSics, "email");
|
|
if (pVar) {
|
|
iStat = NXputattr(pFile, "owner_email", pVar->text,
|
|
strlen(pVar->text) + 1, NX_CHAR);
|
|
if (iStat == NX_ERROR) {
|
|
SCWrite(pCon, "ERROR: writing owner_email attribute to Nexus file",
|
|
eError);
|
|
}
|
|
}
|
|
pVar = NULL;
|
|
return pFile;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int SNXStartEntry(NXhandle Nfil, int iNew, SicsInterp * pSics)
|
|
{
|
|
int iStat;
|
|
char pName[80];
|
|
pSicsVariable pVar = NULL;
|
|
int iDim[2];
|
|
|
|
/* format an entry name */
|
|
if (iNew < 10) {
|
|
sprintf(pName, "entry%1.1d", iNew);
|
|
} else if ((iNew > 9) && (iNew < 100)) {
|
|
sprintf(pName, "entry%2.2d", iNew);
|
|
} else if ((iNew > 99) && (iNew < 1000)) {
|
|
sprintf(pName, "entry%3.3d", iNew);
|
|
} else if ((iNew > 9999) && (iNew < 10000)) {
|
|
sprintf(pName, "entry%4.4d", iNew);
|
|
} else {
|
|
return 0;
|
|
}
|
|
|
|
/* create entry and step into it */
|
|
iStat = NXmakegroup(Nfil, pName, "NXentry");
|
|
if (iStat == NX_ERROR) {
|
|
return 0;
|
|
}
|
|
iStat = NXopengroup(Nfil, pName, "NXentry");
|
|
if (iStat == NX_ERROR) {
|
|
return 0;
|
|
}
|
|
|
|
/* write entry level attributes here */
|
|
pVar = FindVariable(pSics, "title");
|
|
if (pVar) {
|
|
iDim[0] = strlen(pVar->text) + 1;
|
|
NXmakedata(Nfil, "title", NX_CHAR, 1, iDim);
|
|
NXopendata(Nfil, "title");
|
|
NXputdata(Nfil, pVar->text);
|
|
NXclosedata(Nfil);
|
|
}
|
|
/* write time */
|
|
SNXFormatTime(pName, 79);
|
|
iDim[0] = strlen(pName) + 1;
|
|
NXmakedata(Nfil, "start_time", NX_CHAR, 1, iDim);
|
|
NXopendata(Nfil, "start_time");
|
|
NXputdata(Nfil, pName);
|
|
NXclosedata(Nfil);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int SNenter(NXhandle Nfil, char *name, char *class)
|
|
{
|
|
int iStat;
|
|
|
|
iStat = NXmakegroup(Nfil, name, class);
|
|
if (iStat == NX_ERROR) {
|
|
NXclose(&Nfil);
|
|
return 0;
|
|
}
|
|
iStat = NXopengroup(Nfil, name, class);
|
|
if (iStat == NX_ERROR) {
|
|
NXclose(&Nfil);
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int SNputdata1(NXhandle Nfil, char *name, int datatype, int iLong,
|
|
void *pData)
|
|
{
|
|
int iStat;
|
|
int iDim[2];
|
|
|
|
iDim[0] = iLong;
|
|
iStat = NXmakedata(Nfil, name, datatype, 1, (int *) iDim);
|
|
if (iStat == NX_ERROR) {
|
|
NXclose(&Nfil);
|
|
return 0;
|
|
}
|
|
iStat = NXopendata(Nfil, name);
|
|
if (iStat == NX_ERROR) {
|
|
NXclose(&Nfil);
|
|
return 0;
|
|
}
|
|
iStat = NXputdata(Nfil, pData);
|
|
if (iStat == NX_ERROR) {
|
|
NXclose(&Nfil);
|
|
return 0;
|
|
}
|
|
iStat = NXclosedata(Nfil);
|
|
if (iStat == NX_ERROR) {
|
|
NXclose(&Nfil);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int SNputdata1att(NXhandle Nfil, char *name, int datatype, int iLong,
|
|
void *pData, char *attname, char *val)
|
|
{
|
|
int iStat;
|
|
int iDim[2];
|
|
|
|
iDim[0] = iLong;
|
|
iStat = NXmakedata(Nfil, name, datatype, 1, (int *) iDim);
|
|
if (iStat == NX_ERROR) {
|
|
NXclose(&Nfil);
|
|
return 0;
|
|
}
|
|
iStat = NXopendata(Nfil, name);
|
|
if (iStat == NX_ERROR) {
|
|
NXclose(&Nfil);
|
|
return 0;
|
|
}
|
|
iStat = NXputdata(Nfil, pData);
|
|
if (iStat == NX_ERROR) {
|
|
NXclose(&Nfil);
|
|
return 0;
|
|
}
|
|
iStat = NXputattr(Nfil, attname, val, strlen(val) + 1, NX_CHAR);
|
|
if (iStat == NX_ERROR) {
|
|
NXclose(&Nfil);
|
|
return 0;
|
|
}
|
|
iStat = NXclosedata(Nfil);
|
|
if (iStat == NX_ERROR) {
|
|
NXclose(&Nfil);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
static int SNPutMotor(NXhandle hfil, SicsInterp * pSics,
|
|
SConnection * pCon, char *sicsname,
|
|
char *dataname, char *units)
|
|
{
|
|
float fVal;
|
|
char pBueffel[512];
|
|
int iRet;
|
|
pMotor pMot;
|
|
|
|
pMot = FindMotor(pSics, sicsname);
|
|
if (!pMot) {
|
|
sprintf(pBueffel, "ERROR: motor %s not found ", sicsname);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = MotorGetSoftPosition(pMot, pCon, &fVal);
|
|
if (iRet != 1) {
|
|
sprintf(pBueffel, "ERROR: cannot read motor %s", sicsname);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
return SNputdata1att(hfil, dataname, NX_FLOAT32, 1, &fVal, "Units",
|
|
units);
|
|
}
|
|
|
|
#ifdef NONINTF
|
|
extern float nintf(float f);
|
|
#endif
|
|
/*--------------------------------------------------------------------------*/
|
|
int SNMakeDMC(SConnection * pCon, SicsInterp * pSics)
|
|
{
|
|
NXhandle Nfil;
|
|
NXlink lWave, lDetData, lStart, lTemp, lMoni, lStep, lNumber,
|
|
lTheta, lSetData;
|
|
int iDim[2];
|
|
float fEnd, fStart, fStep;
|
|
int iStat;
|
|
pSicsVariable pVar;
|
|
pSicsSelector pSel = NULL;
|
|
pICountable pCountInt;
|
|
pIDrivable pDrive = NULL;
|
|
pSelVar pPell;
|
|
char *pP;
|
|
float fVal;
|
|
float *fTheta;
|
|
float fTh, f2Th, fB1, fB2;
|
|
pMotor pMot = NULL;
|
|
CommandList *pCom = NULL;
|
|
int iVal, i;
|
|
char pBuffer[132];
|
|
pHistMem pHist = NULL;
|
|
HistInt *lData = NULL;
|
|
CounterMode eCount;
|
|
int *iTVal = NULL;
|
|
pDummy pDum;
|
|
int bHRPT = 0;
|
|
float fMean, fStdDev;
|
|
pVarLog pLog = NULL;
|
|
|
|
/* open the file & entry */
|
|
Nfil = SNXStartFile(pCon, pSics);
|
|
if (!Nfil) {
|
|
return 0;
|
|
}
|
|
|
|
iStat = SNXStartEntry(Nfil, 1, pSics);
|
|
if (!iStat) {
|
|
NXclose(&Nfil);
|
|
return 0;
|
|
}
|
|
|
|
/* create the instrument Vgroup */
|
|
pVar = FindVariable(pSics, "instrument");
|
|
if (strcmp(pVar->text, "HRPT") == 0) {
|
|
bHRPT = 1;
|
|
}
|
|
assert(pVar);
|
|
iStat = SNenter(Nfil, pVar->text, "NXpsdpowder");
|
|
if (!iStat) {
|
|
return 0;
|
|
}
|
|
/* write the Kollimator for HRPT */
|
|
if (bHRPT) {
|
|
iStat = SNenter(Nfil, "kollimator", "NXkollimator");
|
|
if (!iStat) {
|
|
return 0;
|
|
}
|
|
pMot = FindMotor(pSics, "CEX1");
|
|
if (pMot) {
|
|
iStat = MotorGetSoftPosition(pMot, pCon, &fStart);
|
|
iStat = SNputdata1att(Nfil, "kollimator1", NX_FLOAT32, 1,
|
|
&fStart, "Units", "degrees");
|
|
}
|
|
pMot = FindMotor(pSics, "CEX2");
|
|
if (pMot) {
|
|
iStat = MotorGetSoftPosition(pMot, pCon, &fStart);
|
|
iStat = SNputdata1att(Nfil, "kollimator2", NX_FLOAT32, 1,
|
|
&fStart, "Units", "degrees");
|
|
}
|
|
NXclosegroup(Nfil); /* leave kollimator */
|
|
}
|
|
|
|
/* write the Monochromator data */
|
|
iStat = SNenter(Nfil, "Monochromator", "NXcrystal");
|
|
if (!iStat) {
|
|
return 0;
|
|
}
|
|
if (bHRPT) {
|
|
pVar = FindVariable(pSics, "lambda");
|
|
if (pVar) {
|
|
VarGetFloat(pVar, &fVal);
|
|
SNputdata1att(Nfil, "lambda", NX_FLOAT32, 1, &fVal,
|
|
"Units", "Angstroem");
|
|
NXopendata(Nfil, "lambda");
|
|
NXgetdataID(Nfil, &lWave);
|
|
NXclosedata(Nfil);
|
|
}
|
|
pVar = FindVariable(pSics, "monotype");
|
|
if (pVar) {
|
|
iStat = SNputdata1(Nfil, "type", NX_CHAR, strlen(pVar->text),
|
|
pVar->text);
|
|
}
|
|
/* write tons of motors for the monochromator */
|
|
SNPutMotor(Nfil, pSics, pCon, "momu", "omega_upper", "degree");
|
|
SNPutMotor(Nfil, pSics, pCon, "mtvu",
|
|
"vertical_translation_upper", "mm");
|
|
SNPutMotor(Nfil, pSics, pCon, "mtpu",
|
|
"paralell_translation_upper", "mm");
|
|
SNPutMotor(Nfil, pSics, pCon, "mgvu", "vertical_tilt_upper", "degree");
|
|
SNPutMotor(Nfil, pSics, pCon, "mgpu", "parallel_tilt_upper", "degree");
|
|
SNPutMotor(Nfil, pSics, pCon, "mcvu", "curvature_upper", "");
|
|
SNPutMotor(Nfil, pSics, pCon, "moml", "omega_lower", "degree");
|
|
SNPutMotor(Nfil, pSics, pCon, "mtvl",
|
|
"vertical_translation_lower", "mm");
|
|
SNPutMotor(Nfil, pSics, pCon, "mtpl",
|
|
"parallel_translation_lower", "degree");
|
|
SNPutMotor(Nfil, pSics, pCon, "mgvl", "vertical_tilt_lower", "degree");
|
|
SNPutMotor(Nfil, pSics, pCon, "mgpl", "parallel_tilt_lower", "degree");
|
|
SNPutMotor(Nfil, pSics, pCon, "mcvl", "curvature_lower", "degree");
|
|
SNPutMotor(Nfil, pSics, pCon, "mexz", "lift", "mm");
|
|
} else {
|
|
pCom = FindCommand(pSics, "mono");
|
|
assert(pCom);
|
|
pSel = (pSicsSelector) pCom->pData;
|
|
pP = MonoGetType(pSel);
|
|
iStat = SNputdata1(Nfil, "type", NX_CHAR, strlen(pP), pP);
|
|
if (!iStat) {
|
|
return 0;
|
|
}
|
|
pCom = NULL;
|
|
pCom = FindCommand(pSics, "lambda");
|
|
assert(pCom);
|
|
pPell = (pSelVar) pCom->pData;
|
|
assert(iHasType(pPell, "SicsSelVar"));
|
|
fVal = GetSelValue(pPell, pCon);
|
|
iStat = SNputdata1(Nfil, "lambda", NX_FLOAT32, 1, &fVal);
|
|
if (!iStat) {
|
|
return 0;
|
|
}
|
|
NXopendata(Nfil, "lambda");
|
|
NXputattr(Nfil, "Units", "Angstroem", 10, NX_CHAR);
|
|
NXgetdataID(Nfil, &lWave);
|
|
NXclosedata(Nfil);
|
|
iStat = GetMonoPositions(pSel, pCon, &fTh, &f2Th, &fB1, &fB2);
|
|
if (iStat)
|
|
/* skip if not readable, error has been reported lower down */
|
|
{
|
|
SNputdata1att(Nfil, "theta", NX_FLOAT32, 1, &fTh,
|
|
"Units", "degrees");
|
|
SNputdata1att(Nfil, "two_theta", NX_FLOAT32, 1, &f2Th,
|
|
"Units", "degrees");
|
|
SNputdata1att(Nfil, "curvature", NX_FLOAT32, 1, &fB1, "Units", "mm");
|
|
}
|
|
/* more monochromatic motors */
|
|
SNPutMotor(Nfil, pSics, pCon, "monox", "x_translation", "mm");
|
|
SNPutMotor(Nfil, pSics, pCon, "monoy", "y_translation", "mm");
|
|
SNPutMotor(Nfil, pSics, pCon, "monophi", "phi", "degree");
|
|
SNPutMotor(Nfil, pSics, pCon, "monochi", "chi", "degree");
|
|
}
|
|
NXclosegroup(Nfil); /* leave monochromator */
|
|
|
|
/* start Detector vGroup */
|
|
if (bHRPT) {
|
|
iStat = SNenter(Nfil, HRPTDETNAM, "NXpsd");
|
|
} else {
|
|
iStat = SNenter(Nfil, DMCDETNAM, "NXpsd");
|
|
}
|
|
/* get the histogram memory object */
|
|
pCom = FindCommand(pSics, "banana");
|
|
assert(pCom);
|
|
pHist = pCom->pData;
|
|
assert(pHist);
|
|
|
|
/* counter mode */
|
|
eCount = GetHistCountMode(pHist);
|
|
if (eCount == eTimer) {
|
|
strcpy(pBuffer, "Timer");
|
|
} else {
|
|
strcpy(pBuffer, "Monitor");
|
|
}
|
|
iStat =
|
|
SNputdata1(Nfil, "CounterMode", NX_CHAR, strlen(pBuffer), pBuffer);
|
|
if (!iStat) {
|
|
return 0;
|
|
}
|
|
|
|
/* count preset */
|
|
fVal = GetHistPreset(pHist);
|
|
if (eCount == eTimer) {
|
|
iStat = SNputdata1(Nfil, "Preset", NX_FLOAT32, 1, &fVal);
|
|
} else {
|
|
fVal = nintf(fVal);
|
|
iStat = SNputdata1(Nfil, "Preset", NX_FLOAT32, 1, &fVal);
|
|
}
|
|
if (!iStat) {
|
|
return 0;
|
|
}
|
|
|
|
/* monitor value */
|
|
pDum = (pDummy) pHist;
|
|
pCountInt = pDum->pDescriptor->GetInterface(pDum, COUNTID);
|
|
{
|
|
pCountInt->TransferData(pHist, pCon);
|
|
}
|
|
iVal = GetHistMonitor(pHist, 1, pCon);
|
|
if (iVal < 0) {
|
|
return 0;
|
|
}
|
|
iStat = SNputdata1(Nfil, "Monitor", NX_INT32, 1, &iVal);
|
|
/*
|
|
count time
|
|
*/
|
|
fVal = GetHistCountTime(pHist, pCon);
|
|
SNputdata1att(Nfil, "time", NX_FLOAT32, 1, &fVal, "Units", "seconds");
|
|
|
|
/*
|
|
more monitors
|
|
*/
|
|
iVal = GetHistMonitor(pHist, 0, pCon);
|
|
SNputdata1(Nfil, "beam_monitor", NX_INT32, 1, &iVal);
|
|
iVal = GetHistMonitor(pHist, 4, pCon);
|
|
SNputdata1(Nfil, "proton_monitor", NX_INT32, 1, &iVal);
|
|
NXopendata(Nfil, "Monitor");
|
|
NXgetdataID(Nfil, &lMoni);
|
|
NXclosedata(Nfil);
|
|
|
|
|
|
/* stepwidth */
|
|
pVar = FindVariable(pSics, "detstepwidth");
|
|
if (!pVar) {
|
|
return 0;
|
|
}
|
|
fVal = pVar->fVal;
|
|
iStat = SNputdata1(Nfil, "Step", NX_FLOAT32, 1, &fVal);
|
|
if (!iStat) {
|
|
return 0;
|
|
}
|
|
NXopendata(Nfil, "Step");
|
|
NXgetdataID(Nfil, &lStep);
|
|
NXclosedata(Nfil);
|
|
|
|
/* histogram Length */
|
|
GetHistDim(pHist, iDim, &iVal);
|
|
iVal = iDim[0];
|
|
if (iVal < 1) {
|
|
return 0;
|
|
}
|
|
iStat = SNputdata1(Nfil, "no_of_steps", NX_INT32, 1, &iVal);
|
|
if (iStat < 1) {
|
|
return 0;
|
|
}
|
|
NXopendata(Nfil, "no_of_steps");
|
|
NXgetdataID(Nfil, &lNumber);
|
|
NXclosedata(Nfil);
|
|
|
|
/* actual data */
|
|
lData = (HistInt *) malloc(iVal * sizeof(HistInt));
|
|
if (!lData) {
|
|
return 0;
|
|
}
|
|
iStat =
|
|
GetHistogram(pHist, pCon, 0, 0, iVal, lData, iVal * sizeof(HistInt));
|
|
if (!iStat) {
|
|
return 0;
|
|
}
|
|
iStat = SNputdata1(Nfil, "Counts", NX_INT32, iVal, lData);
|
|
if (!iStat) {
|
|
return 0;
|
|
}
|
|
free(lData);
|
|
NXopendata(Nfil, "Counts");
|
|
NXgetdataID(Nfil, &lSetData);
|
|
strcpy(pBuffer, "1");
|
|
NXputattr(Nfil, "signal", pBuffer, strlen(pBuffer) + 1, NX_CHAR);
|
|
NXclosedata(Nfil);
|
|
|
|
/* motor position */
|
|
pMot = FindMotor(pSics, "a4");
|
|
assert(pMot);
|
|
iStat = MotorGetSoftPosition(pMot, pCon, &fStart);
|
|
iStat = SNputdata1att(Nfil, "two_theta_start", NX_FLOAT32, 1,
|
|
&fStart, "Units", "degrees");
|
|
if (!iStat) {
|
|
return 0;
|
|
}
|
|
|
|
/* create 2Theta array and store it */
|
|
fTheta = NULL;
|
|
fTheta = (float *) malloc(iVal * sizeof(NX_FLOAT32));
|
|
if (!fTheta) {
|
|
return 0;
|
|
}
|
|
for (i = 0; i < iVal; i++) {
|
|
fTheta[i] = fStart + i * fVal;
|
|
}
|
|
iStat = SNputdata1att(Nfil, "two_theta", NX_FLOAT32, iVal,
|
|
fTheta, "Units", "degrees");
|
|
if (!iStat) {
|
|
return 0;
|
|
}
|
|
/* get link, put axis attribute */
|
|
NXopendata(Nfil, "two_theta");
|
|
NXputattr(Nfil, "axis", "1", strlen("1") + 1, NX_CHAR);
|
|
NXgetdataID(Nfil, &lTheta);
|
|
NXclosedata(Nfil);
|
|
free(fTheta);
|
|
|
|
|
|
NXopendata(Nfil, "two_theta_start");
|
|
NXgetdataID(Nfil, &lStart);
|
|
NXclosedata(Nfil);
|
|
NXclosegroup(Nfil); /* detector Vgroup */
|
|
NXclosegroup(Nfil); /* instrument Vgroup */
|
|
|
|
/* do the sample Vgroup */
|
|
iStat = SNenter(Nfil, "Sample", "NXpowder");
|
|
if (!iStat) {
|
|
return 0;
|
|
}
|
|
pVar = FindVariable(pSics, "sample");
|
|
if (pVar) {
|
|
iDim[0] = strlen(pVar->text) + 1;
|
|
NXmakedata(Nfil, "sample_name", NX_CHAR, 1, iDim);
|
|
NXopendata(Nfil, "sample_name");
|
|
NXputdata(Nfil, pVar->text);
|
|
NXclosedata(Nfil);
|
|
}
|
|
pVar = FindVariable(pSics, "sample_mur");
|
|
if (pVar) {
|
|
SNputdata1att(Nfil, "sample_mur", NX_FLOAT32, 1, &pVar->fVal,
|
|
"Units", "???");
|
|
}
|
|
/* do a3 */
|
|
SNPutMotor(Nfil, pSics, pCon, "a3", "sample_table_rotation", "degree");
|
|
|
|
/* write sample environment here */
|
|
pCom = FindCommand(pSics, "temperature");
|
|
if (pCom) {
|
|
pDum = (pDummy) pCom->pData;
|
|
pDrive = pDum->pDescriptor->GetInterface(pDum, DRIVEID);
|
|
if (pDrive) { /* a proper environment device */
|
|
pLog = EVCGetVarLog((pEVControl) pCom->pData);
|
|
if (pLog) {
|
|
VarlogGetMean(pLog, &fMean, &fStdDev);
|
|
SNputdata1att(Nfil, "temperature_mean", NX_FLOAT32, 1, &fMean,
|
|
"Units", "K");
|
|
SNputdata1att(Nfil, "temperature_stddev", NX_FLOAT32, 1,
|
|
&fStdDev, "Units", "K");
|
|
}
|
|
fVal = pDrive->GetValue(pCom->pData, pCon);
|
|
} else { /* a simple variable */
|
|
|
|
VarGetFloat((pSicsVariable) pDum, &fVal);
|
|
}
|
|
SNputdata1att(Nfil, "sample_temperature", NX_FLOAT32, 1, &fVal,
|
|
"Units", "K");
|
|
}
|
|
NXclosegroup(Nfil); /* sample Vgroup */
|
|
|
|
/* write the data Vgroup */
|
|
SNenter(Nfil, "data1", "NXdata");
|
|
NXmakelink(Nfil, &lWave);
|
|
NXmakelink(Nfil, &lTheta);
|
|
NXmakelink(Nfil, &lStart);
|
|
NXmakelink(Nfil, &lSetData);
|
|
NXmakelink(Nfil, &lMoni);
|
|
NXmakelink(Nfil, &lStep);
|
|
NXmakelink(Nfil, &lNumber);
|
|
|
|
/* send quieck message */
|
|
i = 131;
|
|
iVal = NX_CHAR;
|
|
NXgetattr(Nfil, "file_name", pBuffer, &i, &iVal);
|
|
SendQuieck(QUIECK, pBuffer);
|
|
|
|
/* done */
|
|
NXclose(&Nfil);
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int SNStoreDMC(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
return SNMakeDMC(pCon, pSics);
|
|
}
|