
syntax checking input purposes - Rectified an error message in fourmess.c - HMcontrol did not check for the HM to stop before returning. This caused weird data files at AMOR as the data had not yet been downloaded from the HM. - Fixed an issue about parameters in multicounter - Temporary fix in nxscript.c to always read the Hm from the HM and not a buffer. This is prior to rethinking caching strategies for old style HM's. - Synchronize now copies fixed motors correctly. This used to cause irritation with users. This now requires a script syncdrive to exist in the sync server which takes care of handling the fixed flag when this is desired. - Added initify to sicsdata in order to copy large value timebins over properly at AMOR
1037 lines
28 KiB
C
1037 lines
28 KiB
C
/*--------------------------------------------------------------------------
|
|
A M O R S T A T U S
|
|
|
|
The implementation file for the amor status display facilitator module. The
|
|
reflectometer AMOR needs some advanced feautures for its status display.
|
|
These needs are taken care of here.
|
|
|
|
copyright: see copyright.h
|
|
|
|
Mark Koennecke, September 1999
|
|
|
|
As AMOR's histogram memory becomes too big in tof mode to transfer it
|
|
for status information the collapse and subsample functionalities have
|
|
been moved to the histogram memory. This code had to be modified to
|
|
call SINQHMProject directly.
|
|
|
|
Mark Koennecke, August 2001
|
|
|
|
An additional projection mode: onto the y -tof plane was added
|
|
|
|
Mark Koennecke, June 2005
|
|
|
|
Support for new HTTP HM added
|
|
|
|
Mark Koennecke, July 2006
|
|
|
|
Lightly ammended for the new second generation HM module.
|
|
|
|
Mark koennecke, May 2009
|
|
--------------------------------------------------------------------------*/
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <tcl.h>
|
|
#include "fortify.h"
|
|
#include "sics.h"
|
|
#include "counter.h"
|
|
#include "stringdict.h"
|
|
#include "HistMem.h"
|
|
#include "HistMem.i"
|
|
#include "HistDriv.i"
|
|
#include "hardsup/sinqhm.h"
|
|
#include "sinqhmdriv.i"
|
|
#include "scan.h"
|
|
#include "lld.h"
|
|
#include "amorstat.i"
|
|
#include "amorstat.h"
|
|
#include "sicshipadaba.h"
|
|
/*-------------------------------------------------------------------
|
|
Manually from SinqHM_def.h
|
|
--------------------------------------------------------------------*/
|
|
#define PROJECT__FRAME 0x0005
|
|
#define PROJECT__AMOR 0x0006
|
|
|
|
|
|
/*-------------------------------------------------------------------------
|
|
A static which determines if we are in TOF or scan mode.
|
|
*/
|
|
static int iTOF = 0;
|
|
static pHistMem pHMHM = NULL;
|
|
/*-------------------------------------------------------------------------*/
|
|
static int HMCountStartCallback(int iEvent, void *pEvent, void *pUser)
|
|
{
|
|
SConnection *pCon = (SConnection *) pUser;
|
|
const float *fTime = NULL;
|
|
int *iTime = NULL;
|
|
int iLength, iRet, i;
|
|
pHdb tbin = NULL;
|
|
|
|
/* check kill condition */
|
|
if (pCon == NULL || !SCisConnected(pCon)) {
|
|
return -1;
|
|
}
|
|
|
|
if (iEvent == COUNTSTART) {
|
|
/* send current time binning */
|
|
iTOF = 1;
|
|
if(pHMHM->pDes->parNode != NULL){
|
|
tbin = GetHipadabaNode(pHMHM->pDes->parNode,"time_binning");
|
|
assert(tbin != NULL);
|
|
iLength = tbin->value.arrayLength;
|
|
iTime = (int *) malloc((iLength + 1) * sizeof(int));
|
|
if ((!iTime)) {
|
|
return 0;
|
|
}
|
|
iTime[0] = htonl(iLength);
|
|
for (i = 0; i < iLength; i++) {
|
|
iTime[i + 1] = htonl( (int) ( (tbin->value.v.floatArray[i]) / 10.) * 65536.) ;
|
|
}
|
|
} else {
|
|
fTime = GetHistTimeBin(pHMHM, &iLength);
|
|
iTime = (int *) malloc((iLength + 1) * sizeof(int));
|
|
if ((!fTime) || (!iTime)) {
|
|
return 0;
|
|
}
|
|
iTime[0] = htonl(iLength);
|
|
for (i = 0; i < iLength; i++) {
|
|
iTime[i + 1] = htonl((int) ((fTime[i] / 10.) * 65536.));
|
|
}
|
|
}
|
|
/* send new time binning to all clients */
|
|
SCWrite(pCon, "TOFClear", eError);
|
|
SCWriteUUencoded(pCon, "arrowaxis_time", iTime,
|
|
(iLength + 1) * sizeof(int));
|
|
free(iTime);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
static int ScanStartCallback(int iEvent, void *pEvent, void *pUser)
|
|
{
|
|
float *fAxis = NULL;
|
|
int *iAxis = NULL;
|
|
int iLength, iRet, i;
|
|
char pBueffel[80], pName[40];
|
|
SConnection *pCon = (SConnection *) pUser;
|
|
pScanData pScan = (pScanData) pEvent;
|
|
|
|
assert(pScan);
|
|
|
|
/* check kill conditions */
|
|
if (pCon == NULL || !SCisConnected(pCon)) {
|
|
return -1;
|
|
}
|
|
|
|
if (iEvent == SCANSTART) {
|
|
iTOF = 0;
|
|
/* send current axis */
|
|
iLength = GetScanNP(pScan);
|
|
fAxis = (float *) malloc((iLength + 1) * sizeof(float));
|
|
iAxis = (int *) malloc((iLength + 1) * sizeof(int));
|
|
if ((!fAxis) || (!iAxis)) {
|
|
return 0;
|
|
}
|
|
iAxis[0] = htonl(iLength);
|
|
GetSoftScanVar(pScan, 0, fAxis, iLength);
|
|
GetScanVarName(pScan, 0, pName, 39);
|
|
sprintf(pBueffel, "arrowaxis_%s", pName);
|
|
for (i = 0; i < iLength; i++) {
|
|
iAxis[i + 1] = htonl((int) (fAxis[i] * 65536.));
|
|
}
|
|
/* send new axis to client */
|
|
SCWrite(pCon, "SCANClear", eError);
|
|
SCWriteUUencoded(pCon, pBueffel, iAxis, (iLength + 1) * sizeof(int));
|
|
free(iAxis);
|
|
free(fAxis);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static int ScanPointCallback(int iEvent, void *pEvent, void *pUser)
|
|
{
|
|
long *lData = NULL;
|
|
int *iData = NULL;
|
|
int iLength, iRet, i;
|
|
SConnection *pCon = (SConnection *) pUser;
|
|
pScanData pScan = (pScanData) pEvent;
|
|
|
|
assert(pScan);
|
|
|
|
/* check kill conditions */
|
|
if (pCon == NULL || !SCisConnected(pCon)) {
|
|
return -1;
|
|
}
|
|
|
|
if ((iEvent == SCANPOINT) || (iEvent == SCANEND)) {
|
|
/* send current data */
|
|
iTOF = 0;
|
|
iLength = GetScanNP(pScan);
|
|
lData = (long *) malloc((iLength + 1) * sizeof(long));
|
|
iData = (int *) malloc((iLength + 1) * sizeof(int));
|
|
if ((!lData) || (!iData)) {
|
|
return 0;
|
|
}
|
|
iData[0] = htonl(iLength);
|
|
GetScanCounts(pScan, lData, iLength);
|
|
for (i = 0; i < iLength; i++) {
|
|
iData[i + 1] = htonl((int) (lData[i]));
|
|
}
|
|
/* send counts to client */
|
|
SCWriteUUencoded(pCon, "arrow_spinupup", iData,
|
|
(iLength + 1) * sizeof(int));
|
|
/* send counts for other detector */
|
|
GetScanMonitor(pScan, 2, lData, iLength);
|
|
for (i = 0; i < iLength; i++) {
|
|
iData[i + 1] = htonl((int) (lData[i]));
|
|
}
|
|
SCWriteUUencoded(pCon, "arrow_spinuplo", iData,
|
|
(iLength + 1) * sizeof(int));
|
|
/* to do: check for polarization and send spinlo */
|
|
free(iData);
|
|
free(lData);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static int SendLoadedData(pAmorStat self, SConnection * pCon)
|
|
{
|
|
int i, iRet, *iData = NULL;
|
|
char pBueffel[80];
|
|
UserData ud;
|
|
|
|
SCWrite(pCon, "loaded_CLEAR", eValue);
|
|
iRet = LLDnodePtr2First(self->iUserList);
|
|
while (iRet != 0) {
|
|
LLDnodeDataTo(self->iUserList, &ud);
|
|
iData = (int *) malloc((ud.iNP * 2 + 1) * sizeof(int));
|
|
if (!iData) {
|
|
return 0;
|
|
}
|
|
iData[0] = htonl(ud.iNP);
|
|
for (i = 0; i < ud.iNP; i++) {
|
|
iData[i + 1] = htonl((int) (ud.fX[i] * 65536));
|
|
iData[i + 1 + ud.iNP] = htonl((int) (ud.fY[i] * 65536));
|
|
}
|
|
sprintf(pBueffel, "loaded_%s", ud.name);
|
|
SCWriteUUencoded(pCon, pBueffel, iData,
|
|
(ud.iNP * 2 + 1) * sizeof(int));
|
|
iRet = LLDnodePtr2Next(self->iUserList);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static int LoadCallback(int iEvent, void *pEvent, void *pUser)
|
|
{
|
|
pAmorStat pAS = NULL;
|
|
SConnection *pCon = NULL;
|
|
|
|
pCon = (SConnection *) pUser;
|
|
|
|
/* check kill conditions */
|
|
if (pCon == NULL || !SCisConnected(pCon)) {
|
|
return -1;
|
|
}
|
|
|
|
if (iEvent == FILELOADED) {
|
|
pAS = (pAmorStat) pEvent;
|
|
assert(pAS);
|
|
assert(pCon);
|
|
SendLoadedData(pAS, pCon);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
static void ClearUserData(pAmorStat self)
|
|
{
|
|
int iRet;
|
|
UserData ud;
|
|
|
|
iRet = LLDnodePtr2First(self->iUserList);
|
|
while (iRet != 0) {
|
|
LLDnodeDataTo(self->iUserList, &ud);
|
|
if (ud.fX != NULL)
|
|
free(ud.fX);
|
|
if (ud.fY != NULL)
|
|
free(ud.fY);
|
|
if (ud.name != NULL)
|
|
free(ud.name);
|
|
iRet = LLDnodePtr2Next(self->iUserList);
|
|
}
|
|
LLDdelete(self->iUserList);
|
|
self->iUserList = LLDcreate(sizeof(UserData));
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
void KillAmorStatus(void *pData)
|
|
{
|
|
pAmorStat self = (pAmorStat) pData;
|
|
|
|
if (!self)
|
|
return;
|
|
|
|
if (self->iUserList >= 0) {
|
|
ClearUserData(self);
|
|
LLDdelete(self->iUserList);
|
|
}
|
|
if (self->pDes)
|
|
DeleteDescriptor(self->pDes);
|
|
if (self->pCall)
|
|
DeleteCallBackInterface(self->pCall);
|
|
free(self);
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
int AmorStatusFactory(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pAmorStat pNew = NULL;
|
|
CommandList *pCom = NULL;
|
|
char pBueffel[256];
|
|
int iRet;
|
|
|
|
/* check number of arguments */
|
|
if (argc < 4) {
|
|
sprintf(pBueffel, "ERROR: insufficient number of arguments to %s",
|
|
argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
/* allocate a new data structure */
|
|
pNew = (pAmorStat) malloc(sizeof(AmorStat));
|
|
if (!pNew) {
|
|
sprintf(pBueffel, "ERROR: out of memory in %s", argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
memset(pNew, 0, sizeof(AmorStat));
|
|
pNew->pDes = CreateDescriptor("AmorStatus");
|
|
pNew->iUserList = LLDcreate(sizeof(UserData));
|
|
pNew->pCall = CreateCallBackInterface();
|
|
if ((!pNew->pDes) || (pNew->iUserList < 0) || (!pNew->pCall)) {
|
|
sprintf(pBueffel, "ERROR: out of memory in %s", argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
KillAmorStatus(pNew);
|
|
return 0;
|
|
}
|
|
|
|
/* to locate the HM and the scan object */
|
|
pCom = FindCommand(pSics, argv[2]);
|
|
if (pCom) {
|
|
if (pCom->pData) {
|
|
if (!iHasType(pCom->pData, "ScanObject")) {
|
|
sprintf(pBueffel, "ERROR: %s is NO scan object", argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
KillAmorStatus(pNew);
|
|
return 0;
|
|
}
|
|
} else {
|
|
sprintf(pBueffel, "ERROR: %s is NO scan object", argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
KillAmorStatus(pNew);
|
|
return 0;
|
|
}
|
|
} else {
|
|
sprintf(pBueffel, "ERROR: %s NOT found", argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
KillAmorStatus(pNew);
|
|
return 0;
|
|
}
|
|
pNew->pScan = (pScanData) pCom->pData;
|
|
pCom = FindCommand(pSics, argv[3]);
|
|
if (pCom) {
|
|
if (pCom->pData) {
|
|
if (!iHasType(pCom->pData, "HistMem") && !iHasType(pCom->pData,"HistMemSec")) {
|
|
sprintf(pBueffel, "ERROR: %s is NO histogram memory object",
|
|
argv[3]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
KillAmorStatus(pNew);
|
|
return 0;
|
|
}
|
|
} else {
|
|
sprintf(pBueffel, "ERROR: %s is NO histogram memory object",
|
|
argv[3]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
KillAmorStatus(pNew);
|
|
return 0;
|
|
}
|
|
} else {
|
|
sprintf(pBueffel, "ERROR: %s NOT found", argv[3]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
KillAmorStatus(pNew);
|
|
return 0;
|
|
}
|
|
pNew->pHM = (pHistMem) pCom->pData;
|
|
pHMHM = (pHistMem) pCom->pData;
|
|
|
|
/* install command */
|
|
iRet = AddCommand(pSics, argv[1],
|
|
AmorStatusAction, KillAmorStatus, pNew);
|
|
if (!iRet) {
|
|
sprintf(pBueffel, "ERROR: duplicate command %s NOT created", argv[1]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
KillAmorStatus(pNew);
|
|
return 0;
|
|
}
|
|
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
static int RegisterInterest(pAmorStat self, SConnection * pCon)
|
|
{
|
|
long lID;
|
|
pDummy pDum = NULL;
|
|
pICallBack pCall = NULL;
|
|
|
|
assert(self);
|
|
assert(pCon);
|
|
|
|
/* Register all the callbacks. Dependent on the state of
|
|
iTOF invoke the apropriate callbacks in order to force
|
|
an initial update.
|
|
*/
|
|
/* file load callback */
|
|
lID = RegisterCallback(self->pCall, FILELOADED, LoadCallback,
|
|
SCCopyConnection(pCon), SCDeleteConnection);
|
|
SendLoadedData(self, pCon);
|
|
|
|
/* scan object */
|
|
pDum = (pDummy) self->pScan;
|
|
pCall = pDum->pDescriptor->GetInterface(pDum, CALLBACKINTERFACE);
|
|
if (pCall) {
|
|
lID = RegisterCallback(pCall, SCANSTART, ScanStartCallback,
|
|
SCCopyConnection(pCon), SCDeleteConnection);
|
|
lID = RegisterCallback(pCall, SCANPOINT, ScanPointCallback,
|
|
SCCopyConnection(pCon), SCDeleteConnection);
|
|
lID = RegisterCallback(pCall, SCANEND, ScanPointCallback,
|
|
SCCopyConnection(pCon), SCDeleteConnection);
|
|
if (iTOF == 0) {
|
|
ScanStartCallback(SCANSTART, pDum, pCon);
|
|
ScanPointCallback(SCANPOINT, pDum, pCon);
|
|
}
|
|
}
|
|
/*
|
|
* histmem
|
|
*/
|
|
pDum = (pDummy) self->pHM;
|
|
pCall = pDum->pDescriptor->GetInterface(pDum, CALLBACKINTERFACE);
|
|
if (pCall) {
|
|
lID = RegisterCallback(pCall, COUNTSTART, HMCountStartCallback,
|
|
SCCopyConnection(pCon), SCDeleteConnection);
|
|
if (iTOF == 1) {
|
|
HMCountStartCallback(COUNTSTART, pDum, pCon);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------*/
|
|
static int FileLoad(pAmorStat self, SConnection * pCon,
|
|
char *name, double dScale)
|
|
{
|
|
char pBueffel[256], pDummy[50];
|
|
FILE *fd = NULL;
|
|
UserData ud;
|
|
int iNP, i;
|
|
float fDummy;
|
|
|
|
/* open the file */
|
|
fd = fopen(name, "r");
|
|
if (!fd) {
|
|
sprintf(pBueffel, "ERROR: cannot open %s for reading", name);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
/* skip first line */
|
|
if (fgets(pBueffel, 255, fd) == NULL) {
|
|
SCWrite(pCon, "ERROR: premature end of file", eError);
|
|
fclose(fd);
|
|
return 0;
|
|
}
|
|
|
|
/* read number of points in second line */
|
|
if (fgets(pBueffel, 255, fd) == NULL) {
|
|
SCWrite(pCon, "ERROR: premature end of file", eError);
|
|
fclose(fd);
|
|
return 0;
|
|
}
|
|
sscanf(pBueffel, "%s %d", pDummy, &iNP);
|
|
/* allocate data */
|
|
ud.iNP = iNP;
|
|
ud.fX = (float *) malloc(iNP * sizeof(float));
|
|
ud.fY = (float *) malloc(iNP * sizeof(float));
|
|
ud.name = strdup(name);
|
|
|
|
/* skip two lines */
|
|
if (fgets(pBueffel, 255, fd) == NULL) {
|
|
SCWrite(pCon, "ERROR: premature end of file", eError);
|
|
fclose(fd);
|
|
return 0;
|
|
}
|
|
if (fgets(pBueffel, 255, fd) == NULL) {
|
|
SCWrite(pCon, "ERROR: premature end of file", eError);
|
|
fclose(fd);
|
|
return 0;
|
|
}
|
|
|
|
/* loop reading data */
|
|
for (i = 0; i < iNP; i++) {
|
|
if (fgets(pBueffel, 255, fd) == NULL) {
|
|
SCWrite(pCon, "WARNING: premature end of file", eError);
|
|
break;
|
|
}
|
|
sscanf(pBueffel, " %f %f %f", &ud.fX[i], &fDummy, &ud.fY[i]);
|
|
ud.fY[i] *= dScale;
|
|
}
|
|
fclose(fd);
|
|
|
|
/* enter ud into list */
|
|
LLDnodeInsertFrom(self->iUserList, &ud);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------
|
|
Collapse creates a 2D image from the detector by summing all time
|
|
channels together in any given detector.
|
|
*/
|
|
|
|
static int Collapse(pAmorStat self, SConnection * pCon)
|
|
{
|
|
HistInt *lData = NULL;
|
|
int i, i2, i3, iDim[MAXDIM], iIdx, iSum, status, length;
|
|
int *iImage = NULL, *iPtr;
|
|
pSINQHM pHist;
|
|
SinqHMDriv *pTata;
|
|
int iMax = -999999;
|
|
char hmCommand[256];
|
|
HistInt *data = NULL;
|
|
|
|
/* get size of our problem */
|
|
GetHistDim(self->pHM, iDim, &i3);
|
|
/* assert(i3 == 3); */
|
|
|
|
/* allocate some data */
|
|
length = 2 + iDim[0] * iDim[1];
|
|
iImage = (int *) malloc(length * sizeof(int));
|
|
if (iImage == NULL) {
|
|
SCWrite(pCon, "ERROR: failed to allocate memory in Collapse", eError);
|
|
return 0;
|
|
}
|
|
memset(iImage, 0, (2 + iDim[0] * iDim[1]) * sizeof(int));
|
|
|
|
/* first two numbers are the dimension of the image */
|
|
iImage[0] = htonl(iDim[0]);
|
|
iImage[1] = htonl(iDim[1]);
|
|
|
|
|
|
if (isSINQHMDriv(self->pHM->pDriv)) {
|
|
/*
|
|
send a Project request to the histogram memory
|
|
*/
|
|
pTata = (SinqHMDriv *) self->pHM->pDriv->pPriv;
|
|
pHist = (pSINQHM) pTata->pMaster;
|
|
/*
|
|
The 3 in the following call has to be identical to
|
|
PROJECT__COLL in sinqhm_def.h
|
|
*/
|
|
status = SINQHMProject(pHist, 3, 0, iDim[0],
|
|
0, iDim[1], iImage + 2,
|
|
(length - 2) * sizeof(int));
|
|
/*
|
|
Byte swapping
|
|
*/
|
|
for (i = 2; i < length; i++) {
|
|
/*
|
|
if(iImage[i] > iMax){
|
|
iMax = iImage[i];
|
|
}
|
|
*/
|
|
iImage[i] = htonl(iImage[i]);
|
|
}
|
|
/*
|
|
printf("Collapsed maximum: %d\n",iMax);
|
|
*/
|
|
if (status != 1) {
|
|
SCWrite(pCon, "ERROR: histogram memory refused to Collapse", eError);
|
|
return 0;
|
|
}
|
|
} else if (self->iHTTP == 1) {
|
|
if (i3 > 2) {
|
|
snprintf(hmCommand, 255, "sum:2:0:%d", iDim[2]);
|
|
if (self->pHM->pDriv->SubSample != NULL) {
|
|
data =
|
|
self->pHM->pDriv->SubSample(self->pHM->pDriv, pCon, 0,
|
|
hmCommand);
|
|
} else {
|
|
data = NULL;
|
|
}
|
|
if (data == NULL) {
|
|
SCWrite(pCon, "ERROR: failed to retrieve collapsed data from HM",
|
|
eError);
|
|
return 0;
|
|
}
|
|
for (i = 2; i < length; i++) {
|
|
iImage[i] = htonl(data[i - 1]);
|
|
}
|
|
free(data);
|
|
} else {
|
|
GetHistogramDirect(self->pHM, pCon, 0, 0, length - 2,
|
|
&iImage[2], length * sizeof(HistInt));
|
|
for (i = 2; i < length; i++) {
|
|
iImage[i] = htonl(iImage[i]);
|
|
}
|
|
}
|
|
} else {
|
|
/*
|
|
we are in simulation and just create some random numbers
|
|
*/
|
|
for (i = 0; i < iDim[0]; i++) {
|
|
for (i2 = 0; i2 < iDim[1]; i2++) {
|
|
iIdx = i * iDim[1] + i2;
|
|
iImage[iIdx + 2] = htonl(random());
|
|
/* iImage[iIdx+2] = htonl(77); */
|
|
}
|
|
}
|
|
}
|
|
|
|
/* send image */
|
|
SCWriteUUencoded(pCon, "arrow_image", iImage,
|
|
((iDim[0] * iDim[1]) + 2) * sizeof(int));
|
|
free(iImage);
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------
|
|
projectYTOF creates a 2D image from the detector by summing all x channels
|
|
together onto the y - tof plane
|
|
*/
|
|
|
|
static int projectYTOF(pAmorStat self, SConnection * pCon)
|
|
{
|
|
HistInt *lData = NULL;
|
|
int i, i2, i3, iDim[MAXDIM], iIdx, iSum, status, length;
|
|
int *iImage = NULL, *iPtr;
|
|
pSINQHM pHist;
|
|
SinqHMDriv *pTata;
|
|
int iMax = -999999;
|
|
char hmCommand[256];
|
|
HistInt *data = NULL;
|
|
|
|
/* get size of our problem */
|
|
GetHistDim(self->pHM, iDim, &i3);
|
|
if (i3 < 3 || iDim[2] < 2) {
|
|
SCWrite(pCon, "ERROR: cannot project on Y - TOF, not in TOF mode",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
/* allocate some data */
|
|
length = 2 + iDim[1] * iDim[2];
|
|
iImage = (int *) malloc(length * sizeof(int));
|
|
if (iImage == NULL) {
|
|
SCWrite(pCon, "ERROR: failed to allocate memory in projectYTOF",
|
|
eError);
|
|
return 0;
|
|
}
|
|
memset(iImage, 0, (2 + iDim[1] * iDim[2]) * sizeof(int));
|
|
|
|
/* first two numbers are the dimensions of the image */
|
|
iImage[0] = htonl(iDim[1]);
|
|
iImage[1] = htonl(iDim[2]);
|
|
|
|
|
|
if (isSINQHMDriv(self->pHM->pDriv)) {
|
|
/*
|
|
send a Project request to the histogram memory
|
|
*/
|
|
pTata = (SinqHMDriv *) self->pHM->pDriv->pPriv;
|
|
pHist = (pSINQHM) pTata->pMaster;
|
|
status = SINQHMProject(pHist, PROJECT__AMOR, 0, 0,
|
|
0, 0, iImage + 2, (length - 2) * sizeof(int));
|
|
|
|
for (i = 2; i < length; i++) {
|
|
iImage[i] = htonl(iImage[i]);
|
|
}
|
|
if (status != 1) {
|
|
SCWrite(pCon, "ERROR: histogram memory refused to project", eError);
|
|
return 0;
|
|
}
|
|
} else if (self->iHTTP == 1) {
|
|
snprintf(hmCommand, 255, "sum:0:0:%d", iDim[0]);
|
|
data =
|
|
self->pHM->pDriv->SubSample(self->pHM->pDriv, pCon, 0, hmCommand);
|
|
if (data == NULL) {
|
|
SCWrite(pCon, "ERROR: failed to retrieve Y-projection from HM",
|
|
eError);
|
|
return 0;
|
|
}
|
|
for (i = 2; i < length; i++) {
|
|
iImage[i] = htonl(data[i - 1]);
|
|
}
|
|
free(data);
|
|
} else {
|
|
/*
|
|
we are in simulation and just create some random numbers
|
|
*/
|
|
for (i = 0; i < iDim[1]; i++) {
|
|
for (i2 = 0; i2 < iDim[2]; i2++) {
|
|
iIdx = i * iDim[2] + i2;
|
|
iImage[iIdx + 2] = htonl(random());
|
|
iImage[iIdx + 2] = htonl(77);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* send image */
|
|
SCWriteUUencoded(pCon, "y_tof_projection", iImage,
|
|
((iDim[1] * iDim[2]) + 2) * sizeof(int));
|
|
free(iImage);
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------
|
|
SendSingleTOF sends single detector data for TOF mode
|
|
--------------------------------------------------------------------*/
|
|
|
|
static int SendSingleTOF(pAmorStat self, SConnection * pCon)
|
|
{
|
|
HistInt *lData = NULL;
|
|
int i, i2, i3, iDim[MAXDIM], iIdx, iSum, status, length, nTime;
|
|
pSINQHM pHist;
|
|
SinqHMDriv *pTata;
|
|
int iMax = -999999;
|
|
const float *timebin;
|
|
HistInt *iData = NULL;
|
|
int iStart;
|
|
|
|
/* get size of our problem */
|
|
GetHistDim(self->pHM, iDim, &i3);
|
|
|
|
/* allocate some data */
|
|
timebin = GetHistTimeBin(self->pHM, &nTime);
|
|
if (nTime < 2) {
|
|
return 1;
|
|
}
|
|
|
|
length = 1 + 2 * nTime;
|
|
iData = (HistInt *) malloc(length * sizeof(HistInt));
|
|
if (iData == NULL) {
|
|
SCWrite(pCon, "ERROR: failed to allocate memory in SendSingleTOF",
|
|
eError);
|
|
return 0;
|
|
}
|
|
memset(iData, 0, length * sizeof(int));
|
|
|
|
/* first number is the length of each single histogram */
|
|
iData[0] = htonl(nTime);
|
|
|
|
|
|
if (isSINQHMDriv(self->pHM->pDriv)) {
|
|
iStart = iDim[0] * iDim[1] * nTime;
|
|
GetHistogramDirect(self->pHM, pCon, 0, iStart,
|
|
iStart + 2 * nTime, &iData[1],
|
|
2 * nTime * sizeof(HistInt));
|
|
for (i = 1; i < length; i++) {
|
|
iData[i] = htonl(iData[i]);
|
|
}
|
|
} else if (self->iHTTP == 1) {
|
|
GetHistogramDirect(self->pHM, pCon, 1, 0, 2 * nTime, &iData[1],
|
|
2 * nTime * sizeof(HistInt));
|
|
for (i = 1; i < length; i++) {
|
|
iData[i] = htonl(iData[i]);
|
|
}
|
|
} else {
|
|
/*
|
|
we are in simulation and just create some random numbers
|
|
*/
|
|
for (i = 1; i < length; i++) {
|
|
iData[i] = htonl(random());
|
|
}
|
|
}
|
|
|
|
/*
|
|
send, with a little trick to do two histograms.
|
|
*/
|
|
SCWriteUUencoded(pCon, "SING1", iData, (nTime + 1) * sizeof(int));
|
|
iData[nTime] = htonl(nTime);
|
|
SCWriteUUencoded(pCon, "SING2", &iData[nTime],
|
|
(nTime + 1) * sizeof(int));
|
|
free(iData);
|
|
return 1;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------
|
|
SubSample sums histogram data in the area defined by the rectangle
|
|
x1,y1 x2, y2. Summing is along the time axis.
|
|
----------------------------------------------------------------------*/
|
|
static int SubSample(pAmorStat self, SConnection * pCon,
|
|
char *name, int x1, int x2, int y1, int y2)
|
|
{
|
|
int iDim[MAXDIM], i, i2, i3, *iSum = NULL, iLang, *iPtr;
|
|
HistInt *lData = NULL;
|
|
int iLimit, status, nTime;
|
|
char pBueffel[132];
|
|
pSINQHM pHist;
|
|
SinqHMDriv *pTata;
|
|
const float *fTime;
|
|
char hmCommand[256];
|
|
HistInt *data = NULL;
|
|
|
|
/* get histogram dimensions */
|
|
GetHistDim(self->pHM, iDim, &i3);
|
|
fTime = GetHistTimeBin(self->pHM, &nTime);
|
|
iDim[i3] = nTime;
|
|
i3++;
|
|
|
|
/* check limits */
|
|
if (x2 < x1) {
|
|
i = x1;
|
|
x1 = x2;
|
|
x2 = i + 1;
|
|
}
|
|
if (y2 < y1) {
|
|
i = y1;
|
|
y1 = y2;
|
|
y2 = i + 1;
|
|
}
|
|
|
|
iLimit = 0;
|
|
if (x1 > iDim[0]) {
|
|
iLimit = 1;
|
|
x1 = iDim[0] - 1;
|
|
}
|
|
if (x1 < 0) {
|
|
iLimit = 1;
|
|
x1 = 0;
|
|
}
|
|
if (x2 > iDim[0]) {
|
|
iLimit = 2;
|
|
x2 = iDim[0] - 1;
|
|
}
|
|
if (x2 < 0) {
|
|
iLimit = 2;
|
|
x2 = 0;
|
|
}
|
|
if (y1 > iDim[1]) {
|
|
iLimit = 3;
|
|
y1 = iDim[1] - 1;
|
|
}
|
|
if (y1 < 0) {
|
|
iLimit = 3;
|
|
y1 = 0;
|
|
}
|
|
if (y2 > iDim[1]) {
|
|
iLimit = 4;
|
|
y2 = iDim[1] - 1;
|
|
}
|
|
if (y2 < 0) {
|
|
iLimit = 4;
|
|
y2 = 0;
|
|
}
|
|
if (iLimit != 0) {
|
|
switch (iLimit) {
|
|
case 1:
|
|
strcpy(pBueffel, "WARNING: limit violation on x1");
|
|
break;
|
|
case 2:
|
|
strcpy(pBueffel, "WARNING: limit violation on x2");
|
|
break;
|
|
case 3:
|
|
strcpy(pBueffel, "WARNING: limit violation on y1");
|
|
break;
|
|
case 4:
|
|
strcpy(pBueffel, "WARNING: limit violation on y2");
|
|
break;
|
|
}
|
|
SCWrite(pCon, pBueffel, eWarning);
|
|
}
|
|
|
|
/* allocate space for result */
|
|
iSum = (int *) malloc((iDim[2] + 1) * sizeof(int));
|
|
if (!iSum) {
|
|
SCWrite(pCon, "ERROR: out of memory in SubSample", eError);
|
|
return 0;
|
|
}
|
|
memset(iSum, 0, (iDim[2] + 1) * sizeof(int));
|
|
|
|
iSum[0] = htonl(iDim[2]);
|
|
if (isSINQHMDriv(self->pHM->pDriv)) {
|
|
/*
|
|
send project message to histogram memory
|
|
*/
|
|
pTata = (SinqHMDriv *) self->pHM->pDriv->pPriv;
|
|
pHist = (pSINQHM) pTata->pMaster;
|
|
status = SINQHMProject(pHist, 4, x1, x2 - x1,
|
|
y1, y2 - y1, iSum + 1, iDim[2] * sizeof(int));
|
|
/*
|
|
convert to network byte order
|
|
*/
|
|
for (i = 1; i < iDim[2] + 1; i++) {
|
|
iSum[i] = htonl(iSum[i]);
|
|
}
|
|
if (status != 1) {
|
|
SCWrite(pCon, "ERROR: histogram memory refused to SubSample",
|
|
eError);
|
|
return 0;
|
|
}
|
|
} else if (self->iHTTP == 1) {
|
|
snprintf(hmCommand, 255,
|
|
"sample:%d:%d:%d:%d:0:%d;sum:0:0:%d;sum:0:0:%d", x1, x2, y1,
|
|
y2, iDim[2] - 1, x2 - x1, y2 - y1);
|
|
data =
|
|
self->pHM->pDriv->SubSample(self->pHM->pDriv, pCon, 0, hmCommand);
|
|
if (data == NULL) {
|
|
SCWrite(pCon, "ERROR: failed to retrieve sub sampled data fromHM",
|
|
eError);
|
|
return 0;
|
|
}
|
|
for (i = 1; i < iDim[2] + 1; i++) {
|
|
iSum[i] = htonl(data[i - 1]);
|
|
}
|
|
free(data);
|
|
} else {
|
|
/* do acouple of random numbers! */
|
|
for (i = 1; i < iDim[2] + 1; i++) {
|
|
iSum[i] = htonl(random());
|
|
}
|
|
}
|
|
|
|
/* send */
|
|
sprintf(pBueffel, "arrowsum_%s", name);
|
|
SCWriteUUencoded(pCon, pBueffel, iSum, (iDim[2] + 1) * sizeof(int));
|
|
|
|
free(iSum);
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------*/
|
|
int AmorStatusAction(SConnection * pCon, SicsInterp * pSics,
|
|
void *pData, int argc, char *argv[])
|
|
{
|
|
pAmorStat self = (pAmorStat) pData;
|
|
char pBueffel[512];
|
|
double dScale;
|
|
int iRet;
|
|
int x1, x2, y1, y2;
|
|
|
|
assert(self);
|
|
|
|
if (argc < 2) {
|
|
sprintf(pBueffel, "ERROR: need argument to %s", argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
strtolower(argv[1]);
|
|
if (strcmp(argv[1], "interest") == 0) {
|
|
RegisterInterest(self, pCon);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "load") == 0) {
|
|
if (argc < 4) {
|
|
sprintf(pBueffel,
|
|
"ERROR: need filename and scale argument to %s load",
|
|
argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetDouble(pSics->pTcl, argv[3], &dScale);
|
|
if (iRet != TCL_OK) {
|
|
sprintf(pBueffel, "ERROR: cannot convert %s to scale factor",
|
|
argv[3]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
FileLoad(self, pCon, argv[2], dScale);
|
|
InvokeCallBack(self->pCall, FILELOADED, self);
|
|
SCSendOK(pCon);
|
|
} else if (strcmp(argv[1], "collapse") == 0) {
|
|
iRet = Collapse(self, pCon);
|
|
if (iRet) {
|
|
SCSendOK(pCon);
|
|
}
|
|
return iRet;
|
|
} else if (strcmp(argv[1], "projectytof") == 0) {
|
|
iRet = projectYTOF(self, pCon);
|
|
if (iRet) {
|
|
SCSendOK(pCon);
|
|
}
|
|
return iRet;
|
|
} else if (strcmp(argv[1], "http") == 0) {
|
|
if (argc > 2) {
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
return 0;
|
|
}
|
|
self->iHTTP = atoi(argv[2]);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
snprintf(pBueffel, 511, "amorstat.http = %d", self->iHTTP);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
}
|
|
} else if (strcmp(argv[1], "sample") == 0) {
|
|
if (argc < 7) {
|
|
SCWrite(pCon, "ERROR: insufficent number of arguments to sample",
|
|
eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[3], &x1);
|
|
if (iRet != TCL_OK) {
|
|
sprintf(pBueffel, "ERROR: cannot convert %s to int", argv[3]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[6], &y2);
|
|
if (iRet != TCL_OK) {
|
|
sprintf(pBueffel, "ERROR: cannot convert %s to int", argv[6]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[4], &x2);
|
|
if (iRet != TCL_OK) {
|
|
sprintf(pBueffel, "ERROR: cannot convert %s to int", argv[4]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetInt(pSics->pTcl, argv[5], &y1);
|
|
if (iRet != TCL_OK) {
|
|
sprintf(pBueffel, "ERROR: cannot convert %s to int", argv[5]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet = SubSample(self, pCon, argv[2], x1, x2, y1, y2);
|
|
if (iRet)
|
|
SCSendOK(pCon);
|
|
return iRet;
|
|
} else if (strcmp(argv[1], "singletof") == 0) {
|
|
return SendSingleTOF(self, pCon);
|
|
} else if (strcmp(argv[1], "sendloaded") == 0) {
|
|
SendLoadedData(self, pCon);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "clear") == 0) {
|
|
ClearUserData(self);
|
|
InvokeCallBack(self->pCall, FILELOADED, self);
|
|
SCSendOK(pCon);
|
|
} else if (strcmp(argv[1], "tofmode") == 0) {
|
|
HMCountStartCallback(COUNTSTART, NULL, pCon);
|
|
return 1;
|
|
} else {
|
|
sprintf(pBueffel, "ERROR: %s nor recognized as subcommand to %s",
|
|
argv[1], argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|