- Refactored histogram memory code a little
- motor driver for ECB now fully working - Fixed an anticollider bug - Untested version of a driver for the Risoe TDC histogram memory
This commit is contained in:
361
hmdata.c
Normal file
361
hmdata.c
Normal file
@ -0,0 +1,361 @@
|
||||
/*-----------------------------------------------------------------------
|
||||
This is a data handling class for histogram memory data.
|
||||
For more information see hmdata.tex.
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, January 2003
|
||||
-------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include "fortify.h"
|
||||
#include "hmdata.h"
|
||||
#include "HistMem.h"
|
||||
#include "HistMem.i"
|
||||
#include "HistDriv.i"
|
||||
#include "countdriv.h"
|
||||
/*----------------------------------------------------------------------*/
|
||||
pHMdata makeHMData(void) {
|
||||
pHMdata self = NULL;
|
||||
|
||||
self = (pHMdata)malloc(sizeof(HMdata));
|
||||
if(self == NULL){
|
||||
return NULL;
|
||||
}
|
||||
memset(self,0,sizeof(HMdata));
|
||||
self->nTimeChan = 1;
|
||||
|
||||
return self;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
void killHMData(pHMdata self){
|
||||
if(self->localBuffer != NULL){
|
||||
free(self->localBuffer);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int resizeBuffer(pHMdata self){
|
||||
long size;
|
||||
int i;
|
||||
|
||||
size = 1;
|
||||
for(i = 0; i < self->rank; i++){
|
||||
size *= self->iDim[i];
|
||||
}
|
||||
if(self->tofMode){
|
||||
size *= self->nTimeChan;
|
||||
}
|
||||
if(self->localBuffer != NULL){
|
||||
free(self->localBuffer);
|
||||
self->localBuffer = NULL;
|
||||
}
|
||||
self->localBuffer = (HistInt *)malloc(size*sizeof(HistInt));
|
||||
if(!self->localBuffer){
|
||||
return 0;
|
||||
}
|
||||
memset(self->localBuffer,0,size*sizeof(HistInt));
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int configureHMdata(pHMdata self, pStringDict pOpt,
|
||||
SConnection *pCon){
|
||||
int status, i;
|
||||
float fVal;
|
||||
char pValue[80];
|
||||
|
||||
self->tofMode = 0;
|
||||
status = StringDictGetAsNumber(pOpt,"rank",&fVal);
|
||||
if(!status){
|
||||
SCWrite(pCon,"ERROR: critical configuration problem: no rank found",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
self->rank = (int)rint(fVal);
|
||||
|
||||
for(i = 0; i < self->rank; i++){
|
||||
sprintf(pValue,"dim%1.1d",i);
|
||||
status = StringDictGetAsNumber(pOpt,pValue,&fVal);
|
||||
if(!status){
|
||||
sprintf(pValue,"ERROR dimension %d not found!!", i);
|
||||
return 0;
|
||||
}
|
||||
self->iDim[i] = (int)rint(fVal);
|
||||
}
|
||||
|
||||
status = StringDictGetAsNumber(pOpt,"update",&fVal);
|
||||
if(!status){
|
||||
self->updateIntervall = 0; /* no buffering */
|
||||
} else {
|
||||
self->updateIntervall = (int)rint(fVal);
|
||||
}
|
||||
/*
|
||||
note: remove update request in histmem.c
|
||||
*/
|
||||
if(self->updateIntervall > 0){
|
||||
/*
|
||||
we do buffer
|
||||
*/
|
||||
status = resizeBuffer(self);
|
||||
if(!status){
|
||||
SCWrite(pCon,"ERROR: failed to resize buffer",eError);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
int genTimeBinning(pHMdata self, float start, float step, int noSteps){
|
||||
int i;
|
||||
|
||||
if(noSteps >= MAXCHAN){
|
||||
return 0;
|
||||
}
|
||||
for(i = 0; i < noSteps; i++){
|
||||
self->timeBinning[i] = start + i*step;
|
||||
}
|
||||
self->tofMode = 1;
|
||||
self->nTimeChan = noSteps;
|
||||
return resizeBuffer(self);
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
int setTimeBin(pHMdata self, int index, float value){
|
||||
if(index > 0 || index < MAXCHAN){
|
||||
self->timeBinning[index] = value;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
self->tofMode = 1;
|
||||
if(index > self->nTimeChan){
|
||||
self->nTimeChan = index;
|
||||
return resizeBuffer(self);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
int isInTOFMode(pHMdata self){
|
||||
return self->tofMode;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
int getNoOfTimebins(pHMdata self){
|
||||
return self->nTimeChan;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
float *getTimeBinning(pHMdata self){
|
||||
return self->timeBinning;
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
void clearTimeBinning(pHMdata self){
|
||||
self->nTimeChan = 1;
|
||||
self->tofMode = 0;
|
||||
resizeBuffer(self);
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
void getHMDataDim(pHMdata self, int iDim[MAXDIM], int *rank){
|
||||
memcpy(iDim,self->iDim,self->rank*sizeof(int));
|
||||
*rank = self->rank;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
long getHMDataLength(pHMdata self){
|
||||
long length = 1;
|
||||
int i;
|
||||
for(i = 0; i < self->rank; i++){
|
||||
length *= self->iDim[i];
|
||||
}
|
||||
if(self->tofMode){
|
||||
length *= self->nTimeChan;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
void updateHMData(pHMdata self){
|
||||
self->updateFlag = 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------
|
||||
The idea here is that upper level code sets the updateFlag through
|
||||
updateHMData (above) whenever the HM changes (counts). If this flag is set
|
||||
the next call to get getHMDataHistogram will read a new copy from the HM.
|
||||
After reading nextUpdate is set to time + updateIntervall. In order to
|
||||
prevent clients hammering the HM nextUpdate is checked as well.
|
||||
updateIntervall can be set to a reasonable time intervall between updates in seconds. If updateIntervall is 0, a direct read is always perfomed.
|
||||
If this system needs to be bypassed altogether (because there is no memory
|
||||
to buffer all HM) use GetHistogramDirect (histogram.c) instead which acts
|
||||
on the driver level.
|
||||
--------------------------------------------------------------------------*/
|
||||
static int mustUpdate(pHMdata self){
|
||||
if(self->updateFlag == 1 && time(NULL) >= self->nextUpdate){
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static int updateHMbuffer(pHistMem hist, int bank, SConnection *pCon){
|
||||
int status, iErr, i;
|
||||
char pError[80], pBueffel[256];
|
||||
pHMdata self = hist->pDriv->data;
|
||||
|
||||
assert(self);
|
||||
|
||||
for(i = 0; i < 3; i++){
|
||||
status = hist->pDriv->GetHistogram(hist->pDriv,pCon,
|
||||
bank,0,getHMDataLength(self),
|
||||
self->localBuffer);
|
||||
if(status == OKOK){
|
||||
self->nextUpdate = time(NULL) + self->updateIntervall;
|
||||
self->updateFlag = 0;
|
||||
break;
|
||||
} else{
|
||||
status = hist->pDriv->GetError(hist->pDriv,&iErr,pError,79);
|
||||
sprintf(pBueffel,"ERROR: %s ",pError);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
status = hist->pDriv->TryAndFixIt(hist->pDriv,iErr);
|
||||
if(status == COTERM) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(status == OKOK){
|
||||
return 1;
|
||||
} else {
|
||||
return HWFault;
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
int getHMDataHistogram(pHistMem hist, SConnection *pCon,
|
||||
int bank, int start, int length,
|
||||
HistInt *lData){
|
||||
int status;
|
||||
pHMdata self = hist->pDriv->data;
|
||||
HistInt *lStart;
|
||||
|
||||
assert(self);
|
||||
|
||||
if(self->localBuffer == NULL){
|
||||
resizeBuffer(self);
|
||||
}
|
||||
|
||||
/*
|
||||
update buffer if necessary
|
||||
*/
|
||||
if(mustUpdate(self)){
|
||||
status = updateHMbuffer(hist,bank,pCon);
|
||||
if(status != OKOK){
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
copy buffered data to lData
|
||||
*/
|
||||
lStart = self->localBuffer + start;
|
||||
if(start + length > getHMDataLength(self)){
|
||||
length = getHMDataLength(self) - start - 1;
|
||||
}
|
||||
memcpy(lData,lStart,length*sizeof(HistInt));
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
HistInt *getHMDataBufferPointer(pHistMem hist,SConnection *pCon){
|
||||
int status;
|
||||
pHMdata self = hist->pDriv->data;
|
||||
|
||||
assert(self);
|
||||
|
||||
if(self->localBuffer == NULL){
|
||||
resizeBuffer(self);
|
||||
}
|
||||
/*
|
||||
update buffer if necessary
|
||||
*/
|
||||
if(mustUpdate(self)){
|
||||
status = updateHMbuffer(hist,0,pCon);
|
||||
if(status != OKOK){
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return self->localBuffer;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
static long SumRow(HistInt *iData, int iDataLength, int iStart, int iEnd){
|
||||
int i;
|
||||
long lSum;
|
||||
|
||||
if(iEnd > iDataLength){
|
||||
return -1;
|
||||
}
|
||||
|
||||
lSum = 0;
|
||||
for(i = iStart; i < iEnd; i++){
|
||||
lSum += iData[i];
|
||||
}
|
||||
return lSum;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
||||
int iStart[MAXDIM], int iEnd[MAXDIM]) {
|
||||
HistInt *iData;
|
||||
pHMdata self = hist->pDriv->data;
|
||||
int i, iHistLength, status, iIndex;
|
||||
char pBueffel[256];
|
||||
long lSum;
|
||||
|
||||
assert(self);
|
||||
|
||||
/*
|
||||
error checking
|
||||
*/
|
||||
for(i = 0; i < self->rank; i++){
|
||||
if( (iStart[i] < 0) || (iStart[i] > self->iDim[i]) ) {
|
||||
sprintf(pBueffel,"ERROR: %d is out of data dimension range",
|
||||
iStart[i]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return -1;
|
||||
}
|
||||
if( (iEnd[i] < 0) || (iEnd[i] > self->iDim[i]) ){
|
||||
sprintf(pBueffel,"ERROR: %d is out of data dimension range",
|
||||
iEnd[i]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
get an update of the HM if necessary
|
||||
*/
|
||||
if(mustUpdate(self)){
|
||||
status = updateHMbuffer(hist,0,pCon);
|
||||
if(status != OKOK){
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
iHistLength = getHMDataLength(self);
|
||||
/* actually sum */
|
||||
switch(self->rank)
|
||||
{
|
||||
case 1:
|
||||
lSum = SumRow(self->localBuffer, iHistLength,
|
||||
iStart[0], iEnd[0]);
|
||||
break;
|
||||
case 2:
|
||||
lSum = 0;
|
||||
for(i = iStart[0]; i < iEnd[0]; i++){
|
||||
iIndex = i*self->iDim[1];
|
||||
lSum += SumRow(self->localBuffer,iHistLength,
|
||||
iIndex+iStart[1], iIndex+iEnd[1]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sprintf(pBueffel,
|
||||
"ERROR: summing in %d dimensions not yet implemented",
|
||||
self->rank);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
lSum = -1;
|
||||
break;
|
||||
}
|
||||
return lSum;
|
||||
}
|
Reference in New Issue
Block a user