- Added a local maximum search for 2D detectors in support of peak

search for TRICS
This commit is contained in:
cvs
2001-11-02 15:31:49 +00:00
parent 3c916c9a7d
commit 6c5db4ffd0
10 changed files with 892 additions and 30 deletions

476
lomax.c Normal file
View File

@ -0,0 +1,476 @@
/*-------------------------------------------------------------------------
L o c a l M a x i m u m
This is a module for searching a local maximum in a 2D histogram as
collected at TRICS.
copyright: see copyright.h
Mark Koennecke, November 2001
-------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <tcl.h>
#include <math.h>
#include "fortify.h"
#include "sics.h"
#include "lomax.h"
#include "lomax.i"
#include "HistMem.h"
#define WINDOW 0
#define THRESHOLD 1
#define STEEPNESS 2
#define COGWINDOW 3
#define COGCONTOUR 4
/*-------------------------------------------------------------------*/
static int testBoundaries(int xsize, int ysize, int window,
int i, int j)
{
int half;
/*
if the window touches the data boundary the result is probably not
very useful. Discarding these cases early on also protects us
against data array overrun problems.
*/
half = window/2;
if( i - half < 0 || i + half > xsize)
return 0;
if( j - half < 0 || j + half > ysize)
return 0;
return 1;
}
/*-------------------------------------------------------------------*/
static int testSteepness(int *iData, int xsize, int ysize,
int i, int j, int window, int steepness)
{
int testValue, x, y, half;
int *iPtr;
testValue = iData[j * xsize + i] - steepness;
half = window/2;
/*
test upper row
*/
iPtr = iData + (j - half) * xsize + i - half;
for(x = 0; x < window; x++)
{
if(iPtr[x] > testValue)
return 0;
}
/*
test lower row
*/
iPtr = iData + (j + half) * xsize + i - half;
for(x = 0; x < window; x++)
{
if(iPtr[x] > testValue)
return 0;
}
/*
test columns
*/
for(y = j - half; y < j + half; y++)
{
/*
left
*/
if(iData[y*xsize + i - half] > testValue)
return 0;
/*
right
*/
if(iData[y*xsize + i + half] > testValue)
return 0;
}
return 1;
}
/*--------------------------------------------------------------------*/
static int testMaximum(int *iData, int xsize, int ysize,
int i, int j, int window)
{
int testValue, x, y, half;
int *iPtr;
testValue = iData[j * xsize + i];
half = window/2;
for(y = j - half; y < j + half; y++)
{
iPtr = iData + y * xsize + i - half;
for(x = 0; x < window; x++)
{
if(iPtr[x] > testValue)
return 0;
}
}
return 1;
}
/*--------------------------------------------------------------------*/
int testLocalMaximum(int *iData, int xsize, int ysize,
int i, int j,
int window, int steepness, int threshold,
int *intensity)
{
if(!testBoundaries(xsize,ysize,window,i,j))
return 0;
if(!testMaximum(iData,xsize,ysize,i,j,window))
return 0;
if(iData[j * xsize + i] < threshold)
return 0;
if(!testSteepness(iData,xsize,ysize,i,j,window, steepness))
return 0;
*intensity = iData[j * xsize + i];
return 1;
}
/*-------------------------------------------------------------------*/
int calculateCOG(int *iData, int xsize, int ysize,
int *i, int *j, int *intensity,
int cogWindow,
float contour)
{
int x, xLow, xMax, y, yLow, yMax;
int threshold;
float cogTotal, cogX, cogY;
int *iPtr;
/*
preparations
*/
xLow = *i - cogWindow/2;
if(xLow < 0)
xLow = 0;
xMax = *i + cogWindow/2;
if(xLow >= xsize)
xMax = xsize-1;
yLow = *j - cogWindow/2;
if(yLow < 0)
yLow = 0;
yMax = *j + cogWindow/2;
if(yLow >= ysize)
yMax = ysize-1;
threshold = (int)(float)iData[*j * xsize + *i] * contour;
/*
build the sums
*/
cogTotal = cogY = cogX = .0;
for(y = yLow; y < yMax; y++)
{
iPtr = iData + y *xsize;
for(x = xLow; x < xMax; x++)
{
if(iPtr[x] > threshold)
{
cogTotal += iPtr[x];
cogY += y * iPtr[x];
cogX += x * iPtr[x];
}
}
}
if(cogTotal < .0)
{
return 0;
}
*i = (int)nintf(cogX/cogTotal);
*j = (int)nintf(cogY/cogTotal);
*intensity = (int)cogTotal;
return 1;
}
/*-------------------------------------------------------------------*/
static int checkHM(pHistMem *pHM, SicsInterp *pSics, SConnection *pCon,
char *name, int *iDim)
{
CommandList *pCom = NULL;
char pBueffel[256];
int nDim;
pCom = FindCommand(pSics, name);
if(!pCom)
{
sprintf(pBueffel,"ERROR: histogram memory %s not found", name);
SCWrite(pCon,pBueffel,eError);
return 0;
}
if(!pCom->pData)
{
sprintf(pBueffel,"ERROR: histogram memory %s not found", name);
SCWrite(pCon,pBueffel,eError);
return 0;
}
*pHM = (pHistMem)pCom->pData;
if(!iHasType(*pHM, "HistMem"))
{
sprintf(pBueffel,"ERROR: %s is no histogram memory!", name);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/*
we now know that we have a histogram memory, now check Sizes
*/
GetHistDim(*pHM,iDim,&nDim);
if(nDim < 2)
{
sprintf(pBueffel,"ERROR: %s is not 2 dimensional!", name);
SCWrite(pCon,pBueffel,eError);
return 0;
}
return 1;
}
/*--------------------------------------------------------------------*/
int LoMaxAction(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[])
{
pLoMax self = NULL;
char pBueffel[256], pNum[20];
int iRet, i, j, intensity;
int iDim[10], nDim;
pHistMem pHM = NULL;
CommandList *pCom = NULL;
Tcl_DString result;
int window;
int *iData;
double dVal;
ObPar *ob = NULL;
self = (pLoMax)pData;
assert(pCon);
assert(pSics);
assert(self);
/*
we need arguments
*/
if(argc < 2)
{
sprintf(pBueffel,"ERROR: insufficient number of arguments to %s",
argv[0]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/*
interpret arguments
*/
strtolower(argv[1]);
if(strcmp(argv[1],"search") == 0)
{
if(argc < 3)
{
sprintf(pBueffel,"ERROR: insufficient number of arguments to %s.search",
argv[0]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
if(!checkHM(&pHM, pSics,pCon, argv[2],iDim))
{
return 0;
}
Tcl_DStringInit(&result);
Tcl_DStringStartSublist(&result);
iData = GetHistogramPointer(pHM,pCon);
window = (int)ObVal(self->pParam,WINDOW);
for(i = 0 + window/2; i < iDim[0] - window/2; i++)
{
for(j = 0 + window/2; j < iDim[1] - window/2; j++)
{
if(testLocalMaximum(iData,iDim[0], iDim[1],
i,j,
(int)ObVal(self->pParam,WINDOW),
(int)ObVal(self->pParam,STEEPNESS),
(int)ObVal(self->pParam,THRESHOLD),
&intensity))
{
Tcl_DStringStartSublist(&result);
sprintf(pNum,"%d", i);
Tcl_DStringAppendElement(&result,pNum);
sprintf(pNum,"%d", j);
Tcl_DStringAppendElement(&result,pNum);
sprintf(pNum,"%d", intensity);
Tcl_DStringAppendElement(&result,pNum);
Tcl_DStringEndSublist(&result);
}
}
}
Tcl_DStringEndSublist(&result);
SCWrite(pCon,Tcl_DStringValue(&result),eValue);
Tcl_DStringFree(&result);
return 1;
}
else if(strcmp(argv[1],"cog") == 0) /* COG calculation */
{
if(argc < 5)
{
sprintf(pBueffel,"ERROR: insufficient number of arguments to %s.cog",
argv[0]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
if(!checkHM(&pHM, pSics,pCon, argv[2],iDim))
{
return 0;
}
if(Tcl_GetInt(pSics->pTcl,argv[3],&i)!= TCL_OK)
{
sprintf(pBueffel,"ERROR: expected number, got %s",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
if(Tcl_GetInt(pSics->pTcl,argv[4],&j)!= TCL_OK)
{
sprintf(pBueffel,"ERROR: expected number, got %s",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
Tcl_DStringInit(&result);
Tcl_DStringStartSublist(&result);
iData = GetHistogramPointer(pHM,pCon);
window = (int)ObVal(self->pParam,COGWINDOW);
iRet = calculateCOG(iData,iDim[0], iDim[1], &i, &j, &intensity,
window, ObVal(self->pParam,COGCONTOUR));
if(!iRet)
{
SCWrite(pCon,"ERROR: no intensity in data",eError);
return 0;
}
sprintf(pNum,"%d", i);
Tcl_DStringAppendElement(&result,pNum);
sprintf(pNum,"%d", j);
Tcl_DStringAppendElement(&result,pNum);
sprintf(pNum,"%d", intensity);
Tcl_DStringAppendElement(&result,pNum);
Tcl_DStringEndSublist(&result);
SCWrite(pCon,Tcl_DStringValue(&result),eValue);
Tcl_DStringFree(&result);
return 1;
}
else
{
/* we are handling one of the parameter commands
*/
if(argc > 2) /* set case */
{
if(Tcl_GetDouble(pSics->pTcl,argv[2],&dVal) != TCL_OK)
{
sprintf(pBueffel,"ERROR: expected number, got %s",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
return ObParSet(self->pParam,argv[0],argv[1],(float)dVal,pCon);
}
else /* read case */
{
ob = ObParFind(self->pParam,argv[1]);
if(!ob)
{
sprintf(pBueffel,"ERROR: parameter %s not found or wrong command",
argv[1]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
sprintf(pBueffel,"%s.%s = %f",argv[0],argv[1],ob->fVal);
SCWrite(pCon,pBueffel,eError);
return 1;
}
}
/*
not reached
*/
assert(0);
return 0;
}
/*-------------------------------------------------------------------*/
static void KillLoMax(void *pData)
{
pLoMax self = (pLoMax)pData;
if(!self)
return;
if(self->pDes)
DeleteDescriptor(self->pDes);
if(self->pParam)
ObParDelete(self->pParam);
free(self);
}
/*-------------------------------------------------------------------*/
int LoMaxFactory(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[])
{
pLoMax pNew = NULL;
if(argc < 2)
{
SCWrite(pCon,"ERROR: Insufficient number of arguments to LoMaxfactory",
eError);
return 0;
}
pNew = (pLoMax)malloc(sizeof(LoMax));
if(!pNew)
{
SCWrite(pCon,"ERROR: out of memory creating local maximum searcher",
eError);
return 0;
}
memset(pNew,0,sizeof(LoMax));
/*
create Descriptor
*/
pNew->pDes = CreateDescriptor("Local Maximum Detector");
if(!pNew->pDes)
{
KillLoMax(pNew);
SCWrite(pCon,"ERROR: out of memory creating local maximum searcher",
eError);
return 0;
}
/*
create and install parameters
*/
pNew->pParam = ObParCreate(5);
if(!pNew->pParam)
{
KillLoMax(pNew);
SCWrite(pCon,"ERROR: out of memory creating local maximum searcher",
eError);
return 0;
}
ObParInit(pNew->pParam,WINDOW,"window",10,usUser);
ObParInit(pNew->pParam,THRESHOLD,"threshold",30,usUser);
ObParInit(pNew->pParam,STEEPNESS,"steepness",5,usUser);
ObParInit(pNew->pParam,COGWINDOW,"cogwindow",50,usUser);
ObParInit(pNew->pParam,COGCONTOUR,"cogcontour",.2,usUser);
return AddCommand(pSics,
argv[1],
LoMaxAction,
KillLoMax,
pNew);
}