1842 lines
50 KiB
C
1842 lines
50 KiB
C
/*--------------------------------------------------------------------------
|
|
|
|
H I S T M E M
|
|
|
|
The SICS histogram memory object.
|
|
|
|
Mark Koennecke, April 1996
|
|
|
|
revised: Mark Koennecke, June 1997
|
|
|
|
added getzip: Mark Koennecke, October 2000
|
|
|
|
Refactored data handling into separater HMdata class.
|
|
Mark Koennecke, January 2003
|
|
|
|
Added function to retrieve time delay and to format TOF bin array in order
|
|
to speed up TOF configuration for new http based HM's
|
|
|
|
Mark Koennecke, March 2009
|
|
|
|
Added an error field in the options stringdict
|
|
|
|
Mark Koennecke, June 2013
|
|
|
|
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 <arpa/inet.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <tcl.h>
|
|
#include <time.h>
|
|
#include "sics.h"
|
|
#include "fortify.h"
|
|
#include "countdriv.h"
|
|
#include "counter.h"
|
|
#include "stringdict.h"
|
|
#include "splitter.h"
|
|
#include "HistMem.h"
|
|
#include "HistDriv.i"
|
|
#include "HistMem.i"
|
|
#include "histsim.h"
|
|
#include "mcstashm.h"
|
|
#include "dynstring.h"
|
|
#include "event.h"
|
|
#include "status.h"
|
|
#include "site.h"
|
|
#include "histmemsec.h"
|
|
#define ABS(x) (x < 0 ? -(x) : (x))
|
|
|
|
/*
|
|
#define LOADDEBUG 1
|
|
*/
|
|
/*
|
|
* from histregress.c
|
|
*/
|
|
extern pHistDriver CreateRegressHM(pStringDict pOpt);
|
|
/*
|
|
* from slavehm.c
|
|
*/
|
|
extern pHistDriver MakeHMSlaveHM(pStringDict pOpt);
|
|
/*------------------------------------------------------------------------*/
|
|
int isSecondGen(pHistMem self)
|
|
{
|
|
pDummy test = (pDummy)self;
|
|
if(strcmp(test->pDescriptor->name,"HistMemSec") == 0) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
pHistMem FindHM(SicsInterp *pSics, char *name)
|
|
{
|
|
pHistMem result = NULL;
|
|
|
|
result = (pHistMem)FindCommandData(pSics,name,"HistMem");
|
|
if(result == NULL){
|
|
result = (pHistMem)FindCommandData(pSics,name,"HistMemSec");
|
|
}
|
|
return result;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static int HistHalt(void *pData)
|
|
{
|
|
pHistMem self = NULL;
|
|
|
|
self = (pHistMem) pData;
|
|
assert(self);
|
|
|
|
if (!self->iInit) {
|
|
return 0;
|
|
}
|
|
return self->pDriv->Halt(self->pDriv);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static int HistSave(void *pData, char *name, FILE * fd)
|
|
{
|
|
pHistMem self = NULL;
|
|
char *pMode[] = {
|
|
"timer",
|
|
"monitor",
|
|
NULL
|
|
};
|
|
CounterMode eCount;
|
|
float fVal;
|
|
|
|
self = (pHistMem) pData;
|
|
assert(self);
|
|
|
|
if (!self->iInit) {
|
|
return 0;
|
|
}
|
|
|
|
/* counting modes */
|
|
eCount = GetHistCountMode(self);
|
|
fprintf(fd, "%s CountMode %s\n", name, pMode[eCount]);
|
|
fVal = GetHistPreset(self);
|
|
fprintf(fd, "%s preset %f\n", name, fVal);
|
|
|
|
/* time binning if TOF */
|
|
if (isInTOFMode(self->pDriv->data)) {
|
|
fprintf(fd, "%s genbin %f %f %d\n",
|
|
name, self->pDriv->data->timeBinning[0],
|
|
self->pDriv->data->timeBinning[1] -
|
|
self->pDriv->data->timeBinning[0],
|
|
self->pDriv->data->nTimeChan);
|
|
fprintf(fd, "%s init\n", name);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static void *GetHistInterface(void *pData, int iID)
|
|
{
|
|
pHistMem self = NULL;
|
|
|
|
self = (pHistMem) pData;
|
|
if (iID == COUNTID) {
|
|
return self->pCountInt;
|
|
} else if (iID == CALLBACKINTERFACE) {
|
|
return self->pCall;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static void HistSetParameter(void *pData, float fPreset, CounterMode eMode)
|
|
{
|
|
pHistMem self = NULL;
|
|
|
|
self = (pHistMem) pData;
|
|
assert(self);
|
|
|
|
self->pDriv->eCount = eMode;
|
|
self->pDriv->fCountPreset = fPreset;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
static int HistStartCount(void *pData, SConnection * pCon)
|
|
{
|
|
pHistMem self = NULL;
|
|
char pBueffel[512];
|
|
char pError[80];
|
|
int iErr, iRet, i;
|
|
|
|
self = (pHistMem) pData;
|
|
assert(self);
|
|
|
|
if (!GetCountLock(self->pCountInt, pCon)) {
|
|
return HWFault;
|
|
}
|
|
|
|
if (!self->iInit) {
|
|
SCWrite(pCon, "ERROR: histogram memory not initialised", eLogError);
|
|
return 0;
|
|
}
|
|
|
|
/* try at least three times to do it */
|
|
StringDictUpdate(self->pDriv->pOption, "error", "None");
|
|
for (i = 0; i < 3; i++) {
|
|
iRet = self->pDriv->Start(self->pDriv, pCon);
|
|
if (iRet == OKOK) {
|
|
/* send a COUNTSTART event */
|
|
clearHMData(self->pDriv->data);
|
|
InvokeCallBack(self->pCall, COUNTSTART, pCon);
|
|
return iRet;
|
|
} else {
|
|
iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: %s ", pError);
|
|
SCWrite(pCon, pBueffel, eLogError);
|
|
iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr);
|
|
if (iRet == COTERM) {
|
|
SCWrite(pCon, "ERROR: failed to fix histogram memory problem",
|
|
eLogError);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
ReleaseCountLock(self->pCountInt);
|
|
StringDictUpdate(self->pDriv->pOption, "error", pError);
|
|
return HWFault;
|
|
}
|
|
}
|
|
}
|
|
SCWrite(pCon, "ERROR: failed to fix histogram memory problem", eError);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
ReleaseCountLock(self->pCountInt);
|
|
return HWFault;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
static int HistPause(void *pData, SConnection * pCon)
|
|
{
|
|
pHistMem self = NULL;
|
|
char pBueffel[512];
|
|
char pError[80];
|
|
int iErr, iRet, i;
|
|
|
|
self = (pHistMem) pData;
|
|
assert(self);
|
|
|
|
if (!self->iInit) {
|
|
SCWrite(pCon, "ERROR: histogram memory not initialised", eError);
|
|
return 0;
|
|
}
|
|
|
|
/* try at least three times to do it */
|
|
for (i = 0; i < 3; i++) {
|
|
iRet = self->pDriv->Pause(self->pDriv, pCon);
|
|
if (iRet == OKOK) {
|
|
updateHMData(self->pDriv->data);
|
|
return iRet;
|
|
} else {
|
|
iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: %s ", pError);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr);
|
|
if (iRet == COTERM) {
|
|
SCWrite(pCon, "ERROR: failed to fix histogram memory problem",
|
|
eError);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
ReleaseCountLock(self->pCountInt);
|
|
return HWFault;
|
|
}
|
|
}
|
|
}
|
|
SCWrite(pCon, "ERROR: failed to fix histogram memory problem", eError);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
ReleaseCountLock(self->pCountInt);
|
|
return HWFault;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
static int HistContinue(void *pData, SConnection * pCon)
|
|
{
|
|
pHistMem self = NULL;
|
|
char pBueffel[512];
|
|
char pError[80];
|
|
int iErr, iRet, i;
|
|
|
|
self = (pHistMem) pData;
|
|
assert(self);
|
|
|
|
if (!self->iInit) {
|
|
SCWrite(pCon, "ERROR: histogram memory not initialised", eError);
|
|
return 0;
|
|
}
|
|
|
|
/* try at least three times to do it */
|
|
for (i = 0; i < 3; i++) {
|
|
iRet = self->pDriv->Continue(self->pDriv, pCon);
|
|
if (iRet == OKOK) {
|
|
updateHMData(self->pDriv->data);
|
|
return iRet;
|
|
} else {
|
|
iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: %s ", pError);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr);
|
|
if (iRet == COTERM) {
|
|
SCWrite(pCon, "ERROR: failed to fix histogram memory problem",
|
|
eError);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
ReleaseCountLock(self->pCountInt);
|
|
return HWFault;
|
|
}
|
|
}
|
|
}
|
|
SCWrite(pCon, "ERROR: failed to fix histogram memory problem", eError);
|
|
ReleaseCountLock(self->pCountInt);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
return HWFault;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
static int HistCountStatus(void *pData, SConnection * pCon)
|
|
{
|
|
pHistMem self = NULL;
|
|
int eCt, iRet, iErr;
|
|
char pBueffel[512], pError[90];
|
|
|
|
self = (pHistMem) pData;
|
|
assert(self);
|
|
|
|
if (!self->iInit) {
|
|
SCWrite(pCon, "ERROR: histogram memory not initialised", eError);
|
|
InvokeCallBack(self->pCall, COUNTEND, NULL);
|
|
ReleaseCountLock(self->pCountInt);
|
|
return COTERM;
|
|
}
|
|
|
|
eCt = self->pDriv->GetCountStatus(self->pDriv, pCon);
|
|
if (eCt == HWFault) {
|
|
iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: %s ", pError);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr);
|
|
if (iRet == COTERM) {
|
|
SCWrite(pCon, "ERROR: failed to fix histogram memory problem",
|
|
eError);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
InvokeCallBack(self->pCall, COUNTEND, NULL);
|
|
ReleaseCountLock(self->pCountInt);
|
|
StringDictUpdate(self->pDriv->pOption, "error", pError);
|
|
return eCt;
|
|
} else {
|
|
updateHMData(self->pDriv->data);
|
|
return HWBusy;
|
|
}
|
|
}
|
|
/* if (eCt == HWBusy){ */
|
|
/* updateHMData(self->pDriv->data); */
|
|
/* } */
|
|
|
|
if (eCt == HWIdle) {
|
|
/* force an update of local histogram data with next
|
|
GetHistogram
|
|
*/
|
|
updateHMData(self->pDriv->data);
|
|
InvokeCallBack(self->pCall, COUNTEND, NULL);
|
|
ReleaseCountLock(self->pCountInt);
|
|
}
|
|
|
|
return eCt;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------
|
|
The question arises if the histograms shall be duplicated on the host
|
|
computer or not. They need to be in order to be written to file!
|
|
*/
|
|
static int HistTransfer(void *pData, SConnection * pCon)
|
|
{
|
|
pHistMem self = NULL;
|
|
int i, iErr, iRet, iStatus;
|
|
char pBueffel[512], pError[80];
|
|
|
|
self = (pHistMem) pData;
|
|
assert(self);
|
|
|
|
if (!self->iInit) {
|
|
SCWrite(pCon, "ERROR: histogram memory not initialised", eError);
|
|
return COTERM;
|
|
}
|
|
|
|
/* try at least three times */
|
|
for (i = 0; i < 3; i++) {
|
|
iRet = self->pDriv->GetData(self->pDriv, pCon);
|
|
if (iRet == OKOK) {
|
|
self->pDriv->iUpdate = 0;
|
|
iStatus = iRet;
|
|
} else {
|
|
iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "WARNING: %s ", pError);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr);
|
|
if (iRet == COTERM) {
|
|
SCWrite(pCon, "ERROR: failed to fix histogram memory problem",
|
|
eError);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
StringDictUpdate(self->pDriv->pOption, "error", pError);
|
|
iStatus = HWFault;
|
|
}
|
|
}
|
|
}
|
|
if (iRet == OKOK) {
|
|
return iStatus;
|
|
}
|
|
SCWrite(pCon, "ERROR: failed to fix histogram memory problem", eError);
|
|
SCSetInterrupt(pCon, eAbortBatch);
|
|
return HWFault;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
pHistMem CreateHistMemory(char *driver)
|
|
{
|
|
pHistMem pNew = NULL;
|
|
pSite site = NULL;
|
|
pStringDict pOption;
|
|
|
|
/* make memory */
|
|
pNew = (pHistMem) malloc(sizeof(HistMem));
|
|
if (!pNew) {
|
|
return NULL;
|
|
}
|
|
memset(pNew, 0, sizeof(HistMem));
|
|
|
|
/* make object descriptor */
|
|
pNew->pDes = CreateDescriptor("HistMem");
|
|
if (!pNew->pDes) {
|
|
free(pNew);
|
|
return NULL;
|
|
}
|
|
pNew->pDes->SaveStatus = HistSave;
|
|
pNew->pDes->GetInterface = GetHistInterface;
|
|
|
|
/* initialise countable interface */
|
|
pNew->pCountInt = CreateCountableInterface();
|
|
if (!pNew->pCountInt) {
|
|
DeleteDescriptor(pNew->pDes);
|
|
free(pNew);
|
|
return NULL;
|
|
}
|
|
/* initialise callback interface */
|
|
pNew->pCall = CreateCallBackInterface();
|
|
if (!pNew->pCall) {
|
|
DeleteDescriptor(pNew->pDes);
|
|
free(pNew);
|
|
return NULL;
|
|
}
|
|
pNew->pCountInt->SetCountParameters = HistSetParameter;
|
|
pNew->pCountInt->StartCount = HistStartCount;
|
|
pNew->pCountInt->CheckCountStatus = HistCountStatus;
|
|
pNew->pCountInt->TransferData = HistTransfer;
|
|
pNew->pCountInt->Halt = HistHalt;
|
|
pNew->pCountInt->Pause = HistPause;
|
|
pNew->pCountInt->Continue = HistContinue;
|
|
|
|
/* initialise options dictionary */
|
|
pOption = CreateStringDict();
|
|
if (!pOption) {
|
|
DeleteDescriptor(pNew->pDes);
|
|
free(pNew);
|
|
return NULL;
|
|
}
|
|
StringDictAddPair(pOption, "driver", driver);
|
|
StringDictAddPair(pOption, "update", "0");
|
|
StringDictAddPair(pOption, "error", "None");
|
|
|
|
/* initialise driver */
|
|
if (strcmp(driver, "sim") == 0) {
|
|
pNew->pDriv = CreateSIMHM(pOption);
|
|
} else if (strcmp(driver, "mcstas") == 0) {
|
|
pNew->pDriv = NewMcStasHM(pOption);
|
|
} else if (strcmp(driver, "regress") == 0) {
|
|
pNew->pDriv = CreateRegressHM(pOption);
|
|
}
|
|
/*
|
|
else if(strcmp(driver,"slave") == 0)
|
|
{
|
|
pNew->pDriv = MakeHMSlaveHM(pOption);
|
|
}
|
|
*/
|
|
else {
|
|
site = getSite();
|
|
if (site != NULL) {
|
|
pNew->pDriv = site->CreateHistogramMemoryDriver(driver, pOption);
|
|
}
|
|
}
|
|
|
|
if (pNew->pDriv == NULL) {
|
|
DeleteDescriptor(pNew->pDes);
|
|
DeleteStringDict(pOption);
|
|
free(pNew);
|
|
return NULL;
|
|
}
|
|
pNew->iAccess = usUser;
|
|
pNew->iExponent = 0;
|
|
pNew->iInit = 0;
|
|
pNew->pDriv->pOption = pOption;
|
|
|
|
return pNew;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void DeleteHistMemory(void *pData)
|
|
{
|
|
pHistMem self;
|
|
|
|
self = (pHistMem) pData;
|
|
assert(self);
|
|
|
|
if (self->pDriv) {
|
|
DeleteHistDriver(self->pDriv);
|
|
}
|
|
if (self->pDes) {
|
|
DeleteDescriptor(self->pDes);
|
|
}
|
|
(void)Fortify_CheckAllMemory();
|
|
|
|
if (self->pCountInt) {
|
|
free(self->pCountInt);
|
|
}
|
|
if (self->pCall) {
|
|
DeleteCallBackInterface(self->pCall);
|
|
}
|
|
free(self);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int MakeHistMemory(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pHistMem pNew = NULL;
|
|
char pBueffel[512];
|
|
int iRet;
|
|
|
|
/* check no of arguments */
|
|
if (argc < 3) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: insufficient no of arguments to %s",
|
|
argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
/* make new HM */
|
|
strtolower(argv[2]);
|
|
pNew = CreateHistMemory(argv[2]);
|
|
if (!pNew) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1,
|
|
"ERROR: failed to create Histogram Memory %s, driver %s may be invalid or no memory",
|
|
argv[1], argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
StringDictAddPair(pNew->pDriv->pOption, "name", argv[1]);
|
|
|
|
/* install HM as command */
|
|
iRet =
|
|
AddCommand(pSics, argv[1], HistAction, DeleteHistMemory,
|
|
(void *) pNew);
|
|
if (!iRet) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: duplicate command %s not created", argv[1]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
DeleteHistMemory((void *) pNew);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
int HistGetOption(pHistMem self, char *name, char *result, int iLen)
|
|
{
|
|
assert(self);
|
|
strtolower(name);
|
|
return StringDictGet(self->pDriv->pOption, name, result, iLen);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
int HistSetOption(pHistMem self, char *name, char *value)
|
|
{
|
|
int status;
|
|
|
|
assert(self);
|
|
self->iInit = 1;
|
|
strtolower(name);
|
|
status = StringDictUpdate(self->pDriv->pOption, name, value);
|
|
if (status == 0) {
|
|
return StringDictAddPair(self->pDriv->pOption, name, value);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
int HistConfigure(pHistMem self, SConnection * pCon, SicsInterp * pSics)
|
|
{
|
|
int iRet, iVal;
|
|
char pValue[80];
|
|
|
|
assert(self);
|
|
assert(pCon);
|
|
|
|
if (isRunning(self->pCountInt)) {
|
|
SCWrite(pCon,
|
|
"ERROR: cannot configure histogram memory while counting",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
iRet = HistDriverConfig(self->pDriv, self->pDriv->pOption, pCon);
|
|
if (!iRet) {
|
|
SCWrite(pCon, "ERROR: failed to configure histogram memory", eError);
|
|
return 0;
|
|
}
|
|
iRet =
|
|
self->pDriv->Configure(self->pDriv, pCon, self->pDriv->pOption,
|
|
pSics);
|
|
if (!iRet) {
|
|
SCWrite(pCon, "ERROR: failed to configure histogram memory", eError);
|
|
return 0;
|
|
}
|
|
tracePar(self->pDes->name,"initialized");
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
float GetHistPreset(pHistMem self)
|
|
{
|
|
int i;
|
|
float fVal;
|
|
|
|
assert(self);
|
|
|
|
fVal = self->pDriv->fCountPreset;
|
|
if (self->pDriv->eCount == ePreset) {
|
|
for (i = 0; i < self->iExponent; i++) {
|
|
fVal /= 10.;
|
|
}
|
|
}
|
|
return fVal;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int SetHistPreset(pHistMem self, float fVal)
|
|
{
|
|
int i;
|
|
|
|
assert(self);
|
|
|
|
if (fVal < .0) {
|
|
return 0;
|
|
}
|
|
if (GetHistCountMode(self) == ePreset) {
|
|
for (i = 0; i < self->iExponent; i++) {
|
|
fVal *= 10.;
|
|
}
|
|
}
|
|
self->pDriv->fCountPreset = fVal;
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int GetHistDim(pHistMem self, int iDim[MAXDIM], int *nDim)
|
|
{
|
|
|
|
assert(self);
|
|
pDummy pDum;
|
|
hdbValue v;
|
|
pHdb node;
|
|
|
|
pDum = (pDummy)self;
|
|
if(strcmp(pDum->pDescriptor->name,"HistMemSec") == 0){
|
|
node = GetHipadabaNode(pDum->pDescriptor->parNode,"dim");
|
|
assert(node != NULL);
|
|
GetHipadabaPar(node,&v,NULL);
|
|
*nDim = v.arrayLength;
|
|
memcpy(iDim,v.v.intArray, *nDim*sizeof(int));
|
|
return 1;
|
|
}
|
|
|
|
getHMDataDim(self->pDriv->data, iDim, nDim);
|
|
if (isInTOFMode(self->pDriv->data)) {
|
|
iDim[*nDim] = getNoOfTimebins(self->pDriv->data);
|
|
*nDim = *nDim + 1;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
long HistSum(pHistMem self, SConnection * pCon,
|
|
int iStart[MAXDIM], int iEnd[MAXDIM])
|
|
{
|
|
assert(self);
|
|
return sumHMDataRectangle(self, pCon, iStart, iEnd);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
CounterMode GetHistCountMode(pHistMem self)
|
|
{
|
|
assert(self);
|
|
return self->pDriv->eCount;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int SetHistCountMode(pHistMem self, CounterMode eNew)
|
|
{
|
|
int i;
|
|
|
|
assert(self);
|
|
if (eNew == self->pDriv->eCount) {
|
|
return 1;
|
|
}
|
|
|
|
if (eNew == eTimer) {
|
|
for (i = 0; i < self->iExponent; i++) {
|
|
self->pDriv->fCountPreset /= 10.;
|
|
}
|
|
}
|
|
if (eNew == ePreset) {
|
|
for (i = 0; i < self->iExponent; i++) {
|
|
self->pDriv->fCountPreset *= 10.;
|
|
}
|
|
}
|
|
self->pDriv->eCount = eNew;
|
|
return 1;
|
|
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
long GetHistMonitor(pHistMem self, int i, SConnection * pCon)
|
|
{
|
|
assert(self);
|
|
return self->pDriv->GetMonitor(self->pDriv, i, pCon);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
void HistDirty(pHistMem self)
|
|
{
|
|
assert(self);
|
|
|
|
if(isSecondGen(self)){
|
|
SecHistDirty(self);
|
|
return;
|
|
}
|
|
|
|
if(self->pDriv != NULL){
|
|
updateHMData(self->pDriv->data);
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
const float *GetHistTimeBin(pHistMem self, int *iLength)
|
|
{
|
|
assert(self);
|
|
|
|
if(isSecondGen(self)){
|
|
return GetSecHistTimeBin(self,iLength);
|
|
}
|
|
|
|
*iLength = getNoOfTimebins(self->pDriv->data);
|
|
return getTimeBinning(self->pDriv->data);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int GetHistLength(pHistMem self)
|
|
{
|
|
assert(self);
|
|
|
|
if(isSecondGen(self)){
|
|
return GetSecHistLength(self);
|
|
}
|
|
|
|
return getHMDataLength(self->pDriv->data);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
float GetHistCountTime(pHistMem self, SConnection * pCon)
|
|
{
|
|
assert(self);
|
|
return self->pDriv->GetTime(self->pDriv, pCon);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int HistDoCount(pHistMem self, SConnection * pCon)
|
|
{
|
|
assert(self);
|
|
|
|
|
|
/* start */
|
|
return StartDevice(GetExecutor(), "HistogramMemory", self->pDes, self,
|
|
pCon, RUNRUN, self->pDriv->fCountPreset);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
int HistBlockCount(pHistMem self, SConnection * pCon)
|
|
{
|
|
int iRet;
|
|
|
|
assert(self);
|
|
|
|
/* start counting */
|
|
iRet = StartDevice(GetExecutor(), "HistogramMemory", self->pDes, self,
|
|
pCon, RUNDRIVE, self->pDriv->fCountPreset);
|
|
if (!iRet) {
|
|
/* error has already been reported */
|
|
return 0;
|
|
}
|
|
|
|
/* wait till end */
|
|
iRet = Wait4Success(GetExecutor());
|
|
if (iRet == DEVINT) {
|
|
SCWrite(pCon, "Counting aborted due to Interrupt", eError);
|
|
} else if (iRet == DEVERROR) {
|
|
SCWrite(pCon, "Counting finished with Problems", eValue);
|
|
iRet = 1;
|
|
} else {
|
|
SCWrite(pCon, "Counting finished", eValue);
|
|
iRet = 1;
|
|
}
|
|
|
|
|
|
return iRet;
|
|
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int SetHistogram(pHistMem self, SConnection * pCon,
|
|
int i, int iStart, int iEnd, HistInt * lData)
|
|
{
|
|
int ii, iErr, iRet;
|
|
char pBueffel[512], pError[80];
|
|
|
|
assert(self);
|
|
|
|
if (!self->iInit) {
|
|
SCWrite(pCon, "ERROR: histogram memory not initialised", eError);
|
|
return 0;
|
|
}
|
|
|
|
/* try at least three times */
|
|
for (ii = 0; ii < 3; ii++) {
|
|
iRet = self->pDriv->SetHistogram(self->pDriv, pCon,
|
|
i, iStart, iEnd, lData);
|
|
if (iRet == OKOK) {
|
|
updateHMData(self->pDriv->data);
|
|
return 1;
|
|
} else {
|
|
iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s ", pError);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr);
|
|
if (iRet == COTERM) {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int GetHistogram(pHistMem self, SConnection * pCon,
|
|
int i, int iStart, int iEnd, HistInt * lData,
|
|
int iDataLen)
|
|
{
|
|
assert(self);
|
|
|
|
if(isSecondGen(self)){
|
|
return GetSecHistogram(self,pCon,i,iStart,iEnd,lData,iDataLen);
|
|
}
|
|
|
|
|
|
if (!self->iInit) {
|
|
SCWrite(pCon, "ERROR: histogram memory not initialised", eError);
|
|
return 0;
|
|
}
|
|
|
|
if ((iEnd - iStart) > iDataLen / sizeof(HistInt)) {
|
|
SCWrite(pCon, "WARNING: truncating request to fit data space",
|
|
eWarning);
|
|
iEnd = (iDataLen / sizeof(HistInt)) - 1;
|
|
}
|
|
return getHMDataHistogram(self, pCon, i, iStart, iEnd-iStart, lData);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int GetHistogramDirect(pHistMem self, SConnection * pCon,
|
|
int i, int iStart, int iEnd, HistInt * lData,
|
|
int iDataLen)
|
|
{
|
|
int ii, iErr, iRet, iCopy;
|
|
char pBueffel[512], pError[80];
|
|
HistInt *lHist = NULL;
|
|
|
|
assert(self);
|
|
|
|
if (!self->iInit) {
|
|
SCWrite(pCon, "ERROR: histogram memory not initialised", eError);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* try at least three times */
|
|
for (ii = 0; ii < 3; ii++) {
|
|
iRet = self->pDriv->GetHistogram(self->pDriv, pCon,
|
|
i, iStart, iEnd, lData);
|
|
if (iRet == OKOK) {
|
|
tracePar(self->pDes->name,"!!datachange!!");
|
|
break;
|
|
} else {
|
|
iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s ", pError);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr);
|
|
if (iRet == COTERM) {
|
|
StringDictUpdate(self->pDriv->pOption, "error", pError);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
HistInt *GetHistogramPointer(pHistMem self, SConnection * pCon)
|
|
{
|
|
assert(self);
|
|
|
|
if(isSecondGen(self)){
|
|
return GetSecHistogramPointer(self,pCon);
|
|
}
|
|
|
|
|
|
if (!self->iInit) {
|
|
SCWrite(pCon, "ERROR: histogram memory not initialised", eError);
|
|
return NULL;
|
|
}
|
|
|
|
return getHMDataBufferPointer(self, pCon);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int PresetHistogram(pHistMem self, SConnection * pCon, HistInt lVal)
|
|
{
|
|
int ii, iErr, iRet;
|
|
char pBueffel[512], pError[80];
|
|
|
|
assert(self);
|
|
|
|
if (!self->iInit) {
|
|
SCWrite(pCon, "ERROR: histogram memory not initialised", eError);
|
|
return 0;
|
|
}
|
|
|
|
/* try at least three times */
|
|
for (ii = 0; ii < 3; ii++) {
|
|
iRet = self->pDriv->Preset(self->pDriv, pCon, lVal);
|
|
if (iRet == OKOK) {
|
|
updateHMData(self->pDriv->data);
|
|
return 1;
|
|
} else {
|
|
iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79);
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s ", pError);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr);
|
|
if (iRet == COTERM) {
|
|
StringDictUpdate(self->pDriv->pOption, "error", pError);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
static int HMCountInterest(int iEvent, void *pEvent, void *pUser)
|
|
{
|
|
SConnection *pCon = NULL;
|
|
char pBueffel[512];
|
|
|
|
pCon = (SConnection *) pUser;
|
|
|
|
if (pCon == NULL || !SCisConnected(pCon)) {
|
|
return -1;
|
|
}
|
|
|
|
if (iEvent == COUNTSTART && pUser != NULL) {
|
|
pCon = (SConnection *) pUser;
|
|
assert(pCon);
|
|
SCWrite(pCon, "HMCOUNTSTART", eEvent);
|
|
return 1;
|
|
} else if (iEvent == COUNTEND) {
|
|
assert(pCon);
|
|
SCWrite(pCon, "HMCOUNTEND", eEvent);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
static int checkHMEnd(pHistMem self, char *text)
|
|
{
|
|
int iTest, iEnd;
|
|
|
|
iEnd = getHMDataLength(self->pDriv->data);
|
|
if (text == NULL) {
|
|
return iEnd;
|
|
} else {
|
|
iTest = atoi(text);
|
|
if (iTest > iEnd) {
|
|
return iEnd;
|
|
} else {
|
|
return iTest;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
void HMListOption(pHistMem self, SConnection * pCon)
|
|
{
|
|
char pBuffer[512];
|
|
char name[20];
|
|
char pValue[128];
|
|
const char *pKey;
|
|
int i, iRet, iLen, iRank, iDiscard, tofMode;
|
|
float fVal;
|
|
char *pMode[] = { "timer", "monitor", NULL };
|
|
pDynString buf = NULL;
|
|
|
|
memset(pBuffer, 0, sizeof(pBuffer));
|
|
memset(pValue, 0, sizeof(pValue));
|
|
memset(name, 0, sizeof(name));
|
|
|
|
buf = CreateDynString(256,256);
|
|
if(buf == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory listing HM Options",eError);
|
|
return;
|
|
}
|
|
iRet = StringDictGet(self->pDriv->pOption, "name", name, 19);
|
|
if (0 == iRet) {
|
|
strcpy(name, "*");
|
|
}
|
|
iRet =
|
|
StringDictGet(self->pDriv->pOption, "driver", pValue,
|
|
sizeof(pValue) - 1);
|
|
if (0 < iRet) {
|
|
snprintf(pBuffer,sizeof(pBuffer)-1, "%s.driver = %s", name, pValue);
|
|
DynStringConcatLine(buf,pBuffer);
|
|
}
|
|
|
|
iRet = StringDictGetAsNumber(self->pDriv->pOption, "update", &fVal);
|
|
if (0 < iRet) {
|
|
snprintf(pBuffer,sizeof(pBuffer)-1, "%s.update = %d", name, (int) rint(fVal));
|
|
} else {
|
|
snprintf(pBuffer,sizeof(pBuffer)-1, "%s.update = 0 (no buffering)", name);
|
|
}
|
|
DynStringConcatLine(buf,pBuffer);
|
|
|
|
iRet = StringDictGetAsNumber(self->pDriv->pOption, "rank", &fVal);
|
|
if (0 < iRet) {
|
|
iRank = (int) rint(fVal);
|
|
snprintf(pBuffer,sizeof(pBuffer)-1, "%s.rank = %d", name, iRank);
|
|
DynStringConcatLine(buf,pBuffer);
|
|
} else {
|
|
iRank = 0;
|
|
}
|
|
for (i = 0; i < iRank; i++) {
|
|
snprintf(pValue,sizeof(pValue)-1, "dim%1.1d", i);
|
|
iRet = StringDictGetAsNumber(self->pDriv->pOption, pValue, &fVal);
|
|
if (0 < iRet) {
|
|
snprintf(pBuffer,sizeof(pBuffer)-1, "%s.dim%1.1d = %d", name, i, (int) rint(fVal));
|
|
DynStringConcatLine(buf,pBuffer);
|
|
}
|
|
}
|
|
|
|
pKey =
|
|
StringDictGetNext(self->pDriv->pOption, pValue, sizeof(pValue) - 1);
|
|
while (pKey != NULL) {
|
|
iDiscard = 0;
|
|
if (0 == strcmp("name", pKey))
|
|
iDiscard = 1;
|
|
if (0 == strcmp("driver", pKey))
|
|
iDiscard = 1;
|
|
if (0 == strcmp("update", pKey))
|
|
iDiscard = 1;
|
|
if (0 == strcmp("rank", pKey))
|
|
iDiscard = 1;
|
|
if (NULL != strstr(pKey, "dim"))
|
|
iDiscard = 1;
|
|
if (0 == iDiscard) {
|
|
snprintf(pBuffer, 511, "%s.%s = %s", name, pKey, pValue);
|
|
DynStringConcatLine(buf,pBuffer);
|
|
}
|
|
pKey =
|
|
StringDictGetNext(self->pDriv->pOption, pValue,
|
|
sizeof(pValue) - 1);
|
|
}
|
|
|
|
/* Display Count Mode */
|
|
snprintf(pBuffer,sizeof(pBuffer)-1, "%s.CountMode = %s", name, pMode[self->pDriv->eCount]);
|
|
DynStringConcatLine(buf,pBuffer);
|
|
SCWrite(pCon, pBuffer, eValue);
|
|
|
|
/* Display Preset */
|
|
snprintf(pBuffer,sizeof(pBuffer)-1, "%s.preset = %f", name, self->pDriv->fCountPreset);
|
|
DynStringConcatLine(buf,pBuffer);
|
|
|
|
if (self->pDriv->data->nTimeChan > 2) {
|
|
tofMode = 1;
|
|
} else {
|
|
tofMode = 0;
|
|
}
|
|
snprintf(pBuffer,sizeof(pBuffer)-1, "%s.tofMode = %d", name, tofMode);
|
|
DynStringConcatLine(buf,pBuffer);
|
|
SCWrite(pCon, GetCharArray(buf), eValue);
|
|
DeleteDynString(buf);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static pDynString formatTOF(pHistMem self)
|
|
{
|
|
const float *timebin;
|
|
int iLength, i, delay, delta = .0;
|
|
char number[20];
|
|
pDynString result = NULL;
|
|
|
|
timebin = GetHistTimeBin(self, &iLength);
|
|
if(timebin != NULL){
|
|
delay = timebin[0];
|
|
result = CreateDynString(512,512);
|
|
if(result == NULL){
|
|
return NULL;
|
|
}
|
|
for(i = 0; i < iLength; i++){
|
|
snprintf(number,20," %12d", (int)(timebin[i] - delay));
|
|
DynStringConcat(result,number);
|
|
if(i % 5 == 0 && i != 0){
|
|
DynStringConcatChar(result,'\n');
|
|
}
|
|
}
|
|
/*
|
|
* add the extra one
|
|
*/
|
|
if(iLength > 3){
|
|
delta = ABS(timebin[iLength -2] - timebin[iLength -1]);
|
|
}
|
|
snprintf(number,20," %12d", (int)(timebin[iLength -1] + delta - delay ));
|
|
DynStringConcat(result,number);
|
|
return result;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pHistMem self = NULL;
|
|
char pBueffel[512], pNumber[20];
|
|
int iaStart[MAXDIM], iaEnd[MAXDIM];
|
|
Tcl_DString tResult;
|
|
int iRet, iVal;
|
|
char *pBuf = NULL, *pPtr;
|
|
float fVal;
|
|
long lVal;
|
|
HistInt *lData = NULL;
|
|
int iStart, iEnd, iNum, i;
|
|
pDynString tofres = NULL;
|
|
CounterMode eCount;
|
|
char *pMode[] = {
|
|
"timer",
|
|
"monitor",
|
|
NULL
|
|
};
|
|
double dStart, dStep;
|
|
int nDim, iSwitch;
|
|
long lID;
|
|
|
|
|
|
assert(pCon);
|
|
assert(pSics);
|
|
assert(pData);
|
|
|
|
self = (pHistMem) pData;
|
|
|
|
/* check arguments */
|
|
if (argc < 2) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: no arguments specified to %s", argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
/* interest command */
|
|
strtolower(argv[1]);
|
|
if (strcmp(argv[1], "interest") == 0) {
|
|
lID = RegisterCallback(self->pCall,
|
|
COUNTSTART, HMCountInterest,
|
|
SCCopyConnection(pCon), SCDeleteConnection);
|
|
lID = RegisterCallback(self->pCall,
|
|
COUNTEND, HMCountInterest,
|
|
SCCopyConnection(pCon), SCDeleteConnection);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "configure") == 0) {
|
|
/* enough arguments ? */
|
|
if (argc < 4) {
|
|
if (argc < 3) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: not enough arguments to %s configure",
|
|
argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
} else { /* get value case */
|
|
|
|
strtolower(argv[2]);
|
|
iRet = HistGetOption(self, argv[2], NULL, 0);
|
|
if (!iRet) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: option %s not known", argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
pBuf = (char *) malloc((iRet + 60) * sizeof(char));
|
|
if (!pBuf) {
|
|
SCWrite(pCon, "ERROR: no memory in HistAction", eError);
|
|
return 0;
|
|
}
|
|
memset(pBuf, 0, iRet + 60);
|
|
HistGetOption(self, argv[2], pBuf, iRet + 60);
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "%s.%s = %s", argv[0], argv[2], pBuf);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
free(pBuf);
|
|
return 1;
|
|
}
|
|
}
|
|
/* do it */
|
|
Arg2Text(argc - 3, &argv[3], pBueffel, 511);
|
|
/* authorise */
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1,
|
|
"ERROR: you need to be manager in order to configure %s",
|
|
argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
strtolower(argv[2]);
|
|
iRet = HistSetOption(self, argv[2], pBueffel);
|
|
if (!iRet) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: option %s not known", argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "preset") == 0) { /* preset */
|
|
if (argc < 3) { /* get value */
|
|
fVal = GetHistPreset(self);
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "%s.preset = %f", argv[0], fVal);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else { /* set case */
|
|
|
|
if (isRunning(self->pCountInt)) {
|
|
SCWrite(pCon, "ERROR: cannot change preset while counting",
|
|
eError);
|
|
return 0;
|
|
}
|
|
fVal = atof(argv[2]);
|
|
if (!SCMatchRights(pCon, self->iAccess)) {
|
|
return 0;
|
|
}
|
|
iRet = SetHistPreset(self, fVal);
|
|
SCparChange(pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "exponent") == 0) { /* preset */
|
|
if (argc < 3) { /* get value */
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "%s.exponent = %d", argv[0], self->iExponent);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else { /* set case */
|
|
|
|
if (!SCMatchRights(pCon, self->iAccess)) {
|
|
return 0;
|
|
}
|
|
self->iExponent = atoi(argv[2]);
|
|
SCparChange(pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "countmode") == 0) { /* countmode */
|
|
if (argc < 3) { /* get value */
|
|
eCount = GetHistCountMode(self);
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "%s.CountMode = %s", argv[0], pMode[eCount]);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else { /* set case */
|
|
|
|
strtolower(argv[2]);
|
|
if (isRunning(self->pCountInt)) {
|
|
SCWrite(pCon, "ERROR: cannot change countmode while counting",
|
|
eError);
|
|
return 0;
|
|
}
|
|
if (!SCMatchRights(pCon, self->iAccess)) {
|
|
return 0;
|
|
}
|
|
if (strcmp(argv[2], "timer") == 0) {
|
|
eCount = eTimer;
|
|
} else if (strcmp(argv[2], "monitor") == 0) {
|
|
eCount = ePreset;
|
|
} else {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s invalid as CountMode", argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = SetHistCountMode(self, eCount);
|
|
SCparChange(pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
|
|
} else if (strcmp(argv[1], "init") == 0) {
|
|
if (SCMatchRights(pCon, usMugger)) {
|
|
iRet = HistConfigure(self, pCon, pSics);
|
|
if (iRet) {
|
|
self->iInit = 1;
|
|
InvokeCallBack(self->pCall,DIMCHANGE,NULL);
|
|
SCSendOK(pCon);
|
|
} else {
|
|
self->iInit = 0;
|
|
}
|
|
return iRet;
|
|
} else {
|
|
return 0;
|
|
}
|
|
} else if (strcmp(argv[1], "clearhm") == 0) {
|
|
/*
|
|
clear the local copy of the HM. Assumes that the HM
|
|
clears itself on start. Which it does.
|
|
*/
|
|
if (SCMatchRights(pCon, usUser)) {
|
|
if(self->pDriv->data != NULL){
|
|
clearHMData(self->pDriv->data);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
} else {
|
|
return 0;
|
|
}
|
|
} else if (strcmp(argv[1], "list") == 0) {
|
|
HMListOption(self, pCon);
|
|
return 1;
|
|
}
|
|
/* stop */
|
|
else if (strcmp(argv[1], "stop") == 0) {
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
self->pDriv->Halt(self->pDriv);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/* pause */
|
|
else if (strcmp(argv[1], "pause") == 0) {
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
self->pDriv->Pause(self->pDriv, pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/* state */
|
|
else if (strcmp(argv[1], "status") == 0) {
|
|
HistCountStatus(self,pCon);
|
|
if(isRunning(self->pCountInt)){
|
|
SCPrintf(pCon,eValue,"%s.status = run",argv[0]);
|
|
} else {
|
|
SCPrintf(pCon,eValue,"%s.status = idle",argv[0]);
|
|
}
|
|
return 1;
|
|
}
|
|
/* normal counting */
|
|
else if (strcmp(argv[1], "count") == 0) {
|
|
if (SCMatchRights(pCon, self->iAccess)) {
|
|
if (IsCounting(pServ->pExecutor)) {
|
|
SCWrite(pCon, "WARNING: already counting!", eWarning);
|
|
return 1;
|
|
}
|
|
iRet = HistDoCount(self, pCon);
|
|
if (iRet == 1) {
|
|
SCSendOK(pCon);
|
|
}
|
|
return iRet;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
/* forced count, for the case several hm need to be started */
|
|
else if (strcmp(argv[1], "countf") == 0) {
|
|
if (SCMatchRights(pCon, self->iAccess)) {
|
|
iRet = HistDoCount(self, pCon);
|
|
if (iRet == 1) {
|
|
SCSendOK(pCon);
|
|
}
|
|
return iRet;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
/* count in blocking mode */
|
|
else if (strcmp(argv[1], "countblock") == 0) {
|
|
if (SCMatchRights(pCon, self->iAccess)) {
|
|
iRet = HistBlockCount(self, pCon);
|
|
if (iRet == 1) {
|
|
SCSendOK(pCon);
|
|
}
|
|
return iRet;
|
|
} else {
|
|
return 0;
|
|
}
|
|
} else if (strcmp(argv[1], "initval") == 0) { /* initialize to a value */
|
|
/* check user rights */
|
|
if (!SCMatchRights(pCon, self->iAccess)) {
|
|
return 0;
|
|
}
|
|
|
|
/* enough arguments */
|
|
if (argc < 3) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: insufficient number of arguments to %s %s",
|
|
argv[0], argv[1]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
lVal = atoi(argv[2]);
|
|
iRet = PresetHistogram(self, pCon, lVal);
|
|
if (iRet) {
|
|
SCSendOK(pCon);
|
|
}
|
|
return iRet;
|
|
} else if (strcmp(argv[1], "initfile") == 0) { /* initialize from a file */
|
|
/* check user rights */
|
|
if (!SCMatchRights(pCon, self->iAccess)) {
|
|
return 0;
|
|
}
|
|
|
|
/* enough arguments */
|
|
if (argc < 3) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: insufficient number of arguments to %s %s",
|
|
argv[0], argv[1]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = loadHMData(self->pDriv->data, pCon, argv[2]);
|
|
self->pDriv->SetHistogram(self->pDriv, pCon, 0, 0, GetHistLength(self),
|
|
self->pDriv->data->localBuffer);
|
|
if (iRet) {
|
|
SCSendOK(pCon);
|
|
}
|
|
return iRet;
|
|
} else if (strcmp(argv[1], "get") == 0) { /* get a histogram */
|
|
/* check parameters, first required: no of Hist */
|
|
if (argc < 3) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: insufficient number of arguments to %s %s",
|
|
argv[0], argv[1]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iNum = atoi(argv[2]);
|
|
|
|
/* optional iStart, default 0 */
|
|
iStart = 0;
|
|
if (argc > 3) {
|
|
iStart = atoi(argv[3]);
|
|
}
|
|
|
|
/* check iStart */
|
|
if (iStart < 0) {
|
|
SCWrite(pCon, "WARNING: Invalid start position defaulted to 0",
|
|
eWarning);
|
|
iStart = 0;
|
|
}
|
|
|
|
if (argc > 4) {
|
|
iEnd = checkHMEnd(self, argv[4]);
|
|
} else {
|
|
iEnd = checkHMEnd(self, NULL);
|
|
}
|
|
|
|
if (iNum != 0 && argc > 4) {
|
|
iEnd = atoi(argv[4]);
|
|
}
|
|
|
|
/* allocate data storage and get it */
|
|
lData = (HistInt *) malloc(iEnd * sizeof(HistInt));
|
|
if (!lData) {
|
|
SCWrite(pCon, "ERROR: no memory in HistAction/get", eError);
|
|
return 0;
|
|
}
|
|
memset(lData, 0, iEnd * sizeof(HistInt));
|
|
if (iNum == 0) {
|
|
iRet = GetHistogram(self, pCon, iNum, iStart, iEnd,
|
|
lData, iEnd * sizeof(long));
|
|
} else {
|
|
iRet = GetHistogramDirect(self, pCon, iNum, iStart, iEnd,
|
|
lData, iEnd * sizeof(long));
|
|
}
|
|
if (!iRet) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: cannot retrieve histogram %d", iNum);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
free(lData);
|
|
return 0;
|
|
}
|
|
|
|
/* OK, got it, convert to text using Tcl's Dstring for lazyness */
|
|
Tcl_DStringInit(&tResult);
|
|
Tcl_DStringAppend(&tResult, "Histogram =", -1);
|
|
for (i = 0; i < iEnd - iStart; i++) {
|
|
snprintf(pNumber,sizeof(pNumber)-1, " %d", lData[i]);
|
|
Tcl_DStringAppend(&tResult, pNumber, -1);
|
|
}
|
|
|
|
/* Write it */
|
|
SCWrite(pCon, Tcl_DStringValue(&tResult), eValue);
|
|
|
|
/* clean up and go */
|
|
free(lData);
|
|
Tcl_DStringFree(&tResult);
|
|
return 1;
|
|
}
|
|
/*-------- get uuencoded */
|
|
else if (strcmp(argv[1], "uuget") == 0) { /* get a histogram */
|
|
/* check parameters, first required: no of Hist */
|
|
if (argc < 3) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: insufficient number of arguments to %s %s",
|
|
argv[0], argv[1]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iNum = atoi(argv[2]);
|
|
|
|
/* optional iStart, default 0 */
|
|
iStart = 0;
|
|
if (argc > 3) {
|
|
iStart = atoi(argv[3]);
|
|
}
|
|
|
|
/* check iStart */
|
|
if (iStart < 0) {
|
|
SCWrite(pCon, "WARNING: Invalid start position defaulted to 0",
|
|
eWarning);
|
|
iStart = 0;
|
|
}
|
|
|
|
if (argc > 4) {
|
|
iEnd = checkHMEnd(self, argv[4]);
|
|
} else {
|
|
iEnd = checkHMEnd(self, NULL);
|
|
}
|
|
|
|
/* allocate data storage and get it */
|
|
lData = (HistInt *) malloc((iEnd + 1) * sizeof(HistInt));
|
|
if (!lData) {
|
|
SCWrite(pCon, "ERROR: no memory in HistAction/get", eError);
|
|
return 0;
|
|
}
|
|
memset(lData, 0, (iEnd + 1) * sizeof(HistInt));
|
|
iRet = GetHistogram(self, pCon, iNum, iStart, iEnd,
|
|
&lData[1], iEnd * sizeof(HistInt));
|
|
if (!iRet) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: cannot retrieve histogram %d", iNum);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
free(lData);
|
|
return 0;
|
|
}
|
|
/* lData[0] is the length of the histogram */
|
|
lData[0] = iEnd;
|
|
|
|
/* convert to network byte order */
|
|
for (i = 0; i < iEnd + 1; i++) {
|
|
lData[i] = htonl(lData[i]);
|
|
}
|
|
/* Write it */
|
|
SCWriteUUencoded(pCon, "SicsHistogram", lData,
|
|
(iEnd + 1) * sizeof(HistInt));
|
|
|
|
/* clean up and go */
|
|
free(lData);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "zipget") == 0) { /* get a histogram */
|
|
/* check parameters, first required: no of Hist */
|
|
if (argc < 3) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: insufficient number of arguments to %s %s",
|
|
argv[0], argv[1]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iNum = atoi(argv[2]);
|
|
|
|
/* optional iStart, default 0 */
|
|
iStart = 0;
|
|
if (argc > 3) {
|
|
iStart = atoi(argv[3]);
|
|
}
|
|
|
|
/* check iStart */
|
|
if (iStart < 0) {
|
|
SCWrite(pCon, "WARNING: Invalid start position defaulted to 0",
|
|
eWarning);
|
|
iStart = 0;
|
|
}
|
|
|
|
if (argc > 4) {
|
|
iEnd = checkHMEnd(self, argv[4]);
|
|
} else {
|
|
iEnd = checkHMEnd(self, NULL);
|
|
}
|
|
|
|
/* allocate data storage and get it */
|
|
lData = (HistInt *) malloc((iEnd + 1) * sizeof(HistInt));
|
|
if (!lData) {
|
|
SCWrite(pCon, "ERROR: no memory in HistAction/get", eError);
|
|
return 0;
|
|
}
|
|
memset(lData, 0, (iEnd + 1) * sizeof(HistInt));
|
|
iRet = GetHistogram(self, pCon, iNum, iStart, iEnd,
|
|
&lData[0], iEnd * sizeof(HistInt));
|
|
if (!iRet) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: cannot retrieve histogram %d", iNum);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
free(lData);
|
|
return 0;
|
|
}
|
|
|
|
/* convert to network byte order */
|
|
for (i = 0; i < iEnd; i++) {
|
|
lData[i] = htonl(lData[i]);
|
|
}
|
|
/* Write it */
|
|
SCWriteZipped(pCon, argv[0], lData, iEnd * sizeof(HistInt));
|
|
|
|
/* clean up and go */
|
|
free(lData);
|
|
return 1;
|
|
}
|
|
/* retrive no of Timebins */
|
|
else if (strcmp(argv[1], "notimebin") == 0) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1,
|
|
"%s.notimebin = %d", argv[0],
|
|
getNoOfTimebins(self->pDriv->data));
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
/* retrive time binning */
|
|
else if (strcmp(argv[1], "timebin") == 0) {
|
|
Tcl_DStringInit(&tResult);
|
|
Tcl_DStringAppend(&tResult, "histogram.timebins =", -1);
|
|
for (i = 0; i < self->pDriv->data->nTimeChan; i++) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "%.2f ", self->pDriv->data->timeBinning[i]);
|
|
Tcl_DStringAppend(&tResult, pBueffel, -1);
|
|
}
|
|
/* Write it */
|
|
SCWrite(pCon, Tcl_DStringValue(&tResult), eValue);
|
|
|
|
/* clean up and go */
|
|
Tcl_DStringFree(&tResult);
|
|
return 1;
|
|
}
|
|
/* getdelay */
|
|
else if(strcmp(argv[1],"getdelay") == 0){
|
|
if(self->pDriv->data->nTimeChan > 1) {
|
|
iVal = (int)self->pDriv->data->timeBinning[0];
|
|
SCPrintf(pCon,eValue,"hm.delay = %d", iVal);
|
|
return 1;
|
|
} else {
|
|
SCPrintf(pCon,eError,"ERROR: no TOF configured");
|
|
return 0;
|
|
}
|
|
}
|
|
/* formattof */
|
|
else if(strcmp(argv[1],"formattof") == 0){
|
|
tofres = formatTOF(self);
|
|
if(tofres == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory or not TOF", eError);
|
|
return 0;
|
|
} else {
|
|
SCWrite(pCon,GetCharArray(tofres), eValue);
|
|
DeleteDynString(tofres);
|
|
return 1;
|
|
}
|
|
}
|
|
/* generate time binning */
|
|
else if (strcmp(argv[1], "genbin") == 0) {
|
|
if (isRunning(self->pCountInt)) {
|
|
SCWrite(pCon, "ERROR: cannot change time binning while counting",
|
|
eError);
|
|
return 0;
|
|
}
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
return 0;
|
|
}
|
|
if (argc < 5) {
|
|
SCWrite(pCon, "ERROR: not enough aguments to genbin", eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetDouble(pSics->pTcl, argv[2], &dStart);
|
|
if (iRet != TCL_OK) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Failed to convert %s to number", argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetDouble(pSics->pTcl, argv[3], &dStep);
|
|
if (iRet != TCL_OK) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Failed to convert %s to number", argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[4], &iNum);
|
|
if (iRet != TCL_OK) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Failed to convert %s to number", argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
if (iNum >= MAXCHAN) {
|
|
SCWrite(pCon,
|
|
"ERROR: number of requested time bins exceeds maximum permissible number",
|
|
eError);
|
|
return 0;
|
|
}
|
|
if (iNum <= 0) {
|
|
SCWrite(pCon, "ERROR: at least one time bin required!", eError);
|
|
return 0;
|
|
}
|
|
/* do it */
|
|
genTimeBinning(self->pDriv->data, (float) dStart, (float) dStep, iNum);
|
|
InvokeCallBack(self->pCall,DIMCHANGE,NULL);
|
|
SCparChange(pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/* set a time bin */
|
|
else if (strcmp(argv[1], "setbin") == 0) {
|
|
if (isRunning(self->pCountInt)) {
|
|
SCWrite(pCon, "ERROR: cannot change time binning while counting",
|
|
eError);
|
|
return 0;
|
|
}
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
return 0;
|
|
}
|
|
if (argc < 4) {
|
|
SCWrite(pCon, "ERROR: not enough aguments to setbin", eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[2], &iNum);
|
|
if (iRet != TCL_OK) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Failed to convert %s to number", argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetDouble(pSics->pTcl, argv[3], &dStep);
|
|
if (iRet != TCL_OK) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Failed to convert %s to number", argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
if ((iNum < 0) || (iNum > MAXCHAN)) {
|
|
SCWrite(pCon, "ERROR: requested time bin out or permissible range",
|
|
eError);
|
|
return 0;
|
|
}
|
|
setTimeBin(self->pDriv->data, iNum, (float) dStep);
|
|
InvokeCallBack(self->pCall,DIMCHANGE,NULL);
|
|
self->iInit = 0;
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/* clear time bin info */
|
|
else if (strcmp(argv[1], "clearbin") == 0) {
|
|
if (isRunning(self->pCountInt)) {
|
|
SCWrite(pCon, "ERROR: cannot change time binning while counting",
|
|
eError);
|
|
return 0;
|
|
}
|
|
clearTimeBinning(self->pDriv->data);
|
|
InvokeCallBack(self->pCall,DIMCHANGE,NULL);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/* error */
|
|
else if (strcmp(argv[1], "error") == 0) {
|
|
StringDictGet(self->pDriv->pOption, "error", pBueffel, sizeof(pBueffel));
|
|
SCPrintf(pCon,eValue,"%s.error = %s", argv[0], pBueffel);
|
|
return 1;
|
|
}
|
|
/*-------- sum */
|
|
else if (strcmp(argv[1], "sum") == 0) {
|
|
/* read following arguments as ints and put them
|
|
into the iStart and iEnd array in succession.
|
|
But first check if we have an even number.
|
|
*/
|
|
if (((argc - 2) % 2) || (argc - 2) == 0) {
|
|
SCWrite(pCon,
|
|
"ERROR: need start and end for each dimension", eError);
|
|
return 0;
|
|
}
|
|
nDim = 0;
|
|
iSwitch = 0;
|
|
for (i = 0; i < argc - 2; i++) {
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[i + 2], &iVal);
|
|
if (iSwitch) {
|
|
iaEnd[nDim] = iVal;
|
|
nDim++;
|
|
iSwitch = 0;
|
|
} else {
|
|
iSwitch = 1;
|
|
iaStart[nDim] = iVal;
|
|
}
|
|
}
|
|
lVal = HistSum(self, pCon, iaStart, iaEnd);
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "%s.sum = %ld", argv[0], lVal);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s does not understand command %s",
|
|
argv[0], argv[1]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|