841 lines
24 KiB
C
841 lines
24 KiB
C
/*--------------------------------------------------------------------------
|
|
P O L T E R W R I T E
|
|
|
|
Polterwrite is an object for writing POLTI data files.
|
|
|
|
copyright: see copyright.h
|
|
|
|
Uwe Filges, November 2001
|
|
|
|
Various edits, added rotation_speed_targets, Mark Koennecke, 2011
|
|
----------------------------------------------------------------------------*/
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
#include <tcl.h>
|
|
#undef VOID
|
|
#include "sics.h"
|
|
#include "event.h"
|
|
#include "counter.h"
|
|
#include "HistMem.h"
|
|
#include "nxdict.h"
|
|
#include "nxutil.h"
|
|
#include "motor.h"
|
|
#include "sicsvar.h"
|
|
#include "polterwrite.h"
|
|
#include "sicsvar.h"
|
|
#include "nxscript.h"
|
|
#include "sicshipadaba.h"
|
|
|
|
/*
|
|
diaphragm1 - chopper
|
|
*/
|
|
#define DIA1DIST 8000
|
|
|
|
/*
|
|
histogram memory name
|
|
*/
|
|
#define HM "hm"
|
|
|
|
#define DETRADIUS 3000
|
|
|
|
typedef struct {
|
|
pObjectDescriptor pDes;
|
|
pHistMem pHist;
|
|
int iNew;
|
|
time_t tUpdate;
|
|
int iInterval;
|
|
int iEnd;
|
|
SConnection *pCon;
|
|
char *dictfile;
|
|
char *pFile;
|
|
} Polterdi, *pPolterdi;
|
|
|
|
|
|
/* ------------------- forward declaration of task function --------------*/
|
|
static int PoldiTask(void *pData);
|
|
static void PoldiUpdate(pPolterdi self, SConnection * pCon);
|
|
static void PoldiStart(pPolterdi s, SConnection * pCon);
|
|
static void PoldiLink(pPolterdi s, SConnection * pCon);
|
|
|
|
/*------------------ The Countstart Callback Function ----------------------*/
|
|
static int Countstartcallback(int iEvent, void *pEventData, void *pUser)
|
|
{
|
|
pPolterdi self = NULL;
|
|
|
|
if (iEvent == COUNTSTART) {
|
|
self = (pPolterdi) pUser;
|
|
assert(self);
|
|
self->iNew = 1;
|
|
self->iEnd = 0;
|
|
self->tUpdate = time(NULL);
|
|
self->pCon = (SConnection *) pEventData;
|
|
TaskRegisterN(pServ->pTasker,"POLDIUpdater", PoldiTask, NULL, NULL, self, TASK_PRIO_LOW);
|
|
return 1;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*------------------ The Countend Callback Function ----------------------*/
|
|
static int Countendcallback(int iEvent, void *pEventData, void *pUser)
|
|
{
|
|
pPolterdi self = NULL;
|
|
|
|
if (iEvent == COUNTEND) {
|
|
self = (pPolterdi) pUser;
|
|
assert(self);
|
|
self->tUpdate = time(NULL);
|
|
self->iEnd = 1;
|
|
if (self->iNew == 1) {
|
|
PoldiStart(self, self->pCon);
|
|
PoldiLink(self, self->pCon);
|
|
} else {
|
|
PoldiUpdate(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 writePolterdiGlobal(NXhandle hfil, NXdict hdict,
|
|
SConnection * pCon)
|
|
{
|
|
char pBueffel[512];
|
|
|
|
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "etitle", "title");
|
|
SNXFormatTime(pBueffel, 511);
|
|
|
|
NXDputalias(hfil, hdict, "estart", pBueffel);
|
|
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "iname", "instrument");
|
|
sprintf(pBueffel, "%d", (int) strlen("SINQ, PSI, Switzerland"));
|
|
NXDupdate(hdict, "strdim", pBueffel);
|
|
NXDputalias(hfil, hdict, "sname", "SINQ, PSI, Switzerland");
|
|
sprintf(pBueffel, "%d", (int) strlen("continous spallation source"));
|
|
NXDupdate(hdict, "strdim", pBueffel);
|
|
NXDputalias(hfil, hdict, "stype", "continous spallation source");
|
|
NXDupdate(hdict, "strdim", "132");
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
static void writeChopper(NXhandle hfil, NXdict hdict, SConnection * pCon)
|
|
{
|
|
pHdb node = NULL;
|
|
float fVal;
|
|
|
|
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "cname", "choppername");
|
|
SNXSPutDrivable(pServ->pSics, pCon, hfil, hdict, "chopperspeed", "crot");
|
|
SNXSPutDrivable(pServ->pSics, pCon, hfil, hdict, "chopperphase", "cphase");
|
|
|
|
node = FindHdbNode(NULL,"/sics/choco/chopper/nspee", NULL);
|
|
if(node != NULL){
|
|
fVal = atof(node->value.v.text);
|
|
NXDputalias(hfil,hdict,"crottarget",&fVal);
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
static void writeDiaphragm1(NXhandle hfil, NXdict hdict,
|
|
SConnection * pCon)
|
|
{
|
|
float dist;
|
|
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "dia1x", "d1hl");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "dia1x0", "d1hl");
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "dia1y", "d1hr");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "dia1y0", "d1hr");
|
|
dist = (float) DIA1DIST;
|
|
NXDputalias(hfil, hdict, "dia1dist", &dist);
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
|
|
static void writeDiaphragm2(NXhandle hfil, NXdict hdict,
|
|
SConnection * pCon)
|
|
{
|
|
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "dia2x_plus", "d2hl");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "dia2xplus0", "d2hl");
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "dia2x_minus", "d2hr");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "dia2xminus0", "d2hr");
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "dia2z_plus", "d2vu");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "dia2zplus0", "d2vu");
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "dia2z_minus", "d2vl");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "dia2zminus0", "d2vl");
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "dia2z_x", "d2x");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "dia2z_x0", "d2x");
|
|
|
|
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "dia2dist",
|
|
"dia1_dia2");
|
|
}
|
|
/*---------------------------------------------------------------------*/
|
|
static void writeCollimator(NXhandle hfil, NXdict hdict,
|
|
SConnection * pCon)
|
|
{
|
|
char pBueffel[50];
|
|
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "cov", "cov");
|
|
memset(pBueffel,0,sizeof(pBueffel));
|
|
Tcl_Eval(InterpGetTcl(pServ->pSics),"coll");
|
|
strncpy(pBueffel,Tcl_GetStringResult(InterpGetTcl(pServ->pSics)), 49);
|
|
NXDputalias(hfil, hdict, "collpos", pBueffel);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
static void writeSample(NXhandle hfil, NXdict hdict, SConnection * pCon)
|
|
{
|
|
pSicsVariable active = NULL;
|
|
int iActive;
|
|
CommandList *pCom = NULL;
|
|
|
|
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "sdist", "dia2_sample");
|
|
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "chopperdist",
|
|
"chopper_sample");
|
|
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "saname", "sample");
|
|
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "senvir",
|
|
"environment");
|
|
|
|
if ((pCom = FindCommand(pServ->pSics, "temperature"))
|
|
!= NULL) {
|
|
SNXSPutDrivable(pServ->pSics, pCon, hfil, hdict, "temperature",
|
|
"stemp");
|
|
}
|
|
active = FindCommandData(pServ->pSics, "activetable", "SicsVariable");
|
|
if (active != NULL) {
|
|
VarGetInt(active, &iActive);
|
|
if (iActive == 1) {
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "srsu", "rsu");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "srsu0", "rsu");
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "srsl", "rsl");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "srsl0", "rsl");
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "srsa", "rsa");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "srsa0", "rsa");
|
|
}
|
|
}
|
|
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "sshu", "shu");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "sshu0", "shu");
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "sshl", "shl");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "sshl0", "shl");
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "ssgu", "sgu");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "ssgu0", "sgu");
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "ssgl", "sgl");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "ssgl0", "sgl");
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "ssv", "sv");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "ssv0", "sv");
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "ssa", "sa");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "ssa0", "sa");
|
|
|
|
pCom = FindCommand(pServ->pSics,"chi");
|
|
if(pCom != NULL){
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "schi", "chi");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "schi0", "chi");
|
|
SNXSPutMotor(pServ->pSics, pCon, hfil, hdict, "sphi", "phi");
|
|
SNXSPutMotorNull(pServ->pSics, pCon, hfil, hdict, "sphi0", "phi");
|
|
}
|
|
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
static void PoldiStart(pPolterdi self, SConnection * pCon)
|
|
{
|
|
char pBueffel[256];
|
|
NXhandle hfil = NULL;
|
|
NXdict hdict = NULL;
|
|
int status;
|
|
const float *fTime = NULL;
|
|
CounterMode eMode;
|
|
float *fTime2 = NULL, fTheta0[801], fTheta[801], fVal;
|
|
pSicsVariable pVar = NULL;
|
|
float det_radius, det_size, x0det, y0det, twothet;
|
|
float pi, alpha1, alphasamp, sms, phidetav, phim;
|
|
float phi2det, val1, val2, nodet, scancheck;
|
|
int iLength, i, nzell;
|
|
pMotor sa;
|
|
HistInt *lData = NULL;
|
|
long lVal;
|
|
pCounter pCount;
|
|
|
|
/* create filename */
|
|
self->pFile = makeFilename(pServ->pSics, pCon);
|
|
if (!self->pFile) {
|
|
SCWrite(pCon, "ERROR: Extra severe: failed to create data file name",
|
|
eError);
|
|
return;
|
|
}
|
|
/* create a Nexus file */
|
|
NXopen(self->pFile, NXACC_CREATE5, &hfil);
|
|
if (!hfil) {
|
|
SCWrite(pCon, "ERROR: cannot create data file ", eError);
|
|
return;
|
|
}
|
|
/* tell Uwe User what we are doing */
|
|
pVar = NULL;
|
|
pVar = FindVariable(pServ->pSics, "scancheck");
|
|
if (pVar) {
|
|
VarGetFloat(pVar, &scancheck);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: Command not found!", eError);
|
|
return;
|
|
}
|
|
if (scancheck == 0) {
|
|
snprintf(pBueffel,255, "Writing %s ......", self->pFile);
|
|
SCWrite(pCon, pBueffel, eLog);
|
|
}
|
|
|
|
|
|
/* write globals */
|
|
SNXSPutGlobals(hfil, self->pFile, "POLDI", pCon);
|
|
|
|
/* open nxdict */
|
|
status = NXDinitfromfile(self->dictfile, &hdict);
|
|
if (status != NX_OK) {
|
|
sprintf(pBueffel, "ERROR: failed to open dictionary file %s",
|
|
self->dictfile);
|
|
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(&hfil);
|
|
return;
|
|
}
|
|
|
|
|
|
writePolterdiGlobal(hfil, hdict, pCon);
|
|
|
|
writeChopper(hfil, hdict, pCon);
|
|
|
|
writeDiaphragm1(hfil, hdict, pCon);
|
|
|
|
writeDiaphragm2(hfil, hdict, pCon);
|
|
|
|
writeCollimator(hfil, hdict, pCon);
|
|
|
|
writeSample(hfil, hdict, pCon);
|
|
|
|
/*
|
|
write time binning
|
|
*/
|
|
|
|
fTime = GetHistTimeBin(self->pHist, &iLength);
|
|
fTime2 = (float *) malloc(iLength * sizeof(float));
|
|
if (fTime2) {
|
|
for (i = 0; i < iLength; i++) {
|
|
fTime2[i] = fTime[i] / 2.;
|
|
}
|
|
if(iLength > 2){
|
|
sprintf(pBueffel, "%d", iLength);
|
|
} else {
|
|
sprintf(pBueffel, "%d", 1);
|
|
}
|
|
NXDupdate(hdict, "timebin", pBueffel);
|
|
NXDputalias(hfil, hdict, "dtime", fTime2);
|
|
free(fTime2);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: out of memory while writing time binning",
|
|
eError);
|
|
}
|
|
|
|
/*
|
|
theta calculation
|
|
*/
|
|
det_radius = (float) DETRADIUS;
|
|
pVar = FindVariable(pServ->pSics, "det_size");
|
|
if (pVar) {
|
|
VarGetFloat(pVar, &det_size);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: Command not found!", eError);
|
|
return;
|
|
}
|
|
pVar = NULL;
|
|
pVar = FindVariable(pServ->pSics, "nodet");
|
|
if (pVar) {
|
|
VarGetFloat(pVar, &nodet);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: Command not found!", eError);
|
|
return;
|
|
}
|
|
pVar = NULL;
|
|
nzell = (int) nodet;
|
|
|
|
pVar = FindVariable(pServ->pSics, "x0_det");
|
|
if (pVar) {
|
|
VarGetFloat(pVar, &x0det);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: Command not found!", eError);
|
|
return;
|
|
}
|
|
pVar = NULL;
|
|
pVar = FindVariable(pServ->pSics, "y0_det");
|
|
if (pVar) {
|
|
VarGetFloat(pVar, &y0det);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: Command not found!", eError);
|
|
return;
|
|
}
|
|
pVar = NULL;
|
|
pVar = FindVariable(pServ->pSics, "twotheta");
|
|
if (pVar) {
|
|
VarGetFloat(pVar, &twothet);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: Command not found!", eError);
|
|
return;
|
|
}
|
|
|
|
pi = 3.1415926536;
|
|
/* transformation to radient */
|
|
twothet = twothet * pi / 180;
|
|
if (x0det < 0) {
|
|
alpha1 = atan(y0det / x0det);
|
|
}
|
|
if (x0det > 0) {
|
|
alpha1 = pi + atan(y0det / x0det);
|
|
}
|
|
alphasamp = pi + alpha1 - twothet;
|
|
sms = sqrt(x0det * x0det + y0det * y0det);
|
|
phidetav =
|
|
pi - alphasamp - asin(sms / det_radius * sin(alphasamp)) + alpha1;
|
|
phim = atan(y0det / x0det);
|
|
if (phim < 0) {
|
|
phim = pi + phim;
|
|
}
|
|
for (i = 0; i <= nzell; i++) {
|
|
phi2det =
|
|
phidetav + (i - 0.5 * (nzell - 1.0)) * det_size / (det_radius);
|
|
val1 = det_radius * sin(phi2det) - sms * sin(phim);
|
|
val2 = det_radius * cos(phi2det) - sms * cos(phim);
|
|
fTheta0[i] = atan(val1 / val2);
|
|
if (fTheta0[i] < 0) {
|
|
fTheta0[i] = pi + fTheta0[i];
|
|
}
|
|
/* transformation to degree */
|
|
fTheta0[i] = fTheta0[i] * 180 / pi;
|
|
}
|
|
for (i = 0; i <= nzell; i++) {
|
|
fTheta[i] = fTheta0[nzell - i];
|
|
}
|
|
NXDputalias(hfil, hdict, "dtheta", fTheta);
|
|
NXDputalias(hfil, hdict, "detector_radius", &det_radius);
|
|
NXDputalias(hfil, hdict, "cell_size", &det_size);
|
|
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "ddist",
|
|
"detectordist");
|
|
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "sangle",
|
|
"scatt_angle");
|
|
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "detx0", "x0_det");
|
|
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "dety0", "y0_det");
|
|
SNXSPutVariable(pServ->pSics, pCon, hfil, hdict, "theta", "twotheta");
|
|
SNXSPutDrivable(pServ->pSics, pCon, hfil, hdict, "cnhepress","he_pressure");
|
|
/*
|
|
write Histogram
|
|
*/
|
|
lData = GetHistogramPointer(self->pHist, pCon);
|
|
if (lData) {
|
|
NXDputalias(hfil, hdict, "dcounts", lData);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: failed to get histogram data", eError);
|
|
}
|
|
|
|
/*
|
|
write counting data
|
|
*/
|
|
pCount = (pCounter)FindCommandData(pServ->pSics,"counter","SingleCounter");
|
|
if(pCount){
|
|
fVal = GetCountTime(pCount, pCon);
|
|
NXDputalias(hfil, hdict, "cntime", &fVal);
|
|
lVal = GetMonitor(pCount, 1, pCon);
|
|
NXDputalias(hfil, hdict, "cnmon1", &lVal);
|
|
lVal = GetMonitor(pCount, 2, pCon);
|
|
NXDputalias(hfil, hdict, "cnmon3", &lVal);
|
|
lVal = GetMonitor(pCount, 3, pCon);
|
|
NXDputalias(hfil, hdict, "cnmon4", &lVal);
|
|
eMode = GetCounterMode(pCount);
|
|
if (eMode == eTimer) {
|
|
strcpy(pBueffel, "timer");
|
|
} else {
|
|
strcpy(pBueffel, "monitor");
|
|
}
|
|
NXDputalias(hfil, hdict, "cnmode", pBueffel);
|
|
fVal = GetCounterPreset(pCount);
|
|
NXDputalias(hfil, hdict, "cnpreset", &fVal);
|
|
} else {
|
|
SCWrite(pCon,"ERROR: counter not found writing data file", eLogError);
|
|
}
|
|
|
|
/* close everything */
|
|
NXclose(&hfil);
|
|
NXDclose(hdict, NULL);
|
|
self->iNew = 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static void PoldiUpdate(pPolterdi self, SConnection * pCon)
|
|
{
|
|
char pBueffel[256];
|
|
NXhandle hfil = NULL;
|
|
NXdict hdict = NULL;
|
|
int status;
|
|
const float *fTime = NULL;
|
|
CounterMode eMode;
|
|
float *fTime2 = NULL, fTheta[801], fVal;
|
|
pSicsVariable pVar = NULL;
|
|
float det_radius, det_size, x0det, y0det, twothet;
|
|
float pi, alpha1, alphasamp, sms, phidetav, phim;
|
|
float phi2det, val1, val2, nodet, scancheck;
|
|
int iLength, i, nzell;
|
|
pMotor sa;
|
|
HistInt *lData = NULL;
|
|
long lVal;
|
|
time_t zeit;
|
|
pCounter pCount = NULL;
|
|
|
|
/* open everything again */
|
|
status = NXopen(self->pFile, NXACC_RDWR, &hfil);
|
|
if (status != NX_OK) {
|
|
SCWrite(pCon, "ERROR: cannot reopen data file ", eError);
|
|
return;
|
|
}
|
|
status = NXDinitfromfile(self->dictfile, &hdict);
|
|
if (status != NX_OK) {
|
|
sprintf(pBueffel, "ERROR: failed to open dictionary file %s",
|
|
self->dictfile);
|
|
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(&hfil);
|
|
return;
|
|
}
|
|
|
|
/* tell the user that something is happening */
|
|
pVar = NULL;
|
|
pVar = FindVariable(pServ->pSics, "scancheck");
|
|
if (pVar) {
|
|
VarGetFloat(pVar, &scancheck);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: Command not found!", eError);
|
|
return;
|
|
}
|
|
if (scancheck == 0) {
|
|
time(&zeit);
|
|
snprintf(pBueffel,255, "Updating %s on %s ", self->pFile,
|
|
asctime(localtime(&zeit)));
|
|
SCWrite(pCon, pBueffel, eWarning);
|
|
}
|
|
SNXFormatTime(pBueffel, sizeof(pBueffel));
|
|
NXDputalias(hfil, hdict, "eend", pBueffel);
|
|
|
|
|
|
/*
|
|
write time binning
|
|
*/
|
|
|
|
/*
|
|
fTime = GetHistTimeBin(self->pHist, &iLength);
|
|
fTime2 = (float *) malloc(iLength * sizeof(float));
|
|
if (fTime2) {
|
|
for (i = 0; i < iLength; i++) {
|
|
fTime2[i] = fTime[i] / 2.;
|
|
}
|
|
sprintf(pBueffel, "%d", iLength);
|
|
NXDupdate(hdict, "timebin", pBueffel);
|
|
NXDputalias(hfil, hdict, "dtime", fTime2);
|
|
free(fTime2);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: out of memory while writing time binning",
|
|
eError);
|
|
}
|
|
*/
|
|
|
|
/*
|
|
write Histogram
|
|
*/
|
|
|
|
lData = GetHistogramPointer(self->pHist, pCon);
|
|
if (lData) {
|
|
NXDputalias(hfil, hdict, "dcounts", lData);
|
|
} else {
|
|
SCWrite(pCon, "ERROR: failed to get histogram data", eError);
|
|
}
|
|
|
|
/*
|
|
write counting data
|
|
*/
|
|
pCount = (pCounter)FindCommandData(pServ->pSics,"counter","SingleCounter");
|
|
if(pCount){
|
|
fVal = GetCountTime(pCount, pCon);
|
|
NXDputalias(hfil, hdict, "cntime", &fVal);
|
|
lVal = GetMonitor(pCount, 1, pCon);
|
|
NXDputalias(hfil, hdict, "cnmon1", &lVal);
|
|
lVal = GetMonitor(pCount, 4, pCon);
|
|
NXDputalias(hfil, hdict, "cnprot", &lVal);
|
|
lVal = GetMonitor(pCount, 2, pCon);
|
|
NXDputalias(hfil, hdict, "cnmon3", &lVal);
|
|
lVal = GetMonitor(pCount, 3, pCon);
|
|
NXDputalias(hfil, hdict, "cnmon4", &lVal);
|
|
eMode = GetCounterMode(pCount);
|
|
if (eMode == eTimer) {
|
|
strcpy(pBueffel, "timer");
|
|
} else {
|
|
strcpy(pBueffel, "monitor");
|
|
}
|
|
NXDputalias(hfil, hdict, "cnmode", pBueffel);
|
|
fVal = GetCounterPreset(pCount);
|
|
NXDputalias(hfil, hdict, "cnpreset", &fVal);
|
|
} else {
|
|
SCWrite(pCon,"ERROR: counter not found writing data file", eLogError);
|
|
}
|
|
|
|
|
|
/* close everything */
|
|
NXclose(&hfil);
|
|
NXDclose(hdict, 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 PoldiLink(pPolterdi self, SConnection * pCon)
|
|
{
|
|
NXhandle hfil = NULL;
|
|
NXdict hdict = NULL;
|
|
int status;
|
|
char pBueffel[512];
|
|
|
|
/* open everything again */
|
|
NXopen(self->pFile, NXACC_RDWR, &hfil);
|
|
if (!self->pFile) {
|
|
SCWrite(pCon, "ERROR: cannot reopen data file ", eError);
|
|
return;
|
|
}
|
|
status = NXDinitfromfile(self->dictfile, &hdict);
|
|
if (status != NX_OK) {
|
|
sprintf(pBueffel, "ERROR: failed to open dictionary file %s",
|
|
self->dictfile);
|
|
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(&hfil);
|
|
return;
|
|
}
|
|
|
|
NXDaliaslink(hfil, hdict, "dana", "dcounts");
|
|
NXDaliaslink(hfil, hdict, "dana", "dtheta");
|
|
NXDaliaslink(hfil, hdict, "dana", "dtime");
|
|
|
|
/* close everything */
|
|
NXclose(&hfil);
|
|
NXDclose(hdict, NULL);
|
|
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
This is the task function for updating the data file any now and then
|
|
automatically
|
|
--------------------------------------------------------------------------*/
|
|
static int PoldiTask(void *pData)
|
|
{
|
|
pPolterdi self = NULL;
|
|
int iWrite, iRet, ltask;
|
|
|
|
self = (pPolterdi) 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) {
|
|
ltask = GetDevexecID(pServ->pExecutor);
|
|
if (ltask > 0) {
|
|
self->tUpdate = time(NULL) + self->iInterval;
|
|
iWrite = 1;
|
|
iRet = 1;
|
|
} else {
|
|
self->iEnd = 1;
|
|
}
|
|
}
|
|
|
|
if (self->iEnd == 1) {
|
|
self->tUpdate = 0;
|
|
iWrite = 0;
|
|
iRet = 0;
|
|
}
|
|
|
|
if (iWrite) {
|
|
if (self->iNew) {
|
|
PoldiStart(self, self->pCon);
|
|
PoldiUpdate(self, self->pCon);
|
|
PoldiLink(self, self->pCon);
|
|
} else {
|
|
PoldiUpdate(self, self->pCon);
|
|
}
|
|
}
|
|
return iRet;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
static void KillPolterdi(void *pData)
|
|
{
|
|
pPolterdi self = (pPolterdi) pData;
|
|
if (!self)
|
|
return;
|
|
|
|
if (self->pDes) {
|
|
DeleteDescriptor(self->pDes);
|
|
}
|
|
if (self->pFile) {
|
|
free(self->pFile);
|
|
}
|
|
if (self->dictfile) {
|
|
free(self->dictfile);
|
|
}
|
|
free(self);
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
int PolterInstall(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pPolterdi pNew = NULL;
|
|
pICallBack pCall = NULL;
|
|
pDummy pDum;
|
|
pHistMem pHist = NULL;
|
|
commandContext comCon;
|
|
|
|
/* configure fortify */
|
|
/*
|
|
iFortifyScope = Fortify_EnterScope();
|
|
Fortify_CheckAllMemory();
|
|
*/
|
|
if (argc < 2) {
|
|
SCWrite(pCon,
|
|
"ERROR: insufficient number of arguments to PolterInstall",
|
|
eError);
|
|
return 0;
|
|
}
|
|
pHist = (pHistMem) FindCommandData(pSics, HM, "HistMem");
|
|
|
|
if (!pHist) {
|
|
SCWrite(pCon, "ERROR: Histogram memory NOT found", eError);
|
|
return 0;
|
|
}
|
|
|
|
pNew = (pPolterdi) malloc(sizeof(Polterdi));
|
|
if (!pNew) {
|
|
SCWrite(pCon, "ERROR: out of memory in PolterInstall", eError);
|
|
return 0;
|
|
}
|
|
memset(pNew, 0, sizeof(Polterdi));
|
|
pNew->pDes = CreateDescriptor("PoldiWrite");
|
|
pNew->pHist = pHist;
|
|
pNew->dictfile = strdup(argv[1]);
|
|
pNew->iInterval = 20 * 60;
|
|
if (!pNew->pDes || !pNew->dictfile) {
|
|
SCWrite(pCon, "ERROR: out of memory in PolterInstall", eError);
|
|
return 0;
|
|
}
|
|
/* 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);
|
|
KillPolterdi(pNew);
|
|
return 0;
|
|
}
|
|
strlcpy(comCon.deviceID, "internal", SCDEVIDLEN);
|
|
RegisterCallback(pCall, COUNTSTART, Countstartcallback, pNew, NULL);
|
|
RegisterCallback(pCall, COUNTEND, Countendcallback, pNew, NULL);
|
|
|
|
AddCommand(pSics, "storedata", PolterAction, KillPolterdi, pNew);
|
|
return 1;
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
int PolterAction(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
int iRet, iVal;
|
|
pPolterdi self = NULL;
|
|
char pBueffel[512];
|
|
|
|
if (argc < 2) {
|
|
SCWrite(pCon, "ERROR: Insufficient number of arguments to StoreData",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
self = (pPolterdi) pData;
|
|
assert(self);
|
|
|
|
strtolower(argv[1]);
|
|
if (strcmp(argv[1], "start") == 0) {
|
|
PoldiStart(self, pCon);
|
|
PoldiUpdate(self, pCon);
|
|
PoldiLink(self, pCon);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "update") == 0) {
|
|
if ((self->iNew) || (!self->pFile)) {
|
|
PoldiStart(self, pCon);
|
|
PoldiUpdate(self, pCon);
|
|
PoldiLink(self, pCon);
|
|
} else {
|
|
PoldiUpdate(self, pCon);
|
|
}
|
|
return 1;
|
|
} else if (strcmp(argv[1], "getfile") == 0) {
|
|
snprintf(pBueffel,511, "StoreData.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) {
|
|
snprintf(pBueffel,511, "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, "storedata.interval = %d", self->iInterval / 60);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
SCWrite(pCon, "ERROR: subcommand to StoreData not recognized", eError);
|
|
return 0;
|
|
}
|