- A couple of TAS fixes - o2t was fixed to work with any drivable - FOCUS was mended to include beam monitor in data file
1007 lines
30 KiB
C
1007 lines
30 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 "fomerge.h"
|
|
|
|
/* the name of the SICS chopper controller object */
|
|
#define CHOPPERNAME "choco"
|
|
|
|
/*--------- the internal data structure ------------------------------------*/
|
|
typedef struct {
|
|
pObjectDescriptor pDes;
|
|
pHistMem pHist;
|
|
int iNew;
|
|
time_t tUpdate;
|
|
int iInterval;
|
|
int iEnd;
|
|
SConnection *pCon;
|
|
char *pFile;
|
|
char *pDictFile;
|
|
pFit pFitter;
|
|
float fElastic;
|
|
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;
|
|
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 */
|
|
eMode = GetHistCountMode(self->pHist);
|
|
if(eMode == eTimer)
|
|
{
|
|
strcpy(pBueffel,"timer");
|
|
}
|
|
else
|
|
{
|
|
strcpy(pBueffel,"monitor");
|
|
}
|
|
NXDputalias(pFile,pDict,"cnmode",pBueffel);
|
|
fVal = GetHistPreset(self->pHist);
|
|
NXDputalias(pFile,pDict,"cnpreset",&fVal);
|
|
|
|
|
|
/* detector banks */
|
|
fTime = GetHistTimeBin(self->pHist,&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(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 = getFMdim(MIDDLE);
|
|
sprintf(pBuffer,"%d",iLength);
|
|
NXDupdate(pDict,"noofdetectors",pBuffer);
|
|
fArray = getFMBankTheta(MIDDLE);
|
|
NXDputalias(pFile,pDict,"dtheta",fArray);
|
|
}
|
|
if(self->iLower)
|
|
{
|
|
NXDupdate(pDict,"bank","lowerbank");
|
|
iLength = getFMdim(LOWER);
|
|
sprintf(pBuffer,"%d",iLength);
|
|
NXDupdate(pDict,"noofdetectors",pBuffer);
|
|
fArray = getFMBankTheta(LOWER);
|
|
NXDputalias(pFile,pDict,"dtheta",fArray);
|
|
}
|
|
if(self->iUpper)
|
|
{
|
|
NXDupdate(pDict,"bank","upperbank");
|
|
iLength = getFMdim(UPPER);
|
|
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 = getFMdim(MERGED);
|
|
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);
|
|
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void FoUpdate(pFoWrite self, SConnection *pCon)
|
|
{
|
|
char pBueffel[512];
|
|
int iInt, iStat, iTime, i, j, iDet, iIndex;
|
|
long lVal;
|
|
float fVal;
|
|
const float *fTime;
|
|
NXhandle pFile = NULL;
|
|
NXdict pDict;
|
|
HistInt *lData = 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 */
|
|
fVal = GetHistCountTime(self->pHist,pCon);
|
|
NXDputalias(pFile,pDict,"cntime",&fVal);
|
|
lVal = GetHistMonitor(self->pHist,1,pCon);
|
|
NXDputalias(pFile,pDict,"cnmon1",&lVal);
|
|
lVal = GetHistMonitor(self->pHist,0,pCon);
|
|
NXDputalias(pFile,pDict,"cnmon2",&lVal);
|
|
lVal = GetHistMonitor(self->pHist,4,pCon);
|
|
NXDputalias(pFile,pDict,"cnmon3",&lVal);
|
|
|
|
|
|
/* histogram with three detector banks */
|
|
fTime = GetHistTimeBin(self->pHist,&iInt);
|
|
iTime = iInt;
|
|
sprintf(pBueffel,"%d",iInt);
|
|
NXDupdate(pDict,"timebin",pBueffel);
|
|
lData = GetHistogramPointer(self->pHist,pCon);
|
|
if(!lData)
|
|
{
|
|
SCWrite(pCon,"ERROR: failed to find Histogram Memory Data",eError);
|
|
NXclose(&pFile);
|
|
NXDclose(pDict,NULL);
|
|
return;
|
|
}
|
|
setFMDataPointer(lData,iTime);
|
|
if(self->iUpper)
|
|
{
|
|
NXDupdate(pDict,"bank","upperbank");
|
|
iDet = getFMdim(UPPER);
|
|
sprintf(pBueffel,"%d",iDet);
|
|
NXDupdate(pDict,"noofdetectors",pBueffel);
|
|
lData = getFMBankPointer(UPPER);
|
|
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);
|
|
}
|
|
}
|
|
/* middle bank */
|
|
if(self->iMiddle)
|
|
{
|
|
NXDupdate(pDict,"bank","bank1");
|
|
iDet = getFMdim(MIDDLE);
|
|
sprintf(pBueffel,"%d",iDet);
|
|
NXDupdate(pDict,"noofdetectors",pBueffel);
|
|
lData = getFMBankPointer(MIDDLE);
|
|
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);
|
|
}
|
|
}
|
|
if(self->iLower)
|
|
{
|
|
NXDupdate(pDict,"bank","lowerbank");
|
|
iDet = getFMdim(LOWER);
|
|
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);
|
|
}
|
|
}
|
|
/* merged data */
|
|
if( (self->iUpper || self->iLower) && self->iMiddle)
|
|
{
|
|
NXDupdate(pDict,"bank","merged");
|
|
iDet = getFMdim(MERGED);
|
|
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");
|
|
lData = getFMBankPointer(MIDDLE);
|
|
if(lData)
|
|
{
|
|
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] += lData[iIndex+j];
|
|
}
|
|
}
|
|
for(i = 0; i < iTime; i++)
|
|
{
|
|
fAxis[i] = (float)i;
|
|
}
|
|
iStat = CalculateFitFromData(self->pFitter,fAxis,lSum,iTime);
|
|
if(iStat != 1)
|
|
{
|
|
SCWrite(pCon,"WARNING: problem locating elastic peak",eWarning);
|
|
}
|
|
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.)
|
|
{
|
|
SCWrite(pCon,
|
|
"WARNING: bad fit result, using theoretical elastic peak position",
|
|
eWarning);
|
|
}
|
|
else
|
|
{
|
|
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;
|
|
}
|
|
|
|
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[])
|
|
{
|
|
|
|
pHistMem pHist= NULL;
|
|
char pBueffel[512];
|
|
pFoWrite pNew = NULL;
|
|
pICallBack pCall = NULL;
|
|
pDummy pDum;
|
|
|
|
/* check arguments */
|
|
if(argc < 4 )
|
|
{
|
|
SCWrite(pCon,"ERROR: Insufficient number of arguments to FoInstall",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
pHist = (pHistMem)FindCommandData(pSics,argv[1],"HistMem");
|
|
if(!pHist)
|
|
{
|
|
SCWrite(pCon,"ERROR: Histogram memory NOT found",eError);
|
|
return 0;
|
|
}
|
|
|
|
if(!initializeFM(argv[3]))
|
|
{
|
|
SCWrite(pCon,"ERROR: bad merge data file",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->pFitter = CreateFitCenter(NULL);
|
|
if( (!pNew->pDes) || (!pNew->pFitter) )
|
|
{
|
|
SCWrite(pCon,"ERROR: out of memory in FoInstall",eError);
|
|
return 0;
|
|
}
|
|
pNew->pHist = pHist;
|
|
pNew->pDictFile = strdup(argv[2]);
|
|
pNew->iInterval = 20*60;
|
|
pNew->iMiddle =1;
|
|
|
|
/* install callbacks */
|
|
pDum = (pDummy)pHist;
|
|
pCall = (pICallBack)pDum->pDescriptor->GetInterface(pHist,
|
|
CALLBACKINTERFACE);
|
|
if(!pCall)
|
|
{
|
|
SCWrite(pCon,
|
|
"ERROR: no callback interface found at your histogram memory",
|
|
eError);
|
|
KillFoWrite(pNew);
|
|
return 0;
|
|
}
|
|
RegisterCallback(pCall,COUNTSTART,Countstartcallback,pNew,NULL);
|
|
RegisterCallback(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;
|
|
}
|