1723 lines
48 KiB
C
1723 lines
48 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
|
|
|
|
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"
|
|
/*
|
|
#define LOADDEBUG 1
|
|
*/
|
|
/*------------------------------------------------------------------------*/
|
|
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(!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->Start(self->pDriv, pCon);
|
|
if(iRet == OKOK)
|
|
{
|
|
updateHMData(self->pDriv->data);
|
|
return iRet;
|
|
}
|
|
else
|
|
{
|
|
iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
|
|
sprintf(pBueffel,"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);
|
|
return HWFault;
|
|
}
|
|
}
|
|
}
|
|
SCWrite(pCon,"ERROR: failed to fix histogram memory problem",eError);
|
|
SCSetInterrupt(pCon,eAbortBatch);
|
|
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);
|
|
sprintf(pBueffel,"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);
|
|
return HWFault;
|
|
}
|
|
}
|
|
}
|
|
SCWrite(pCon,"ERROR: failed to fix histogram memory problem",eError);
|
|
SCSetInterrupt(pCon,eAbortBatch);
|
|
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);
|
|
sprintf(pBueffel,"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);
|
|
return HWFault;
|
|
}
|
|
}
|
|
}
|
|
SCWrite(pCon,"ERROR: failed to fix histogram memory problem",eError);
|
|
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);
|
|
return COTERM;
|
|
}
|
|
|
|
eCt = self->pDriv->GetCountStatus(self->pDriv,pCon);
|
|
if(eCt == HWFault)
|
|
{
|
|
iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
|
|
sprintf(pBueffel,"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);
|
|
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);
|
|
}
|
|
|
|
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);
|
|
sprintf(pBueffel,"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);
|
|
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");
|
|
|
|
/* initialise driver */
|
|
if(strcmp(driver,"sim") == 0)
|
|
{
|
|
pNew->pDriv = CreateSIMHM(pOption);
|
|
}
|
|
else if(strcmp(driver,"mcstas") == 0)
|
|
{
|
|
pNew->pDriv = NewMcStasHM(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);
|
|
}
|
|
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)
|
|
{
|
|
sprintf(pBueffel,"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)
|
|
{
|
|
sprintf(pBueffel,"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)
|
|
{
|
|
sprintf(pBueffel,"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);
|
|
|
|
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;
|
|
}
|
|
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);
|
|
|
|
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);
|
|
updateHMData(self->pDriv->data);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
const float *GetHistTimeBin(pHistMem self, int *iLength)
|
|
{
|
|
assert(self);
|
|
*iLength = getNoOfTimebins(self->pDriv->data);
|
|
return getTimeBinning(self->pDriv->data);
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
int GetHistLength(pHistMem self)
|
|
{
|
|
assert(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);
|
|
|
|
/* send a COUNTSTART event */
|
|
InvokeCallBack(self->pCall,COUNTSTART,pCon);
|
|
|
|
/* start */
|
|
return StartDevice(GetExecutor(),"HistogramMemory", self->pDes, self,
|
|
pCon, self->pDriv->fCountPreset);
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
int HistBlockCount(pHistMem self, SConnection *pCon)
|
|
{
|
|
int iRet;
|
|
|
|
assert(self);
|
|
|
|
/* start counting */
|
|
iRet = StartDevice(GetExecutor(),"HistogramMemory", self->pDes, self,
|
|
pCon, self->pDriv->fCountPreset);
|
|
if(!iRet)
|
|
{
|
|
/* error has already been reported */
|
|
return 0;
|
|
}
|
|
|
|
/* send a COUNTSTART event */
|
|
InvokeCallBack(self->pCall,COUNTSTART,pCon);
|
|
|
|
/* wait till end */
|
|
iRet = Wait4Success(GetExecutor());
|
|
if(iRet == DEVINT)
|
|
{
|
|
SCWrite(pCon,"Counting aborted due to Interrupt",eStatus);
|
|
}
|
|
else if(iRet == DEVERROR)
|
|
{
|
|
SCWrite(pCon,"Counting finished with Problems",eStatus);
|
|
iRet = 1;
|
|
}
|
|
else
|
|
{
|
|
SCWrite(pCon,"Counting finished",eStatus);
|
|
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);
|
|
sprintf(pBueffel,"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(!self->iInit)
|
|
{
|
|
SCWrite(pCon,"ERROR: histogram memory not initialised",eError);
|
|
return 0;
|
|
}
|
|
|
|
if(iEnd > 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,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)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
|
|
sprintf(pBueffel,"ERROR: %s ",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
|
|
if(iRet == COTERM)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
HistInt *GetHistogramPointer(pHistMem self, SConnection *pCon)
|
|
{
|
|
assert(self);
|
|
|
|
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);
|
|
sprintf(pBueffel,"ERROR: %s ",pError);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
|
|
if(iRet == COTERM)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static int HMCountInterest(int iEvent, void *pEvent, void *pUser,
|
|
commandContext cc)
|
|
{
|
|
SConnection *pCon = NULL;
|
|
char pBueffel[512];
|
|
|
|
if(iEvent == COUNTSTART)
|
|
{
|
|
pCon = (SConnection *)pUser;
|
|
assert(pCon);
|
|
SCWriteInContext(pCon,"HMCOUNTSTART",eWarning,cc);
|
|
return 1;
|
|
}
|
|
else if(iEvent == COUNTEND)
|
|
{
|
|
pCon = (SConnection *)pUser;
|
|
assert(pCon);
|
|
SCWriteInContext(pCon,"HMCOUNTEND",eWarning,cc);
|
|
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};
|
|
|
|
memset(pBuffer, 0, sizeof(pBuffer));
|
|
memset(pValue, 0, sizeof(pValue));
|
|
memset(name, 0, sizeof(name));
|
|
|
|
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) {
|
|
sprintf(pBuffer,"%s.driver = %s",name,pValue);
|
|
SCWrite(pCon,pBuffer,eStatus);
|
|
}
|
|
|
|
iRet = StringDictGetAsNumber(self->pDriv->pOption,"update",&fVal);
|
|
if(0<iRet) {
|
|
sprintf(pBuffer,"%s.update = %d",name,(int)rint(fVal));
|
|
} else {
|
|
sprintf(pBuffer,"%s.update = 0 (no buffering)",name);
|
|
}
|
|
SCWrite(pCon,pBuffer,eStatus);
|
|
|
|
iRet = StringDictGetAsNumber(self->pDriv->pOption,"rank",&fVal);
|
|
if(0<iRet) {
|
|
iRank = (int)rint(fVal);
|
|
sprintf(pBuffer,"%s.rank = %d",name,iRank);
|
|
SCWrite(pCon,pBuffer,eStatus);
|
|
} else {
|
|
iRank = 0;
|
|
}
|
|
for(i=0; i<iRank; i++){
|
|
sprintf(pValue,"dim%1.1d",i);
|
|
iRet = StringDictGetAsNumber(self->pDriv->pOption,pValue,&fVal);
|
|
if(0<iRet){
|
|
sprintf(pBuffer,"%s.dim%1.1d = %d",name,i,(int)rint(fVal));
|
|
SCWrite(pCon,pBuffer,eStatus);
|
|
}
|
|
}
|
|
|
|
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);
|
|
SCWrite(pCon,pBuffer,eStatus);
|
|
}
|
|
pKey = StringDictGetNext(self->pDriv->pOption,pValue,sizeof(pValue)-1);
|
|
}
|
|
|
|
/* Display Count Mode */
|
|
sprintf(pBuffer,"%s.CountMode = %s",name,pMode[self->pDriv->eCount]);
|
|
SCWrite(pCon,pBuffer,eStatus);
|
|
|
|
/* Display Preset */
|
|
sprintf(pBuffer,"%s.preset = %f",name,self->pDriv->fCountPreset);
|
|
SCWrite(pCon,pBuffer,eStatus);
|
|
|
|
if(self->pDriv->data->nTimeChan > 2) {
|
|
tofMode = 1;
|
|
} else {
|
|
tofMode = 0;
|
|
}
|
|
sprintf(pBuffer,"%s.tofMode = %d",name,tofMode);
|
|
SCWrite(pCon,pBuffer,eStatus);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
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;
|
|
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)
|
|
{
|
|
sprintf(pBueffel,"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, SCGetContext(pCon),
|
|
COUNTSTART, HMCountInterest,
|
|
pCon, NULL);
|
|
SCRegister(pCon,pSics, self->pCall,lID);
|
|
lID = RegisterCallback(self->pCall, SCGetContext(pCon),
|
|
COUNTEND, HMCountInterest,
|
|
pCon, NULL);
|
|
SCRegister(pCon,pSics, self->pCall,lID);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
else if(strcmp(argv[1],"configure") == 0)
|
|
{
|
|
/* enough arguments ? */
|
|
if(argc < 4)
|
|
{
|
|
if(argc < 3)
|
|
{
|
|
sprintf(pBueffel,"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)
|
|
{
|
|
sprintf(pBueffel,"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);
|
|
sprintf(pBueffel,"%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))
|
|
{
|
|
sprintf(pBueffel,
|
|
"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)
|
|
{
|
|
sprintf(pBueffel,"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);
|
|
sprintf(pBueffel,"%s.preset = %f",argv[0],fVal);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
else /* set case */
|
|
{
|
|
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 */
|
|
{
|
|
sprintf(pBueffel,"%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);
|
|
sprintf(pBueffel,"%s.CountMode = %s",argv[0],pMode[eCount]);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
else /* set case */
|
|
{
|
|
strtolower(argv[2]);
|
|
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
|
|
{
|
|
sprintf(pBueffel,"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;
|
|
SCSendOK(pCon);
|
|
}
|
|
else
|
|
{
|
|
self->iInit = 0;
|
|
}
|
|
return iRet;
|
|
}
|
|
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;
|
|
}
|
|
/* 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)
|
|
{
|
|
sprintf(pBueffel,"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],"get") == 0) /* get a histogram */
|
|
{
|
|
/* check parameters, first required: no of Hist */
|
|
if(argc < 3)
|
|
{
|
|
sprintf(pBueffel,"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*sizeof(HistInt));
|
|
if(!lData)
|
|
{
|
|
SCWrite(pCon,"ERROR: no memory in HistAction/get",eError);
|
|
return 0;
|
|
}
|
|
memset(lData,0,iEnd*sizeof(HistInt));
|
|
iRet = GetHistogram(self,pCon,iNum,iStart,iEnd,
|
|
lData,iEnd*sizeof(long));
|
|
if(!iRet)
|
|
{
|
|
sprintf(pBueffel,"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++)
|
|
{
|
|
sprintf(pNumber," %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)
|
|
{
|
|
sprintf(pBueffel,"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)
|
|
{
|
|
sprintf(pBueffel,"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)
|
|
{
|
|
sprintf(pBueffel,"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)
|
|
{
|
|
sprintf(pBueffel,"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)
|
|
{
|
|
sprintf(pBueffel,
|
|
"%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++)
|
|
{
|
|
sprintf(pBueffel," %8.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;
|
|
}
|
|
/* generate time binning */
|
|
else if(strcmp(argv[1],"genbin") == 0)
|
|
{
|
|
if(!SCMatchRights(pCon,usMugger))
|
|
{
|
|
return 0;
|
|
}
|
|
if(GetStatus() == eCounting)
|
|
{
|
|
SCWrite(pCon,"ERROR: cannot modify timebinning while counting",
|
|
eError);
|
|
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)
|
|
{
|
|
sprintf(pBueffel,"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)
|
|
{
|
|
sprintf(pBueffel,"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)
|
|
{
|
|
sprintf(pBueffel,"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);
|
|
SCparChange(pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/* set a time bin */
|
|
else if(strcmp(argv[1],"setbin") == 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)
|
|
{
|
|
sprintf(pBueffel,"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)
|
|
{
|
|
sprintf(pBueffel,"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);
|
|
self->iInit = 0;
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/* clear time bin info */
|
|
else if(strcmp(argv[1],"clearbin") == 0)
|
|
{
|
|
clearTimeBinning(self->pDriv->data);
|
|
SCSendOK(pCon);
|
|
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);
|
|
sprintf(pBueffel,"%s.sum = %ld",argv[0],lVal);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
sprintf(pBueffel,"ERROR: %s does not understand command %s",
|
|
argv[0], argv[1]);
|
|
SCWrite(pCon, pBueffel,eError);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|