- Changes to Hipadaba - Added project to histogram memory code - Started regression testing code - Added hill climbing as optimization method to optimise
1198 lines
31 KiB
C
1198 lines
31 KiB
C
/*-----------------------------------------------------------------------
|
|
N X S C R I P T
|
|
|
|
This is a class for scripting the contents of NeXus files from
|
|
SICS.
|
|
|
|
copyright: see file COPYRIGHT
|
|
|
|
Mark Koennecke, February 2003
|
|
Mark Koennecke, January 2004
|
|
------------------------------------------------------------------------*/
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <tcl.h>
|
|
#include <math.h>
|
|
#include <unistd.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <dirent.h>
|
|
#include "fortify.h"
|
|
#include "sics.h"
|
|
#include "splitter.h"
|
|
#include "HistMem.h"
|
|
#include "motor.h"
|
|
#include "counter.h"
|
|
#include "sicsvar.h"
|
|
#include "danu.h"
|
|
#include "udpquieck.h"
|
|
#include "nxdict.h"
|
|
#include "nxscript.h"
|
|
#include "sicsdata.h"
|
|
|
|
extern char *trim(char *str);
|
|
|
|
/* missing in nxdict.h: */
|
|
NXstatus NXDdefget(NXdict handle, char *pKey, char *pBuffer, int iBufLen);
|
|
/*------------------------------------------------------------------------*/
|
|
char *makeFilename(SicsInterp *pSics, SConnection *pCon) {
|
|
pSicsVariable pPath = NULL, pPref = NULL, pEnd = NULL;
|
|
char *pRes = NULL;
|
|
int iLen, iNum, iYear, thousand;
|
|
char pNumText[10], pBueffel[256];
|
|
CommandList *pCom = NULL;
|
|
DIR *dir = NULL;
|
|
|
|
/* Try, get all the Variables */
|
|
pPath = FindVariable(pSics,"sicsdatapath");
|
|
pPref = FindVariable(pSics,"sicsdataprefix");
|
|
pCom = FindCommand(pSics,"sicsdatanumber");
|
|
pEnd = FindVariable(pSics,"sicsdatapostfix");
|
|
|
|
if( (!pPath) || (!pPref) || (!pCom) || (!pEnd) ){
|
|
SCWrite(pCon,
|
|
"ERROR: cannot read variables for automatic data file name creation",
|
|
eError);
|
|
SCWrite(pCon,
|
|
"ERROR: This is a VERY, VERY, VERY serious installation problem",
|
|
eError);
|
|
SCWrite(pCon,"ERROR: your data will be dumped into emergency.hdf",eError);
|
|
return NULL;
|
|
}
|
|
|
|
/* find length */
|
|
iLen = strlen(pPath->text) + 4; /* extra 4 for dir number */
|
|
iLen += strlen(pPref->text);
|
|
iLen += 10; /* for number + year */
|
|
iLen += strlen(pEnd->text);
|
|
iLen += 10; /* safety margin */
|
|
|
|
/* allocate memory */
|
|
pRes = (char *)malloc(iLen*sizeof(char));
|
|
if(!pRes){
|
|
SCWrite(pCon,"ERROR: no memory in makeFilename",eError);
|
|
return NULL;
|
|
}
|
|
memset(pRes,0,iLen);
|
|
|
|
/* increment the data file number */
|
|
iNum = IncrementDataNumber(pCom->pData,&iYear);
|
|
if(iNum < 0){
|
|
SCWrite(pCon,"ERROR: cannot increment data number!",eError);
|
|
SCWrite(pCon,"ERROR: your data will be dumped to emergency.hdf",eError);
|
|
free(pRes);
|
|
return NULL;
|
|
}
|
|
strcpy(pRes,pPath->text);
|
|
thousand = (int)floor(iNum/1000.);
|
|
snprintf(pNumText,9,"%3.3d",thousand);
|
|
strcat(pRes,pNumText);
|
|
|
|
/*
|
|
check for existence of directory and create if neccessary
|
|
*/
|
|
dir = opendir(pRes);
|
|
if(dir == NULL){
|
|
mkdir(pRes,S_IRWXU | S_IRGRP | S_IXGRP);
|
|
snprintf(pBueffel,255,"Creating dir: %s", pRes);
|
|
SCWrite(pCon,pBueffel,eWarning);
|
|
} else {
|
|
closedir(dir);
|
|
}
|
|
|
|
/*
|
|
build the rest of the filename
|
|
*/
|
|
strcat(pRes,"/");
|
|
strcat(pRes,pPref->text);
|
|
sprintf(pNumText,"%4.4d",iYear);
|
|
strcat(pRes,pNumText);
|
|
strcat(pRes,"n");
|
|
sprintf(pNumText,"%6.6d",iNum);
|
|
strcat(pRes,pNumText);
|
|
strcat(pRes,pEnd->text);
|
|
|
|
return pRes;
|
|
}
|
|
/*---------------------------------------------------------------------*/
|
|
void changeExtension(char *filename, char *newExtension){
|
|
char *pPtr = NULL;
|
|
|
|
pPtr = strrchr(filename,(int)'.');
|
|
assert(pPtr != NULL);
|
|
|
|
pPtr++;
|
|
assert(strlen(pPtr) >= strlen(newExtension));
|
|
strcpy(pPtr,newExtension);
|
|
}
|
|
/*======================== Action =======================================*/
|
|
static int handleFileOperations(SConnection *pCon, pNXScript self,
|
|
int argc, char *argv[]){
|
|
int status,i, iVal;
|
|
NXaccess access;
|
|
char buffer[512];
|
|
|
|
if(strcmp(argv[1],"close") == 0){
|
|
/*
|
|
close everything! and send a message to trigger file synchronisation
|
|
to the central server
|
|
*/
|
|
if(self->fileHandle == NULL){
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
i = 511;
|
|
iVal = NX_CHAR;
|
|
NXgetattr(self->fileHandle,"file_name",buffer,&i,&iVal);
|
|
NXclose(&self->fileHandle);
|
|
NXDclose(self->dictHandle,NULL);
|
|
self->fileHandle = NULL;
|
|
self->dictHandle = NULL;
|
|
SendQuieck(QUIECK,buffer);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else if(strcmp(argv[1],"reopen") == 0){
|
|
access = NXACC_RDWR;
|
|
} else if(strcmp(argv[1],"create4") == 0){
|
|
access = NXACC_CREATE4;
|
|
unlink(argv[2]); /* kill file for overwrite */
|
|
} else if(strcmp(argv[1],"create5") == 0){
|
|
access = NXACC_CREATE5;
|
|
unlink(argv[2]); /* kill file for overwrite */
|
|
} else if(strcmp(argv[1],"createxml") == 0){
|
|
access = NXACC_CREATEXML;
|
|
} else {
|
|
return 0;
|
|
}
|
|
if(argc < 4){
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments for file operation",
|
|
eError);
|
|
return -1;
|
|
}
|
|
/*
|
|
be considerate: close files left open
|
|
*/
|
|
if(self->fileHandle != NULL){
|
|
NXclose(&self->fileHandle);
|
|
self->fileHandle = NULL;
|
|
}
|
|
if(self->dictHandle != NULL){
|
|
NXDclose(self->dictHandle, NULL);
|
|
self->dictHandle = NULL;
|
|
}
|
|
/*
|
|
now initialize ourselves
|
|
*/
|
|
status = NXopen(argv[2],access,&self->fileHandle);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to open %s",argv[2]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return -1;
|
|
}
|
|
status = NXDinitfromfile(argv[3],&self->dictHandle);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to open dictionary %s",argv[3]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return -1;
|
|
}
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void putMotor(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
|
int argc, char *argv[]){
|
|
int status;
|
|
pMotor brumm = NULL;
|
|
float fVal;
|
|
char buffer[132], dummy[256];
|
|
|
|
if(argc < 4){
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments to putmotor",
|
|
eError);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
find motor
|
|
*/
|
|
brumm = (pMotor)FindCommandData(pSics,argv[3],"Motor");
|
|
if(!brumm){
|
|
sprintf(buffer,"ERROR: motor %s not found!", argv[3]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
do position
|
|
*/
|
|
status = MotorGetSoftPosition(brumm, pCon,&fVal);
|
|
if(!status){
|
|
sprintf(buffer,"ERROR: failed to read position of %s", argv[3]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return;
|
|
}
|
|
status = NXDputalias(self->fileHandle,self->dictHandle,argv[2],&fVal);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to write %s with alias %s",
|
|
argv[3],argv[2]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
if alias_null is available: write zero point
|
|
*/
|
|
strcpy(buffer,argv[2]);
|
|
strcat(buffer,"_null");
|
|
if(NXDdefget(self->dictHandle,buffer,dummy,255)){
|
|
MotorGetPar(brumm,"softzero",&fVal);
|
|
status = NXDputalias(self->fileHandle,self->dictHandle,buffer, &fVal);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to write %s zero with alias %s",
|
|
argv[3],argv[2]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------*/
|
|
static void putCounter(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
|
int argc, char *argv[]){
|
|
pCounter cter = NULL;
|
|
float fVal;
|
|
long counts;
|
|
char buffer[256], newAlias[256], dummy[80];
|
|
int status, i, icounts;
|
|
CounterMode eMode;
|
|
|
|
if(argc < 4){
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments to putcounter",
|
|
eError);
|
|
return;
|
|
}
|
|
memset(dummy,0,80*sizeof(char));
|
|
|
|
/*
|
|
find counter
|
|
*/
|
|
cter = (pCounter)FindCommandData(pSics,argv[3],"SingleCounter");
|
|
if(!cter){
|
|
sprintf(buffer,"ERROR: counter %s not found!", argv[3]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
do preset
|
|
*/
|
|
fVal = GetCounterPreset(cter);
|
|
strcpy(newAlias,argv[2]);
|
|
strcat(newAlias,"_preset");
|
|
status = NXDputalias(self->fileHandle,self->dictHandle,newAlias,&fVal);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to write preset to %s", newAlias);
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
|
|
/*
|
|
do countmode
|
|
*/
|
|
eMode = GetCounterMode(cter);
|
|
strcpy(newAlias,argv[2]);
|
|
strcat(newAlias,"_mode");
|
|
if(eMode == eTimer){
|
|
strcpy(dummy,"timer");
|
|
} else {
|
|
strcpy(dummy,"monitor");
|
|
}
|
|
status = NXDputalias(self->fileHandle,self->dictHandle,newAlias,dummy);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to write counter mode to %s", newAlias);
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
|
|
/*
|
|
do time
|
|
*/
|
|
fVal = GetCountTime(cter,pCon);
|
|
strcpy(newAlias,argv[2]);
|
|
strcat(newAlias,"_time");
|
|
if(NXDdefget(self->dictHandle,newAlias,dummy,79)){
|
|
status = NXDputalias(self->fileHandle,self->dictHandle,newAlias,&fVal);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to write count time to %s", newAlias);
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
do counter and monitors
|
|
*/
|
|
for(i = 0; i < 10; i++){
|
|
sprintf(newAlias,"%s_%2.2d",argv[2],i);
|
|
if(NXDdefget(self->dictHandle,newAlias,dummy,79)){
|
|
counts = GetMonitor(cter,i,pCon);
|
|
icounts = (int)counts;
|
|
status = NXDputalias(self->fileHandle,self->dictHandle,newAlias,
|
|
&icounts);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void putSicsData(SConnection *pCon, SicsInterp *pSics,
|
|
pNXScript self, int argc, char *argv[]){
|
|
|
|
pSICSData data = NULL;
|
|
int status;
|
|
char buffer[256];
|
|
|
|
if(argc < 4){
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments to putSicsData",
|
|
eError);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
find data
|
|
*/
|
|
data = (pSICSData)FindCommandData(pSics,argv[3],"SICSData");
|
|
if(data == NULL){
|
|
snprintf(buffer,255,"ERROR: sicsdata %s not found!", argv[3]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return;
|
|
}
|
|
|
|
status = NXDputalias(self->fileHandle,self->dictHandle,argv[2],data->data);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to write sicsdata to %s", argv[2]);
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void putAttribute(SConnection *pCon, SicsInterp *pSics,
|
|
pNXScript self, int argc, char *argv[]){
|
|
int status, type = NX_CHAR;
|
|
char buffer[256];
|
|
|
|
if(argc < 5){
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments to putAttribute",
|
|
eError);
|
|
return;
|
|
}
|
|
|
|
status = NXDopenalias(self->fileHandle,self->dictHandle,argv[2]);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to open alias %s", argv[2]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return;
|
|
}
|
|
status = NXputattr(self->fileHandle,argv[3],(void *)argv[4],
|
|
strlen(argv[4])+1, type);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to write attribute %s", argv[3]);
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void updateHMDim(NXScript *self, pHistMem mem){
|
|
int iDim[MAXDIM];
|
|
int i, rank, timeLength, status;
|
|
char dummy[40], value[20];
|
|
const float *timeBin;
|
|
|
|
/*
|
|
update the dimension variables in the dictionary
|
|
*/
|
|
GetHistDim(mem,iDim,&rank);
|
|
for(i = 0; i < rank; i++){
|
|
sprintf(dummy,"dim%1.1d", i);
|
|
sprintf(value,"%d",iDim[i]);
|
|
status = NXDupdate(self->dictHandle,dummy,value);
|
|
if(status == 0) {
|
|
NXDadd(self->dictHandle,dummy,value);
|
|
}
|
|
}
|
|
timeBin = GetHistTimeBin(mem,&timeLength);
|
|
if(timeLength > 2){
|
|
sprintf(dummy,"%d",timeLength);
|
|
} else {
|
|
sprintf(dummy,"%d",1);
|
|
}
|
|
status = NXDupdate(self->dictHandle,"timedim",dummy);
|
|
if(status == 0) {
|
|
NXDadd(self->dictHandle,"timedim",dummy);
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------
|
|
The sequence of things is important in here: The code for updating
|
|
the dimensions variables also applies the time binning to the length.
|
|
Thus subsets can only be checked for after that. And then we can allocate
|
|
memory.
|
|
-------------------------------------------------------------------------*/
|
|
static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics,
|
|
pNXScript self,
|
|
int argc, char *argv[]){
|
|
pHistMem mem = NULL;
|
|
int status, start, length, i, subset = 0, bank = 0;
|
|
HistInt *iData = NULL;
|
|
char buffer[256];
|
|
|
|
if(argc < 4){
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments to puthm",
|
|
eError);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
find Histogram Memory
|
|
*/
|
|
mem = (pHistMem)FindCommandData(pSics,argv[3],"HistMem");
|
|
if(!mem){
|
|
sprintf(buffer,"ERROR: HistMem %s not found!", argv[3]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
default: everything
|
|
*/
|
|
start = 0;
|
|
length = GetHistLength(mem);
|
|
|
|
updateHMDim(self,mem);
|
|
|
|
/*
|
|
check for further arguments specifying a subset
|
|
*/
|
|
if(argc > 5){
|
|
subset = 1;
|
|
status = Tcl_GetInt(InterpGetTcl(pSics),argv[4],&start);
|
|
if(status != TCL_OK){
|
|
sprintf(buffer,"ERROR: failed to convert %s to integer",
|
|
argv[4]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return;
|
|
}
|
|
status = Tcl_GetInt(InterpGetTcl(pSics),argv[5],&length);
|
|
if(status != TCL_OK){
|
|
sprintf(buffer,"ERROR: failed to convert %s to integer",
|
|
argv[5]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* check for additional bank number
|
|
*/
|
|
if(argc > 6){
|
|
status = Tcl_GetInt(InterpGetTcl(pSics),argv[6],&bank);
|
|
if(status != TCL_OK){
|
|
sprintf(buffer,"ERROR: failed to convert %s to integer",
|
|
argv[6]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*
|
|
read HM
|
|
*/
|
|
if(subset){
|
|
iData = (HistInt *)malloc(length*sizeof(HistInt));
|
|
if(!iData){
|
|
SCWrite(pCon,"ERROR: out of memory for reading histogram memory",
|
|
eError);
|
|
return;
|
|
}
|
|
memset(iData,0,length*sizeof(HistInt));
|
|
status = GetHistogramDirect(mem,pCon,bank,start,start+length,iData,
|
|
length*sizeof(HistInt));
|
|
}else{
|
|
/*
|
|
status = GetHistogram(mem,pCon,0,start,length,iData,
|
|
length*sizeof(HistInt));
|
|
*/
|
|
iData = GetHistogramPointer(mem,pCon);
|
|
if(iData == NULL){
|
|
status = 0;
|
|
} else {
|
|
status = 1;
|
|
}
|
|
}
|
|
if(!status){
|
|
SCWrite(pCon,"ERROR: failed to read histogram memory",eError);
|
|
if(subset){
|
|
free(iData);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/*
|
|
finally: write
|
|
*/
|
|
status = NXDputalias(self->fileHandle, self->dictHandle,argv[2],iData);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to write histogram memory data");
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
|
|
if(subset){
|
|
free(iData);
|
|
}
|
|
SCSendOK(pCon);
|
|
|
|
return;
|
|
}
|
|
/*---------------------------------------------------------------------
|
|
defunct as of december 2003
|
|
*/
|
|
static void putHistogramMemoryChunked(SConnection *pCon, SicsInterp *pSics,
|
|
pNXScript self,
|
|
int argc, char *argv[]){
|
|
pHistMem mem = NULL;
|
|
int status, start, length, i, noChunks, chunkDim[MAXDIM], rank;
|
|
HistInt *iData = NULL;
|
|
char buffer[256];
|
|
int subset;
|
|
|
|
if(argc < 5){
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments to puthmchunked",
|
|
eError);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
find Histogram Memory
|
|
*/
|
|
mem = (pHistMem)FindCommandData(pSics,argv[3],"HistMem");
|
|
if(!mem){
|
|
sprintf(buffer,"ERROR: HistMem %s not found!", argv[3]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
default: everything
|
|
*/
|
|
start = 0;
|
|
length = GetHistLength(mem);
|
|
|
|
updateHMDim(self,mem);
|
|
|
|
/*
|
|
check for an argument defining the number of chunks
|
|
*/
|
|
status = Tcl_GetInt(InterpGetTcl(pSics),argv[4],&noChunks);
|
|
if(status != TCL_OK){
|
|
sprintf(buffer,"ERROR: failed to convert %s to integer",
|
|
argv[4]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
read HM
|
|
*/
|
|
if(subset){
|
|
iData = (HistInt *)malloc(length*sizeof(HistInt));
|
|
if(!iData){
|
|
SCWrite(pCon,"ERROR: out of memory for reading histogram memory",
|
|
eError);
|
|
return;
|
|
}
|
|
memset(iData,0,length*sizeof(HistInt));
|
|
status = GetHistogramDirect(mem,pCon,0,start,start+length,iData,
|
|
length*sizeof(HistInt));
|
|
}else{
|
|
/*
|
|
status = GetHistogram(mem,pCon,0,start,length,iData,
|
|
length*sizeof(HistInt));
|
|
*/
|
|
iData = GetHistogramPointer(mem,pCon);
|
|
if(iData == NULL){
|
|
status = 0;
|
|
} else {
|
|
status = 1;
|
|
}
|
|
}
|
|
if(!status){
|
|
SCWrite(pCon,"ERROR: failed to read histogram memory",eError);
|
|
if(subset){
|
|
free(iData);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/*
|
|
finally: write
|
|
*/
|
|
status = NXDputalias(self->fileHandle, self->dictHandle,argv[2],iData);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to write histogram memory data");
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
|
|
if(subset){
|
|
free(iData);
|
|
}
|
|
SCSendOK(pCon);
|
|
|
|
return;
|
|
}
|
|
/*-------------------------------------------------------------------*/
|
|
static void putTimeBinning(SConnection *pCon, SicsInterp *pSics,
|
|
pNXScript self,
|
|
int argc, char *argv[]){
|
|
pHistMem mem = NULL;
|
|
int i, status, timeLength;
|
|
char buffer[256], defString[512], dummy[40];
|
|
const float *timeBin;
|
|
float *timeCopy = NULL;
|
|
|
|
if(argc < 4){
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments to puttimebinning",
|
|
eError);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
find Histogram Memory
|
|
*/
|
|
mem = (pHistMem)FindCommandData(pSics,argv[3],"HistMem");
|
|
if(!mem){
|
|
sprintf(buffer,"ERROR: HistMem %s not found!", argv[3]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
build definition string
|
|
*/
|
|
status = NXDdefget(self->dictHandle,argv[2],buffer,254);
|
|
if(!status){
|
|
sprintf(buffer,"ERROR: alias %s for time binning not found",
|
|
argv[2]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return;
|
|
}
|
|
timeBin = GetHistTimeBin(mem,&timeLength);
|
|
sprintf(defString,"%s -dim {%d} ",buffer,timeLength);
|
|
|
|
/*
|
|
Divide the time binning when appropriate and write
|
|
*/
|
|
if(self->timeDivisor != 1){
|
|
timeCopy = (float *)malloc(timeLength*sizeof(float));
|
|
if(timeCopy == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory writing time binning",eError);
|
|
return;
|
|
}
|
|
for(i = 0; i < timeLength; i++){
|
|
timeCopy[i] = timeBin[i]/self->timeDivisor;
|
|
}
|
|
status = NXDputdef(self->fileHandle, self->dictHandle,
|
|
defString,(void *)timeCopy);
|
|
free(timeCopy);
|
|
} else {
|
|
status = NXDputdef(self->fileHandle, self->dictHandle,
|
|
defString,(void *)timeBin);
|
|
}
|
|
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to write time binning");
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
SCSendOK(pCon);
|
|
return;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void putArray(SConnection *pCon, SicsInterp *pSics,
|
|
pNXScript self,
|
|
int argc, char *argv[]){
|
|
float *data = NULL;
|
|
int length, i, status;
|
|
char num[20];
|
|
char buffer[256], defString[512], *varData;
|
|
Tcl_Interp *tcl = NULL;
|
|
double dVal;
|
|
|
|
if(argc < 5){
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments to array",
|
|
eError);
|
|
return;
|
|
}
|
|
tcl = InterpGetTcl(pSics);
|
|
assert(tcl != NULL);
|
|
|
|
/*
|
|
get array length
|
|
*/
|
|
status = Tcl_GetInt(tcl,argv[4],&length);
|
|
if(status != TCL_OK){
|
|
sprintf(buffer,"ERROR: failed to convert %s to integer",argv[4]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
allocate
|
|
*/
|
|
if(length > 0){
|
|
data = (float *)malloc(length*sizeof(float));
|
|
}
|
|
if(data == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory or invalid length",eError);
|
|
return;
|
|
}
|
|
memset(data,0,length*sizeof(float));
|
|
|
|
/*
|
|
try getting data
|
|
*/
|
|
for(i = 0; i < length; i++){
|
|
sprintf(num,"%d",i);
|
|
varData = (char *)Tcl_GetVar2(tcl,argv[3],num,0);
|
|
if(varData != NULL){
|
|
status = Tcl_GetDouble(tcl,varData,&dVal);
|
|
if(status != TCL_OK){
|
|
sprintf(buffer,"ERROR: failed to convert %s to double",
|
|
varData);
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
data[i] = (float)dVal;
|
|
} else {
|
|
snprintf(buffer,254,"WARNING: failed to find array element %d", i);
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
}
|
|
|
|
/*
|
|
build definition string
|
|
*/
|
|
status = NXDdefget(self->dictHandle,argv[2],buffer,254);
|
|
if(!status){
|
|
sprintf(buffer,"ERROR: alias %s for array not found",
|
|
argv[2]);
|
|
SCWrite(pCon,buffer,eError);
|
|
free(data);
|
|
return;
|
|
}
|
|
snprintf(defString,511,"%s -dim {%d} ",buffer,length);
|
|
|
|
/*
|
|
write it!
|
|
*/
|
|
status = NXDputdef(self->fileHandle,self->dictHandle,defString,data);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to write array");
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
free(data);
|
|
SCSendOK(pCon);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void putIntArray(SConnection *pCon, SicsInterp *pSics,
|
|
pNXScript self,
|
|
int argc, char *argv[]){
|
|
int *data = NULL;
|
|
int length, i, status;
|
|
char num[20];
|
|
char buffer[256], defString[512], *varData;
|
|
Tcl_Interp *tcl = NULL;
|
|
int iVal;
|
|
|
|
if(argc < 5){
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments to array",
|
|
eError);
|
|
return;
|
|
}
|
|
tcl = InterpGetTcl(pSics);
|
|
assert(tcl != NULL);
|
|
|
|
/*
|
|
get array length
|
|
*/
|
|
status = Tcl_GetInt(tcl,argv[4],&length);
|
|
if(status != TCL_OK){
|
|
sprintf(buffer,"ERROR: failed to convert %s to integer",argv[4]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
allocate
|
|
*/
|
|
if(length > 0){
|
|
data = (int *)malloc(length*sizeof(int));
|
|
}
|
|
if(data == NULL){
|
|
SCWrite(pCon,"ERROR: out of memory or invalid length",eError);
|
|
return;
|
|
}
|
|
memset(data,0,length*sizeof(int));
|
|
|
|
/*
|
|
try getting data
|
|
*/
|
|
for(i = 0; i < length; i++){
|
|
sprintf(num,"%d",i);
|
|
varData = (char *)Tcl_GetVar2(tcl,argv[3],num,0);
|
|
if(varData != NULL){
|
|
status = Tcl_GetInt(tcl,varData,&iVal);
|
|
if(status != TCL_OK){
|
|
sprintf(buffer,"ERROR: failed to convert %s to int",
|
|
varData);
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
data[i] = iVal;
|
|
} else {
|
|
snprintf(buffer,254,"WARNING: failed to find array element %d", i);
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
}
|
|
|
|
/*
|
|
build definition string
|
|
*/
|
|
status = NXDdefget(self->dictHandle,argv[2],buffer,254);
|
|
if(!status){
|
|
sprintf(buffer,"ERROR: alias %s for array not found",
|
|
argv[2]);
|
|
SCWrite(pCon,buffer,eError);
|
|
free(data);
|
|
return;
|
|
}
|
|
snprintf(defString,511,"%s -dim {%d} ",buffer,length);
|
|
|
|
/*
|
|
write it!
|
|
*/
|
|
status = NXDputdef(self->fileHandle,self->dictHandle,defString,data);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to write array");
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
free(data);
|
|
SCSendOK(pCon);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void putGlobal(SConnection *pCon, SicsInterp *pSics,
|
|
pNXScript self,
|
|
int argc, char *argv[]){
|
|
char value[1024];
|
|
int status;
|
|
|
|
if(argc < 4){
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments to putglobal",
|
|
eError);
|
|
return;
|
|
}
|
|
|
|
Arg2Text(argc-3,&argv[3],value,1023);
|
|
status = NXputattr(self->fileHandle,argv[2],value,strlen(value),
|
|
NX_CHAR);
|
|
if(status != NX_OK){
|
|
SCWrite(pCon,"ERROR: failed to write attribute",eError);
|
|
}
|
|
SCSendOK(pCon);
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
|
int argc, char *argv[]){
|
|
int status, iVal;
|
|
char buffer[1024], defString[1024], numBuf[25];
|
|
double dVal;
|
|
float fVal;
|
|
|
|
/*============ */
|
|
if(strcmp(argv[1],"putfloat") == 0){
|
|
if(argc < 4){
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments to putfloat",
|
|
eError);
|
|
return 1;
|
|
}
|
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&dVal);
|
|
if(status != TCL_OK){
|
|
sprintf(buffer,"ERROR: failed to convert %s to float",
|
|
argv[3]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return 1;
|
|
}
|
|
fVal = (float)dVal;
|
|
status = NXDputalias(self->fileHandle, self->dictHandle,
|
|
argv[2],&fVal);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to write %f to alias %s",
|
|
fVal, argv[2]);
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
return 1;
|
|
} else if(strcmp(argv[1],"putint") == 0){
|
|
if(argc < 4){
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments to putint",
|
|
eError);
|
|
return 1;
|
|
}
|
|
status = Tcl_GetInt(InterpGetTcl(pSics),argv[3],&iVal);
|
|
if(status != TCL_OK){
|
|
sprintf(buffer,"ERROR: failed to convert %s to int",
|
|
argv[3]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return 1;
|
|
}
|
|
status = NXDputalias(self->fileHandle, self->dictHandle,
|
|
argv[2],&iVal);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to write %d to alias %s",
|
|
iVal, argv[2]);
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
return 1;
|
|
} else if (strcmp(argv[1],"puttext") == 0){
|
|
/*====================*/
|
|
if(argc < 4){
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments to puttext",
|
|
eError);
|
|
return 1;
|
|
}
|
|
Arg2Text(argc-3,&argv[3],buffer,1023);
|
|
trim(buffer);
|
|
status = NXDdefget(self->dictHandle,argv[2],defString,1023);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: alias %s not found in puttext",
|
|
argv[2]);
|
|
SCWrite(pCon,buffer,eError);
|
|
return 1;
|
|
}
|
|
if(strlen(defString) < 900){
|
|
strcat(defString," -dim {");
|
|
sprintf(numBuf,"%d",strlen(buffer)+1);
|
|
strcat(defString,numBuf);
|
|
strcat(defString," }");
|
|
} else {
|
|
SCWrite(pCon,"ERROR: out of definition string space in puttext",
|
|
eError);
|
|
return 1;
|
|
}
|
|
status = NXDputdef(self->fileHandle,self->dictHandle,
|
|
defString,buffer);
|
|
if(status != NX_OK){
|
|
sprintf(buffer,"ERROR: failed to write alias %s",
|
|
argv[2]);
|
|
SCWrite(pCon,buffer,eError);
|
|
}
|
|
return 1;
|
|
} else if(strcmp(argv[1],"putmot") == 0){
|
|
/*=========== */
|
|
putMotor(pCon,pSics,self,argc,argv);
|
|
return 1;
|
|
} else if(strcmp(argv[1],"putcounter") == 0){
|
|
/* ================*/
|
|
putCounter(pCon,pSics,self, argc,argv);
|
|
return 1;
|
|
}else if(strcmp(argv[1],"puthm") == 0){
|
|
/*=================*/
|
|
putHistogramMemory(pCon,pSics,self,argc, argv);
|
|
return 1;
|
|
}else if(strcmp(argv[1],"puttimebinning") == 0){
|
|
/*=================*/
|
|
putTimeBinning(pCon,pSics,self,argc,argv);
|
|
}else if(strcmp(argv[1],"putarray") == 0){
|
|
/*================*/
|
|
putArray(pCon,pSics,self,argc,argv);
|
|
}else if(strcmp(argv[1],"putintarray") == 0){
|
|
/*================*/
|
|
putIntArray(pCon,pSics,self,argc,argv);
|
|
}else if(strcmp(argv[1],"putglobal") == 0){
|
|
/*===============*/
|
|
putGlobal(pCon,pSics,self,argc,argv);
|
|
}else if(strcmp(argv[1],"putsicsdata") == 0){
|
|
/*===============*/
|
|
putSicsData(pCon,pSics,self,argc,argv);
|
|
}else if(strcmp(argv[1],"putattribute") == 0){
|
|
/*===============*/
|
|
putAttribute(pCon,pSics,self,argc,argv);
|
|
} else {
|
|
SCWrite(pCon,"ERROR: put command not recognised",eError);
|
|
}
|
|
return 1;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void makeLink(SConnection *pCon, SicsInterp *pSics,
|
|
pNXScript self,
|
|
int argc, char *argv[]){
|
|
int status;
|
|
char pBueffel[256];
|
|
|
|
if(argc < 4){
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments to makelink",
|
|
eError);
|
|
return;
|
|
}
|
|
|
|
status = NXDaliaslink(self->fileHandle, self->dictHandle,
|
|
argv[2],argv[3]);
|
|
if(status != NX_OK){
|
|
snprintf(pBueffel,255,"ERROR: linking %s against %s failed",
|
|
argv[2], argv[3]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return;
|
|
}
|
|
|
|
SCSendOK(pCon);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
static void updateDictVar(SConnection *pCon, pNXScript self, int argc,
|
|
char *argv[]){
|
|
int status;
|
|
|
|
if(self->dictHandle == NULL){
|
|
SCWrite(pCon,"ERROR: cannot update variable, dictionary not open",
|
|
eError);
|
|
return;
|
|
}
|
|
if(argc < 4){
|
|
SCWrite(pCon,"ERROR: insufficient number of arguments to updateDictVar",
|
|
eError);
|
|
return;
|
|
}
|
|
NXDupdate(self->dictHandle,argv[2],argv[3]);
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[]){
|
|
pNXScript self = (pNXScript)pData;
|
|
char *pFile = NULL;
|
|
int status;
|
|
|
|
/*
|
|
preliminary checks
|
|
*/
|
|
assert(self);
|
|
if(!SCMatchRights(pCon,usUser)){
|
|
return 1;
|
|
}
|
|
if(argc < 2){
|
|
SCWrite(pCon,"ERROR: no keyword found",eError);
|
|
return 1;
|
|
}
|
|
strtolower(argv[1]);
|
|
|
|
if(strcmp(argv[1],"makefilename") == 0){
|
|
pFile = makeFilename(pSics,pCon);
|
|
if(pFile != NULL){
|
|
SCWrite(pCon,pFile,eValue);
|
|
free(pFile);
|
|
return 1;
|
|
} else {
|
|
SCWrite(pCon,"ERROR: failed to create filename",eError);
|
|
return 0;
|
|
}
|
|
} else if(strcmp(argv[1],"divisor") == 0){
|
|
if(argc < 3) {
|
|
SCWrite(pCon,"ERROR: no diviso found",eError);
|
|
return 1;
|
|
}
|
|
if(!SCMatchRights(pCon,usMugger)){
|
|
return 1;
|
|
}
|
|
self->timeDivisor = atoi(argv[2]);
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
status = handleFileOperations(pCon,self,argc,argv);
|
|
if(status < 0){
|
|
return 0;
|
|
} else if(status == 1){
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
if we are here, we can only continue if files are open
|
|
*/
|
|
if(self->fileHandle == NULL || self->dictHandle == NULL){
|
|
SCWrite(pCon,"ERROR: cannot write, files not open",eError);
|
|
return 1;
|
|
}
|
|
|
|
if(strcmp(argv[1],"updatedictvar") == 0){
|
|
updateDictVar(pCon,self,argc,argv);
|
|
return 1;
|
|
}
|
|
|
|
if(strstr(argv[1],"put") != NULL){
|
|
handlePut(pCon,pSics,self,argc,argv);
|
|
return 1;
|
|
}
|
|
|
|
if(strcmp(argv[1],"makelink") == 0){
|
|
makeLink(pCon,pSics,self,argc,argv);
|
|
return 1;
|
|
}
|
|
return 1;
|
|
}
|
|
/*=============== make it ==============================================*/
|
|
static void KillNXScript(void *pData){
|
|
pNXScript self = (pNXScript)pData;
|
|
if(self == NULL){
|
|
return;
|
|
}
|
|
if(self->pDes){
|
|
DeleteDescriptor(self->pDes);
|
|
}
|
|
if(self->fileHandle){
|
|
NXclose(&self->fileHandle);
|
|
}
|
|
if(self->dictHandle){
|
|
NXDclose(self->dictHandle, NULL);
|
|
}
|
|
free(self);
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
int MakeNXScript(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[]){
|
|
pNXScript self = NULL;
|
|
int status;
|
|
|
|
self = (pNXScript)malloc(sizeof(NXScript));
|
|
if(self == NULL){
|
|
SCWrite(pCon,"ERROR: no memory for NXscript creation",eError);
|
|
return 0;
|
|
}
|
|
memset(self,0,sizeof(NXScript));
|
|
self->pDes = CreateDescriptor("NXScript");
|
|
if(self->pDes == NULL){
|
|
SCWrite(pCon,"ERROR: no memory for NXscript creation",eError);
|
|
free(self);
|
|
return 0;
|
|
}
|
|
self->timeDivisor = 1;
|
|
|
|
/*
|
|
create with with a default name if none specified
|
|
*/
|
|
if(argc > 1){
|
|
status = AddCommand(pSics,argv[1],NXScriptAction,KillNXScript,self);
|
|
} else {
|
|
status = AddCommand(pSics,"nxscript",NXScriptAction,KillNXScript,self);
|
|
}
|
|
if(!status){
|
|
SCWrite(pCon,"ERROR: duplicate NXScript object not created",eError);
|
|
KillNXScript(self);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|