- Many fixes to the triple axis stuff

* update after a1-a6 drive
  * intrduction of targets
- POLDI writing
- Moved HKL calculation 4 TRICS to fourlib
This commit is contained in:
cvs
2002-01-25 14:48:50 +00:00
parent 8c043c8cd1
commit 1e60f3be82
39 changed files with 3513 additions and 1160 deletions

View File

@ -48,7 +48,8 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
circular.o el755driv.o maximize.o sicscron.o tecsdriv.o sanscook.o \
tasinit.o tasutil.o t_rlp.o t_conv.o d_sign.o d_mod.o \
tasdrive.o tasscan.o synchronize.o definealias.o swmotor.o t_update.o \
hmcontrol.o userscan.o slsmagnet.o rs232controller.o lomax.o
hmcontrol.o userscan.o slsmagnet.o rs232controller.o lomax.o \
polterwrite.o fourlib.o
MOTOROBJ = motor.o el734driv.o simdriv.o el734dc.o pipiezo.o pimotor.o
COUNTEROBJ = countdriv.o simcter.o counter.o
@ -61,16 +62,17 @@ VELOOBJ = velo.o velosim.o velodorn.o velodornier.o
#----- comment or uncomment the following according to operating system
#------------- for Digital Unix
#HDFROOT=/data/koenneck
#CC=cc
#EXTRA=
#CFLAGS = -I$(HDFROOT)/include -Ihardsup -DHDF4 -DHDF5 -I. -std1 \
# -g -warnprotos -c
BINTARGET = bin
HDFROOT=/data/lnslib
CC=cc
EXTRA=
CFLAGS = -I$(HDFROOT)/include -Ihardsup -DHDF4 -DHDF5 -I. -std1 \
-g -warnprotos -c
#CFLAGS = -I$(HDFROOT)/include -DFORTIFY -DHDF4 -DHDF5 -Ihardsup -g \
# -std1 -warnprotos -c
#LIBS = -L$(HDFROOT)/lib -Lhardsup -lhlib -Lmatrix -lmatrix -Ltecs \
# -ltecsl -ltcl8.0 -lfor $(HDFROOT)/lib/libhdf5.a \
# -lmfhdf -ldf $(HDFROOT)/lib/libjpeg.a -lz -lm -ll -lc
LIBS = -L$(HDFROOT)/lib -Lhardsup -lhlib -Lmatrix -lmatrix -Ltecs \
-ltecsl -ltcl8.0 -lfor $(HDFROOT)/lib/libhdf5.a \
-lmfhdf -ldf $(HDFROOT)/lib/libjpeg.a -lz -lm -ll -lc
#------- for cygnus
#HDFROOT=../HDF411
@ -81,16 +83,16 @@ VELOOBJ = velo.o velosim.o velodorn.o velodornier.o
# -lmfhdf -ldf -ljpeg -lz -lm
#---------- for linux
BINTARGET=../bin
HDFROOT=/usr/local
CC=gcc
CFLAGS = -I$(HDFROOT)/include -DHDF4 -Ihardsup -fwritable-strings \
-DCYGNUS -DNONINTF -g -c
#BINTARGET=../bin
#HDFROOT=/usr/local
#CC=gcc
#CFLAGS = -I$(HDFROOT)/include -DHDF4 -Ihardsup -fwritable-strings \
# -DCYGNUS -DNONINTF -g -c
#CFLAGS = -I$(HDFROOT)/include -Ihardsup -fwritable-strings -DFORTIFY \
# -DCYGNUS -DNONINTF -g -c
LIBS= -L$(HDFROOT)/lib -Lhardsup -Ltecs -ltecsl -Lmatrix -lmatrix -lhlib \
-ltcl8.0 -lmfhdf -ldf -ljpeg -lz -lm -lg2c -ldl
EXTRA=nintf.o
#LIBS= -L$(HDFROOT)/lib -Lhardsup -Ltecs -ltecsl -Lmatrix -lmatrix -lhlib \
# -ltcl8.0 -lmfhdf -ldf -ljpeg -lz -lm -lg2c -ldl
#EXTRA=nintf.o
#---------------------------------
.c.o:

18
choco.c
View File

@ -174,7 +174,8 @@
*/
extern pCodri MakeSimChopper(void);
extern pCodri MakeDoChoDriver(char *pHost, int iPort, int iChannel);
extern pCodri MakeDoChoDriver(char *pHost, int iPort, int iChannel,
int iSingle);
extern pCodri MakeCookerDriver(char *pHost, int iPort, int iChannel);
/*-----------------------------------------------------------------------*/
int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
@ -185,6 +186,7 @@ extern pCodri MakeCookerDriver(char *pHost, int iPort, int iChannel);
pObjectDescriptor pDes = NULL;
char pBueffel[132];
int iRet, iPort, iChannel;
int iSingle = 0;
if(argc < 3)
{
@ -229,7 +231,19 @@ extern pCodri MakeCookerDriver(char *pHost, int iPort, int iChannel);
SCWrite(pCon,pBueffel,eError);
return 0;
}
pDriv = MakeDoChoDriver(argv[3],iPort,iChannel);
if(argc > 7)
{
iRet = Tcl_GetInt(pSics->pTcl,argv[6],&iSingle);
if(iRet != TCL_OK)
{
sprintf(pBueffel,
"ERROR: expected integer as single flag, got %s",
argv[6]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
}
pDriv = MakeDoChoDriver(argv[3],iPort,iChannel,iSingle);
}
else if(strcmp(argv[2],"sanscook") == 0)
{

View File

@ -534,3 +534,5 @@ L999:
return 0;
} /* erreso_ */

View File

@ -1,3 +1,3 @@
123
174
NEVER, EVER modify or delete this file
You'll risk eternal damnation and a reincarnation as a cockroach!|n

View File

@ -344,6 +344,7 @@ H H L
%html tricspsd.htm 1
%html histogram.htm 2
%html nextrics.htm 2
%html peaksearch.htm 2
%html trscan.htm 2
%html psddata.htm 1

View File

@ -5,12 +5,12 @@
<BODY>
<H1>TRICS with Position Sensitive Detectors</H1>
<P>
There are no PSD's available yet, but the software is already ready. TRICS
with a PSD requires the following special features.
TRICS with a PSD requires the following special features.
<ul>
<li>Instructions for dealing wih <a href="histogram.htm">
histogram memory</a>.
<li><a href="nextrics.htm">NeXus</a> data handling for TRICS.
<li>A <a href="peaksearch.htm">peak search</a> command.
<li>A TRICS specific <a href="trscan.htm">count and scan</a> command.
</ul>
</p>

164
docho.c
View File

@ -13,6 +13,10 @@
Mark Koennecke, January 1999
Modified to support a single chopper only,
Uwe Filges, Mark Koennecke; November 2001
--------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
@ -41,6 +45,8 @@
int iError;
int iBusy;
float fRatio;
int iSingle;
char pError[80];
} DoCho, *pDoCho;
/*
pHost, iPort and iChannel combined are the adress of the chopper
@ -69,6 +75,9 @@
other parameters, its target value cannot be extracted from the chopper
status message.
iSingle is a flag which is true if only a single chopper is controlled
through this driver. This supports the POLDI single choper case.
*/
/*----------------------------------------------------------------------
ERROR CODES:
@ -78,13 +87,64 @@
#define PARERROR -8004
#define BADSYNC -8005
#define BADSTOP -8006
#define CHOPERROR -8007
extern char *trim(char *pTrim); /* trim.c */
/*----------------------------------------------------------------------*/
static void SplitChopperReply(pCodri self, char *prefix, char *pBueffel)
{
char pToken[30], pValue[20];
char *pPtr, *pTok, *pVal;
int iCount, iRet;
pDoCho pPriv = NULL;
pPriv = (pDoCho)self->pPrivate;
/* decompose pBueffel and store into string dictionary */
pPtr = strtok(pBueffel,";");
while(pPtr != NULL)
{
iCount = sscanf(pPtr,"%s %s",pToken,pValue);
if(iCount == 2)
{
pTok = trim(pToken);
pVal = trim(pValue);
sprintf(pToken,"%s.%s",prefix,pTok);
iRet = StringDictUpdate(pPriv->pPar,pToken,pVal);
if(!iRet)
{
StringDictAddPair(pPriv->pPar,pToken,pVal);
strcat(self->pParList,pToken);
strcat(self->pParList,",");
}
}
else
{
/* this fixes a bug with oversized messages in dphas */
if(strstr(pPtr,"dphas") != NULL)
{
sprintf(pToken,"%s.dphas",prefix);
iRet = StringDictUpdate(pPriv->pPar,
pToken,pPtr+5);
if(!iRet)
{
StringDictAddPair(pPriv->pPar,pToken,
pPtr+5);
strcat(self->pParList,pToken);
strcat(self->pParList,",");
}
}
}
pPtr = strtok(NULL,";");
}
}
/*-------------------------------------------------------------------------
Well, DoChoStatus sends a status request to the Dornier chopper control
system. There is a gotcha, you need three reads to get the full information.
Then the answer is parsed and decomposed into parameter content for the
string dictionary. The single status components are separated by ;.
-------------------------------------------------------------------------*/
extern char *trim(char *pTrim); /* trim.c */
static int DoChoStatus(pCodri self)
{
@ -115,86 +175,21 @@ extern char *trim(char *pTrim); /* trim.c */
pPriv->iError = iRet;
return 0;
}
/* decompose pBueffel and store into string dictionary */
pPtr = strtok(pBueffel,";");
while(pPtr != NULL)
SplitChopperReply(self,"chopper1",pBueffel);
if(!pPriv->iSingle)
{
iCount = sscanf(pPtr,"%s %s",pToken,pValue);
if(iCount == 2)
/* second send: get next second chopper line */
iRet = SerialWriteRead(&(pPriv->pData),"",pBueffel,1023);
if(iRet < 0)
{
pTok = trim(pToken);
pVal = trim(pValue);
sprintf(pToken,"chopper1.%s",pTok);
iRet = StringDictUpdate(pPriv->pPar,pToken,pVal);
if(!iRet)
{
StringDictAddPair(pPriv->pPar,pToken,pVal);
strcat(self->pParList,pToken);
strcat(self->pParList,",");
}
pPriv->iError = iRet;
return 0;
}
else
{
/* this fixes a bug with oversized messages in dphas */
if(strstr(pPtr,"dphas") != NULL)
{
iRet = StringDictUpdate(pPriv->pPar,
"chopper1.dphas",pPtr+5);
if(!iRet)
{
StringDictAddPair(pPriv->pPar,"chopper1.dphas",
pPtr+5);
strcat(self->pParList,"chopper1.dphas");
strcat(self->pParList,",");
}
}
}
pPtr = strtok(NULL,";");
SplitChopperReply(self,"chopper2",pBueffel);
}
/* second send: get next second chopper line */
iRet = SerialWriteRead(&(pPriv->pData),"",pBueffel,1023);
if(iRet < 0)
{
pPriv->iError = iRet;
return 0;
}
/* decompose pBueffel and store into string dictionary */
pPtr = strtok(pBueffel,";");
while(pPtr != NULL)
{
iCount = sscanf(pPtr,"%s %s",pToken,pValue);
if(iCount == 2)
{
pTok = trim(pToken);
pVal = trim(pValue);
sprintf(pToken,"chopper2.%s",pTok);
iRet = StringDictUpdate(pPriv->pPar,pToken,pVal);
if(!iRet)
{
StringDictAddPair(pPriv->pPar,pToken,pVal);
strcat(self->pParList,pToken);
strcat(self->pParList,",");
}
}
else
{
/* this fixes a bug with oversized messages in dphas */
if(strstr(pPtr,"dphas") != NULL)
{
iRet = StringDictUpdate(pPriv->pPar,
"chopper2.dphas",pPtr+5);
if(!iRet)
{
StringDictAddPair(pPriv->pPar,"chopper2.dphas",
pPtr+5);
strcat(self->pParList,"chopper2.dphas");
strcat(self->pParList,",");
}
}
}
pPtr = strtok(NULL,";");
}
return 1;
}
/*-------------------------------------------------------------------------*/
@ -393,7 +388,16 @@ extern char *trim(char *pTrim); /* trim.c */
pPriv->iError = iRet;
return 0;
}
pPriv->iError = 0;
if(strstr(pReply,"error") != NULL)
{
pPriv->iError = CHOPERROR;
strncpy(pPriv->pError,pReply,79);
return 0;
}
else
{
pPriv->iError = 0;
}
pPriv->iBusy = 1;
return 1;
}
@ -610,6 +614,9 @@ extern char *trim(char *pTrim); /* trim.c */
case BADSYNC:
strncpy(pError,"Cannot drive slave chopper",iLen);
break;
case CHOPERROR:
strncpy(pError,pPriv->pError,iLen);
break;
case BADSTOP:
strncpy(pError,
"User called STOP. WARNING: chopper is still untamed!",
@ -680,7 +687,7 @@ extern char *trim(char *pTrim); /* trim.c */
return CHFAIL;
}
/*-------------------------------------------------------------------------*/
pCodri MakeDoChoDriver(char *pHost, int iPort, int iChannel)
pCodri MakeDoChoDriver(char *pHost, int iPort, int iChannel, int iSingle)
{
pCodri pNew = NULL;
pDoCho pPriv = NULL;
@ -706,6 +713,7 @@ extern char *trim(char *pTrim); /* trim.c */
pPriv->iRefreshIntervall = 60;
pPriv->pPar = CreateStringDict();
pPriv->tRefresh = time(NULL);
pPriv->iSingle = iSingle;
if(!pPriv->pPar)
{
free(pText);

791
fourlib.c Normal file
View File

@ -0,0 +1,791 @@
/*
F O U R L I B
This is a library of routines for doing transformations between the
various coordinate systems used on a four circle diffractometer as
used for neutron or X-ray diffraction. The coordinate systems used are
described in Busing, Levy, Acta Cryst (1967),22, 457 ff.
Generally we have:
Z = [OM][CHI][PHI][UB]h
where: Z is a vector in the diffractometer coordinate system
OM CHI PHI are rotation matrices around the respective angles
UB is the UB matrix
h is the reciprocal lattice vector.
The vector Z cannot only be expressed in terms of the angles stt, om, chi,
and phi put also by polar coordinates gamma and nu.
This code is a reimplementation based on a F77 code from Gary McIntyre, ILL
and code extracted from the ILL MAD control program.
Mark Koennecke, November-December 2001
*/
#include <stdio.h>
#include <assert.h>
#include <math.h>
#include "fortify.h"
#include "fourlib.h"
#define PI 3.141592653589793
#define RD 57.30
#define ABS(x) (x < 0 ? -(x) : (x))
/*------------------------------------------------------------------------
a safe routine for calculating the atan of y/x
------------------------------------------------------------------------*/
static double myatan(double y, double x){
if(ABS(x) < 0.0001){
if(y > .0){
return PI/2;
}else {
return -PI/2;
}
}
if(x > .0){
return atan(y/x);
} else {
if(y > .0){
return PI + atan(y/x);
} else {
return -PI + atan(y/x);
}
}
}
/*-------------------------------------------------------------------------*/
static double rtan(double y, double x){
double val;
if( (x == 0.) && (y == 0.) ) {
return .0;
}
if( x == 0.) {
if(y < 0.){
return -PI/2.;
} else {
return PI/2.;
}
}
if(ABS(y) < ABS(x)) {
val = atan(ABS(y/x));
if(x < 0.) {
val = PI - val;
}
if(y < 0.){
val = -val;
}
return val;
} else {
val = PI/2. - atan(ABS(x/y));
if(x < 0.) {
val = PI - val;
}
if( y < 0.) {
val = - val;
}
}
return val;
}
/*----------------------------------------------------------------------
clear3x3 sets a 3x3 matrix to 0
-----------------------------------------------------------------------*/
static void clear3x3(MATRIX target){
int i, j;
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++){
target[i][j] = .0;
}
}
}
/*---------------------------------------------------------------------*/
MATRIX vectorToMatrix(double z[3]){
int i;
MATRIX res;
res = mat_creat(3,1,ZERO_MATRIX);
for(i = 0; i < 3; i++){
res[i][0] = z[i];
}
return res;
}
/*---------------------------------------------------------------------*/
void matrixToVector(MATRIX zm, double z[3]){
int i;
for(i = 0; i < 3; i++){
z[i] = zm[i][0];
}
}
/*----------------------------------------------------------------------
A Busing & levy PSI matrix
----------------------------------------------------------------------*/
static void psimat(MATRIX target, double psi){
double psird = psi/RD;
clear3x3(target);
target[0][0] = 1.;
target[1][1] = cos(psird);
target[1][2] = sin(psird);
target[2][1] = -target[1][2];
target[2][2] = target[1][1];
}
/*----------------------------------------------------------------------
A Busing & levy CHI matrix
----------------------------------------------------------------------*/
void chimat(MATRIX target, double chi){
double chird = chi/RD;
clear3x3(target);
target[0][0] = cos(chird);
target[0][2] = sin(chird);
target[1][1] = 1.;
target[2][0] = -target[0][2];
target[2][2] = target[0][0];
}
/*----------------------------------------------------------------------
A Busing & levy PHI matrix
----------------------------------------------------------------------*/
void phimat(MATRIX target, double phi){
double phird = phi/RD;
clear3x3(target);
target[0][0] = cos(phird);
target[0][1] = sin(phird);
target[1][0] = -target[0][1];
target[1][1] = target[0][0];
target[2][2] = 1.;
}
/*------------------- PSD specific code ----------------------------*/
void det2pol(psdDescription *psd, int x, int y, double *gamma, double *nu) {
double xobs, yobs, b, z, d;
assert(ABS(psd->distance ) > .001);
xobs = (x - psd->xZero)*psd->xScale;
yobs = (y - psd->yZero)*psd->yScale;
b = psd->distance*cos(yobs/psd->distance);
z = psd->distance*sin(yobs/psd->distance);
d = sqrt(xobs*xobs + b*b);
*gamma = psd->gamma + myatan(xobs,b)*RD;
*nu = psd->nu + myatan(z,d)*RD;
}
/*----------------------------------------------------------------------*/
void pol2det(psdDescription *psd, double gamma, double nu, int *x, int *y){
double delga, delnu, td, tn, e, f, g, zobs, xobs;
delga = gamma - psd->gamma;
delnu = nu - psd->nu;
td = tan(delga/RD);
tn = tan(delnu/RD);
e = sqrt(1. + td*td);
f = tn*e;
g = psd->distance*(1. + tn*tn +tn*tn*td*td);
zobs = psd->distance*(atan(tn*e) + asin(f/g));
xobs = td*(psd->distance*cos(zobs/psd->distance));
*y = (int)nint(psd->yZero + zobs/psd->yScale);
*x = (int)nint(psd->xZero + xobs/psd->xScale);
}
/*--------------- bisecting geometry code -----------------------------*/
/*
turn chi and phi in order to get Z1 into the equatorial plane
*/
static void turnEquatorial(MATRIX z1, double *chi, double *phi){
if(ABS(z1[0][0]) < .0001 || ABS(z1[1][0]) < .0001){
*phi = .0;
*chi = 90.;
if(z1[2][0] < .0){
*chi = - *chi;
}
} else {
*phi = myatan(z1[1][0],z1[0][0])*RD;
*chi = myatan(z1[2][0],
sqrt(z1[0][0]*z1[0][0] + z1[1][0]*z1[1][0]))*RD;
}
}
/*----------------------------------------------------------------------
calculate d-spacing and theta from z1
-----------------------------------------------------------------------*/
static int calcTheta(double lambda, MATRIX z1, double *d, double *theta){
double dstar, sintheta;
dstar = sqrt(z1[0][0]*z1[0][0] + z1[1][0]*z1[1][0] + z1[2][0]*z1[2][0]);
if(dstar < .0001){
*d = .0;
*theta = 0;
return 0;
}
*d = 1./dstar;
sintheta = lambda * dstar/2.;
if(ABS(sintheta) > 1.0){
*d = .0;
*theta = .0;
return 0;
}
*theta = asin(sintheta)*RD;
return 1;
}
/*-------------------------------------------------------------------*/
int z1ToBisecting(double lambda, double z1[3], double *stt, double *om,
double *chi, double *phi) {
MATRIX zz1;
int status;
zz1 = vectorToMatrix(z1);
status = z1mToBisecting(lambda,zz1,stt,om,chi,phi);
mat_free(zz1);
return status;
}
/*------------------------------------------------------------------------*/
int z1mToBisecting(double lambda, MATRIX z1, double *stt, double *om,
double *chi, double *phi) {
double d;
int status;
status = calcTheta(lambda,z1,&d,om);
if(!status){
*stt = .0;
*om = .0;
*chi = .0;
*phi = .0;
return status;
}
turnEquatorial(z1,chi,phi);
*stt = *om*2.;
*chi = 180. - *chi;
*phi = 180. + *phi;
return 1;
}
/*---------------------------------------------------------------------*/
int z1ToAnglesWithOffset(double lambda, MATRIX z1m,double omOffset,
double *stt, double *om,
double *chi, double *phi){
int status, i;
double d, delOm, sinchi, q, cosp, sinp, dstar;
MATRIX z1;
status = calcTheta(lambda,z1m,&d,om);
if(!status){
*stt = .0;
*om = .0;
*chi = .0;
*phi = .0;
return status;
}
*stt = 2. * *om;
*om += omOffset;
z1 = mat_copy(z1m); /* routine messes z1m up! */
dstar = sqrt(z1[0][0]*z1[0][0] + z1[1][0]*z1[1][0] + z1[2][0]*z1[2][0]);
for(i = 0; i < 3; i++){
z1[i][0] /= dstar;
}
delOm = -omOffset/RD;
sinchi = z1[2][0]/cos(delOm);
if(ABS(sinchi) > 1.){
mat_free(z1);
return 0;
}
*chi = asin(sinchi);
*chi = PI - *chi;
if(*chi > PI){
*chi = *chi - 2* PI;
}
q = cos(delOm)*cos(*chi);
cosp = (sin(delOm)*z1[0][0] + q*z1[1][0])/
(sin(delOm)*sin(delOm) + q*q);
sinp = (z1[0][0] - sin(delOm)*cosp)/ q;
*phi = rtan(cosp,sinp);
*phi *= RD;
*chi *= RD;
mat_free(z1);
return 1;
}
/*---------------------------------------------------------------------*/
int psiForOmegaOffset(MATRIX z1m, double omOffset,
double chi, double phi, double *psi){
double chibi, sinps, cosps, sinchi, dstar;
MATRIX z1;
z1 = mat_copy(z1m); /* routine messes z1m up! */
dstar = sqrt(z1[0][0]*z1[0][0] + z1[1][0]*z1[1][0] + z1[2][0]*z1[2][0]);
z1[2][0] /= dstar;
omOffset /= RD;
if(-z1[2][0] == 1.){
*psi = phi;
} else {
chibi = PI - asin(-z1[2][0]);
if(chibi > PI){
chibi -= 2*PI;
}
sinps = tan(chibi)*tan(-omOffset);
sinchi = -z1[2][0]/cos(-omOffset);
if(ABS(sinchi) > 1.){
mat_free(z1);
return 0;
}
cosps = (cos(chibi) - sinps*sin(-omOffset)*sinchi)/cos(chi/RD);
*psi = -rtan(sinps,cosps)*RD;
}
mat_free(z1);
return 1;
}
/*----------------------------------------------------------------------*/
void rotatePsi(double om, double chi, double phi, double psi,
double *newom, double *newchi, double *newphi){
MATRIX chim, phim, psim, r0, r0psi;
chim = mat_creat(3,3,ZERO_MATRIX);
chimat(chim,chi);
phim = mat_creat(3,3,ZERO_MATRIX);
phimat(phim,phi);
r0 = mat_mul(chim,phim);
psim = mat_creat(3,3,ZERO_MATRIX);
psimat(psim,psi);
r0psi = mat_mul(psim,r0);
*newchi = rtan(sqrt(r0psi[2][0]*r0psi[2][0] + r0psi[2][1]*r0psi[2][1]),
r0psi[2][2])*RD;
*newphi = rtan(-r0psi[2][1],-r0psi[2][0])*RD;
*newom = om + rtan(-r0psi[1][2],r0psi[0][2])*RD;
mat_free(chim);
mat_free(phim);
mat_free(psim);
mat_free(r0);
mat_free(r0psi);
}
/*--------------------------------------------------------------------
calculate Z1 = [PHI]TZ3
The T means transposed matrixes for the return calculation!
---------------------------------------------------------------------*/
static void z1fromz2(double z1[3], MATRIX z2,
double phi){
MATRIX phim, phimt, zz1;
phim = mat_creat(3,3,ZERO_MATRIX);
phimat(phim, phi);
phimt = mat_tran(phim);
zz1 = mat_mul(phimt,z2);
matrixToVector(zz1,z1);
mat_free(phim);
mat_free(phimt);
mat_free(zz1);
}
/*--------------------------------------------------------------------
calculate Z1 = [PHI]T*[CHI]T*Z3
The T means transposed matrixes for the return calculation!
---------------------------------------------------------------------*/
static void z1fromz3(double z1[3], MATRIX z3, double chi,
double phi){
MATRIX chim, chimt, z2;
chim = mat_creat(3,3,ZERO_MATRIX);
chimat(chim, chi);
chimt = mat_tran(chim);
z2 = mat_mul(chimt,z3);
z1fromz2(z1,z2,phi);
mat_free(chim);
mat_free(chimt);
mat_free(z2);
}
/*--------------------------------------------------------------------
calculate Z1 = [PHI]T*[CHI]T*[OM]T*Z4
The T means transposed matrixes for the return calculation!
---------------------------------------------------------------------*/
static void z1fromz4(double z1[3], MATRIX z4, double om, double chi,
double phi){
MATRIX oma, oma2, z3;
oma = mat_creat(3,3,ZERO_MATRIX);
phimat(oma, om);
oma2 = mat_tran(oma);
z3 = mat_mul(oma2,z4);
z1fromz3(z1,z3,chi,phi);
mat_free(oma);
mat_free(oma2);
mat_free(z3);
}
/*---------------------------------------------------------------------*/
void z1FromAngles(double lambda, double stt, double om,
double chi, double phi, double z1[3]){
MATRIX z4;
double th;
z4 = mat_creat(3,1,ZERO_MATRIX);
th = (stt/2.)/RD;
z4[0][0] = (2. * sin(th)*cos(th))/lambda;
z4[1][0] = (-2. *sin(th)*sin(th))/lambda;
z4[2][0] = .0;
z1fromz4(z1,z4,om,chi,phi);
mat_free(z4);
}
/*----------------------------------------------------------------------
Normal Beam geometry specific calculations. This means the reflection is
expressed through the three angles omega, gamma (two theta detector) and
nu (detector tilt).
bisToNormalBeam was lifted from HKLGEN.
-----------------------------------------------------------------------*/
double sign(double a, double b){
if(b >= .0){
return ABS(a);
} else {
-ABS(a);
}
}
/*----------------------------------------------------------------------*/
int bisToNormalBeam(double twotheta, double omega, double chi, double phi,
double *omeganb, double *gamma, double *nu){
double tth, fom, fchi, fphi, sint, sinnu, del;
tth = twotheta/RD;
fom = omega/RD;
fchi = chi/RD;
fphi = phi/RD;
/* nu calculation */
sint = sin(tth/2.);
*nu = 2. * sin(fchi)*sint;
if(*nu > 1.){
return 0;
}
*nu = asin(*nu);
*nu = ABS(*nu)*sign(1.,fchi);
sinnu = sin(*nu);
/* gamma calculation */
*gamma = cos(tth)/cos(*nu);
if(ABS(*gamma) > 1.0){
return 0;
}
*gamma = acos(*gamma);
*gamma = *gamma * sign(1.,tth);
/* omega normal beam */
del = asin(sint/cos(fchi));
*omeganb = del + fphi;
*omeganb *= RD;
*gamma *= RD;
*nu *= RD;
if(ABS(*omeganb) > 180.){
if(*omeganb < -180.){
*omeganb += 360.;
}
if(*omeganb > 180.){
*omeganb -= 360.;
}
}
return 1;
}
/* --------------------------------------------------------------------*/
static void z4FromNormalBeam(MATRIX z4, double lambda, double gamma,
double nu){
double gar, nur;
gar = gamma/RD;
nur = nu/RD;
/*
this is basically a conversion from polar coordinates to
x,y,z coordinates. However, sin and cos are exchanged in
comparison to textbook formulas for this conversion. But this
is only a shift of origin
*/
z4[0][0] = (sin(gar) * cos(nur))/lambda;
z4[1][0] = (cos (gar) * cos(nur) -1.)/lambda;
z4[2][0] = (sin(nur))/lambda;
}
/*----------------------------------------------------------------------*/
void z1FromNormalBeam(double lambda, double omega, double gamma,
double nu, double z1[3]){
MATRIX z4, omm, omt, z1m;
z4 = mat_creat(3,1,ZERO_MATRIX);
z4FromNormalBeam(z4,lambda, gamma,nu);
omm = mat_creat(3,3,ZERO_MATRIX);
phimat(omm,omega);
omt = mat_tran(omm);
z1m = mat_mul(omt,z4);
matrixToVector(z1m,z1);
mat_free(z4);
mat_free(omm);
mat_free(omt);
mat_free(z1m);
}
/*--------------------------------------------------------------------*/
double circlify(double val){
while(val > 360.){
val -= 360.;
}
while(val < 0.){
val += 360.;
}
return val;
}
/*----------------------------------------------------------------------*/
void z1FromAllAngles(double lambda, double omega , double gamma,
double nu, double chi, double phi, double z1[3]){
MATRIX z3;
z1FromNormalBeam(lambda, omega, gamma, nu, z1);
z3 = vectorToMatrix(z1);
z1fromz3(z1,z3,chi,phi);
mat_free(z3);
}
/*------------------- a test program ------------------------------------*/
#ifdef TESTCODE
int main(int argc, char *argv[]){
psdDescription psd;
double gamma,nu, lambda, stt, om, chi, phi, z1[3], psi;
double psiom, psichi, psiphi;
double sttex, omex, chiex, phiex;
int x, y, status, i;
MATRIX UB, UBinv, zz1,zz1b, hkl, hklback;
double gaex, omnbex, nuex, omeganb;
/* initializations */
UB = mat_creat(3,3,ZERO_MATRIX);
UB[0][0] = 0.016169;
UB[0][1] = 0.011969;
UB[0][2] = 0.063195;
UB[1][0] = -.000545;
UB[1][1] = 0.083377;
UB[1][2] = -0.009117;
UB[2][0] = -0.162051;
UB[2][1] = 0.000945;
UB[2][2] = 0.006321;
UBinv = mat_inv(UB);
lambda = 1.179;
/* test PSD code */
psd.xScale = .7;
psd.yScale = 1.4;
psd.xZero = 128;
psd.yZero = 64;
psd.distance = 450.;
psd.gamma = 43.;
psd.nu = 12.3;
det2pol(&psd,200, 111,&gamma, &nu);
pol2det(&psd,gamma,nu, &x, &y);
if(x == 200 && y == 111){
printf("PSD test: OK\n");
}
/* test bisecting calculations. The tests were taken from a system known
to work
*/
status = 1;
sttex = 30.58704;
omex = 15.293520;
chiex = 129.053604;
phiex = 134.191132;
hkl = mat_creat(3,1,ZERO_MATRIX);
hkl[0][0] = -2.;
hkl[1][0] = -2.;
hkl[2][0] = 4.;
zz1 = mat_mul(UB,hkl);
z1mToBisecting(lambda,zz1,&stt,&om,&chi,&phi);
if(ABS(stt - sttex) > .01 ||
ABS(om - omex) > .01 ||
ABS(chi - chiex) > .01 ||
ABS(phi - phiex) > .01){
printf("Bisecting Angles calculation FAILED!!!!!!!!!\n");
printf("Expected: %12.4f %12.4f %12.4f %12.4f\n", sttex, omex, chiex,phiex);
printf("Got: %12.4f %12.4f %12.4f %12.4f\n", stt,om,chi,phi);
status = 0;
}
z1FromAngles(lambda,sttex,omex,chiex,phiex,z1);
for(i = 0; i < 3; i++){
if(ABS(zz1[i][0] - z1[i]) > .0001){
printf("Calculation of Z1 from Angles FAILED!!!!\n");
printf("Expected: %8.4f %8.4f %8.4f\n", zz1[0][0], zz1[1][0],
zz1[2][0]);
printf("GOT: %8.4f %8.4f %8.4f\n",z1[0],z1[1],z1[2]);
status = 0;
}
}
hklback = mat_mul(UBinv,zz1);
for(i = 0; i < 3; i++){
if(ABS(hklback[i][0] - hkl[i][0]) > .0001){
printf("Back Calculation of HKL FAILED!!!!!!!!!\n");
printf("Expected: %8.4f %8.4f %8.4f\n", hkl[0][0], hkl[1][0],
hkl[2][0]);
printf("GOT: %8.4f %8.4f %8.4f\n",hklback[0][0],
hklback[1][0],hklback[2][0]);
status = 0;
}
}
if(status == 1){
printf("Bisecting test: OK\n");
}
/* try turning in psi */
rotatePsi(omex,chiex,phiex,30.,&psiom,&psichi,&psiphi);
omex = 37.374298;
chiex = 123.068192;
phiex = 170.8209099;
if(ABS(psiom - omex) > .01 ||
ABS(psichi - chiex) > .01 ||
ABS(psiphi - phiex) > .01){
printf("Psi Rotation test FAILED!!!!!!!!!\n");
printf("Expected: %12.4f %12.4f %12.4f\n", omex, chiex,phiex);
printf("Got: %12.4f %12.4f %12.4f\n", psiom,psichi,psiphi);
status = 0;
} else {
printf("Psi rotation test: OK\n");
}
/*
try to calculate a psi for a given omega offset
*/
omex = 15.293520;
chiex = 129.053604;
phiex = 134.191132;
if(psiForOmegaOffset(zz1,-5.,chiex, phiex, &psi) != 1){
printf("Failed to calculate PSI for a Omega Offset\n");
} else {
rotatePsi(omex,chiex,phiex,psi,&psiom,&psichi,&psiphi);
if(ABS(psiom +5. - omex) > .5){
printf("Failed to reach desired omega with calculated psi\n");
printf("Expected: %12.4f Got: %12.4f PSI = %12.4f\n", omex -10.,
psiom, psi);
} else {
printf("Psi for Omega Offset: OK\n");
}
}
/*
try to calculate angles with a omega offset
*/
omex = 10.29;
chiex = 128.78;
phiex = 126.24;
sttex = 30.59;
z1ToAnglesWithOffset(lambda, zz1, -5., &stt, &om, &chi, &phi);
if(ABS(stt - sttex) > .01 ||
ABS(om - omex) > .01 ||
ABS(chi - chiex) > .01 ||
ABS(phi - phiex) > .01){
printf("Angles calculation with Omega Offset FAILED!!!!!!!!!\n");
printf("Expected: %12.4f %12.4f %12.4f %12.4f\n", sttex, omex, chiex,phiex);
printf("Got: %12.4f %12.4f %12.4f %12.4f\n", stt,om,chi,phi);
status = 0;
} else {
printf("Angles with Omega Offset: OK\n");
}
/*
test normal beam codes
*/
omex = 37.374298;
gaex = 19.322;
omnbex = -21.057;
nuex = 24.186;
z1mToBisecting(lambda,zz1,&stt,&om,&chi,&phi);
chi = 50.949;
phi = -45.8088;
if(!bisToNormalBeam(stt,om,chi,phi,
&omeganb, &gamma, &nu)){
printf("Error on normal beam calculation!!\n");
}
if(ABS(omeganb - omnbex) > .01 ||
ABS(gamma - gaex) > .01 ||
ABS(nu - nuex) > .01){
printf("Normal Beam Calculation test FAILED!!!!!!!!!\n");
printf("Expected: %12.4f %12.4f %12.4f\n", omnbex, gaex,nuex);
printf("Got: %12.4f %12.4f %12.4f\n", omeganb,gamma,nu);
} else {
printf("Normal Beam Angle Calculation: OK\n");
}
z1FromNormalBeam(lambda, omnbex, gaex, nuex,z1);
status = 1;
for(i = 0; i < 3; i++){
if(ABS(zz1[i][0] - z1[i]) > .0001){
printf("Calculation of Z1 from Normal Beam Angles FAILED!!!!\n");
printf("Expected: %8.4f %8.4f %8.4f\n", zz1[0][0], zz1[1][0],
zz1[2][0]);
printf("GOT: %8.4f %8.4f %8.4f\n",z1[0],z1[1],z1[2]);
break;
status = 0;
}
}
if(status){
printf("Normal Beam Backwards Calculation: OK\n");
}
/*
for interest: try to see how normal beam angles go if we rotate psi
*/
/*
sttex = 30.58704;
om = 15.293520;
chi = 50.949;
phi = -45.8088;
printf(" PSI Omega Gamma Nu\n");
for(i = 0; i < 36; i++){
psi = i*10.;
rotatePsi(om,chi,phi,psi,&psiom,&psichi,&psiphi);
status = bisToNormalBeam(sttex,psiom,psichi,psiphi,&omeganb, &gamma, &nu);
if(status){
printf("%12.4f%12.4f%12.4f%12.4f\n",psi,omeganb,gamma,nu);
}
}
*/
}
#endif

173
fourlib.h Normal file
View File

@ -0,0 +1,173 @@
/*
F O U R L I B
This is a library of routines for doing transformations between the
various coordinate systems used on a four circle diffractometer as
used for neutron or X-ray diffraction. The coordinate systems used are
described in Busing, Levy, Acta Cryst (1967),22, 457 ff.
Generally we have:
Z = [OM][CHI][PHI][UB]h
where: Z is a vector in the diffractometer coordinate system
OM CHI PHI are rotation matrices around the respective angles
UB is the UB matrix
h is the reciprocal lattice vector.
The vector Z cannot only be expressed in terms of the angles stt, om, chi,
and phi put also by polar coordinates gamma and nu.
This code is a reimplementation based on a F77 code from Gary McIntyre, ILL
and code extracted from the ILL MAD control program.
Mark Koennecke, November - December 2001
*/
#ifndef FOURLIB
#define FOURLIB
#include "matrix/matrix.h"
/**---------------------- PSD specific code -------------------------------
Some diffractometers are equipped with position sensitive detectors.
The scheme to handle them implemented here is to convert the detector
coordinates to polar coordinates gamma and nu and use the normal beam
functions for any further work. A lot of information about the detector
is required for this transformation which is held in the datastruture
as defined below
----------------------------------------------------------------------*/
typedef struct{
double xScale; /* scale factor pixel --> mm for x */
double yScale; /* scale factor pixel --> mm for y */
double distance; /* distance sample detector in mm */
double gamma; /* gamma == two theta position of the detector */
double nu; /* tilt angle of the detector */
int xZero; /* x pixel coordinate of the zero point of the detector */
int yZero; /* y pixel coordinate of the zero point of the detector */
} psdDescription;
/**
* det2pol converts the pixel coordinates x and y on the detector described
* by psd to polar coordinates gamma and nu.
*/
void det2pol(psdDescription *psd, int x, int y, double *gamma, double *nu);
/**
* pol2det converts the polar coordinates gamma and nu to detector coordinates
* x and y on the detector described psd
*/
void pol2det(psdDescription *psd, double gamma, double nu, int *x, int *y);
/*------------------------------------------------------------------------
calculation of four circle diffractometer angles stt, om, chi and phi
in order to put a reflection onto the equatorial plane and into a
diffraction condition. In order to cope with angular restrictions
imposed for instance by sample environment devices or the eulerian
cradle itself various variations are implemented.
These routines start at or target the vector Z1:
Z1 = UB *h
------------------------------------------------------------------------*/
/**
* calculate stt, om, chi and phi in order to put z1 into the bissecting
* diffraction condition. Returns 1 on success and 0 if z1 and lambda
* were invalid. The m version acts upon a matrix.
*/
int z1ToBisecting(double lambda, double z1[3], double *stt, double *om,
double *chi, double *phi);
int z1mToBisecting(double lambda, MATRIX z1, double *stt, double *om,
double *chi, double *phi);
/**
* calculates diffraction angles to put z1 into a detector with a given
* offset in omega against the bisecting position. Useful for tweaking
* if omega is restricted.
*/
int z1ToAnglesWithOffset(double lambda, MATRIX z1,double omOffset,
double *stt, double *om,
double *chi, double *phi);
/**
* calculates a PSI for a given offset in omega from the bisecting
* position. This can be useful for tweaking reflections to be
* measurable at omega restricted diffractometers.
*/
int psiForOmegaOffset(MATRIX z1, double omOffset,
double chi, double phi, double *psi);
/**
* calculate new setting angles for a psi rotation. Input are the angles
* calculated for a bisecting diffraction position. Output angles represent
* the new psi setting. This is the method described by Busing & Levy as the
* version when om == theta is psi = 0.
*/
void rotatePsi(double om, double chi, double phi, double psi,
double *newom, double *newchi, double *newphi);
/**
* calculate z1 from angles stt, om, chi and phi. The angles must not describe
* a bissecting position, however it is required that the angles describe a
* reflection measured in the horizontal plane.
*/
void z1FromAngles(double lambda, double stt, double om,
double chi, double phi, double z1[3]);
/*-----------------------------------------------------------------------
Normal beam calculations. Here the diffraction vector is expressed as
polar angles gamma and nu and omega.
-----------------------------------------------------------------------*/
/**
* calculate the normal beam angles omeganb, gamma and nu from the four
* circle angles twotheta, omega, chi and phi.
*/
int bisToNormalBeam(double twotheta, double omega, double chi, double phi,
double *omeganb, double *gamma, double *nu);
/**
* calculate the vector z1 from the normal beam angles omega, gamma and nu.
* chi and phi either do not exist or are 0.
*/
void z1FromNormalBeam(double lambda, double omega, double gamma,
double nu, double z1[3]);
/**
* calculate z1 from four circle angles plus gamma, nu
*/
void z1FromAllAngles(double lambda, double omega, double gamma,
double nu, double chi, double phi, double z1[3]);
/*------------------------------------------------------------------------
Utility
-------------------------------------------------------------------------*/
/**
* return val put into the 0 - 360 degree range
*/
double circlify(double val);
/**
* converts a vector to a Matrix type
*/
MATRIX vectorToMatrix(double z[3]);
/**
* converts Matrix zm to the vector z
*/
void matrixToVector(MATRIX zm, double z[3]);
/**
* chi rotation matrix for chi into chim
*/
void chimat(MATRIX chim, double chi);
/**
* phi rotation matrix for phi into phim
*/
void phimat(MATRIX phim, double phi);
#endif

View File

@ -11,11 +11,11 @@ OBJ= el734_utility.o asynsrv_utility.o stredit.o \
makeprint.o StrMatch.o
#---------- for Redhat linux
CC= gcc
CFLAGS= -I/usr/local/include -I. -I../ -DLINUX -g -c
#CC= gcc
#CFLAGS= -I/usr/local/include -I. -I../ -DLINUX -g -c
#------------ for DigitalUnix
#CC=cc
#CFLAGS= -I/data/koenneck/include -I. -I../ -std1 -g -c
CC=cc
CFLAGS= -I/data/koenneck/include -I. -I../ -std1 -g -c
#------------ for DigitalUnix with Fortify
## CC=cc
## CFLAGS= -DFORTIFY -I. -I../ -std1 -g -c

793
hkl.c
View File

@ -10,6 +10,9 @@
Mark Koennecke, February 1998
Updated to use fourlib.
Mark Koennecke, December 2001
-----------------------------------------------------------------------------*/
#include <math.h>
#include <ctype.h>
@ -18,9 +21,15 @@
#include "motor.h"
#include "selector.h"
#include "selvar.h"
#include "fourlib.h"
#include "matrix/matrix.h"
#include "hkl.h"
#include "hkl.i"
/*
the space we leave in omega in order to allow for a scan to be done
*/
#define SCANBORDER 3.
/*-------------------------------------------------------------------------*/
static int HKLSave(void *pData, char *name, FILE *fd)
{
@ -359,318 +368,371 @@
self->iNOR = iNOB;
return 1;
}
/*-------------------------------------------------------------------------*/
static int hamth[8] = {0,0,1,1,0,0,1,1};
static int hamom[8] = {0,0,1,1,0,0,1,1};
static int hamch[8] = {0,1,1,1,1,1,1,0};
static int hamph[8] = {0,1,0,1,1,0,1,0};
static int hamhkl[8] = {0,1,0,1,0,1,0,1};
static const float RD = 57.2957795, pi = 3.1415926;
/*-----------------------------------------------------------------------*/
static int checkBisecting(pHKL self,
double stt, double om, double chi, double phi)
{
int iTest;
float fHard, fLimit;
char pError[132];
/* check two theta */
iTest = MotorCheckBoundary(self->pTheta,(float)stt, &fHard,pError,131);
if(!iTest)
{
return -1;
}
/* for omega check against the limits +- SCANBORDER in order to allow for
a omega scan
*/
MotorGetPar(self->pOmega,"softlowerlim",&fLimit);
if((float)om < fLimit + SCANBORDER){
iTest = 0;
} else {
iTest = 1;
MotorGetPar(self->pOmega,"softupperlim",&fLimit);
if((float)om > fLimit - SCANBORDER){
iTest = 0;
} else {
iTest = 1;
}
}
/* check chi and phi*/
iTest += MotorCheckBoundary(self->pChi,(float)chi, &fHard,pError,131);
iTest += MotorCheckBoundary(self->pPhi,(float)phi, &fHard,pError,131);
if(iTest == 3) /* none of them burns */
{
return 1;
}
return 0;
}
/*-----------------------------------------------------------------------*/
static int checkNormalBeam(double om, double gamma, double nu,
float fSet[4], SConnection *pCon, pHKL self)
{
int iTest;
char pError[132];
float fHard;
/* check omega, gamma and nu */
iTest = MotorCheckBoundary(self->pOmega,(float)om, &fHard,pError,131);
iTest += MotorCheckBoundary(self->pTheta,(float)gamma, &fHard,pError,131);
iTest += MotorCheckBoundary(self->pNu,(float)nu, &fHard,pError,131);
if(iTest == 3) /* none of them burns */
{
fSet[0] = (float)gamma;
fSet[1] = (float)om;
fSet[2] = (float)nu;
return 1;
}
return 0;
}
/*-----------------------------------------------------------------------
tryOmegaTweak tries to calculate a psi angle in order to put an
offending omega back into range.
-----------------------------------------------------------------------*/
static int tryOmegaTweak(pHKL self, MATRIX z1, double stt, double *om,
double *chi, double *phi){
int status;
float fLower, fUpper, omTarget, omOffset;
double dumstt, offom, offchi, offphi;
status = checkBisecting(self,stt,*om,*chi,*phi);
if(status < 0){
return 0; /* stt is burning */
} else if(status == 1){
return 1;
}
/*
Is omega really the problem?
*/
omTarget = -9999;
MotorGetPar(self->pOmega,"softlowerlim",&fLower);
MotorGetPar(self->pOmega,"softupperlim",&fUpper);
if(*om < fLower + SCANBORDER) {
omTarget = fLower + SCANBORDER + .5;
}
if(*om > fUpper - SCANBORDER){
omTarget = fUpper - SCANBORDER - .5;
}
if(omTarget < -7000){
return 0;
}
/*
calculate omega offset
*/
omOffset = *om - omTarget;
omOffset = -omOffset;
/*
calculate angles with omega offset
*/
status = z1ToAnglesWithOffset(self->fLambda,z1, omOffset, &dumstt,
&offom, &offchi, &offphi);
if(!status){
return 0;
}
if(checkBisecting(self,dumstt,offom,offchi,offphi)){
*om = offom;
*chi = offchi;
*phi = offphi;
return 1;
}
return 0;
}
/*-----------------------------------------------------------------------*/
static MATRIX calculateScatteringVector(pHKL self, float fHKL[3])
{
MATRIX z1, hkl, ubm;
int i;
hkl = mat_creat(3,1,ZERO_MATRIX);
ubm = mat_creat(3,3,ZERO_MATRIX);
for(i = 0; i < 3; i++)
{
hkl[i][0] = fHKL[i];
ubm[0][i] = self->fUB[i];
ubm[1][i] = self->fUB[i+3];
ubm[2][i] = self->fUB[i+6];
}
z1 = mat_mul(ubm,hkl);
mat_free(ubm);
mat_free(hkl);
return z1;
}
/*---------------------------------------------------------------------*/
static int calculateBisecting(MATRIX z1, pHKL self, SConnection *pCon,
float fSet[4], double myPsi, int iRetry)
{
double stt, om, chi, phi, psi, ompsi, chipsi, phipsi;
int i, test;
/*
just the plain angle calculation
*/
if(!z1mToBisecting(self->fLambda,z1,&stt,&om,&chi,&phi))
{
return 0;
}
/*
check if angles in limits. If omega problem: try to tweak
*/
chi = circlify(chi);
phi = circlify(phi);
if(iRetry > 1)
{
if(tryOmegaTweak(self,z1,stt,&om,&chi,&phi)){
fSet[0] = (float)stt;
fSet[1] = (float)om;
fSet[2] = (float)circlify(chi);
fSet[3]= (float)circlify(phi);
return 1;
}
}
/*
if this does not work, try rotating through psi in order to
find a useful setting
*/
for(i = 0; i < iRetry; i++)
{
if(iRetry > 1)
{
psi = i*10.;
}
else
{
psi = myPsi;
}
rotatePsi(om,chi,phi,psi,&ompsi,&chipsi,&phipsi);
chipsi = circlify(chipsi);
phipsi = circlify(phipsi);
test = checkBisecting(self,stt,ompsi,chipsi,phipsi);
if(test == 1)
{
fSet[0] = (float)stt;
fSet[1] = (float)ompsi;
fSet[2] = (float)chipsi;
fSet[3]= (float)phipsi;
return 1;
}
}
/*
giving up!
*/
for(i = 0; i < 4; i++)
{
fSet[i] = .0;
}
return 0;
}
/*----------------------------------------------------------------------*/
#define ABS(x) (x < 0 ? -(x) : (x))
/*-----------------------------------------------------------------------*/
static int calculateNormalBeam(MATRIX z1, pHKL self, SConnection *pCon,
float fSet[4], double myPsi, int iRetry)
{
int i, iTest;
double stt, om, chi, phi, gamma, nu, psi;
float currentPhi, currentChi;
double ompsi, chipsi, phipsi;
MATRIX chim, phim, z4, z3;
/*-------------------------------------------------------------------------*/
static void rtan(double y, double x, double *rt)
/*
The usual condition for normal beam calculations is that both chi
and phi are 0. This is not the case at TRICS. Therefore we have to
multiply the scattering vector first with the chi and phi rotations
before we start.
*/
iTest = MotorGetSoftPosition(self->pChi,pCon,&currentChi);
if(iTest != 1)
{
if( (x == 0.) && (y == 0.) )
return 0;
}
iTest = MotorGetSoftPosition(self->pPhi,pCon,&currentPhi);
if(iTest != 1)
{
return 0;
}
phim = mat_creat(3,3,ZERO_MATRIX);
phimat(phim,(double)currentPhi);
z4 = mat_mul(phim,z1);
chim = mat_creat(3,3,ZERO_MATRIX);
chimat(chim,(double)currentChi);
z3 = mat_mul(chim,z4);
mat_free(phim);
mat_free(chim);
mat_free(z4);
/*
do the bisecting angles first
*/
if(!z1mToBisecting(self->fLambda,z3,&stt,&om,&chi,&phi))
{
return 0;
}
if(ABS(chi -90.) < .001 && ABS(phi-180.) < .001)
{
chi = .0;
phi = .0;
}
/*
in order to cope with all those limitations: rotate through psi
*/
for(i = 0; i < iRetry; i++)
{
if(iRetry > 1)
{
*rt = 0.;
return;
}
if( x == 0.)
{
*rt = pi/2.;
if(y < 0.)
{
*rt = -*rt;
}
return;
}
if(ABS(y) < ABS(x))
{
*rt = atan(ABS(y/x));
if(x < 0.)
{
*rt = pi - *rt;
}
if(y < 0.)
{
*rt = - *rt;
}
return;
psi = 10. *i;
}
else
{
*rt = pi/2 - atan(ABS(x/y));
psi = myPsi;
}
if(x < 0.)
rotatePsi(om,chi,phi,psi,&ompsi,&chipsi,&phipsi);
if(bisToNormalBeam(stt,ompsi,chipsi,phipsi,
&om, &gamma, &nu))
{
*rt = pi - *rt;
if(checkNormalBeam(om, gamma, nu,fSet,pCon,self))
{
return 1;
}
}
if( y < 0.)
{
*rt = - *rt;
}
return;
}
/*------------------------------------------------------------------------*/
static double fsign(double a, double a2)
return 0;
}
/*---------------------------------------------------------------------*/
static int calculateNormalBeamOmega(MATRIX z1, pHKL self,
SConnection *pCon,
float fSet[4], double omOffset)
{
int iTest;
double stt, om, chi, phi, gamma, nu, psi;
float currentPhi, currentChi;
double ompsi, chipsi, phipsi;
MATRIX chim, phim, z4, z3;
/*
The usual condition for normal beam calculations is that both chi
and phi are 0. This is not the case at TRICS. Therefore we have to
multiply the scattering vector first with the chi and phi rotations
before we start.
*/
iTest = MotorGetSoftPosition(self->pChi,pCon,&currentChi);
if(iTest != 1)
{
if(a2 >= 0.)
{
return ABS(a);
}
else
{
return -ABS(a);
}
return 0;
}
/*------------------------------------------------------------------------*/
static void sincos(double *sn, double *cs, double *loc)
iTest = MotorGetSoftPosition(self->pPhi,pCon,&currentPhi);
if(iTest != 1)
{
if(ABS(*sn) >= 1.)
{
*sn = fsign(1.0,*sn);
*cs = 0.;
return;
}
else
{
*cs = sqrt(1. - *sn * *sn);
return;
}
return 0;
}
/*-------------------------------------------------------------------------*/
static int ICAL(pHKL self, float fHKL[3], float fPsi, int iHamil,
int iQuad, float fSet[4], float fDelom)
phim = mat_creat(3,3,ZERO_MATRIX);
phimat(phim,(double)currentPhi);
z4 = mat_mul(phim,z1);
chim = mat_creat(3,3,ZERO_MATRIX);
chimat(chim,(double)currentChi);
z3 = mat_mul(chim,z4);
mat_free(phim);
mat_free(chim);
mat_free(z4);
/*
do the bisecting angles first
*/
if(!z1ToAnglesWithOffset(self->fLambda,z3, omOffset, &stt,
&ompsi, &chi, &phi))
{
double z[3],tang[2],r,r1,phi,delomr,t,dstar,v,theta,omega,chi,cosp;
double sinp,d,q,zer,d2,all,den1,den2,cosps,a,sinc,cosc,b,c,chibi;
double sinps,sinchi,extrap, psi, loc;
int i,ip,ivariz,ipara,nh,nhamil,isign,icry,ii;
delomr = fDelom/(RD * -1);
iHamil -= 1; /* to get iHamil from 1 -- 8 & negative if not requested*/
psi = fPsi;
/* HKl --> Lab Axis through UB */
for(i = 0; i < 3; i++)
{
ii = 3*i;
z[i] = self->fUB[ii]*fHKL[0] + self->fUB[ii+1]*fHKL[1] +
self->fUB[ii+2]*fHKL[2];
}
/* bissecting calculation! */
if(!self->iNOR)
{
/* four circle calculation */
t = z[0]*z[0] + z[1]*z[1] + z[2]*z[2];
dstar = sqrt(t);
for(i = 0; i < 3; i++)
{
z[i] /= dstar;
}
v = self->fLambda *.5 * dstar;
if(v > 1.)
{
return -1;
}
theta = 2 * asin(v);
omega = (.5 * theta) - delomr;
sinchi = -z[2]/cos(delomr);
if(ABS(sinchi) > 1.)
{
return -1;
}
chi = asin(sinchi);
if(iQuad == 1)
{
chi = pi - chi;
if(chi > pi)
{
chi = chi -(2.*pi);
}
}
d = delomr;
q = sin(d);
r = cos(d) * cos(chi);
cosp = (q*z[0] + r*z[1])/(q*q + r*r);
sinp = (z[0] - q*cosp)/r;
rtan(cosp,sinp,&phi);
chi = -chi;
if(fDelom != 0.)
{
/* recalculate psi */
r1 = -z[2];
if(r1 == 1.)
{
psi = phi;
}
else
{
chibi = asin(r1);
if(iQuad == 1)
{
chibi = pi - chibi;
if(chibi > pi)
{
chibi = chibi -(2*pi);
}
}
sinps = tan(chibi)*tan(delomr);
cosps = (cos(chibi) -sinps*sin(delomr)*sinchi)/cos(chi);
rtan(sinps,cosps,&psi);
psi = -psi;
}
psi = RD*psi;
goto hamil;
}
if(psi != 0.)
{
/* non zero psi */
a = psi/RD;
sinps = sin(a);
cosps = cos(a);
sinc = sin(chi);
cosc = cos(chi);
sinp = sin(phi);
cosp = cos(phi);
a = sinps*sinp - sinc*cosp*cosps;
b = -sinps*cosp - sinc*sinp*cosps;
/* do chi */
c = sqrt(a*a + b*b);
d = cosps*cosc;
rtan(c,d,&chi);
/* do phi */
rtan(-b,-a,&phi);
/* do omega */
a = -sinps *cosc;
rtan(a,sinc,&omega);
omega = omega + theta *.5;
}
hamil:
theta = theta *RD;
omega = omega *RD;
chi = chi*RD;
phi = phi*RD;
if(iHamil >= 0)
{
/* hamilton logic */
if(hamth[iHamil]) theta = theta * -1;
if(hamom[iHamil]) omega = omega -ABS(theta);
if(hamph[iHamil])
{
phi += 180.;
if(phi > 180.)
{
phi -= 360;
}
}
if(hamch[iHamil])
{
if( (iHamil == 1) || (iHamil == 6) )
{
chi *= -1;
}else if((iHamil == 1) || (iHamil == 5))
{
chi -= 180.;
if(chi < -180.)
{
chi += 360.;
}
}
else
{
chi = chi* -1 - 180;
if(chi > 180.)
{
chi -= 360;
}
}
}
}
/* hamhkl left out */
fSet[0] = theta;
fSet[1] = omega;
fSet[2] = chi;
fSet[3] = phi;
return 1;
} /* end four circle */
else
{
/* start normal bissecting calculation */
/* ignore psi values */
d2 = 0.;
for(i = 0; i < 3; i++)
{
d2 += z[i]*z[i];
}
d = sqrt(d2);
d2 *= self->fLambda*self->fLambda;
tang[0] = z[2]*self->fLambda;
all = tang[0]*tang[0];
den1 = sqrt(d2-all);
if(all > 1.)
{
return -1;
}
den2 = sqrt(1. - all);
if(!((den1+den2 > 1.) && (ABS(den2-den1) < 1.)))
{
return -1;
}
isign = 1;
fSet[3] = 0.;
sincos(&tang[0],&tang[1],&loc);
fSet[2] = RD*atan2(tang[0],tang[1]);
tang[1] = (2-d2)/(2*den2);
sincos(&tang[1],&tang[0],&loc);
fSet[0] = RD*atan2(tang[0],tang[1])*isign;
tang[1] = d2/(2*den1);
sincos(&tang[1],&tang[0],&loc);
all = atan2(tang[0],tang[1]);
all -= isign*atan2(z[1],z[0]);
fSet[1] = 180. - RD*all -90.;
if(fSet[1] < 0.)
{
fSet[1] = 360. + fSet[1];
}
return 1;
}
return 0;
}
if(ABS(chi -90.) < .001 && ABS(phi-180.) < .001)
{
chi = .0;
phi = .0;
}
if(bisToNormalBeam(stt,ompsi,chi,phi,
&om, &gamma, &nu))
{
if(checkNormalBeam(om, gamma, nu,fSet,pCon,self))
{
return 1;
}
}
return 0;
}
/*-------------------------------------------------------------------------
calculates the four circle settings. If the position can not be reached
because of a limit violation, then psi is rotated in 10 degree steps
until either the loop ends or we finally succeed. If there is a omega
violation we first try to calculate a delta omega which puts omega
into the right range. This is a fix because the omega movement is quite
often restricted due to the crygenic garbage around the sample.
often restricted due to the cryogenic garbage around the sample.
*/
int CalculateSettings(pHKL self, float fHKL[3], float fPsi, int iHamil,
float fSet[4], SConnection *pCon)
{
int iRet,iRetry, i;
int iQuad = 0;
int iTest;
float fDelom = 0.;
char pError[132];
char pBueffel[512];
float fHard, fVal, fUpper, fLower;
float myPsi = fPsi;
double myPsi = fPsi;
MATRIX z1;
double stt, om, chi, phi, ompsi, chipsi, phipsi;
int i,iRetry, status;
/* catch shitty input */
if( (fHKL[0] == 0.) && (fHKL[1] == 0.) && (fHKL[2] == 0.))
@ -681,19 +743,12 @@
}
/* some people are stupid.......... */
if(myPsi > 360.)
{
myPsi -= 360;
}
if(myPsi < .0)
{
myPsi += 360.;
}
myPsi = circlify(myPsi);
/* no retries if normal beam calculation
or specific Hamilton or specific
psi requested */
if( (self->iNOR) || (iHamil != 0) || (myPsi > 0.1) )
/*
no retries if specific psi requested.
*/
if((myPsi > 0.1) )
{
iRetry = 1;
}
@ -703,99 +758,33 @@
}
/* loop till success */
for(i = 0, myPsi = fPsi; i < iRetry; i++, myPsi += 10.)
z1 = calculateScatteringVector(self,fHKL);
if(self->iNOR == 0)
{
/* just try it*/
iRet = ICAL(self,fHKL, myPsi, iHamil, self->iQuad,fSet,fDelom);
if(iRet < 0 ) /* could not do it */
{
sprintf(pBueffel,"ERROR: cannot calculate %4.1f %4.1f %4.1f",
status = calculateBisecting(z1,self,pCon,fSet, myPsi, iRetry);
}
else if(self->iNOR == 1)
{
status = calculateNormalBeam(z1,self,pCon,fSet, myPsi, iRetry);
}
else
{
myPsi = fPsi;
status = calculateNormalBeamOmega(z1,self,pCon,fSet, myPsi);
}
if(!status)
{
sprintf(pBueffel,"ERROR: cannot calculate %4.1f %4.1f %4.1f",
fHKL[0], fHKL[1], fHKL[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* check two theta */
iTest = MotorCheckBoundary(self->pTheta,fSet[0], &fHard,pError,131);
if(!iTest)
{
/* this cannot be fixed */
sprintf(pBueffel,
"ERROR: %4.1f, %4.1f, %4.1f, %5.2f violates two theta limits",
fSet[0], fHKL[0], fHKL[1],fHKL[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* check nu and omega if normal beam */
if(self->iNOR)
{
/* check omega */
iTest = MotorCheckBoundary(self->pOmega,fSet[1], &fHard,pError,131);
iTest += MotorCheckBoundary(self->pNu,fSet[2], &fHard,pError,131);
if(iTest != 2)
{
sprintf(pBueffel,
"ERROR: %4.1f, %4.1f, %4.1f, %5.2f %5.2f %5.2f violates nu limits",
fHKL[0], fHKL[1],fHKL[2],fSet[0], fSet[1],fSet[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
else
{
return 1;
}
}
/* check chi and phi and omega, but first put into 0-360 degrees */
if(fSet[2] < 0.0)
{
fSet[2] = 360.0 + fSet[2];
}
/*
if(fSet[3] < 0.0)
{
fSet[3] = 360.0 + fSet[3];
}
*/
iTest = MotorCheckBoundary(self->pOmega,fSet[1], &fHard,pError,131);
if(iTest == 0 && i == 0)
{
/*
calculate a delta omega to put omega into center of range
*/
MotorGetPar(self->pOmega,"softupperlim",&fUpper);
MotorGetPar(self->pOmega,"softlowerlim",&fLower);
if(fSet[1] > fUpper)
{
fVal = fUpper - 5.; /* 5 degree safety for scanning */
}
else if (fSet[1] < fLower)
{
fVal = fLower + 5.; /* same */
}
fDelom = fSet[1] - fVal;
fDelom = -fDelom;
}
iTest += MotorCheckBoundary(self->pChi,fSet[2], &fHard,pError,131);
iTest += MotorCheckBoundary(self->pPhi,fSet[3], &fHard,pError,131);
if(iTest == 3) /* none of them burns */
{
sprintf(pBueffel,"Solution found at psi = %4.1f",myPsi);
SCWrite(pCon,pBueffel,eWarning);
return 1;
}
}
if(iRetry != 1)
{
sprintf(pBueffel,
"ERROR: failed to find a possible setting for %4.1f %4.1f %4.1f %s",
fHKL[0], fHKL[1], fHKL[2], "\n Even tried 36 psi settings");
SCWrite(pCon,pBueffel,eError);
return 0;
}
mat_free(z1);
return status;
return 0;
}
/*-------------------------------------------------------------------------*/
@ -1098,32 +1087,19 @@ ente:
static int angle2HKL(pHKL self ,double tth, double om,
double chi, double phi, float fHKL[3])
{
double dTh, dOm, dChi, dPhi, dHM;
MATRIX res, rez;
MATRIX rez, z1m;
double z1[3];
int i;
/* conversion to radians */
dTh = tth/(2*RD);
dOm = (om - tth/2.)/RD;
dChi = chi/RD;
dPhi = phi/RD;
dHM = 2* sin(dTh)/self->fLambda;
/* angles to XYZ, stolen from DIFRAC code in PRPXYZ */
res = mat_creat(3,1,ZERO_MATRIX);
res[0][0] = dHM*(cos(dChi)*cos(dPhi)*cos(dOm) -
sin(dPhi)*sin(dOm));
res[1][0] = dHM*(cos(dChi)*sin(dPhi)*cos(dOm) +
cos(dPhi)*sin(dOm));
res[2][0] = dHM*sin(dChi)*cos(dOm);
z1FromAngles(self->fLambda,tth,om,chi,phi,z1);
z1m = vectorToMatrix(z1);
/* multiply with UBinv in order to yield HKL */
rez = mat_mul(self->UBinv,res);
rez = mat_mul(self->UBinv,z1m);
for(i = 0; i < 3; i++)
{
fHKL[i] = rez[i][0];
fHKL[i] = (float)rez[i][0];
}
mat_free(res);
mat_free(z1m);
mat_free(rez);
return 1;
@ -1448,9 +1424,18 @@ ente:
return 0;
}
iRet = CalculateSettings(self,fHKL, fPsi, iHamil, fSet,pCon);
sprintf(pBueffel," theta = %f, omega = %f, chi = %f, phi = %f",
if(self->iNOR)
{
sprintf(pBueffel," gamma = %f, omega = %f, nu = %f",
fSet[0], fSet[1], fSet[2]);
SCWrite(pCon,pBueffel,eValue);
}
else
{
sprintf(pBueffel," theta = %f, omega = %f, chi = %f, phi = %f",
fSet[0], fSet[1], fSet[2],fSet[3]);
SCWrite(pCon,pBueffel,eValue);
SCWrite(pCon,pBueffel,eValue);
}
if(!iRet)
{
SCWrite(pCon,

195
lomax.c
View File

@ -103,6 +103,7 @@ static int testMaximum(int *iData, int xsize, int ysize,
{
int testValue, x, y, half;
int *iPtr;
int equalCount = 0;
testValue = iData[j * xsize + i];
half = window/2;
@ -114,8 +115,16 @@ static int testMaximum(int *iData, int xsize, int ysize,
{
if(iPtr[x] > testValue)
return 0;
if(iPtr[x] == testValue)
equalCount++;
}
}
/*
if(equalCount > 3)
{
return 0;
}
*/
return 1;
}
/*--------------------------------------------------------------------*/
@ -144,7 +153,7 @@ int testLocalMaximum(int *iData, int xsize, int ysize,
}
/*-------------------------------------------------------------------*/
int calculateCOG(int *iData, int xsize, int ysize,
int *i, int *j, int *intensity,
int *i, int *j, int *intensity,int *nCount,
int cogWindow,
float contour)
{
@ -153,6 +162,9 @@ int calculateCOG(int *iData, int xsize, int ysize,
float cogTotal, cogX, cogY;
int *iPtr;
if(!testBoundaries(xsize,ysize,cogWindow,*i,*j))
return 0;
/*
preparations
*/
@ -175,6 +187,7 @@ int calculateCOG(int *iData, int xsize, int ysize,
/*
build the sums
*/
*nCount = 0;
cogTotal = cogY = cogX = .0;
for(y = yLow; y < yMax; y++)
{
@ -183,13 +196,14 @@ int calculateCOG(int *iData, int xsize, int ysize,
{
if(iPtr[x] > threshold)
{
*nCount++;
cogTotal += iPtr[x];
cogY += y * iPtr[x];
cogX += x * iPtr[x];
}
}
}
if(cogTotal < .0)
if(cogTotal <= .0)
{
return 0;
}
@ -200,6 +214,82 @@ int calculateCOG(int *iData, int xsize, int ysize,
return 1;
}
/*-------------------------------------------------------------------*/
void calculateStatistics(int *iData, int xsize, int ysize,
float *average, float *maximum)
{
int i, iLength;
int max = -9999999999999;
long sum = 0;
iLength = xsize*ysize;
for(i = 0; i < iLength; i++)
{
sum += iData[i];
if(iData[i] > max)
max = iData[i];
}
*average = (float)sum/(float)iLength;
*maximum = (float)max;
}
/*-------------------------------------------------------------------*/
int wellFormed(int *iData, int xsize, int ysize,
int i, int j, int window, float contour,
int maxBad)
{
int testValue, x, y, half;
int *iPtr;
int badCount = 0;
testValue = (int)((float)iData[j * xsize + i]*contour);
half = window/2;
/*
test upper row
*/
iPtr = iData + (j - half) * xsize + i - half;
for(x = 0; x < window; x++)
{
if(iPtr[x] > testValue)
badCount++;
}
/*
test lower row
*/
iPtr = iData + (j + half) * xsize + i - half;
for(x = 0; x < window; x++)
{
if(iPtr[x] > testValue)
badCount++;
}
/*
test columns
*/
for(y = j - half; y < j + half; y++)
{
/*
left
*/
if(iData[y*xsize + i - half] > testValue)
badCount++;
/*
right
*/
if(iData[y*xsize + i + half] > testValue)
badCount++;
}
if(badCount > maxBad)
{
return 0;
}
return 1;
}
/*-------------------------------------------------------------------*/
static int checkHM(pHistMem *pHM, SicsInterp *pSics, SConnection *pCon,
char *name, int *iDim)
@ -247,7 +337,7 @@ int LoMaxAction(SConnection *pCon, SicsInterp *pSics,
{
pLoMax self = NULL;
char pBueffel[256], pNum[20];
int iRet, i, j, intensity;
int iRet, i, j, intensity, count, badMax;
int iDim[10], nDim;
pHistMem pHM = NULL;
CommandList *pCom = NULL;
@ -256,6 +346,7 @@ int LoMaxAction(SConnection *pCon, SicsInterp *pSics,
int *iData;
double dVal;
ObPar *ob = NULL;
float average, maximum;
self = (pLoMax)pData;
assert(pCon);
@ -291,9 +382,9 @@ int LoMaxAction(SConnection *pCon, SicsInterp *pSics,
return 0;
}
Tcl_DStringInit(&result);
Tcl_DStringStartSublist(&result);
iData = GetHistogramPointer(pHM,pCon);
window = (int)ObVal(self->pParam,WINDOW);
count = 0;
for(i = 0 + window/2; i < iDim[0] - window/2; i++)
{
for(j = 0 + window/2; j < iDim[1] - window/2; j++)
@ -305,18 +396,20 @@ int LoMaxAction(SConnection *pCon, SicsInterp *pSics,
(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);
if(count != 0)
{
Tcl_DStringAppend(&result,"@",strlen("@"));
}
sprintf(pNum,"%d ", i);
Tcl_DStringAppend(&result,pNum,strlen(pNum));
sprintf(pNum,"%d ", j);
Tcl_DStringAppend(&result,pNum,strlen(pNum));
sprintf(pNum,"%d", intensity);
Tcl_DStringAppendElement(&result,pNum);
Tcl_DStringEndSublist(&result);
Tcl_DStringAppend(&result,pNum,strlen(pNum));
count++;
}
}
}
Tcl_DStringEndSublist(&result);
SCWrite(pCon,Tcl_DStringValue(&result),eValue);
Tcl_DStringFree(&result);
return 1;
@ -347,27 +440,87 @@ int LoMaxAction(SConnection *pCon, SicsInterp *pSics,
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,
iRet = calculateCOG(iData,iDim[0], iDim[1], &i, &j, &intensity,&count,
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);
sprintf(pNum,"%d ", i);
Tcl_DStringAppend(&result,pNum,strlen(pNum));
sprintf(pNum,"%d ", j);
Tcl_DStringAppend(&result,pNum,strlen(pNum));
sprintf(pNum,"%d ", intensity);
Tcl_DStringAppend(&result,pNum,strlen(pNum));
sprintf(pNum,"%d ", count);
Tcl_DStringAppend(&result,pNum,strlen(pNum));
SCWrite(pCon,Tcl_DStringValue(&result),eValue);
Tcl_DStringFree(&result);
return 1;
}
else if(strcmp(argv[1],"wellformed") == 0) /* test for wellformedness */
{
if(argc < 6)
{
sprintf(pBueffel,
"ERROR: insufficient number of arguments to %s.wellformed",
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;
}
if(Tcl_GetInt(pSics->pTcl,argv[5],&badMax)!= TCL_OK)
{
sprintf(pBueffel,"ERROR: expected number, got %s",argv[2]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
iData = GetHistogramPointer(pHM,pCon);
window = (int)ObVal(self->pParam,COGWINDOW);
iRet = wellFormed(iData,iDim[0], iDim[1], i, j,
window, ObVal(self->pParam,COGCONTOUR),
badMax);
sprintf(pBueffel,"%5d", iRet);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
else if(strcmp(argv[1],"stat") == 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;
}
iData = GetHistogramPointer(pHM,pCon);
calculateStatistics(iData,iDim[0],iDim[1],&average,&maximum);
sprintf(pBueffel," %f %f", average, maximum);
SCWrite(pCon,pBueffel,eValue);
return 1;
}
else
{
/* we are handling one of the parameter commands

View File

@ -27,9 +27,14 @@
int window, int threshold, int steepness,
int *intensity);
int calculateCOG(int *iData, int xsize, int ysize,
int *i, int *j, int *intensity,
int *i, int *j, int *intensity, int *count,
int cogWindow,
float contour);
void calculateStatistics(int *iData, int xsize, int ysize,
float *average, float *maximum);
int wellFormed(int *iData, int xsize, int ysize,
int x, int y, int window, float contour,
int maxBad);

16
lomax.w
View File

@ -46,9 +46,14 @@ ever needed.
int window, int threshold, int steepness,
int *intensity);
int calculateCOG(int *iData, int xsize, int ysize,
int *i, int *j, int *intensity,
int *i, int *j, int *intensity, int *count,
int cogWindow,
float contour);
void calculateStatistics(int *iData, int xsize, int ysize,
float *average, float *maximum);
int wellFormed(int *iData, int xsize, int ysize,
int x, int y, int window, float contour,
int maxBad);
@}
@ -63,6 +68,15 @@ calculateCOG calculates the center of gravity for point i, j,. Points within a
calculation. The position of the maximum (i,j) and its intensity are
updated by calculateCOG.
calculateStatistics finds the average and the maximum value of the data
in iData.
wellFormed checks a candidate peak position at x, y for well
formedness. Basically it checks if there are points above
contour * maximum at the borders of the COG window. If this count is
larger then maxBad 0 is returned else 1. This should catch powder
lines and guard against overlapped peaks.
@o lomax.h @{
/*-------------------------------------------------------------------------

9
napi.h
View File

@ -34,7 +34,6 @@
#ifndef NEXUSAPI
#define NEXUSAPI
/* NeXus HDF45 */
#define NEXUS_VERSION "2.1.0." /* major.minor.patch */
@ -162,6 +161,7 @@ typedef struct {
# define NXgetgroupinfo MANGLE(nxigetgroupinfo)
# define NXinitgroupdir MANGLE(nxiinitgroupdir)
# define NXinitattrdir MANGLE(nxiinitattrdir)
# define NXsetcache MANGLE(nxisetcache)
/* FORTRAN helpers - for NeXus internal use only */
# define NXfopen MANGLE(nxifopen)
# define NXfclose MANGLE(nxifclose)
@ -171,7 +171,6 @@ typedef struct {
# define NXfcompress MANGLE(nxifcompress)
# define NXfputattr MANGLE(nxifputattr)
/*
* Standard interface
*/
@ -220,8 +219,10 @@ NX_EXTERNAL NXstatus CALLING_STYLE NXfree(void** data);
*/
NX_EXTERNAL void CALLING_STYLE NXMSetError(void *pData, void (*ErrFunc)(void *pD, char *text));
/*
another special function for setting the default cache size for HDF-5
*/
NX_EXTERNAL NXstatus CALLING_STYLE NXsetcache(long newVal);
#endif /*NEXUSAPI*/

View File

@ -307,7 +307,7 @@ name of hkl object holding crystallographic information
char pBueffel[512];
CounterMode eMode;
HistInt lData[DET1X*DET1Y], i, lVal;
int32 iVal;
int32 iVal,lBeam;
float fVal, fTTheta;
pMotor pMot;
@ -347,24 +347,28 @@ name of hkl object holding crystallographic information
eMode = GetHistCountMode(self->pHistogram1);
fVal = GetHistPreset(self->pHistogram1);
lVal = GetHistMonitor(self->pHistogram1,1,pCon);
lBeam = GetHistMonitor(self->pHistogram1,4,pCon);
}
if(self->pHistogram2 != NULL)
{
eMode = GetHistCountMode(self->pHistogram2);
fVal = GetHistPreset(self->pHistogram2);
lVal = GetHistMonitor(self->pHistogram2,1,pCon);
lBeam = GetHistMonitor(self->pHistogram2,4,pCon);
}
if(self->pHistogram3 != NULL)
{
eMode = GetHistCountMode(self->pHistogram3);
fVal = GetHistPreset(self->pHistogram3);
lVal = GetHistMonitor(self->pHistogram3,1,pCon);
lBeam = GetHistMonitor(self->pHistogram2,4,pCon);
}
if(self->pCount != NULL)
{
eMode = GetCounterMode(self->pCount);
fVal = GetCounterPreset(self->pCount);
lVal = GetMonitor(self->pCount,1,pCon);
lBeam = GetMonitor(self->pCount,4,pCon);
}
if(eMode == eTimer)
{
@ -378,6 +382,8 @@ name of hkl object holding crystallographic information
NXDputalias(hfil,self->pDict,"framepreset",&fVal);
iVal = (int32)lVal;
NXDputalias(hfil,self->pDict,"framemonitor",&iVal);
iVal = (int32)lBeam;
NXDputalias(hfil,self->pDict,"sinqmonitor",&iVal);
/* write detector1 histogram */
if(self->pHistogram1 != NULL)
@ -676,7 +682,7 @@ name of hkl object holding crystallographic information
SCWrite(pCon,"ERROR: failed to write detecor y zero point",eError);
}
pVar = NULL;
pVar = FindVariable(pServ->pSics,"det1dist");
pVar = FindVariable(pServ->pSics,"detdist1");
if(pVar)
{
fVal = pVar->fVal;
@ -772,7 +778,7 @@ name of hkl object holding crystallographic information
eError);
}
pVar = NULL;
pVar = FindVariable(pServ->pSics,"det2dist");
pVar = FindVariable(pServ->pSics,"detdist2");
if(pVar)
{
fVal = pVar->fVal;
@ -799,7 +805,7 @@ name of hkl object holding crystallographic information
/*
third detector, but only if present
*/
if(self->pHistogram2 != NULL)
if(self->pHistogram3 != NULL)
{
strcpy(pBueffel,"detector3");
NXDupdate(self->pDict,"dnumber",pBueffel);
@ -811,7 +817,7 @@ name of hkl object holding crystallographic information
iRet = NXDputalias(hfil,self->pDict,"ddescription",pBueffel);
if(iRet != NX_OK)
{
SCWrite(pCon,"ERROR: failed to write detector2 description",eError);
SCWrite(pCon,"ERROR: failed to write detector3 description",eError);
}
for(i = 0; i < DET3X; i++)
{
@ -870,7 +876,7 @@ name of hkl object holding crystallographic information
eError);
}
pVar = NULL;
pVar = FindVariable(pServ->pSics,"det3dist");
pVar = FindVariable(pServ->pSics,"detdist3");
if(pVar)
{
fVal = pVar->fVal;

View File

@ -76,6 +76,7 @@ pAmor2T pAmor = NULL;
float fVal;
/* open files */
NXsetcache(TOFBLOCK);
iRet = NXopen(file,NXACC_CREATE5,&hfil);
if(iRet != NX_OK)
{

3
ofac.c
View File

@ -106,6 +106,7 @@
#include "hmcontrol.h"
#include "rs232controller.h"
#include "lomax.h"
#include "polterwrite.h"
/*----------------------- Server options creation -------------------------*/
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
@ -287,6 +288,7 @@
AddCommand(pInter,"MakeHMControl",MakeHMControl,NULL,NULL);
AddCommand(pInter,"MakeRS232Controller",RS232Factory,NULL,NULL);
AddCommand(pInter,"MakeMaxDetector",LoMaxFactory,NULL,NULL);
AddCommand(pInter,"PolterInstall",PolterInstall,NULL,NULL);
}
/*---------------------------------------------------------------------------*/
static void KillIniCommands(SicsInterp *pSics)
@ -345,6 +347,7 @@
RemoveCommand(pSics,"MakeHMControl");
RemoveCommand(pSics,"MakeRS232Controller");
RemoveCommand(pSics,"MakeMaxDetector");
RemoveCommand(pSics,"PolterInstall");
}

View File

@ -5,6 +5,8 @@
#---------------------------------------------------------------------------
proc initPeakSearch {} {
#------- phi Range
VarMake ps.phiStart Float User
ps.phiStart 0
VarMake ps.phiEnd Float User
@ -12,6 +14,7 @@ proc initPeakSearch {} {
VarMake ps.phiStep Float User
ps.phiStep 3.
#-------- chi range
VarMake ps.chiStart Float User
ps.chiStart 0
VarMake ps.chiEnd Float User
@ -19,6 +22,7 @@ proc initPeakSearch {} {
VarMake ps.chiStep Float User
ps.chiStep 12.
#-------- omega range
VarMake ps.omStart Float User
ps.omStart 0
VarMake ps.omEnd Float User
@ -26,6 +30,7 @@ proc initPeakSearch {} {
VarMake ps.omStep Float User
ps.omStep 3.
#------- two theta range
VarMake ps.sttStart Float User
ps.sttStart 5
VarMake ps.sttEnd Float User
@ -33,6 +38,7 @@ proc initPeakSearch {} {
VarMake ps.sttStep Float User
ps.sttStep 3.
#------- maximum finding parameters
VarMake ps.threshold Int User
ps.threshold 30
VarMake ps.steepness Int User
@ -44,21 +50,51 @@ proc initPeakSearch {} {
VarMake ps.cogcontour Float User
ps.cogcontour .2
#-------- counting parameters
VarMake ps.countmode Text User
ps.countmode monitor
VarMake ps.preset Float User
ps.preset 1000
#-------- final scan counting parameters
VarMake ps.scanpreset Float User
ps.scanpreset 1000000
VarMake ps.scansteps Int User
ps.scansteps 24
#--------- file to which to write the results
VarMake ps.listfile Text User
ps.listfile peaksearch.dat
#--------- conversion factors from Pixel to mm
VarMake xfactor Float Mugger
xfactor 0.715
VarMake yfactor Float Mugger
yfactor 1.42
#--------- published functions
Publish ps.phirange User
Publish ps.chirange User
Publish ps.omrange User
Publish ps.sttrange User
Publish ps.countpar User
Publish ps.scanpar User
Publish ps.maxpar User
Publish ps.list User
Publish ps.listpeaks User
Publish ps.run User
Publish ps.continue User
Publish ps.scanlist User
#------- these are for debugging only!
Publish checkomega User
Publish optimizedetector User
Publish optimizepeak User
Publish printpeak User
Publish initsearch User
Publish catchdrive User
Publish catchdriveval User
Publish scandetectorsD User
Publish scandetectors User
}
#--------------------------------------------------------------------------
proc ps.phirange args {
@ -122,6 +158,16 @@ proc ps.countpar args {
[SplitReply [ps.countmode]] [SplitReply [ps.preset]]]
}
#-------------------------------------------------------------------------
proc ps.scanpar args {
if { [llength $args] >= 2 } {
ps.scanpreset [lindex $args 0]
ps.scansteps [lindex $args 1]
}
clientput "Peak Search Scan Parameters:"
return [format " Count Preset = %12.2f, No. Steps %4d" \
[SplitReply [ps.scanpreset]] [SplitReply [ps.scansteps]]]
}
#-------------------------------------------------------------------------
proc ps.maxpar args {
if { [llength $args] >= 5 } {
ps.window [lindex $args 0]
@ -131,28 +177,43 @@ proc ps.maxpar args {
ps.cogcontour [lindex $args 4]
}
clientput "Peak Search Maximum Detection Parameters:"
set t1 [format " Window = %d, Threshold = %d, Steepness = %d" \
set t1 [format " Window = %d, Threshold = %d * average, Steepness = %d" \
[SplitReply [ps.window]] [SplitReply [ps.threshold]] \
[SplitReply [ps.steepness] ]]
set t2 [format " COGWindow = %d, COGcontour = %f " \
[SplitReply [ps.cogwindow]] [SplitReply [ps.cogcontour]]]
return [format "%s\n%s" $t1 $t2]
}
#-----------------------------------------------------------------------
proc ps.list {} {
clientput [ps.sttrange]
clientput [ps.omrange]
clientput [ps.chirange]
clientput [ps.phirange]
clientput [ps.countpar]
clientput [ps.scanpar]
clientput [ps.maxpar]
}
#------------------------------------------------------------------------
proc checknewomega {omega maxIntensity} {
if {[catch {drive $omega} msg] != 0} {
proc string2list {txt} {
return [split [string trim $txt \{\}]]
}
#------------------------------------------------------------------------
proc checknewomega {hm x y omega maxIntensity} {
if {[catch {drive om $omega} msg] != 0} {
error $msg
}
if {[catch {hmc start [SplitReply [ps.preset]] [SplitReply \
[ps.countmode]]} msg] != 0} {
if {[catch {hmc start [SplitReply [ps.preset]] [string trim [SplitReply \
[ps.countmode]]]} msg] != 0} {
error $msg
}
if {[catch {Success} msg] != 0} {
error $msg
}
if { [catch {lomax cog $hm $x $y} result] != 0} {
error "Failed to calculate COG"
error "Failed to calculate COG: $result"
}
set result [split $result " "]
if {[lindex $result 2] > $maxIntensity } {
return $result
} else {
@ -160,19 +221,45 @@ proc checknewomega {omega maxIntensity} {
}
}
#------------------------------------------------------------------------
proc optimizedetector {hm} {
if { [catch {lomax stat $hm} result] != 0} {
#--- This can be due to the fact that the detector is missing. Sigh ....
return
}
set l2 [split [string trim $result]]
lomax threshold [expr [lindex $l2 0] * [SplitReply [ps.threshold]]]
set result [lomax search $hm]
set oldom [SplitReply [om]]
set result [split $result @]
for {set i 0} { $i < [llength $result]} {incr i} {
if { [catch {drive om $oldom} msg] != 0} {
error $msg
}
set piecks [split [lindex $result $i] " "]
set x [lindex $piecks 0]
set y [lindex $piecks 1]
if { [catch {optimizepeak $hm $x $y} msg] != 0} {
clientput [format "Aborted peak at %d %d with %s" $x $y $msg]
}
}
}
#------------------------------------------------------------------------
proc optimizepeak {hm x y} {
if { [catch {lomax cog $hm $x $y} result] != 0} {
error "Failed to calculate COG"
error "Failed to calculate COG: $result"
}
set result [split $result " "]
set xMax [lindex $result 0]
set ymax [lindex $result 1]
set yMax [lindex $result 1]
set maxIntensity [lindex $result 2]
set maxOmega [SplitReply [om]]
set startOmega $maxOmega
set omSearchStep .1
#--------- move to positive omega until maximum found
while {1} {
set newOm [expr [SplitReply [om]] + [SplitReply [ps.omStep]]]
if {[catch {checknewomega $newOm $maxIntensity} result] != 0} {
set newOm [expr [SplitReply [om]] + $omSearchStep]
if {[catch {checknewomega $hm $xMax $yMax $newOm $maxIntensity} \
result] != 0} {
error $result
}
if {$result != 0} {
@ -189,8 +276,9 @@ proc optimizepeak {hm x y} {
# negative direction
if {$maxOmega == $startOmega} {
while {1} {
set newOm [expr [SplitReply [om]] - [SplitReply [ps.omStep]]]
if {[catch {checknewomega $newOm $maxIntensity} result] != 0} {
set newOm [expr [SplitReply [om]] - $omSearchStep]
if {[catch {checknewomega $hm $xMax $yMax $newOm $maxIntensity} \
result] != 0} {
error $result
}
if {$result != 0} {
@ -204,5 +292,208 @@ proc optimizepeak {hm x y} {
}
}
#----------- print the results we have found
printpeak $hm $xMax $yMax $maxOmega $maxIntensity
#------------ scan the peak for Oksana
# set scanStart [expr $maxOmega - 0.1*([SplitReply [ps.scansteps]]/2)]
# if { [catch {tricsscan $scanStart .1 [SplitReply [ps.scansteps]] \
# [SplitReply [ps.countmode]] [SplitReply [ps.scanpreset]]} msg] } {
# error $msg
# }
}
#---------------------------------------------------------------------------
proc printpeak {hm x y om intensity} {
set phval [SplitReply [phi]]
set chval [SplitReply [chi]]
set gamOffset .0
switch $hm {
hm1 {
set tilt [SplitReply [dg1]]
set gamOffset .0
}
hm2 {
set tilt [SplitReply [dg2]]
set gamOffset 0.
}
hm3 {
set tilt [SplitReply [dg3]]
set gamOffset 45.
}
default {error "Invalid hm requested in printpeak"}
}
set sttval [expr [SplitReply [stt]] + $gamOffset]
set zero [SplitReply [$hm configure dim0]]
set xval [expr $x * [SplitReply [xfactor]]]
set zero [SplitReply [$hm configure dim1]]
set yval [expr $y * [SplitReply [yfactor]]]
set line [format "%7.2f%7.2f%7.2f%7.2f%7.2f%7.2f%7.2f%10d" \
$xval $yval $sttval $om $chval $phval $tilt $intensity]
clientput "Found Peak at:"
clientput $line
set f [open [string trim [SplitReply [ps.listfile]]] a+]
puts $f $line
close $f
}
#--------------------------------------------------------------------------
proc ps.listpeaks {} {
clientput "Peakse found so far: "
clientput " X Y STT OM CHI PHI TILT INTENSITY"
set f [open [string trim [SplitReply [ps.listfile]]] r]
while {[gets $f line] > 0} {
clientput [format "%s" $line]
}
close $f
}
#-------------------------------------------------------------------------
proc initsearch {filename} {
#----- stow away filename and empty it
ps.listfile $filename
set f [open $filename w]
close $f
#----- tell lomax its parameters
lomax threshold [SplitReply [ps.threshold]]
lomax steepness [SplitReply [ps.steepness]]
lomax window [SplitReply [ps.window]]
lomax cogwindow [SplitReply [ps.cogwindow]]
lomax cogcontour [SplitReply [ps.cogcontour]]
#----- drive to start
if { [catch {drive stt [SplitReply [ps.sttStart]] \
om [SplitReply [ps.omStart]] \
chi [SplitReply [ps.chiStart]] \
phi [SplitReply [ps.phiStart]] } msg] != 0} {
error $msg
}
}
#------------------------------------------------------------------------
# This code means: ignore any errors except interrupts when searching
proc scandetectors {} {
# set names [list hm1 hm2 hm3]
set names [list hm2 hm3]
if {[catch {hmc start [SplitReply [ps.preset]] [string trim [SplitReply \
[ps.countmode]]]} msg] != 0} {
if{[string compare [getint] continue] != 0} {
error $msg
} else {
clientput [format "Ignoring: %s" $msg]
}
}
if {[catch {Success} msg] != 0} {
if{[string compare [getint] continue] != 0} {
error $msg
} else {
clientput [format "Ignoring: %s" $msg]
}
}
for {set i 0} { $i < [llength $names]} {incr i} {
set ret [catch {optimizedetector [lindex $names $i]} msg]
if { $ret != 0} {
if {[string compare [getint] continue] != 0} {
error $msg
} else {
clientput [format "Ignoring problem: %s" $msg]
}
}
}
}
#------------------------------------------------------------------------
# loop debugging
proc scandetectorsD {} {
clientput [format "stt = %6.2f, om = %6.2f, chi = %6.2f, phi = %6.2f" \
[SplitReply [stt]] [SplitReply [om]] \
[SplitReply [chi]] [SplitReply [phi]]]
wait 1
}
#-----------------------------------------------------------------------
proc catchdrive { mot step} {
set ret [catch {drive $mot [expr [SplitReply [$mot]] + $step]} msg]
if {$ret != 0} {
if {[string compare [getint] continue] != 0} {
error $msg
} else {
clientput [format "Ignoring: %s" $msg]
}
}
}
#-----------------------------------------------------------------------
proc catchdriveval { mot val} {
set ret [catch {drive $mot $val} msg]
if {$ret != 0} {
if {[string compare [getint] continue] != 0} {
error $msg
} else {
clientput [format "Ignoring: %s" $msg]
}
}
}
#------------------------------------------------------------------------
# The actual loop. It is written in a way which allows for the continuation
# of a search
proc searchloop { } {
set sttStep [SplitReply [ps.sttStep]]
set sttEnd [SplitReply [ps.sttEnd]]
set chiStep [SplitReply [ps.chiStep]]
set chiEnd [SplitReply [ps.chiEnd]]
set phiStep [SplitReply [ps.phiStep]]
set phiEnd [SplitReply [ps.phiEnd]]
set omStep [SplitReply [ps.omStep]]
set omEnd [SplitReply [ps.omEnd]]
while {[SplitReply [stt]] + $sttStep <= $sttEnd} {
while {[SplitReply [chi]] + $chiStep <= $chiEnd} {
while {[SplitReply [om]] + $omStep <= $omEnd} {
while {[SplitReply [phi]] + $phiStep <= $phiEnd} {
scandetectors
catchdrive phi $phiStep
}
catchdrive om $omStep
catchdriveval phi [SplitReply [ps.phiStart]]
}
catchdrive chi $chiStep
catchdriveval om [SplitReply [ps.omStart]]
}
catchdrive stt $sttStep
catchdriveval chi [SplitReply [ps.chiStart]]
}
return "Peak Search finished normally"
}
#---------------------------------------------------------------------------
proc ps.run {filename} {
initsearch $filename
searchloop
}
#-------------------------------------------------------------------------
proc ps.continue {} {
searchloop
}
#------------------------------------------------------------------------
proc ps.scanlist {} {
if { [catch {set f [open [string trim [SplitReply [ps.listfile]]] "r"]} \
msg ] != 0} {
error $msg
}
while { [gets $f line] > 0} {
set n [stscan $line "%f %f %f %f %f %f" x y stt om chi phi]
if {$n < 6} {
clientput [format "Skipping invalid line: %s" line]
continue
}
if { [catch {drive stt $stt om $om chi $chi phi $phi} msg] != 0 } {
clientput $msg
if {[string compare [getint] continue] != 0} {
error "ps.scanlist interupted"
}
}
set scanStart [expr $om - 0.1*([SplitReply [ps.scansteps]]/2)]
if { [catch {tricsscan $scanStart .1 [SplitReply [ps.scansteps]] \
[SplitReply [ps.countmode]] [SplitReply [ps.scanpreset]]} msg] \
!= 0 } {
clientput $msg
if {[string compare [getint] continue] != 0} {
error "ps.scanlist interupted"
}
}
}
close $f
return "Scanning list finished"
}

375
polterwrite.c Normal file
View File

@ -0,0 +1,375 @@
/*--------------------------------------------------------------------------
P O L T E R W R I T E
fowrite is an object for writing POLTERDI data files.
copyright: see copyright.h
Uwe Filges, November 2001
----------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include "fortify.h"
#include "sics.h"
#include "counter.h"
#include "HistMem.h"
#include "nxdict.h"
#include "nxutil.h"
#include "motor.h"
#include "sicsvar.h"
#include "polterwrite.h"
/*
diaphragm1 - chopper
*/
#define DIA1DIST 3000
/*
diaphragm2 - diaphragm1
*/
#define DIA2DIST 500
/*
diaphragm2 - sample position
*/
#define SADIST 500
/*
histogram memory name
*/
#define HM "hm"
/*
detector distance - sample
*/
#define DETDIST 700
/*
no detectors, change in poldi.dic as well
*/
#define NODET 400
/*
theta spacing
*/
#define THSPACE .3
typedef struct {
pObjectDescriptor pDes;
char *dictfile;
}Polterdi, *pPolterdi;
/*----------------------------------------------------------------------*/
static void KillPolterdi(void *pData){
pPolterdi self = (pPolterdi)pData;
if(!self)
return;
if(self->pDes){
DeleteDescriptor(self->pDes);
}
if(self->dictfile){
free(self->dictfile);
}
free(self);
}
/*-----------------------------------------------------------------------*/
int PolterInstall(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[])
{
pPolterdi pNew = NULL;
if(argc < 2){
SCWrite(pCon,"ERROR: insufficient number of arguments to PolterInstall",
eError);
return 0;
}
pNew = (pPolterdi)malloc(sizeof(Polterdi));
if(!pNew){
SCWrite(pCon,"ERROR: out of memory in PolterInstall",
eError);
return 0;
}
memset(pNew,0,sizeof(Polterdi));
pNew->pDes = CreateDescriptor("PolterdiWrite");
pNew->dictfile = strdup(argv[1]);
if(!pNew->pDes || !pNew->dictfile){
SCWrite(pCon,"ERROR: out of memory in PolterInstall",
eError);
return 0;
}
return AddCommand(pSics,"storedata",PolterAction,KillPolterdi,pNew);
}
/*-------------------------------------------------------------------*/
static void writePolterdiGlobal(NXhandle hfil, NXdict hdict, SConnection *pCon,
SicsInterp *pSics){
char pBueffel[512];
SNXSPutVariable(pSics,pCon,hfil,hdict,"etitle","title");
SNXFormatTime(pBueffel,511);
NXDputalias(hfil,hdict,"estart",pBueffel);
SNXSPutVariable(pSics,pCon,hfil,hdict,"iname","instrument");
sprintf(pBueffel,"%d",strlen("SINQ, PSI, Switzerland"));
NXDupdate(hdict,"strdim",pBueffel);
NXDputalias(hfil,hdict,"sname","SINQ, PSI, Switzerland");
sprintf(pBueffel,"%d",strlen("continous spallation source"));
NXDupdate(hdict,"strdim",pBueffel);
NXDputalias(hfil,hdict,"stype","continous spallation source");
NXDupdate(hdict,"strdim","132");
}
/*-------------------------------------------------------------------*/
static void writeChopper(NXhandle hfil, NXdict hdict, SConnection *pCon,
SicsInterp *pSics){
SNXSPutVariable(pSics,pCon,hfil,hdict,"cname","choppername");
SNXSPutDrivable(pSics,pCon,hfil,hdict,"chopperspeed","crot");
}
/*-------------------------------------------------------------------*/
static void writeDiaphragm1(NXhandle hfil, NXdict hdict, SConnection *pCon,
SicsInterp *pSics){
float dist;
SNXSPutMotor(pSics,pCon,hfil,hdict,"dia1x","d1m");
SNXSPutMotorNull(pSics,pCon,hfil,hdict,"dia1x0","d1m");
SNXSPutMotor(pSics,pCon,hfil,hdict,"dia1y","d1o");
SNXSPutMotorNull(pSics,pCon,hfil,hdict,"dia1y0","d1o");
dist = (float)DIA1DIST;
NXDputalias(hfil,hdict,"dia1dist",&dist);
}
/*------------------------------------------------------------------*/
static void writeDiaphragm2(NXhandle hfil, NXdict hdict, SConnection *pCon,
SicsInterp *pSics){
float dist2;
SNXSPutMotor(pSics, pCon, hfil, hdict, "dia2x_plus", "d2m");
SNXSPutMotorNull(pSics, pCon, hfil, hdict, "dia2xplus0", "d2m");
SNXSPutMotor(pSics, pCon, hfil, hdict, "dia2x_minus", "d2u");
SNXSPutMotorNull(pSics, pCon, hfil, hdict, "dia2xminus0", "d2u");
SNXSPutMotor(pSics, pCon, hfil, hdict, "dia2z_plus", "d2o");
SNXSPutMotorNull(pSics, pCon, hfil, hdict, "dia2zplus0", "d2o");
SNXSPutMotor(pSics, pCon, hfil, hdict, "dia2z_minus", "d2l");
SNXSPutMotorNull(pSics, pCon, hfil, hdict, "dia2zminus0", "d2l");
dist2 = (float) DIA2DIST;
}
/*--------------------------------------------------------------------*/
static void writeSample(NXhandle hfil, NXdict hdict, SConnection *pCon,
SicsInterp *pSics)
{
float sadist = (float)SADIST;
NXDputalias(hfil, hdict, "sdist", &sadist);
SNXSPutVariable(pSics,pCon,hfil,hdict,"saname","sample");
SNXSPutVariable(pSics,pCon,hfil,hdict,"senvir","environment");
SNXSPutEVVar(hfil,hdict,"temperature",pCon,"stemp","stddev");
SNXSPutMotor(pSics, pCon, hfil, hdict, "srsu", "rsu");
SNXSPutMotorNull(pSics, pCon, hfil, hdict, "srsu0", "rsu");
SNXSPutMotor(pSics, pCon, hfil, hdict, "srsl", "rsl");
SNXSPutMotorNull(pSics, pCon, hfil, hdict, "srsl0", "rsl");
SNXSPutMotor(pSics, pCon, hfil, hdict, "srsa", "rsa");
SNXSPutMotorNull(pSics, pCon, hfil, hdict, "srsa0", "rsa");
SNXSPutMotor(pSics, pCon, hfil, hdict, "sshu", "shu");
SNXSPutMotorNull(pSics, pCon, hfil, hdict, "sshu0", "shu");
SNXSPutMotor(pSics, pCon, hfil, hdict, "sshl", "shl");
SNXSPutMotorNull(pSics, pCon, hfil, hdict, "sshl0", "shl");
SNXSPutMotor(pSics, pCon, hfil, hdict, "ssgu", "sgu");
SNXSPutMotorNull(pSics, pCon, hfil, hdict, "ssgu0", "sgu");
SNXSPutMotor(pSics, pCon, hfil, hdict, "ssgl", "sgl");
SNXSPutMotorNull(pSics, pCon, hfil, hdict, "ssgl0", "sgl");
SNXSPutMotor(pSics, pCon, hfil, hdict, "ssv", "sv");
SNXSPutMotorNull(pSics, pCon, hfil, hdict, "ssv0", "sv");
}
/*-----------------------------------------------------------------------*/
static void writeDetector(NXhandle hfil, NXdict hdict, SConnection *pCon,
SicsInterp *pSics)
{
const float *fTime = NULL;
CounterMode eMode;
pHistMem pHist= NULL;
float *fTime2 = NULL, fTheta[NODET], fVal;
int iLength, i;
char pBueffel[80];
pMotor sa;
HistInt *lData = NULL;
long lVal;
pHist = (pHistMem)FindCommandData(pSics,HM,"HistMem");
if(!pHist)
{
SCWrite(pCon,"ERROR: Histogram memory NOT found",eError);
return;
}
/*
write time binning
*/
fTime = GetHistTimeBin(pHist,&iLength);
fTime2 = (float *)malloc(iLength*sizeof(float));
if(fTime2)
{
for(i = 0;i < iLength; i++)
{
fTime2[i] = fTime[i]/10.;
}
sprintf(pBueffel,"%d",iLength);
NXDupdate(hdict,"timebin",pBueffel);
NXDputalias(hfil,hdict,"dtime",fTime2);
free(fTime2);
}
else
{
SCWrite(pCon,"ERROR: out of memory while writing time binning",eError);
}
/*
do theta
*/
fVal = -999.;
sa = FindMotor(pSics,"sa");
if(sa)
{
MotorGetSoftPosition(sa,pCon,&fVal);
}
else
{
SCWrite(pCon,"ERROR: failed to locate two theta motor",eError);
}
for(i = 0; i < NODET; i++)
{
fTheta[i] = fVal + i * THSPACE;
}
NXDputalias(hfil,hdict,"dtheta",fTheta);
fVal = (float)DETDIST;
NXDputalias(hfil,hdict,"ddist",&fVal);
/*
write Histogram
*/
lData = GetHistogramPointer(pHist,pCon);
if(lData)
{
NXDputalias(hfil,hdict,"dcounts",lData);
}
else
{
SCWrite(pCon,"ERROR: failed to get histogram data",eError);
}
/*
write counting data
*/
fVal = GetHistCountTime(pHist,pCon);
NXDputalias(hfil,hdict,"cntime",&fVal);
lVal = GetHistMonitor(pHist,1,pCon);
NXDputalias(hfil,hdict,"cnmon1",&lVal);
eMode = GetHistCountMode(pHist);
if(eMode == eTimer)
{
strcpy(pBueffel,"timer");
}
else
{
strcpy(pBueffel,"monitor");
}
NXDputalias(hfil,hdict,"cnmode",pBueffel);
fVal = GetHistPreset(pHist);
NXDputalias(hfil,hdict,"cnpreset",&fVal);
}
/*---------------------------------------------------------------------*/
static void makeLinks(NXhandle hfil, NXdict hdict, SConnection *pCon,
SicsInterp *pSics)
{
NXDaliaslink(hfil,hdict,"dana","dcounts");
NXDaliaslink(hfil,hdict,"dana","dtheta");
NXDaliaslink(hfil,hdict,"dana","dtime");
}
/*--------------------------------------------------------------------*/
static int StoreData(SConnection *pCon, SicsInterp *pSics, pPolterdi self)
{
char pBueffel[256], *pFile = NULL;
NXhandle hfil = NULL;
NXdict hdict= NULL;
int status;
/* create filename */
pFile = SNXMakeFileName(pSics,pCon);
if(!pFile)
{
SCWrite(pCon,"ERROR: Extra severe: failed to create data file name",
eError);
return 0;
}
/* create a Nexus file */
NXopen(pFile,NXACC_CREATE,&hfil);
if(!hfil)
{
SCWrite(pCon,"ERROR: cannot create data file ",eError);
return 0;
}
/* tell Uwe User what we are doing */
sprintf(pBueffel,"Writing %s ......",pFile);
SCWrite(pCon,pBueffel,eWarning);
/* write globals */
SNXSPutGlobals(hfil,pFile,"POLTERDI",pCon);
free(pFile);
pFile = NULL;
/* open nxdict */
status = NXDinitfromfile(self->dictfile,&hdict);
if(status != NX_OK)
{
sprintf(pBueffel,"ERROR: failed to open dictionary file %s",
self->dictfile);
SCWrite(pCon,pBueffel,eError);
SCWrite(pCon,"ERROR: Aborting data file writing",eError);
SCWrite(pCon,"ERROR: This is a SERIOUS problem!",eError);
SCWrite(pCon,"ERROR: DATA NOT WRITTEN",eError);
NXclose(&hfil);
return 0;
}
writePolterdiGlobal(hfil,hdict,pCon,pSics);
writeChopper(hfil,hdict,pCon,pSics);
writeDiaphragm1(hfil,hdict,pCon,pSics);
writeDiaphragm2(hfil,hdict,pCon,pSics);
writeSample(hfil,hdict,pCon,pSics);
writeDetector(hfil,hdict,pCon,pSics);
makeLinks(hfil,hdict,pCon,pSics);
/* close everything */
NXclose(&hfil);
NXDclose(hdict,NULL);
SCSendOK(pCon);
return 1;
}
/*----------------------------------------------------------------------*/
int PolterAction(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[])
{
pPolterdi self = (pPolterdi)pData;
assert(self);
assert(pCon);
assert(pSics);
return StoreData(pCon,pSics,self);
}

21
polterwrite.h Normal file
View File

@ -0,0 +1,21 @@
/*--------------------------------------------------------------------------
P O L T E R W R I T E
fowrite is an object for writing POLTERDI data files.
copyright: see copyright.h
Uwe Filges, November 2001
----------------------------------------------------------------------------*/
#ifndef POLTERDIWRITE
#define POLTERDIWRITE
int PolterInstall(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[]);
int PolterAction(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[]);
#endif

View File

@ -4,7 +4,7 @@
This is a controller driver for a heaiting device developed especially
for use with SANS at SINQ by somebody at the Some God Forsaken University
(SGFU). As this device somes with two motors in addition to the heater
(SGFU). As this device comes with two motors in addition to the heater
the general controller mechanism as described in choco.tex is used.
copyright: see copyright.h

View File

@ -1,343 +1,8 @@
scaninfo 7,en,-0.300000,0.100000
scaninfo setAccess 0
sicsdatapath /data/koenneck/src/sics/tmp/
sicsdatapath setAccess 1
arx2 4.290000
arx2 setAccess 1
arx1 0.150000
arx1 setAccess 1
mrx2 10.420000
mrx2 setAccess 1
mrx1 0.280000
mrx1 setAccess 1
lpa 0
lpa setAccess 2
dt 0.000000
dt setAccess 2
dqm 0.000000
dqm setAccess 2
qm 0.000000
qm setAccess 2
etaa 0.000000
etaa setAccess 2
etas 0.000000
etas setAccess 2
etam 0.000000
etam setAccess 2
wav 0.000000
wav setAccess 2
den 0.100000
den setAccess 2
dql 0.000000
dql setAccess 2
dqk 0.000000
dqk setAccess 2
dqh 0.000000
dqh setAccess 2
dkf 0.000000
dkf setAccess 2
def 0.500000
def setAccess 2
dki 0.000000
dki setAccess 2
dei 0.500000
dei setAccess 2
dagl 0.000000
dagl setAccess 2
dsgu 0.000000
dsgu setAccess 2
dsgl 0.000000
dsgl setAccess 2
dmgl 0.000000
dmgl setAccess 2
datu 0.000000
datu setAccess 2
datl 0.000000
datl setAccess 2
dstu 0.000000
dstu setAccess 2
dstl 0.000000
dstl setAccess 2
dmtu 0.000000
dmtu setAccess 2
dmtl 0.000000
dmtl setAccess 2
dach 0.000000
dach setAccess 2
dsro 0.000000
dsro setAccess 2
dmcv 0.000000
dmcv setAccess 2
da6 0.000000
da6 setAccess 2
da5 0.000000
da5 setAccess 2
da4 0.100000
da4 setAccess 2
da3 0.000000
da3 setAccess 2
da2 0.000000
da2 setAccess 2
da1 0.000000
da1 setAccess 2
bet4 0.000000
bet4 setAccess 2
bet3 0.000000
bet3 setAccess 2
bet2 0.000000
bet2 setAccess 2
bet1 0.000000
bet1 setAccess 2
alf4 0.000000
alf4 setAccess 2
alf3 0.000000
alf3 setAccess 2
alf2 3.000000
alf2 setAccess 2
alf1 11.000000
alf1 setAccess 2
local Mordahl Schlawadini
local setAccess 2
output a4
output setAccess 2
lastcommand sc en 0 den .1 np 7 ti 2
lastcommand setAccess 2
user Billy Looser
user setAccess 2
title SimSulfid Test
title setAccess 2
f2 0
f2 setAccess 2
f1 0
f1 setAccess 2
swunit 0
swunit setAccess 2
hz 0.000000
hz setAccess 2
hy 0.000000
hy setAccess 2
hx 0.000000
hx setAccess 2
helm 0.000000
helm setAccess 2
if2h 0.000000
if2h setAccess 2
if1h 0.000000
if1h setAccess 2
if2v 0.000000
if2v setAccess 2
if1v 0.000000
if1v setAccess 2
mn 700
mn setAccess 2
ti 2.000000
ti setAccess 2
np 7
np setAccess 2
fx 2
fx setAccess 2
sa -1
sa setAccess 2
ss 1
ss setAccess 2
sm 1
sm setAccess 2
da 3.354000
da setAccess 1
dm 3.354000
dm setAccess 1
en 0.300000
en setAccess 2
ql 0.000000
ql setAccess 2
qk 0.000000
qk setAccess 2
qh 2.000000
qh setAccess 2
kf 1.964944
kf setAccess 2
ef 8.000000
ef setAccess 2
ki 2.001447
ki setAccess 2
ei 8.300000
ei setAccess 2
bz 1.000000
bz setAccess 2
by 0.000000
by setAccess 2
bx 0.000000
bx setAccess 2
az 0.000000
az setAccess 2
ay 0.000000
ay setAccess 2
ax 1.000000
ax setAccess 2
cc 90.000000
cc setAccess 2
bb 90.000000
bb setAccess 2
aa 90.000000
aa setAccess 2
cs 5.000000
cs setAccess 2
bs 5.000000
bs setAccess 2
as 5.000000
as setAccess 2
# Counter counter
counter SetPreset 2.000000
counter SetMode Timer
# Motor agl
agl SoftZero -0.490000
agl SoftLowerLim -9.510000
agl SoftUpperLim 10.490000
agl Fixed -1.000000
agl sign 1.000000
agl InterruptMode 0.000000
agl AccessCode 2.000000
# Motor sgu
sgu SoftZero 0.000000
sgu SoftLowerLim -16.000000
sgu SoftUpperLim 16.000000
sgu Fixed -1.000000
sgu sign 1.000000
sgu InterruptMode 0.000000
sgu AccessCode 2.000000
# Motor sgl
sgl SoftZero 1.550000
sgl SoftLowerLim -17.549999
sgl SoftUpperLim 14.450000
sgl Fixed -1.000000
sgl sign 1.000000
sgl InterruptMode 0.000000
sgl AccessCode 2.000000
# Motor mgl
mgl SoftZero 1.300000
mgl SoftLowerLim -11.300000
mgl SoftUpperLim 8.700000
mgl Fixed -1.000000
mgl sign 1.000000
mgl InterruptMode 0.000000
mgl AccessCode 2.000000
# Motor atu
atu SoftZero -0.880000
atu SoftLowerLim -16.120001
atu SoftUpperLim 17.759998
atu Fixed -1.000000
atu sign 1.000000
atu InterruptMode 0.000000
atu AccessCode 2.000000
# Motor atl
atl SoftZero 0.000000
atl SoftLowerLim -17.000000
atl SoftUpperLim 17.000000
atl Fixed -1.000000
atl sign 1.000000
atl InterruptMode 0.000000
atl AccessCode 2.000000
# Motor stu
stu SoftZero 0.000000
stu SoftLowerLim -30.000000
stu SoftUpperLim 30.000000
stu Fixed -1.000000
stu sign 1.000000
stu InterruptMode 0.000000
stu AccessCode 2.000000
# Motor stl
stl SoftZero 0.000000
stl SoftLowerLim -30.000000
stl SoftUpperLim 30.000000
stl Fixed -1.000000
stl sign 1.000000
stl InterruptMode 0.000000
stl AccessCode 2.000000
# Motor mtu
mtu SoftZero 2.850000
mtu SoftLowerLim -19.850000
mtu SoftUpperLim 14.150000
mtu Fixed -1.000000
mtu sign 1.000000
mtu InterruptMode 0.000000
mtu AccessCode 2.000000
# Motor mtl
mtl SoftZero 0.000000
mtl SoftLowerLim -17.000000
mtl SoftUpperLim 17.000000
mtl Fixed -1.000000
mtl sign 1.000000
mtl InterruptMode 0.000000
mtl AccessCode 2.000000
# Motor ach
ach SoftZero 0.000000
ach SoftLowerLim -0.500000
ach SoftUpperLim 11.500000
ach Fixed -1.000000
ach sign 1.000000
ach InterruptMode 0.000000
ach AccessCode 2.000000
# Motor sro
sro SoftZero 0.000000
sro SoftLowerLim 0.000000
sro SoftUpperLim 351.000000
sro Fixed -1.000000
sro sign 1.000000
sro InterruptMode 0.000000
sro AccessCode 2.000000
# Motor mcv
mcv SoftZero 0.000000
mcv SoftLowerLim -9.000000
mcv SoftUpperLim 124.000000
mcv Fixed -1.000000
mcv sign 1.000000
mcv InterruptMode 0.000000
mcv AccessCode 2.000000
# Motor a6
a6 SoftZero 0.040000
a6 SoftLowerLim -116.040001
a6 SoftUpperLim 165.960007
a6 Fixed -1.000000
a6 sign 1.000000
a6 InterruptMode 0.000000
a6 AccessCode 2.000000
# Motor a5
a5 SoftZero 176.479996
a5 SoftLowerLim -200.000000
a5 SoftUpperLim 380.000000
a5 Fixed -1.000000
a5 sign 1.000000
a5 InterruptMode 0.000000
a5 AccessCode 2.000000
# Motor a4
a4 SoftZero -0.710000
a4 SoftLowerLim -134.389999
a4 SoftUpperLim 124.110001
a4 Fixed -1.000000
a4 sign 1.000000
a4 InterruptMode 0.000000
a4 AccessCode 2.000000
# Motor a3
a3 SoftZero 11.540000
a3 SoftLowerLim -188.839996
a3 SoftUpperLim 165.760010
a3 Fixed -1.000000
a3 sign 1.000000
a3 InterruptMode 0.000000
a3 AccessCode 2.000000
# Motor a2
a2 SoftZero -0.010000
a2 SoftLowerLim 33.109997
a2 SoftUpperLim 120.010002
a2 Fixed -1.000000
a2 sign 1.000000
a2 InterruptMode 0.000000
a2 AccessCode 2.000000
# Motor a1
a1 SoftZero 0.590000
a1 SoftLowerLim -0.590000
a1 SoftUpperLim 110.410004
a1 Fixed -1.000000
a1 sign 1.000000
a1 InterruptMode 0.000000
a1 AccessCode 2.000000
# Motor gurke
gurke SoftZero 0.000000
gurke SoftLowerLim -20.000000
gurke SoftUpperLim 20.000000
gurke Fixed -1.000000
gurke sign 1.000000
gurke InterruptMode 0.000000
gurke AccessCode 2.000000

View File

@ -1,50 +1,33 @@
ps.preset 20.000000
ps.preset setAccess 2
ps.countmode timer
ps.countmode setAccess 2
ps.cogcontour 0.200000
ps.cogcontour setAccess 2
ps.cogwindow 60
ps.cogwindow setAccess 2
ps.window 7
ps.window setAccess 2
ps.steepness 2
ps.steepness setAccess 2
ps.threshold 50
ps.threshold setAccess 2
ps.sttstep 5.000000
ps.sttstep setAccess 2
ps.sttend 50.000000
ps.sttend setAccess 2
ps.sttstart 10.000000
ps.sttstart setAccess 2
ps.omstep 5.000000
ps.omstep setAccess 2
ps.omend 20.000000
ps.omend setAccess 2
ps.omstart 10.000000
ps.omstart setAccess 2
ps.chistep 10.000000
ps.chistep setAccess 2
ps.chiend 150.000000
ps.chiend setAccess 2
ps.chistart 10.000000
ps.chistart setAccess 2
ps.phistep 5.000000
ps.phistep setAccess 2
ps.phiend 120.000000
ps.phiend setAccess 2
ps.phistart 10.000000
ps.phistart setAccess 2
hm3 CountMode timer
hm3 preset 10.000000
hm2 CountMode timer
hm2 preset 5.000000
hm1 CountMode timer
hm1 preset 5.000000
a5l.length 80.000000
flightpathlength 0.000000
flightpathlength setAccess 1
flightpath 0.000000
flightpath setAccess 1
delay 2500.000000
delay setAccess 1
hm CountMode timer
hm preset 100.000000
hm genbin 120.000000 35.000000 512
hm init
datafile focus-1001848.hdf
datafile setAccess 3
hm2 CountMode monitor
hm2 preset 2.000000
hm1 CountMode monitor
hm1 preset 2.000000
dbfile UNKNOWN
dbfile setAccess 2
# Motor th
th SoftZero 0.000000
th SoftLowerLim 4.000000
th SoftUpperLim 113.000000
th Fixed -1.000000
th sign 1.000000
th InterruptMode 0.000000
th AccessCode 2.000000
#Crystallographic Settings
hkl lambda 1.179000
hkl setub 0.016169 0.011969 0.063195 -0.000545 0.083377 -0.009117 -0.162051 0.000945 0.006312
hkl setub 0.004076 -0.080526 -0.018163 -0.008113 -0.023908 0.061299 -0.161515 -0.000831 -0.003537
det3dist 300.000000
det3dist setAccess 1
det3zeroy 128.000000
@ -70,25 +53,25 @@ monodescription setAccess 1
# Motor om
om SoftZero 0.000000
om SoftLowerLim -73.000000
om SoftUpperLim 39.000000
om SoftUpperLim 134.000000
om Fixed -1.000000
om sign 1.000000
om InterruptMode 0.000000
om AccessCode 2.000000
# Motor stt
stt SoftZero 0.000000
stt SoftLowerLim -120.000000
stt SoftUpperLim 120.000000
stt SoftLowerLim 4.000000
stt SoftUpperLim 113.000000
stt Fixed -1.000000
stt sign 1.000000
stt InterruptMode 0.000000
stt AccessCode 2.000000
# Motor ch
ch SoftZero 0.000000
ch SoftLowerLim 0.000000
ch SoftUpperLim 360.000000
ch SoftLowerLim 80.000000
ch SoftUpperLim 212.000000
ch Fixed -1.000000
ch sign 0.500000
ch sign 1.000000
ch InterruptMode 0.000000
ch AccessCode 1.000000
# Motor ph
@ -96,7 +79,7 @@ ph SoftZero 0.000000
ph SoftLowerLim -360.000000
ph SoftUpperLim 360.000000
ph Fixed -1.000000
ph sign 1.000000
ph sign -1.000000
ph InterruptMode 0.000000
ph AccessCode 2.000000
# Motor dg3
@ -136,35 +119,37 @@ phi SoftZero 0.000000
phi SoftLowerLim -360.000000
phi SoftUpperLim 360.000000
phi Fixed -1.000000
phi sign 1.000000
phi sign -1.000000
phi InterruptMode 0.000000
phi AccessCode 2.000000
# Motor chi
chi SoftZero 0.000000
chi SoftLowerLim 0.000000
chi SoftUpperLim 360.000000
chi SoftLowerLim 80.000000
chi SoftUpperLim 212.000000
chi Fixed -1.000000
chi sign 0.500000
chi sign 1.000000
chi InterruptMode 0.000000
chi AccessCode 1.000000
# Motor omega
omega SoftZero 0.000000
omega SoftLowerLim -73.000000
omega SoftUpperLim 39.000000
omega SoftUpperLim 134.000000
omega Fixed -1.000000
omega sign 1.000000
omega InterruptMode 0.000000
omega AccessCode 2.000000
# Motor twotheta
twotheta SoftZero 0.000000
twotheta SoftLowerLim -120.000000
twotheta SoftUpperLim 120.000000
twotheta SoftLowerLim 4.000000
twotheta SoftUpperLim 113.000000
twotheta Fixed -1.000000
twotheta sign 1.000000
twotheta InterruptMode 0.000000
twotheta AccessCode 2.000000
lastscancommand cscan a4 10. .1 10 5
lastscancommand setAccess 2
banana CountMode timer
banana preset 100.000000
sample_mur 0.000000
sample_mur setAccess 2
email UNKNOWN
@ -176,7 +161,7 @@ phone setAccess 2
adress UNKNOWN
adress setAccess 2
# Counter counter
counter SetPreset 5.000000
counter SetPreset 1.000000
counter SetMode Timer
# Motor som
som SoftZero 0.000000
@ -444,9 +429,9 @@ a1 InterruptMode 0.000000
a1 AccessCode 2.000000
user Uwe Filges
user setAccess 2
sample test
sample D20 30K SNP Okt 2001 GS
sample setAccess 2
title uwe_test1
title snp gs apd 30K
title setAccess 2
starttime 2001-09-21 16:55:53
starttime 2001-11-16 08:55:46
starttime setAccess 2

View File

@ -735,6 +735,11 @@
p_arg[1], p_arg[2], p_arg[3], p_arg[4], p_arg[5],
p_arg[6], p_arg[7], p_arg[8], p_arg[9]);
if (!status) return status;
}else if (strcmp (p_arg[0], "trans") == 0) {
status = sbpc_config (SQHM__TRANS,
p_arg[1], p_arg[2], p_arg[3], p_arg[4], p_arg[5],
p_arg[6], p_arg[7], p_arg[8], p_arg[9]);
if (!status) return status;
}else {
sprintf (errmsg, "\"%s\" is an unrecognised thing to configure!\n",
p_arg[0]);

View File

@ -1103,12 +1103,16 @@
if (lwl_hdr.ui4 == LWL_FIFO_EMPTY) {
taskDelay (0); /* If FIFO is empty, we can take a breather! */
}else {
#ifdef TRANNY
VmioBase[VMIO_PORT_A] = 0xff; /* Set timer level (if present) */
*my_char_nxt = lwl_Packet_Read (lwl_hdr.ui4, &my_char_nxt[1]);
Bytes_free = Bytes_free - *my_char_nxt - 1;
my_char_nxt = my_char_nxt + *my_char_nxt + 1;
if (Bytes_free < 24) my_char_nxt = selectNewBuffer (my_char_nxt);
VmioBase[VMIO_PORT_A] = 0x00; /* Reset timer level (if present) */
#else
printf("%#8.8x\n",lwl_hdr.ui4);
#endif
}
}
/* Our flag has been set. There should be ..

808
t_conv.c

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,11 @@ C------------------------------------------------------------------------
C slightly edited version for inclusion into SICS
C
C Mark Koennecke, November 2000
C
C Found that ERRESO looks error messages up in a 2D array. Modified IER
C values to refer to a 1D array.
C
C Mark Koennecke, January 2002
C-------------------------------------------------------------------------
SUBROUTINE INICURVE(MIDX, MRX1, MRX2, AIDX, ARX1, ARX2,
+ MMIN, MMAX, AMIN, AMAX)
@ -165,12 +170,12 @@ C
IF (LDK(2*IFX-1) .OR. LDK(2*IFX)) THEN
LMOAN(IFX) = .TRUE.
IF (LDK(2*IFX-1)) THEN
IER = 1
IER = 1 + 8
IF(EDEF(1) .LT. EPS1) GOTO 999
IER = 0
AKDEF(1) = SQRT(EDEF(1)/F)
ELSE
IER = 1
IER = 1 + 8
IF(AKDEF(1) .LT. EPS1) GOTO 999
IER = 0
EDEF(1) = F*AKDEF(1)**2
@ -193,12 +198,12 @@ C
IF (LDK(5-2*IFX) .OR. LDK(6-2*IFX)) THEN
LMOAN(3-IFX) = .TRUE.
IF (LDK(5-2*IFX)) THEN
IER = 1
IER = 1 + 8
IF(EDEF(2) .LT. EPS4) GOTO 999
IER = 0
AKDEF(2) = SQRT(EDEF(2)/F)
ELSE
IER = 1
IER = 1 + 8
IF(AKDEF(2) .LT. EPS4) GOTO 999
IER = 0
EDEF(2) = F*AKDEF(2)**2
@ -207,7 +212,7 @@ C
ELSEIF (LQHKLE) THEN
LMOAN(3-IFX) = .TRUE.
EDEF(2) = EDEF(1)+(2*IFX-3)*EN
IER = 1
IER = 1 + 8
IF(EDEF(2) .LT. EPS4) GOTO 999
IER = 0
AKDEF(2) = SQRT(EDEF(2)/F)
@ -235,6 +240,7 @@ C
LDR_ALM = .TRUE.
endif
ELSE
IER = IER + 8
GOTO 999
ENDIF
ENDIF
@ -254,6 +260,7 @@ C
LDR_RA = .TRUE.
endif
ELSE
IER = IER + 8
GOTO 999
ENDIF
ENDIF
@ -276,6 +283,7 @@ C
LDRA(4) = .TRUE.
QM = DQM
ELSE
IER = IER + 4
GOTO 999
ENDIF
ENDIF

View File

@ -4,7 +4,6 @@
*/
#include "f2c.h"
#include <math.h>
/* Subroutine */ int t_update__(real *p_a__, real *p_ih__, real *c_ih__,
logical *lpa, real *dm, real *da, integer *isa, real *helm, real *f1h,
@ -116,7 +115,7 @@
/* ----------------------------------------------------------------------- */
ieri = 0;
ieru = 1;
ieru = 9;
ex_up__(&ddm, &dei, &daki, &da2, &df, &ieri);
if (ieri == 0) {
*ei = dei;
@ -125,9 +124,10 @@
} else {
imod = 3;
erreso_(&imod, &ieri);
ieru = ieri + 8;
}
ieri = 0;
ieru = 1;
ieru = 9;
ex_up__(&dda, &def, &dakf, &da6, &df, &ieri);
if (ieri == 0) {
*ef = def;
@ -143,6 +143,7 @@
} else {
imod = 3;
erreso_(&imod, &ieri);
ieru = ieri + 8;
}
}
if (*isa == 0) {
@ -156,7 +157,7 @@
*en = dei - def;
}
ieri = 0;
ieru = 1;
ieru = 5;
sam_up__(dbqhkl, &dqm, &dqs, &dphi, &daki, &dakf, &da3, &da4, &ieri);
if (ieri == 0) {
for (id = 1; id <= 3; ++id) {
@ -168,6 +169,7 @@
} else {
imod = 2;
erreso_(&imod, &ieri);
ieru = ieri + 4;
}
ieri = 0;
@ -222,6 +224,9 @@
/* ----------------------------------------------------------------------- */
/* Error - IER=1 if DX OR AX TOO SMALL */
/* ----------------------------------------------------------------------- */
/* !!!!!!!!!! This has to be fixed manually after conversion by f2c. */
/* !!!!!!!!!! The reason is a different definition of the abs function. */
/* !!!!!!!!!! MK, May 2001 */
arg = *dx * sin(*ax2 / 114.59155902616465);
if(arg < .0)
arg = -arg;

View File

@ -89,7 +89,7 @@ C
C-----------------------------------------------------------------------
C
IERI=0
IERU=1
IERU=1 + 8
CALL EX_UP(DDM,DEI,DAKI,DA2,DF,IERI)
IF (IERI.EQ.0) THEN
EI=DEI
@ -98,9 +98,10 @@ C
ELSE
IMOD=3
CALL ERRESO(IMOD,IERI)
IERU = IERI + 8
ENDIF
IERI=0
IERU=1
IERU=1 + 8
CALL EX_UP(DDA,DEF,DAKF,DA6,DF,IERI)
IF (IERI.EQ.0) THEN
EF=DEF
@ -116,6 +117,7 @@ C
ELSE
IMOD=3
CALL ERRESO(IMOD,IERI)
IERU = 8 + IERI
ENDIF
ENDIF
IF (ISA.EQ.0) THEN
@ -127,7 +129,7 @@ C
ENDIF
IF (IERU.EQ.0) EN=DEI-DEF
IERI=0
IERU=1
IERU=1 + 4
CALL SAM_UP(DBQHKL,DQM,DQS,DPHI,DAKI,DAKF,DA3,DA4,IERI)
IF (IERI.EQ.0) THEN
DO ID=1,3
@ -139,6 +141,7 @@ C
ELSE
IMOD=2
CALL ERRESO(IMOD,IERI)
IERU = IERI + 4
ENDIF
C
IERI=0

15
tas.h
View File

@ -107,8 +107,21 @@
#define LOC 91
#define SWUNIT 92
#define SINFO 93
#define TEI 94
#define TKI 95
#define TEF 96
#define TKF 97
#define TQH 98
#define TQK 99
#define TQL 100
#define TEN 101
#define TQM 102
#define HX 34
#define HY 35
#define HZ 36
#define MAXPAR 94
#define MAXPAR 103
#define MAXADD 20
#define MAXEVAR 10

View File

@ -148,7 +148,7 @@ proc scatSense {par {val -1000} } {
if { $val == -1000 } {
return [eval $par]
}
if {$val != 1 && $val != -1 } {
if {$val != 1 && $val != -1 && $val != 0 } {
error "ERROR: invalid scattering sense $val"
}
switch $par {
@ -162,14 +162,43 @@ proc scatSense {par {val -1000} } {
}
sa {
set oldzero [tasSplit [madZero $mot]]
set newZero [expr $val*180 + $oldzero]
madZero $mot $newZero
a5 softlowerlim $newZero
$par $val
set oldupper [tasSplit [$mot softupperlim]]
set oldlower [tasSplit [$mot softlowerlim]]
set oldsa [tasSplit [sa]]
if { $val == 0 && $oldsa == 1} {
set newzero [expr $oldzero - 90.]
set newlower [expr $oldlower - 90.]
set newupper [expr $oldupper - 90.]
} elseif {$val == 0 && $oldsa == -1} {
set newzero [expr $oldzero + 90.]
set newlower [expr $oldlower + 90.]
set newupper [expr $oldupper + 90.]
} elseif { $val == 1 && $oldsa == 0} {
set newzero [expr $oldzero + 90.]
set newlower [expr $oldlower + 90.]
set newupper [expr $oldupper + 90.]
} elseif { $val == -1 && $oldsa == 0} {
set newzero [expr $oldzero - 90.]
set newlower [expr $oldlower - 90.]
set newupper [expr $oldupper - 90.]
} elseif { $val == 1 && $oldsa == -1} {
set newzero [expr $oldzero + 180. ]
set newlower [expr $oldlower + 180. ]
set newupper [expr $oldupper + 180. ]
} elseif {$val == -1 && $oldsa == 1} {
set newzero [expr $oldzero - 180. ]
set newlower [expr $oldlower - 180. ]
set newupper [expr $oldupper - 180. ]
} else {
error "Unknown SA setting combination"
}
$par $val
madZero $mot $newzero
$mot softupperlim $newupper
$mot softlowerlim $newlower
}
}
}
#--------------------------------------------------------------------------
# The output command
@ -190,7 +219,7 @@ proc ou args {
}
#--------------------------------------------------------------------------
# typeATokenizer extracts tokens from acpmmand string. Tokens can be
# typeATokenizer extracts tokens from a command string. Tokens can be
# either variable names or - indicating a series of variables.
# Returns the token value or END if the end of the string text is
# reached. Uses and updates a variable pos which indicates the current
@ -431,7 +460,6 @@ proc varSet { command } {
} else {
clientput [format " %s = %s" $token $value]
}
} else {
set ret [catch {eval $token $value} msg]
if { $ret != 0 } {
@ -443,8 +471,8 @@ proc varSet { command } {
set token [varToken $command $pos]
set value [varToken $command $pos]
}
catch {updateqe} msg
}
#--------------------------------------------------------------------------
# co for count is the funny MAD count procedure. Please note, that the
# count mode is automatically set through the last MN or TI variable.
@ -570,7 +598,7 @@ proc se args {
#------- is it the only command line case?
if {[llength $args] > 0 } {
set line [join $args]
return [varSet $line]
return [varSet $line]
} else {
#------- we are prompting
while { 1== 1} {
@ -728,14 +756,26 @@ proc le args {
set v7 [tasSplit [ql]]
set val [format " %9.4f %9.4f %9.4f %9.4f %9.4f %9.4f %9.4f \n" \
$v1 $v2 $v3 $v4 $v5 $v6 $v7]
set v1 [tasSplit [tei]]
set v2 [tasSplit [tki]]
set v3 [tasSplit [tef]]
set v4 [tasSplit [tkf]]
set v5 [tasSplit [tqh]]
set v6 [tasSplit [tqk]]
set v7 [tasSplit [tql]]
set val2 [format " %9.4f %9.4f %9.4f %9.4f %9.4f %9.4f %9.4f \n" \
$v1 $v2 $v3 $v4 $v5 $v6 $v7]
append output [format "POSN: %s" $val]
append output [format "TARG: %s" $val]
append output [format "TARG: %s" $val2]
append output [format " EN QM\n"]
set v1 [tasSplit [en]]
set v2 [tasSplit [qm]]
set val [format " %9.4f %9.4f\n" $v1 $v2]
set v1 [tasSplit [ten]]
set v2 [tasSplit [qm]]
set val2 [format " %9.4f %9.4f\n" $v1 $v2]
append output [format "POSN: %s" $val]
append output [format "TARG: %s" $val]
append output [format "TARG: %s" $val2]
return $output
}
@ -885,6 +925,7 @@ proc sz args {
#-------action
set newZero [expr $zero + ($val - $pos)]
madZero $mot $newZero
catch {updateqe} msg
#-------- more output
set zero [tasSplit [madZero $mot]]
set loh [tasSplit [eval $mot hardlowerlim]]

View File

@ -148,6 +148,7 @@ int TASDrive(SConnection *pCon, SicsInterp *pSics, void *pData,
tasMask[varPointer] = 1;
oldEnergy[varPointer] = self->tasPar[EMIN+varPointer]->fVal;
self->tasPar[EMIN + varPointer]->fVal = atof(pToken);
self->tasPar[ETARGET + varPointer]->fVal = atof(pToken);
}
else
{

View File

@ -150,6 +150,15 @@ extern char *tasVariableOrder[] = {
"local",
"swunit",
"scaninfo",
"tei",
"tki",
"tef",
"tkf",
"tqh",
"tqk",
"tql",
"ten",
"tqm",
NULL};
/*---------------------------------------------------------------------
There is a special feauture in MAD where the count mode is determined
@ -183,6 +192,25 @@ static int TimerCallback(int iEvent, void *pEvent, void *pUser)
SetCounterPreset(self->pScan->pCounterData,self->tasPar[TI]->fVal);
return 1;
}
/*-----------------------------------------------------------------------
This is an interpreter wrapper function which allows to call for the
recalculation of the energy variables from scripts.
--------------------------------------------------------------------------*/
extern int TASUpdate(pTASdata self,SConnection *pCon); /* tasutil.c */
static int RecalcAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
pTASdata self = NULL;
assert(pCon);
assert(pSics);
self = (pTASdata)pData;
assert(self);
return TASUpdate(self,pCon);
}
/*-----------------------------------------------------------------------
A function for killing the TAS data structure is needed
-------------------------------------------------------------------------*/
@ -293,10 +321,17 @@ int TASFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
TASKill(pNew);
return 0;
}
iError = AddCommand(pSics,"sf",TASScan,NULL,pNew);
iError = AddCommand(pSics,"fs",TASScan,NULL,pNew);
if(!iError)
{
SCWrite(pCon,"ERROR: duplicate set command not created",eError);
SCWrite(pCon,"ERROR: duplicate sf command not created",eError);
TASKill(pNew);
return 0;
}
iError = AddCommand(pSics,"updateqe",RecalcAction,NULL,pNew);
if(!iError)
{
SCWrite(pCon,"ERROR: duplicate updateqe command not created",eError);
TASKill(pNew);
return 0;
}

View File

@ -552,6 +552,8 @@ static int TASScanDrive(pScanData self, int iPoint)
iTAS = 1;
pTAS->tasPar[EI+iPtr]->fVal =
pVar->fStart + iPoint * pVar->fStep;
pTAS->tasPar[ETARGET+iPtr]->fVal =
pVar->fStart + iPoint * pVar->fStep;
tasMask[iPtr] = 1;
}
else
@ -575,14 +577,16 @@ static int TASScanDrive(pScanData self, int iPoint)
{
status = TASCalc(pTAS,self->pCon,tasMask,
tasTargets, tasTargetMask);
if(!status)
return 0;
TASStart(pTAS,self->pCon,
if(status)
{
/*
Errors both in calculation or in starting motors are
ignored here on purpose. There is a slight chance that
other points in the scan fit the bill.
*/
TASStart(pTAS,self->pCon,
self->pSics,tasTargets,tasTargetMask);
/*
again ignore errors, the scan shall continue if an error was
found
*/
}
}
/*

View File

@ -57,8 +57,8 @@ TokenInit connan
SicsUser Spy 007 1
#---------------------------------------------------------------------------
# M O T O R S
Motor A1 SIM 0. 111. -.1 2. # Monochromator Theta
Motor A2 SIM 33.1 120. -.1 2. # Monochromator Two-Theta
Motor A1 SIM -87. 6.1 -.1 2. # Monochromator Theta
Motor A2 SIM -129.1 -22. -.1 2. # Monochromator Two-Theta
Motor A3 SIM -177.3 177.3 -.1 2. # Sample theta or omega
Motor A4 SIM -135.1 123.4 -.1 2. # Sample Two-Theta
Motor A5 SIM -200 200 -.1 2. # Analyzer Theta
@ -122,6 +122,18 @@ VarMake QH Float User
VarMake QK Float User
VarMake QL Float User
VarMake EN Float User
#-------- energy Q targets
VarMake TEI Float User
VarMake TKI Float User
VarMake TEF Float User
VarMake TKF Float User
VarMake TQH Float User
VarMake TQK Float User
VarMake TQL Float User
VarMake TEN Float User
VarMake TQM Float User
#---------------------------------------------------------------------------
# I N S T R U M E N T V A R I A B L E S
# DM, DA d-spacing monochromator, analyzer
@ -142,7 +154,7 @@ instrument lock
VarMake DM Float Mugger
VarMake DA Float Mugger
VarMake SM Int User
SM 1
SM -1
SM lock
VarMake SS Int User
VarMake SA Int User

4
tasu.h
View File

@ -21,11 +21,11 @@ extern char *tasVariableOrder[];
/*
Note: the defines below MUST map the range between EI - HZ in the list
of variables as defined in tas.h. Otherwise quite interesting things
can happen.
can happen. ETARGET is the variable order index for the energy targets.
*/
#define EMIN 25
#define EMAX 36
#define ETARGET 94
int isTASMotor(char *val);
int isTASVar(char *val);

211
tasutil.c
View File

@ -131,7 +131,66 @@ void prepare2Parse(char *line)
}
return 1;
}
/*--------------------------------------------------------------------
print calculation errors.
*/
static int printError(int ier, SConnection *pCon)
{
/*
error messages taken from erreso
*/
switch(ier)
{
case 1:
SCWrite(pCon,"ERROR: Bad lattice parameters(AS,BS,CS)",eError);
return 0;
break;
case 2:
SCWrite(pCon,"ERROR: Bad cell angles",eError);
return 0;
break;
case 3:
SCWrite(pCon,"ERROR: Bad scattering plane ",eError);
return 0;
break;
case 4:
SCWrite(pCon,"ERROR: Bad lattice or lattice plane",eError);
return 0;
break;
case 5:
SCWrite(pCon,"ERROR: Check Lattice and Scattering Plane",eError);
return 0;
break;
case 6:
SCWrite(pCon,"ERROR: Q not in scattering plane",eError);
return 0;
break;
break;
case 7:
SCWrite(pCon,"ERROR: Q-modulus to small",eError);
return 0;
break;
case 8:
case 12:
SCWrite(pCon,"ERROR: KI,KF,Q triangle cannot close",eError);
return 0;
break;
case 9:
SCWrite(pCon,"ERROR: KI or K, check d-spacings",eError);
return 0;
break;
case 10:
SCWrite(pCon,"ERROR: KI or KF cannot be obtained",eError);
return 0;
break;
case 11:
SCWrite(pCon,"ERROR: KI or KF to small",eError);
return 0;
break;
default:
break;
}
}
/*----------------------------------------------------------------------
TASCalc does the triple axis spectrometer calculations. This function is
invoked whenever energy or Q needs to be driven. The parameters:
@ -266,14 +325,14 @@ int TASCalc(pTASdata self, SConnection *pCon,
This done, we painstackingly initialize the tons of parameters required
by the t_conv
*/
ei = (real)self->tasPar[EI]->fVal;
aki = (real)self->tasPar[KI]->fVal;
ef = (real)self->tasPar[EF]->fVal;
akf = (real)self->tasPar[KF]->fVal;
qhkl[0] = (real)self->tasPar[QH]->fVal;
qhkl[1] = (real)self->tasPar[QK]->fVal;
qhkl[2] = (real)self->tasPar[QL]->fVal;
en = (real)self->tasPar[EN]->fVal;
ei = (real)self->tasPar[TEI]->fVal;
aki = (real)self->tasPar[TKI]->fVal;
ef = (real)self->tasPar[TEF]->fVal;
akf = (real)self->tasPar[TKF]->fVal;
qhkl[0] = (real)self->tasPar[TQH]->fVal;
qhkl[1] = (real)self->tasPar[TQK]->fVal;
qhkl[2] = (real)self->tasPar[TQL]->fVal;
en = (real)self->tasPar[TEN]->fVal;
hx = (real)self->tasPar[HX]->fVal;
hy = (real)self->tasPar[HY]->fVal;
hz = (real)self->tasPar[HZ]->fVal;
@ -288,6 +347,9 @@ int TASCalc(pTASdata self, SConnection *pCon,
ldf = (logical)tasMask[9];
if(self->tasPar[LPA]->iVal > 0)
lpa = (logical)1;
else
lpa = (logical)0;
dm = (real)self->tasPar[DM]->fVal;
da = (real)self->tasPar[DA]->fVal;
qm = (real)self->tasPar[QM]->fVal;
@ -323,7 +385,7 @@ int TASCalc(pTASdata self, SConnection *pCon,
{
ldra[i] = 0;
}
l_RA = l_RM = l_ALM = 0;
l_RA = l_RM = l_ALM = ier = 0;
/* now we can call */
t_conv__(&ei, &aki, &ef, &akf,
@ -334,58 +396,11 @@ int TASCalc(pTASdata self, SConnection *pCon,
angles, &tRM, &tALM, &tRA, &qm, ldra,
&l_RM, &l_ALM,&l_RA, currents,helmconv,
&ier);
/*
error messages taken from erreso
*/
switch(ier)
if(ier != 0)
{
case 1:
SCWrite(pCon,"ERROR: Bad lattice parameters",eError);
return 0;
break;
case 2:
SCWrite(pCon,"ERROR: Bad cell angles",eError);
return 0;
break;
case 3:
SCWrite(pCon,"ERROR: Bad scattering plane ",eError);
return 0;
break;
case 4:
SCWrite(pCon,"ERROR: Bad lattice or lattice plane",eError);
return 0;
break;
case 5:
SCWrite(pCon,"ERROR: Q not in scattering plane",eError);
return 0;
break;
case 6:
SCWrite(pCon,"ERROR: Q modulus to small",eError);
return 0;
break;
case 7:
case 12:
SCWrite(pCon,"ERROR: KI, KF, Q triangle cannot close ",eError);
return 0;
break;
case 8:
SCWrite(pCon,"ERROR: in KI, KF, check d-spacings",eError);
return 0;
break;
case 9:
SCWrite(pCon,"ERROR: KI or KF cannot be obtained",eError);
return 0;
break;
case 10:
SCWrite(pCon,"ERROR: KI or KF to small",eError);
return 0;
break;
case 11:
SCWrite(pCon,"ERROR: KI or KF cannot be obtained",eError);
return 0;
break;
default:
break;
printError(ier,pCon);
return 0;
}
/*
@ -409,12 +424,12 @@ int TASCalc(pTASdata self, SConnection *pCon,
{
motorTargets[17+i] = helmconv[i];
}
self->tasPar[EI]->fVal = (float)ei;
self->tasPar[KI]->fVal = (float)aki;
self->tasPar[EF]->fVal = (float)ef;
self->tasPar[KF]->fVal = (float)akf;
self->tasPar[EN]->fVal = (float)en;
self->tasPar[TEI]->fVal = (float)ei;
self->tasPar[TKI]->fVal = (float)aki;
self->tasPar[TEF]->fVal = (float)ef;
self->tasPar[TKF]->fVal = (float)akf;
self->tasPar[TEN]->fVal = (float)en;
self->tasPar[QM]->fVal = (float)qm;
return 1;
}
@ -578,6 +593,9 @@ int TASUpdate(pTASdata self, SConnection *pCon)
*/
if(self->tasPar[LPA]->iVal > 0)
lpa = (logical)1;
else
lpa = (logical)0;
da = (real)self->tasPar[DA]->fVal;
dm = (real)self->tasPar[DM]->fVal;
isa = (integer)self->tasPar[SA]->iVal;
@ -593,12 +611,13 @@ int TASUpdate(pTASdata self, SConnection *pCon)
/*
now call t_update to do the calculation
*/
ier = 0;
t_update__(amot, helmCurrent, convH, &lpa, &dm, &da, &isa, &helm,
&f1h, &f1v, &f2h, &f2v, &f, &ei, &aki, &ef, &akf,
qhkl, &en, &hx, &hy, &hz, &if1, &if2, &qm, &ier);
/*
!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
t_update's function ex_up must be dited manually after conversion
t_update's function ex_up must be edited manually after conversion
to c by f2c. The reason is a different definition of the abs function.
The line:
arg = (d__1 = *dx * sin(*ax2 / 114.59155902616465, abs(d__1));
@ -610,59 +629,10 @@ int TASUpdate(pTASdata self, SConnection *pCon)
!!!!!!!!!!!!!!!!!!!!!! WARNING !!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*
error messages taken from erreso
*/
switch(ier)
if(ier != 0)
{
case 1:
SCWrite(pCon,"ERROR: Bad lattice parameters",eError);
return 0;
break;
case 2:
SCWrite(pCon,"ERROR: Bad cell angles",eError);
return 0;
break;
case 3:
SCWrite(pCon,"ERROR: Bad scattering plane ",eError);
return 0;
break;
case 4:
SCWrite(pCon,"ERROR: Bad lattice or lattice plane",eError);
return 0;
break;
case 5:
SCWrite(pCon,"ERROR: Q not in scattering plane",eError);
return 0;
break;
case 6:
SCWrite(pCon,"ERROR: Q modulus to small",eError);
return 0;
break;
case 7:
case 12:
SCWrite(pCon,"ERROR: KI, KF, Q triangle cannot close ",eError);
return 0;
break;
case 8:
SCWrite(pCon,"ERROR: in KI, KF, check d-spacings",eError);
return 0;
break;
case 9:
SCWrite(pCon,"ERROR: KI or KF cannot be obtained",eError);
return 0;
break;
case 10:
SCWrite(pCon,"ERROR: KI or KF to small",eError);
return 0;
break;
case 11:
SCWrite(pCon,"ERROR: KI or KF cannot be obtained",eError);
return 0;
break;
default:
break;
printError(ier,pCon);
return 0;
}
/*
@ -711,3 +681,4 @@ int TASUpdate(pTASdata self, SConnection *pCon)
return 1;
}

View File

@ -49,7 +49,8 @@ framepreset = \
/$(framename),NXentry/TRICS,NXinstrument/count_control,NXcounter/SDS preset
framemode = /$(framename),NXentry/TRICS,NXinstrument/count_control,NXcounter/SDS countmode \
-type DFNT_UINT8 -rank 1 -dim {132}
framemonitor = /$(framename),NXentry/TRICS,NXinstrument/count_control,NXcounter/SDS monitor \
framemonitor = /$(framename),NXentry/TRICS,NXinstrument/count_control,NXcounter/SDS monitor -type DFNT_INT32
sinqmonitor= /$(framename),NXentry/TRICS,NXinstrument/count_control,NXcounter/SDS beam_monitor \
-type DFNT_INT32
#------------------------ Detector
dnumber = detector1
@ -72,7 +73,7 @@ frametilt = /$(framename),NXentry/TRICS,NXinstrument/$(dnumber),NXdetector/SDS
-attr {units,degrees}
framecounts = /$(framename),NXentry/TRICS,NXinstrument/$(dnumber),NXdetector/SDS counts \
-attr {signal,1} -attr {units,counts} -type DFNT_INT32 \
-LZW -chunk {256,256} -rank 2 -dim {$(framedim1),$(framedim2)}
-LZW -rank 2 -dim {$(framedim1),$(framedim2)}
detzerox = \
/frame0000,NXentry/TRICS,NXinstrument/$(dnumber),NXdetector/SDS x_zero_point \
-attr {units,pixel}