1077 lines
31 KiB
C
1077 lines
31 KiB
C
/*---------------------------------------------------------------------------
|
|
F O W R I T E
|
|
|
|
FOCUS data writing object.
|
|
|
|
copyright: see copyright.h
|
|
|
|
Mark Koennecke, November 1998
|
|
|
|
Added code for three detector banks.
|
|
|
|
Mark Koennecke, March 2000
|
|
-----------------------------------------------------------------------------*/
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <time.h>
|
|
#include <tcl.h>
|
|
/* avoid irritating compiler warning M.Z.08.2001 */
|
|
#undef VOID
|
|
#include "fortify.h"
|
|
#include "sics.h"
|
|
#include "event.h"
|
|
#include "counter.h"
|
|
#include "HistMem.h"
|
|
#include "nxdict.h"
|
|
#include "nxutil.h"
|
|
#include "motor.h"
|
|
#include "selector.h"
|
|
#include "fowrite.h"
|
|
#include "scan.h"
|
|
#include "sicsvar.h"
|
|
#include "fitcenter.h"
|
|
#include "hmcontrol.h"
|
|
#include "fomerge.h"
|
|
|
|
/* histogram memory names */
|
|
#define HM1 "hm1"
|
|
#define HM2 "hm2"
|
|
#define HM3 "hm3"
|
|
|
|
|
|
/* the name of the SICS chopper controller object */
|
|
#define CHOPPERNAME "choco"
|
|
|
|
/*--------- the internal data structure ------------------------------------*/
|
|
typedef struct {
|
|
pObjectDescriptor pDes;
|
|
pHistMem pHistogram1, pHistogram2, pHistogram3;
|
|
int iNew;
|
|
time_t tUpdate;
|
|
int iInterval;
|
|
int iEnd;
|
|
SConnection *pCon;
|
|
pCounter pCount;
|
|
char *pFile;
|
|
char *pDictFile;
|
|
pFit pFitter;
|
|
float fElastic;
|
|
pICallBack pCall;
|
|
int iUpper, iMiddle, iLower;
|
|
/* detector availability flags */
|
|
} FoWrite, *pFoWrite;
|
|
/* ------------------- forward declaration of task function --------------*/
|
|
|
|
static int FoTask(void *pData);
|
|
static void FoUpdate(pFoWrite self, SConnection * pCon);
|
|
|
|
|
|
/*------------------ The Countstart Callback Function ----------------------*/
|
|
static int Countstartcallback(int iEvent, void *pEventData, void *pUser)
|
|
{
|
|
pFoWrite self = NULL;
|
|
|
|
if (iEvent == COUNTSTART) {
|
|
self = (pFoWrite) pUser;
|
|
assert(self);
|
|
self->iNew = 1;
|
|
self->iEnd = 0;
|
|
self->tUpdate = time(NULL);
|
|
self->pCon = (SConnection *) pEventData;
|
|
TaskRegister(pServ->pTasker, FoTask, NULL, NULL, self, 1);
|
|
return 1;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*------------------ The Countend Callback Function ----------------------*/
|
|
static int Countendcallback(int iEvent, void *pEventData, void *pUser)
|
|
{
|
|
pFoWrite self = NULL;
|
|
|
|
if (iEvent == COUNTEND) {
|
|
self = (pFoWrite) pUser;
|
|
assert(self);
|
|
self->tUpdate = time(NULL);
|
|
self->iEnd = 1;
|
|
/*
|
|
FoUpdate(self,self->pCon);
|
|
*/
|
|
return 1;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
static void SNError(void *pData, char *text)
|
|
{
|
|
SConnection *pCon;
|
|
|
|
assert(pData);
|
|
pCon = (SConnection *) pData;
|
|
SCWrite(pCon, text, eError);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static void WriteSelector(NXhandle pFile, NXdict pDict, SConnection * pCon)
|
|
{
|
|
pSicsSelector pSel = NULL;
|
|
char *pName = NULL;
|
|
CommandList *pCom = NULL;
|
|
pDummy pDum = NULL;
|
|
float fTh, fTTH, fB1, fB2;
|
|
int iRet;
|
|
|
|
pCom = FindCommand(pServ->pSics, "mono");
|
|
if (!pCom) {
|
|
SCWrite(pCon, "ERROR: no monochromator found", eError);
|
|
return;
|
|
}
|
|
pSel = (pSicsSelector) pCom->pData;
|
|
if (!pSel) {
|
|
SCWrite(pCon, "ERROR: no monochromator found", eError);
|
|
return;
|
|
}
|
|
pDum = (pDummy) pSel;
|
|
if (strcmp(pDum->pDescriptor->name, "CrystalSelector") != 0) {
|
|
SCWrite(pCon, "ERROR: monochromator is invalid", eError);
|
|
return;
|
|
}
|
|
|
|
NXDputalias(pFile, pDict, "mname", MonoGetType(pSel));
|
|
iRet = GetMonoPositions(pSel, pCon, &fTh, &fTTH, &fB1, &fB2);
|
|
if (!iRet) {
|
|
SCWrite(pCon, "ERROR: Problem reading monochromator positions",
|
|
eError);
|
|
SCWrite(pCon, "ERROR: monochromator data missing in file", eError);
|
|
return;
|
|
}
|
|
NXDputalias(pFile, pDict, "mtheta", &fTh);
|
|
NXDputalias(pFile, pDict, "mttheta", &fTTH);
|
|
SNXSPutDrivable(pServ->pSics, pCon, pFile, pDict, "lambda", "mlambda");
|
|
SNXSPutDrivable(pServ->pSics, pCon, pFile, pDict, "qi", "menergy");
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
static float CalculateElastic(pFoWrite self, SConnection * pCon)
|
|
{
|
|
pIDrivable pDriv;
|
|
pSicsVariable pVar;
|
|
CommandList *pCom = NULL;
|
|
float fLambda, fDist, fResult;
|
|
|
|
pCom = FindCommand(pServ->pSics, "lambda");
|
|
if (!pCom)
|
|
return 0.;
|
|
pDriv = GetDrivableInterface(pCom->pData);
|
|
if (!pDriv)
|
|
return 0.;
|
|
fLambda = pDriv->GetValue(pCom->pData, pCon);
|
|
pVar = FindVariable(pServ->pSics, "sampledist");
|
|
if (!pVar)
|
|
return 0.;
|
|
fDist = pVar->fVal;
|
|
pVar = FindVariable(pServ->pSics, "detectordist");
|
|
if (!pVar)
|
|
return 0.;
|
|
fDist += pVar->fVal;
|
|
fResult = 252.78 * fLambda * (fDist / 1000.);
|
|
return fResult;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
FoStart writes all the fixed data items, creates a new file etc.
|
|
A complete file is obtained after FoStart plus a call to FoUpdate
|
|
*/
|
|
static int FoStart(pFoWrite self, SConnection * pCon)
|
|
{
|
|
NXhandle pFile = NULL;
|
|
NXdict pDict = NULL;
|
|
pSicsVariable var1 = NULL;
|
|
pSicsVariable var2 = NULL;
|
|
int lbank, mbank;
|
|
int iStat, iLength, i;
|
|
char pBueffel[512];
|
|
CounterMode eMode;
|
|
float fVal, *fArray;
|
|
const float *fTime;
|
|
float *fTime2 = NULL;
|
|
char pBuffer[50];
|
|
|
|
/* get a filename */
|
|
if (self->pFile)
|
|
free(self->pFile);
|
|
|
|
self->pFile = SNXMakeFileName(pServ->pSics, pCon);
|
|
if (!self->pFile) {
|
|
SCWrite(pCon, "ERROR: Extra severe: failed to create data file name",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
/* create a Nexus file */
|
|
NXopen(self->pFile, NXACC_CREATE, &pFile);
|
|
if (!pFile) {
|
|
SCWrite(pCon, "ERROR: cannot create data file ", eError);
|
|
return 0;
|
|
}
|
|
|
|
/* tell Uwe User what we are doing */
|
|
sprintf(pBueffel, "Writing %s ......", self->pFile);
|
|
SCWrite(pCon, pBueffel, eWarning);
|
|
|
|
/* write globals */
|
|
SNXSPutGlobals(pFile, self->pFile, "FOCUS", pCon);
|
|
|
|
/* open nxdict and configure nxdict parameters */
|
|
iStat = NXDinitfromfile(self->pDictFile, &pDict);
|
|
if (iStat != NX_OK) {
|
|
sprintf(pBueffel, "ERROR: failed to open dictionary file %s",
|
|
self->pDictFile);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
SCWrite(pCon, "ERROR: Aborting data file writing", eError);
|
|
SCWrite(pCon, "ERROR: This is a SERIOUS problem!", eError);
|
|
SCWrite(pCon, "ERROR: DATA NOT WRITTEN", eError);
|
|
NXclose(&pFile);
|
|
return 0;
|
|
}
|
|
|
|
/* put permanent data */
|
|
SNXSPutVariable(pServ->pSics, pCon, pFile, pDict, "etitle", "title");
|
|
SNXFormatTime(pBueffel, 511);
|
|
|
|
/* entry & instrument stuff */
|
|
NXDputalias(pFile, pDict, "estart", pBueffel);
|
|
SNXSPutVariable(pServ->pSics, pCon, pFile, pDict, "iname", "instrument");
|
|
NXDputalias(pFile, pDict, "sname", "SINQ, PSI, Switzerland");
|
|
NXDputalias(pFile, pDict, "stype", "continous spallation source");
|
|
|
|
/* disk chopper */
|
|
NXDputalias(pFile, pDict, "cname", "Dornier disk chopper");
|
|
|
|
/* be-filter */
|
|
NXDputalias(pFile, pDict, "bname", "BE-filter");
|
|
SNXSPutVariable(pServ->pSics, pCon, pFile, pDict, "bstatus", "bestatus");
|
|
|
|
/* flight path */
|
|
SNXSPutVariable(pServ->pSics, pCon, pFile, pDict, "fltype",
|
|
"flightpath");
|
|
SNXSPutVariable(pServ->pSics, pCon, pFile, pDict, "fllength",
|
|
"flightpathlength");
|
|
|
|
/* monochromator */
|
|
WriteSelector(pFile, pDict, pCon);
|
|
|
|
/* fermi chupper */
|
|
SNXSPutVariable(pServ->pSics, pCon, pFile, pDict, "fcname", "ferminame");
|
|
SNXSPutVariable(pServ->pSics, pCon, pFile, pDict, "fcdist", "fermidist");
|
|
|
|
/* counting data */
|
|
|
|
var2 = FindVariable(pServ->pSics, "mbank");
|
|
if (var2) {
|
|
VarGetInt(var2, &mbank);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: mbank value not found!", eError);
|
|
}
|
|
if (var2) {
|
|
eMode = GetHistCountMode(self->pHistogram2);
|
|
fTime = GetHistTimeBin(self->pHistogram2, &iLength);
|
|
fVal = GetHistPreset(self->pHistogram2);
|
|
} else {
|
|
var1 = FindVariable(pServ->pSics, "lbank");
|
|
if (var1) {
|
|
VarGetInt(var1, &lbank);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: lbank value not found!", eError);
|
|
}
|
|
if (var1) {
|
|
eMode = GetHistCountMode(self->pHistogram1);
|
|
fTime = GetHistTimeBin(self->pHistogram1, &iLength);
|
|
fVal = GetHistPreset(self->pHistogram1);
|
|
} else {
|
|
eMode = GetHistCountMode(self->pHistogram3);
|
|
fTime = GetHistTimeBin(self->pHistogram3, &iLength);
|
|
fVal = GetHistPreset(self->pHistogram3);
|
|
}
|
|
}
|
|
|
|
if (eMode == eTimer) {
|
|
strcpy(pBueffel, "timer");
|
|
} else {
|
|
strcpy(pBueffel, "monitor");
|
|
}
|
|
NXDputalias(pFile, pDict, "cnmode", pBueffel);
|
|
NXDputalias(pFile, pDict, "cnpreset", &fVal);
|
|
|
|
/* detector banks */
|
|
fTime2 = (float *) malloc(iLength * sizeof(float));
|
|
if (fTime2) {
|
|
for (i = 0; i < iLength; i++) {
|
|
fTime2[i] = fTime[i] / 10.;
|
|
}
|
|
sprintf(pBueffel, "%d", iLength);
|
|
NXDupdate(pDict, "timebin", pBueffel);
|
|
if (self->iMiddle) {
|
|
NXDupdate(pDict, "bank", "bank1");
|
|
NXDputalias(pFile, pDict, "dtime", fTime2);
|
|
}
|
|
if (self->iUpper) {
|
|
NXDupdate(pDict, "bank", "upperbank");
|
|
NXDputalias(pFile, pDict, "dtime", fTime2);
|
|
}
|
|
if (self->iLower) {
|
|
NXDupdate(pDict, "bank", "lowerbank");
|
|
NXDputalias(pFile, pDict, "dtime", fTime2);
|
|
}
|
|
if ((self->iLower || self->iUpper) && self->iMiddle) {
|
|
NXDupdate(pDict, "bank", "merged");
|
|
NXDputalias(pFile, pDict, "dtime", fTime2);
|
|
}
|
|
NXDupdate(pDict, "bank", "bank1");
|
|
|
|
|
|
/* calculate theoretical position of elastic peak */
|
|
fVal = CalculateElastic(self, pCon);
|
|
self->fElastic = (fVal - fTime2[0]) / (fTime2[1] - fTime2[0]);
|
|
free(fTime2);
|
|
fTime2 = NULL;
|
|
} else {
|
|
SCWrite(pCon, "ERROR: out of memory while writing time binning",
|
|
eError);
|
|
}
|
|
|
|
SNXSPutVariable(pServ->pSics, pCon, pFile, pDict, "ddist",
|
|
"detectordist");
|
|
|
|
/* theta arrays */
|
|
if (self->iMiddle) {
|
|
NXDupdate(pDict, "bank", "bank1");
|
|
iLength = 150;
|
|
sprintf(pBuffer, "%d", iLength);
|
|
NXDupdate(pDict, "noofdetectors", pBuffer);
|
|
fArray = getFMBankTheta(MIDDLE);
|
|
NXDputalias(pFile, pDict, "dtheta", fArray);
|
|
}
|
|
if (self->iLower) {
|
|
NXDupdate(pDict, "bank", "lowerbank");
|
|
iLength = 115;
|
|
sprintf(pBuffer, "%d", iLength);
|
|
NXDupdate(pDict, "noofdetectors", pBuffer);
|
|
fArray = getFMBankTheta(LOWER);
|
|
NXDputalias(pFile, pDict, "dtheta", fArray);
|
|
}
|
|
if (self->iUpper) {
|
|
NXDupdate(pDict, "bank", "upperbank");
|
|
iLength = 110;
|
|
sprintf(pBuffer, "%d", iLength);
|
|
NXDupdate(pDict, "noofdetectors", pBuffer);
|
|
fArray = getFMBankTheta(UPPER);
|
|
NXDputalias(pFile, pDict, "dtheta", fArray);
|
|
}
|
|
if (self->iMiddle && (self->iLower || self->iUpper)) {
|
|
NXDupdate(pDict, "bank", "merged");
|
|
iLength = 375;
|
|
sprintf(pBuffer, "%d", iLength);
|
|
NXDupdate(pDict, "noofdetectors", pBuffer);
|
|
fArray = getFMBankTheta(MERGED);
|
|
NXDputalias(pFile, pDict, "dtheta", fArray);
|
|
}
|
|
|
|
NXDupdate(pDict, "bank", "bank1");
|
|
SNXSPutVariable(pServ->pSics, pCon, pFile, pDict, "ddelay", "delay");
|
|
|
|
|
|
/* sample info */
|
|
SNXSPutVariable(pServ->pSics, pCon, pFile, pDict, "saname", "sample");
|
|
SNXSPutVariable(pServ->pSics, pCon, pFile, pDict, "senvir",
|
|
"environment");
|
|
SNXSPutVariable(pServ->pSics, pCon, pFile, pDict, "sdist", "sampledist");
|
|
SNXSPutVariable(pServ->pSics, pCon, pFile, pDict, "saangle",
|
|
"sampleangle");
|
|
|
|
/* close everything */
|
|
NXclose(&pFile);
|
|
NXDclose(pDict, NULL);
|
|
return 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
static void FoUpdate(pFoWrite self, SConnection * pCon)
|
|
{
|
|
char pBueffel[512];
|
|
int iInt, iStat, iTime, i, ii, j, iDet, iIndex;
|
|
pSicsVariable var1 = NULL;
|
|
pSicsVariable var2 = NULL;
|
|
pSicsVariable var3 = NULL;
|
|
int lbank, mbank, ubank;
|
|
long lVal;
|
|
float fVal;
|
|
const float *fTime;
|
|
NXhandle pFile = NULL;
|
|
NXdict pDict;
|
|
HistInt *lData = NULL;
|
|
HistInt *mData = NULL;
|
|
HistInt *uData = NULL;
|
|
int *iSum = NULL;
|
|
float *fAxis = NULL;
|
|
long *lSum = NULL;
|
|
float fCenter, fStdDev, fFWHM;
|
|
|
|
/* open everything again */
|
|
NXopen(self->pFile, NXACC_RDWR, &pFile);
|
|
if (!pFile) {
|
|
SCWrite(pCon, "ERROR: cannot reopen data file ", eError);
|
|
return;
|
|
}
|
|
iStat = NXDinitfromfile(self->pDictFile, &pDict);
|
|
if (iStat != NX_OK) {
|
|
sprintf(pBueffel, "ERROR: failed to open dictionary file %s",
|
|
self->pDictFile);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
SCWrite(pCon, "ERROR: Aborting data file writing", eError);
|
|
SCWrite(pCon, "ERROR: This is a SERIOUS problem!", eError);
|
|
SCWrite(pCon, "ERROR: DATA NOT WRITTEN", eError);
|
|
NXclose(&pFile);
|
|
return;
|
|
}
|
|
|
|
/* tell the user that something is happening */
|
|
sprintf(pBueffel, "Updating %s", self->pFile);
|
|
SCWrite(pCon, pBueffel, eWarning);
|
|
|
|
/* do the end time */
|
|
SNXFormatTime(pBueffel, 511);
|
|
NXDputalias(pFile, pDict, "eend", pBueffel);
|
|
|
|
/* chopper speeds */
|
|
SNXSPutDrivable(pServ->pSics, pCon, pFile, pDict, "diskspeed", "crot");
|
|
SNXSPutDrivable(pServ->pSics, pCon, pFile, pDict, "fermispeed", "fcrot");
|
|
SNXSPutDrivable(pServ->pSics, pCon, pFile, pDict, "phase", "fcphase");
|
|
SNXSPutDrivable(pServ->pSics, pCon, pFile, pDict, "ratio", "cratio");
|
|
|
|
/* counter data */
|
|
var2 = FindVariable(pServ->pSics, "mbank");
|
|
if (var2) {
|
|
VarGetInt(var2, &mbank);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: mbank value not found!", eError);
|
|
}
|
|
if (var2) {
|
|
fVal = GetHistCountTime(self->pHistogram2, pCon);
|
|
NXDputalias(pFile, pDict, "cntime", &fVal);
|
|
lVal = GetHistMonitor(self->pHistogram2, 1, pCon);
|
|
NXDputalias(pFile, pDict, "cnmon1", &lVal);
|
|
lVal = GetHistMonitor(self->pHistogram2, 0, pCon);
|
|
NXDputalias(pFile, pDict, "cnmon2", &lVal);
|
|
lVal = GetHistMonitor(self->pHistogram2, 4, pCon);
|
|
NXDputalias(pFile, pDict, "cnmon3", &lVal);
|
|
fTime = GetHistTimeBin(self->pHistogram2, &iInt);
|
|
} else {
|
|
var1 = FindVariable(pServ->pSics, "lbank");
|
|
if (var1) {
|
|
VarGetInt(var1, &lbank);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: lbank value not found!", eError);
|
|
}
|
|
if (var1) {
|
|
fVal = GetHistCountTime(self->pHistogram1, pCon);
|
|
NXDputalias(pFile, pDict, "cntime", &fVal);
|
|
lVal = GetHistMonitor(self->pHistogram1, 1, pCon);
|
|
NXDputalias(pFile, pDict, "cnmon1", &lVal);
|
|
lVal = GetHistMonitor(self->pHistogram1, 0, pCon);
|
|
NXDputalias(pFile, pDict, "cnmon2", &lVal);
|
|
lVal = GetHistMonitor(self->pHistogram1, 4, pCon);
|
|
NXDputalias(pFile, pDict, "cnmon3", &lVal);
|
|
fTime = GetHistTimeBin(self->pHistogram1, &iInt);
|
|
} else {
|
|
fVal = GetHistCountTime(self->pHistogram3, pCon);
|
|
NXDputalias(pFile, pDict, "cntime", &fVal);
|
|
lVal = GetHistMonitor(self->pHistogram3, 1, pCon);
|
|
NXDputalias(pFile, pDict, "cnmon1", &lVal);
|
|
lVal = GetHistMonitor(self->pHistogram3, 0, pCon);
|
|
NXDputalias(pFile, pDict, "cnmon2", &lVal);
|
|
lVal = GetHistMonitor(self->pHistogram3, 4, pCon);
|
|
NXDputalias(pFile, pDict, "cnmon3", &lVal);
|
|
fTime = GetHistTimeBin(self->pHistogram3, &iInt);
|
|
}
|
|
}
|
|
|
|
/* histogram with three detector banks */
|
|
iTime = iInt;
|
|
sprintf(pBueffel, "%d", iInt);
|
|
NXDupdate(pDict, "timebin", pBueffel);
|
|
var1 = FindVariable(pServ->pSics, "lbank");
|
|
if (var1) {
|
|
VarGetInt(var1, &lbank);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: lbank value not found!", eError);
|
|
}
|
|
if (lbank == 1) {
|
|
lData = GetHistogramPointer(self->pHistogram1, pCon);
|
|
if (!lData) {
|
|
SCWrite(pCon,
|
|
"ERROR: failed to find Histogram Memory Data (lower bank)",
|
|
eError);
|
|
NXclose(&pFile);
|
|
NXDclose(pDict, NULL);
|
|
return;
|
|
}
|
|
}
|
|
if (mbank == 1) {
|
|
mData = GetHistogramPointer(self->pHistogram2, pCon);
|
|
if (!mData) {
|
|
SCWrite(pCon,
|
|
"ERROR: failed to find Histogram Memory Data (middle bank)",
|
|
eError);
|
|
NXclose(&pFile);
|
|
NXDclose(pDict, NULL);
|
|
return;
|
|
}
|
|
}
|
|
var3 = FindVariable(pServ->pSics, "ubank");
|
|
if (var3) {
|
|
VarGetInt(var3, &ubank);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: ubank value not found!", eError);
|
|
}
|
|
if (ubank == 1) {
|
|
uData = GetHistogramPointer(self->pHistogram3, pCon);
|
|
if (!uData) {
|
|
SCWrite(pCon,
|
|
"ERROR: failed to find Histogram Memory Data (upper bank)",
|
|
eError);
|
|
NXclose(&pFile);
|
|
NXDclose(pDict, NULL);
|
|
return;
|
|
}
|
|
}
|
|
setFMDataPointer(lData, iTime, LOWER);
|
|
setFMDataPointer(mData, iTime, MIDDLE);
|
|
setFMDataPointer(uData, iTime, UPPER);
|
|
/* middle bank */
|
|
if (self->iMiddle) {
|
|
NXDupdate(pDict, "bank", "bank1");
|
|
iDet = 150;
|
|
sprintf(pBueffel, "%d", iDet);
|
|
NXDupdate(pDict, "noofdetectors", pBueffel);
|
|
mData = getFMBankPointer(MIDDLE);
|
|
NXDputalias(pFile, pDict, "dcounts", mData);
|
|
/* summed counts for each detector */
|
|
iSum = (int *) malloc(iDet * sizeof(int));
|
|
if (iSum) {
|
|
memset(iSum, 0, iDet * sizeof(int));
|
|
for (i = 0; i < iDet; i++) {
|
|
iIndex = i * iTime;
|
|
for (j = 0; j < iTime; j++) {
|
|
iSum[i] += mData[iIndex + j];
|
|
}
|
|
}
|
|
NXDputalias(pFile, pDict, "dsums", iSum);
|
|
free(iSum);
|
|
} else {
|
|
SCWrite(pCon, "WARNING: out of memory, failed to do sums", eWarning);
|
|
}
|
|
}
|
|
if (self->iUpper) {
|
|
NXDupdate(pDict, "bank", "upperbank");
|
|
iDet = 110;
|
|
sprintf(pBueffel, "%d", iDet);
|
|
NXDupdate(pDict, "noofdetectors", pBueffel);
|
|
uData = getFMBankPointer(UPPER);
|
|
NXDputalias(pFile, pDict, "dcounts", uData);
|
|
/* summed counts for each detector */
|
|
iSum = (int *) malloc(iDet * sizeof(int));
|
|
if (iSum) {
|
|
memset(iSum, 0, iDet * sizeof(int));
|
|
for (i = 0; i < iDet; i++) {
|
|
iIndex = i * iTime;
|
|
for (j = 0; j < iTime; j++) {
|
|
iSum[i] += uData[iIndex + j];
|
|
}
|
|
}
|
|
NXDputalias(pFile, pDict, "dsums", iSum);
|
|
free(iSum);
|
|
} else {
|
|
SCWrite(pCon, "WARNING: out of memory, failed to do sums", eWarning);
|
|
}
|
|
}
|
|
if (self->iLower) {
|
|
NXDupdate(pDict, "bank", "lowerbank");
|
|
iDet = 115;
|
|
sprintf(pBueffel, "%d", iDet);
|
|
NXDupdate(pDict, "noofdetectors", pBueffel);
|
|
lData = getFMBankPointer(LOWER);
|
|
NXDputalias(pFile, pDict, "dcounts", lData);
|
|
/* summed counts for each detector */
|
|
iSum = (int *) malloc(iDet * sizeof(int));
|
|
if (iSum) {
|
|
memset(iSum, 0, iDet * sizeof(int));
|
|
for (i = 0; i < iDet; i++) {
|
|
iIndex = i * iTime;
|
|
for (j = 0; j < iTime; j++) {
|
|
iSum[i] += lData[iIndex + j];
|
|
}
|
|
}
|
|
NXDputalias(pFile, pDict, "dsums", iSum);
|
|
free(iSum);
|
|
} else {
|
|
SCWrite(pCon, "WARNING: out of memory, failed to do sums", eWarning);
|
|
}
|
|
/*
|
|
now get and write tof_monitor
|
|
*/
|
|
|
|
lData = (HistInt *) malloc(iTime * sizeof(HistInt));
|
|
if (!lData) {
|
|
SCWrite(pCon, "ERROR: out of memory while writing tof-monitor",
|
|
eError);
|
|
} else {
|
|
memset(lData, 0, iTime * sizeof(HistInt));
|
|
GetHistogramDirect(self->pHistogram1, pCon, 0, 115 * iTime,
|
|
116 * iTime, lData, iTime * sizeof(HistInt));
|
|
NXDputalias(pFile, pDict, "tofmon", lData);
|
|
}
|
|
}
|
|
/* merged data */
|
|
if ((self->iUpper || self->iLower) && self->iMiddle) {
|
|
NXDupdate(pDict, "bank", "merged");
|
|
iDet = 375;
|
|
sprintf(pBueffel, "%d", iDet);
|
|
NXDupdate(pDict, "noofdetectors", pBueffel);
|
|
lData = getFMBankPointer(MERGED);
|
|
NXDputalias(pFile, pDict, "dcounts", lData);
|
|
/* summed counts for each detector */
|
|
iSum = (int *) malloc(iDet * sizeof(int));
|
|
if (iSum) {
|
|
memset(iSum, 0, iDet * sizeof(int));
|
|
for (i = 0; i < iDet; i++) {
|
|
iIndex = i * iTime;
|
|
for (j = 0; j < iTime; j++) {
|
|
iSum[i] += lData[iIndex + j];
|
|
}
|
|
}
|
|
NXDputalias(pFile, pDict, "dsums", iSum);
|
|
free(iSum);
|
|
} else {
|
|
SCWrite(pCon, "WARNING: out of memory, failed to do sums", eWarning);
|
|
}
|
|
}
|
|
|
|
|
|
/* calculate elastic peak position */
|
|
NXDupdate(pDict, "bank", "bank1");
|
|
mData = getFMBankPointer(MIDDLE);
|
|
iDet = getFMdim(MIDDLE);
|
|
if (mData) {
|
|
lSum = (long *) malloc(iTime * sizeof(long));
|
|
fAxis = (float *) malloc(iTime * sizeof(float));
|
|
if (lSum && fAxis) {
|
|
memset(lSum, 0, iTime * sizeof(long));
|
|
memset(fAxis, 0, iTime * sizeof(float));
|
|
for (i = 5; i < iDet - 5; i++) {
|
|
iIndex = i * iTime;
|
|
for (j = 0; j < iTime; j++) {
|
|
lSum[j] += mData[iIndex + j];
|
|
}
|
|
}
|
|
for (i = 0; i < iTime; i++) {
|
|
fAxis[i] = (float) i;
|
|
}
|
|
iStat = CalculateFitFromData(self->pFitter, fAxis, lSum, iTime);
|
|
GetFitResults(self->pFitter, &fCenter, &fStdDev, &fFWHM, &fVal);
|
|
fVal = fCenter - self->fElastic;
|
|
if (fVal < 0.)
|
|
fVal = -fVal;
|
|
/* bad value, leave at theoretical value */
|
|
if (fVal < 10.) {
|
|
self->fElastic = fCenter;
|
|
}
|
|
free(lSum);
|
|
free(fAxis);
|
|
} else {
|
|
SCWrite(pCon, "WARNING: out of memory, failed to do sums", eWarning);
|
|
}
|
|
}
|
|
sprintf(pBueffel, "Elastic peak found at detector: %f", self->fElastic);
|
|
SCWrite(pCon, pBueffel, eWarning);
|
|
NXDputalias(pFile, pDict, "delastic", &self->fElastic);
|
|
|
|
|
|
/* sample temperature */
|
|
SNXSPutEVVar(pFile, pDict, "temperature", pCon, "stemp", NULL);
|
|
|
|
|
|
/* close everything */
|
|
NXclose(&pFile);
|
|
NXDclose(pDict, NULL);
|
|
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
FoLink sets all the links for the NXdata vGroup. Had to be separate because
|
|
at least one update is necessary before this can be done.
|
|
*/
|
|
static void FoLink(pFoWrite self, SConnection * pCon)
|
|
{
|
|
NXhandle pFile;
|
|
NXdict pDict;
|
|
int iStat;
|
|
char pBueffel[512];
|
|
|
|
/* open everything again */
|
|
NXopen(self->pFile, NXACC_RDWR, &pFile);
|
|
if (!pFile) {
|
|
SCWrite(pCon, "ERROR: cannot reopen data file ", eError);
|
|
return;
|
|
}
|
|
iStat = NXDinitfromfile(self->pDictFile, &pDict);
|
|
if (iStat != NX_OK) {
|
|
sprintf(pBueffel, "ERROR: failed to open dictionary file %s",
|
|
self->pDictFile);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
SCWrite(pCon, "ERROR: Aborting data file writing", eError);
|
|
SCWrite(pCon, "ERROR: This is a SERIOUS problem!", eError);
|
|
SCWrite(pCon, "ERROR: DATA NOT WRITTEN", eError);
|
|
NXclose(&pFile);
|
|
return;
|
|
}
|
|
|
|
if ((self->iUpper || self->iLower) && self->iMiddle) {
|
|
NXDupdate(pDict, "bank", "merged");
|
|
NXDaliaslink(pFile, pDict, "dana", "dcounts");
|
|
NXDaliaslink(pFile, pDict, "dana", "dtime");
|
|
NXDaliaslink(pFile, pDict, "dana", "dtheta");
|
|
NXDaliaslink(pFile, pDict, "dana", "cnmon1");
|
|
}
|
|
|
|
if (self->iUpper) {
|
|
NXDupdate(pDict, "bank", "upperbank");
|
|
NXDaliaslink(pFile, pDict, "dana", "dcounts");
|
|
NXDaliaslink(pFile, pDict, "dana", "dtime");
|
|
NXDaliaslink(pFile, pDict, "dana", "dtheta");
|
|
NXDaliaslink(pFile, pDict, "dana", "cnmon1");
|
|
}
|
|
if (self->iMiddle) {
|
|
NXDupdate(pDict, "bank", "bank1");
|
|
NXDaliaslink(pFile, pDict, "dana", "dcounts");
|
|
NXDaliaslink(pFile, pDict, "dana", "dtime");
|
|
NXDaliaslink(pFile, pDict, "dana", "dtheta");
|
|
NXDaliaslink(pFile, pDict, "dana", "cnmon1");
|
|
}
|
|
if (self->iLower) {
|
|
NXDupdate(pDict, "bank", "lowerbank");
|
|
NXDaliaslink(pFile, pDict, "dana", "dcounts");
|
|
NXDaliaslink(pFile, pDict, "dana", "dtime");
|
|
NXDaliaslink(pFile, pDict, "dana", "dtheta");
|
|
NXDaliaslink(pFile, pDict, "dana", "cnmon1");
|
|
}
|
|
|
|
|
|
/* close everything */
|
|
NXclose(&pFile);
|
|
NXDclose(pDict, NULL);
|
|
self->iNew = 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
This is the task function for updating the data file any now and then
|
|
automatically
|
|
*/
|
|
static int FoTask(void *pData)
|
|
{
|
|
pFoWrite self = NULL;
|
|
int iWrite, iRet;
|
|
|
|
self = (pFoWrite) pData;
|
|
if (!self)
|
|
return 0;
|
|
|
|
/* figure out if we need to write */
|
|
iWrite = 0;
|
|
iRet = 1;
|
|
/* first case: update intervall */
|
|
if (time(NULL) >= self->tUpdate) {
|
|
self->tUpdate = time(NULL) + self->iInterval;
|
|
iWrite = 1;
|
|
iRet = 1;
|
|
}
|
|
if (self->iEnd) {
|
|
self->tUpdate = 0;
|
|
iWrite = 0;
|
|
iRet = 0;
|
|
FoUpdate(self, self->pCon);
|
|
}
|
|
|
|
if (iWrite) {
|
|
if (self->iNew) {
|
|
FoStart(self, self->pCon);
|
|
FoUpdate(self, self->pCon);
|
|
FoLink(self, self->pCon);
|
|
} else {
|
|
FoUpdate(self, self->pCon);
|
|
}
|
|
}
|
|
return iRet;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static void KillFoWrite(void *pData)
|
|
{
|
|
pFoWrite self = NULL;
|
|
|
|
self = (pFoWrite) pData;
|
|
if (!self)
|
|
return;
|
|
|
|
if (self->pDes)
|
|
DeleteDescriptor(self->pDes);
|
|
|
|
if (self->pDictFile)
|
|
free(self->pDictFile);
|
|
|
|
if (self->pFile)
|
|
free(self->pFile);
|
|
|
|
if (self->pFitter)
|
|
DeleteFitCenter(self->pFitter);
|
|
|
|
/* free fomerge */
|
|
killFM();
|
|
|
|
free(self);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
int FoInstall(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
CommandList *pCom = NULL;
|
|
char pBueffel[512];
|
|
pFoWrite pNew = NULL;
|
|
pICallBack pCall = NULL;
|
|
pDummy pDum;
|
|
pHMcontrol pHMC = NULL;
|
|
commandContext comCon;
|
|
|
|
/* check arguments */
|
|
if (argc < 4) {
|
|
SCWrite(pCon, "ERROR: Insufficient number of arguments to FoInstall",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
/* allocate data structure */
|
|
pNew = (pFoWrite) malloc(sizeof(FoWrite));
|
|
if (!pNew) {
|
|
SCWrite(pCon, "ERROR: out of memory in FoInstall", eError);
|
|
return 0;
|
|
}
|
|
memset(pNew, 0, sizeof(FoWrite));
|
|
pNew->pDes = CreateDescriptor("FocusWrite");
|
|
pNew->pCall = CreateCallBackInterface();
|
|
pNew->pFitter = CreateFitCenter(NULL);
|
|
if ((!pNew->pDes) || (!pNew->pFitter)) {
|
|
SCWrite(pCon, "ERROR: out of memory in FoInstall", eError);
|
|
free(pNew);
|
|
return 0;
|
|
}
|
|
pNew->pDictFile = strdup(argv[2]);
|
|
pNew->iInterval = 20 * 60;
|
|
|
|
pHMC = FindCommandData(pSics, argv[1], "HMcontrol");
|
|
if (!pHMC) {
|
|
SCWrite(pCon, "ERROR: no histogram memory control found!", eError);
|
|
free(pNew);
|
|
return 0;
|
|
}
|
|
|
|
/* find things in interpreter */
|
|
pCom = FindCommand(pSics, "hm1");
|
|
if (!pCom) {
|
|
SCWrite(pCon,
|
|
"ERROR: Histogram memory for lower detector bank NOT found",
|
|
eError);
|
|
pNew->pHistogram1 = NULL;
|
|
} else {
|
|
pNew->pHistogram1 = (pHistMem) pCom->pData;
|
|
pNew->iLower = 1;
|
|
}
|
|
|
|
|
|
pCom = FindCommand(pSics, HM2);
|
|
if (pCom) {
|
|
pNew->pHistogram2 = (pHistMem) pCom->pData;
|
|
pNew->iMiddle = 1;
|
|
} else {
|
|
SCWrite(pCon,
|
|
"ERROR: Histogram memory for middle detector bank NOT found",
|
|
eError);
|
|
pNew->pHistogram2 = NULL;
|
|
}
|
|
|
|
pCom = FindCommand(pSics, HM3);
|
|
if (pCom) {
|
|
pNew->pHistogram3 = (pHistMem) pCom->pData;
|
|
pNew->iUpper = 1;
|
|
} else {
|
|
SCWrite(pCon,
|
|
"ERROR: Histogram memory for upper detector bank NOT found",
|
|
eError);
|
|
pNew->pHistogram3 = NULL;
|
|
}
|
|
|
|
if (!initializeFM(argv[3])) {
|
|
SCWrite(pCon, "ERROR: bad merge data file", eError);
|
|
return 0;
|
|
}
|
|
|
|
pCom = FindCommand(pSics, "counter");
|
|
if (pCom) {
|
|
pNew->pCount = (pCounter) pCom->pData;
|
|
}
|
|
|
|
comCon.transID = 0;
|
|
strncpy(comCon.deviceID, "internal", SCDEVIDLEN);
|
|
RegisterCallback(pHMC->pCall, COUNTSTART, Countstartcallback, pNew,
|
|
NULL);
|
|
RegisterCallback(pHMC->pCall, COUNTEND, Countendcallback, pNew, NULL);
|
|
|
|
/* install command */
|
|
AddCommand(pSics, "StoreFocus", FoAction, KillFoWrite, pNew);
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int FoAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
int iRet, iVal;
|
|
pFoWrite self = NULL;
|
|
char pBueffel[512];
|
|
|
|
if (argc < 1) {
|
|
SCWrite(pCon, "ERROR: Insufficient number of arguments to StoreFocus",
|
|
eError);
|
|
return 0;
|
|
}
|
|
self = (pFoWrite) pData;
|
|
assert(self);
|
|
|
|
strtolower(argv[1]);
|
|
if (strcmp(argv[1], "start") == 0) {
|
|
FoStart(self, pCon);
|
|
FoUpdate(self, pCon);
|
|
FoLink(self, pCon);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "update") == 0) {
|
|
if ((self->iNew) || (!self->pFile)) {
|
|
FoStart(self, pCon);
|
|
FoUpdate(self, pCon);
|
|
FoLink(self, pCon);
|
|
} else {
|
|
FoUpdate(self, pCon);
|
|
}
|
|
return 1;
|
|
} else if (strcmp(argv[1], "getfile") == 0) {
|
|
sprintf(pBueffel, "storefocus.file = %s", self->pFile);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "interval") == 0) {
|
|
if (argc > 2) { /* set value */
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[2], &iVal);
|
|
if (iRet != TCL_OK) {
|
|
sprintf(pBueffel, "ERROR: cannot convert --> %s <-- to number ",
|
|
argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
self->iInterval = iVal * 60; /* go to seconds from minutes */
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else { /* read the value */
|
|
|
|
sprintf(pBueffel, "storefocus.interval = %d", self->iInterval / 60);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "middle") == 0) {
|
|
if (argc > 2) { /* set value */
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[2], &iVal);
|
|
if (iRet != TCL_OK) {
|
|
sprintf(pBueffel, "ERROR: cannot convert --> %s <-- to number ",
|
|
argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
if (iVal < 0)
|
|
iVal = 0;
|
|
self->iMiddle = iVal;
|
|
setFMconfiguration(self->iUpper, self->iMiddle, self->iLower);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else { /* read the value */
|
|
|
|
sprintf(pBueffel, "storefocus.middle = %d", self->iMiddle);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "lower") == 0) {
|
|
if (argc > 2) { /* set value */
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[2], &iVal);
|
|
if (iRet != TCL_OK) {
|
|
sprintf(pBueffel, "ERROR: cannot convert --> %s <-- to number ",
|
|
argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
if (iVal < 0)
|
|
iVal = 0;
|
|
self->iLower = iVal;
|
|
setFMconfiguration(self->iUpper, self->iMiddle, self->iLower);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else { /* read the value */
|
|
|
|
sprintf(pBueffel, "storefocus.lower = %d", self->iLower);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "upper") == 0) {
|
|
if (argc > 2) { /* set value */
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[2], &iVal);
|
|
if (iRet != TCL_OK) {
|
|
sprintf(pBueffel, "ERROR: cannot convert --> %s <-- to number ",
|
|
argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
if (iVal < 0)
|
|
iVal = 0;
|
|
self->iUpper = iVal;
|
|
setFMconfiguration(self->iUpper, self->iMiddle, self->iLower);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else { /* read the value */
|
|
|
|
sprintf(pBueffel, "storefocus.upper = %d", self->iUpper);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
}
|
|
SCWrite(pCon, "ERROR: subcommand to storefocus not recognized", eError);
|
|
return 0;
|
|
}
|