Files
sics/sansbc.c

250 lines
6.3 KiB
C

/**
* This is a little routine to calculate the beam center from SANS data
* in the detector. This is basically a COG or COC (center of contour)
* calculation above a given threshold. Where we make an effor to
* find the threshold ourselves.
*
* copyright: GPL
*
* Mark Koennecke, July 2009
*/
#include <math.h>
#include <sics.h>
#include "HistMem.h"
#include "sicsobj.h"
#include "sicshipadaba.h"
extern float nintf(float x);
/*---------------------------------------------------------------------*/
static int calculateCOG(int *iData, int xsize, int ysize,
float *i, float *j, int *intensity, float contour,
float level)
{
int threshold, nCount;
float cogTotal, cogX, cogY, conMin, conMax;
int *iPtr, x, y;
conMin = contour - (contour *level);
conMax = contour + (contour *level);
/*
build the sums
*/
nCount = 0;
cogTotal = cogY = cogX = .0;
for (y = 0; y < ysize; y++) {
iPtr = iData + y * xsize;
for (x = 0; x < xsize; x++) {
if (iPtr[x] > conMin && iPtr[x] < conMax) {
nCount++;
cogTotal += iPtr[x];
cogY += y * iPtr[x];
cogX += x * iPtr[x];
}
}
}
if (cogTotal <= .0) {
return 0;
}
*i = cogX / cogTotal;
*j = cogY / cogTotal;
*intensity = (int) cogTotal;
return 1;
}
/*------------------------------------------------------------------*/
static int calculateCOC(int *iData, int xsize, int ysize,
float *i, float *j, int *intensity, float contour)
{
int threshold, nCount;
float cogTotal, cogX, cogY;
int *iPtr, x, y;
/*
build the sums
*/
nCount = 0;
cogTotal = cogY = cogX = .0;
for (y = 0; y < ysize; y++) {
iPtr = iData + y * xsize;
for (x = 0; x < xsize; x++) {
if (iPtr[x] > contour) {
nCount++;
cogTotal += 1;
cogY += y * 1;
cogX += x * 1;
}
}
}
if (cogTotal <= .0) {
return 0;
}
*i = cogX / cogTotal;
*j = cogY / cogTotal;
*intensity = (int) cogTotal;
return 1;
}
/*-------------------------------------------------------------------------*/
static int COGCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHistMem hm = NULL;
float contour, level, x = .0, y = .0;
int length, intensity, dim[3];
if(nPar < 3){
SCWrite(pCon,"ERROR: need hm-name, contour and level for COG calculation",
eError);
return 0;
}
hm = FindHM(pServ->pSics, par[0]->value.v.text);
if(hm == NULL){
SCPrintf(pCon,eError,"ERROR: hm %s not found", par[0]->value.v.text);
return 0;
}
contour = par[1]->value.v.doubleValue;
level = par[2]->value.v.doubleValue;
GetHistDim(hm, dim, &length);
if(length != 2) {
SCPrintf(pCon,eError,"ERROR: hm %s is not 2D", par[0]->value.v.text);
return 0;
}
calculateCOG(GetHistogramPointer(hm,pCon),
dim[0], dim[1], &x, &y, &intensity, contour, level);
SCPrintf(pCon,eValue,"BC = %.2f,%.2f", x,y);
return 1;
}
/*-------------------------------------------------------------------------*/
static int COCCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHistMem hm = NULL;
float contour, x, y;
int length, intensity, dim[3];
if(nPar < 2){
SCWrite(pCon,"ERROR: need hm-name and contour for COG calculation",
eError);
return 0;
}
hm = FindHM(pServ->pSics, par[0]->value.v.text);
if(hm == NULL){
SCPrintf(pCon,eError,"ERROR: hm %s not found", par[0]->value.v.text);
return 0;
}
contour = par[1]->value.v.doubleValue;
GetHistDim(hm, dim, &length);
if(length != 2) {
SCPrintf(pCon,eError,"ERROR: hm %s is not 2D", par[0]->value.v.text);
return 0;
}
calculateCOC(GetHistogramPointer(hm,pCon),
dim[0], dim[1], &x, &y, &intensity, contour);
SCPrintf(pCon,eValue,"BC = %.2f,%.2f", x,y);
return 1;
}
/*-------------------------------------------------------------------------*/
static int StatCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHistMem hm = NULL;
long sum, max, min;
double average;
int dim[3], i, length;
HistInt *data = NULL;
if(nPar < 1){
SCWrite(pCon,"ERROR: need hm-name for statistics",
eError);
return 0;
}
hm = FindHM(pServ->pSics, par[0]->value.v.text);
if(hm == NULL){
SCPrintf(pCon,eError,"ERROR: hm %s not found", par[0]->value.v.text);
return 0;
}
GetHistDim(hm, dim, &i);
if(i != 2) {
SCPrintf(pCon,eError,"ERROR: hm %s is not 2D", par[0]->value.v.text);
return 0;
}
data = GetHistogramPointer(hm,pCon);
if(data == NULL){
SCPrintf(pCon,eError,"ERROR: failed to get data for hm %s", par[0]->value.v.text);
return 0;
}
max = -9999;
min = 99999;
length = dim[0]*dim[1];
for(i = 0, sum = 0; i < length; i++){
sum += data[i];
if(data[i] > max){
max = data[i];
}
if(data[i] < min ){
min = data[i];
}
}
average = (double)sum/(double)length;
SCPrintf(pCon,eValue,"Stat:sum,max,min,av = %ld,%ld,%ld,%f", sum,max,min,average);
return 1;
}
/*--------------------------------------------------------------------*/
int SansBCFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
pSICSOBJ pNew = NULL;
pHdb cmd = NULL, node;
pNew = SetupSICSOBJ(pCon,pSics,pData,argc,argv);
if(pNew == NULL){
return 0;
}
cmd = AddSICSHdbPar(pNew->objectNode, "cog", usSpy,
MakeSICSFunc(COGCmd));
SetHdbProperty(cmd,"type","command");
SetHdbProperty(cmd,"priv","spy");
node = MakeSICSHdbPar("hm",usSpy,MakeHdbText("banana"));
AddHipadabaChild(cmd,node,NULL);
node = MakeSICSHdbPar("contour",usSpy,MakeHdbFloat(100.));
AddHipadabaChild(cmd,node,NULL);
node = MakeSICSHdbPar("level",usSpy,MakeHdbFloat(.1));
AddHipadabaChild(cmd,node,NULL);
cmd = AddSICSHdbPar(pNew->objectNode, "coc", usSpy,
MakeSICSFunc(COCCmd));
SetHdbProperty(cmd,"type","command");
SetHdbProperty(cmd,"priv","spy");
node = MakeSICSHdbPar("hm",usSpy,MakeHdbText("banana"));
AddHipadabaChild(cmd,node,NULL);
node = MakeSICSHdbPar("contour",usSpy,MakeHdbFloat(100.));
AddHipadabaChild(cmd,node,NULL);
cmd = AddSICSHdbPar(pNew->objectNode, "stat", usSpy,
MakeSICSFunc(StatCmd));
SetHdbProperty(cmd,"type","command");
SetHdbProperty(cmd,"priv","spy");
node = MakeSICSHdbPar("hm",usSpy,MakeHdbText("banana"));
AddHipadabaChild(cmd,node,NULL);
return 1;
}
/*-------------------------------------------------------------------*/