- First working version of the triple axis UB matrix code
This commit is contained in:
@ -53,6 +53,7 @@ of the measurement.
|
|||||||
parameter iSkip determines the number of lines to skip in the file. This
|
parameter iSkip determines the number of lines to skip in the file. This
|
||||||
feature allows to continue measurement on not fully processed files.
|
feature allows to continue measurement on not fully processed files.
|
||||||
<DT>dataset reopen filename
|
<DT>dataset reopen filename
|
||||||
|
<DT>dataset reopen 001/trics2005n000051
|
||||||
<DD>Reopens an already existing file set for appending. Only the file root
|
<DD>Reopens an already existing file set for appending. Only the file root
|
||||||
without directory info or endings needs to be given.
|
without directory info or endings needs to be given.
|
||||||
<DT>dataset close
|
<DT>dataset close
|
||||||
@ -93,6 +94,9 @@ This object knows about the following parameters:
|
|||||||
max count in scan - 2* min count in scan.
|
max count in scan - 2* min count in scan.
|
||||||
<dt>fastscan
|
<dt>fastscan
|
||||||
<dd>0 or 1: switches fastscan mode.
|
<dd>0 or 1: switches fastscan mode.
|
||||||
|
<dt>psimode
|
||||||
|
<dd>0 or 1: switches psi scanning mode. Please note that suitable HKL input files for this mode
|
||||||
|
must contain four numbers: H, K, L and psi.
|
||||||
<dt>psd
|
<dt>psd
|
||||||
<dd>0 or 1: switches on PSD mode for measuring with the area detector. Currently this is mapped
|
<dd>0 or 1: switches on PSD mode for measuring with the area detector. Currently this is mapped
|
||||||
to doing a tricsscan with the scan parameters as evaluted from the two theta range table. The
|
to doing a tricsscan with the scan parameters as evaluted from the two theta range table. The
|
||||||
@ -102,7 +106,7 @@ This object knows about the following parameters:
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Then there are command which allow to configure the table of two theta ranges and
|
Then there are command which allow to configure the table of two theta ranges and
|
||||||
scan parameters. All table rleated commands start with: dataset table. The following
|
scan parameters. All table related commands start with: dataset table. The following
|
||||||
commands are supported:
|
commands are supported:
|
||||||
<dl>
|
<dl>
|
||||||
<dt>dataset table list
|
<dt>dataset table list
|
||||||
@ -126,7 +130,7 @@ dataset supports two geometries: the first is the usual bisecting geometry. The
|
|||||||
This is accounted for by two switches:
|
This is accounted for by two switches:
|
||||||
<dl>
|
<dl>
|
||||||
<dt>dataset bi
|
<dt>dataset bi
|
||||||
<dd>switches into bissectiong mode. This is the default.
|
<dd>switches into bissecting mode. This is the default.
|
||||||
<dt>dataset nb
|
<dt>dataset nb
|
||||||
<dd>switches into normal beam mode.
|
<dd>switches into normal beam mode.
|
||||||
</dl>
|
</dl>
|
||||||
|
2
hklmot.c
2
hklmot.c
@ -49,7 +49,7 @@ static int HKLHalt(void *pData){
|
|||||||
static int HKLCheckLimits(void *self, float fVal, char *error, int errLen){
|
static int HKLCheckLimits(void *self, float fVal, char *error, int errLen){
|
||||||
/*
|
/*
|
||||||
There is no meaningful implementation here. This gets called when starting the motor.
|
There is no meaningful implementation here. This gets called when starting the motor.
|
||||||
At that stage not all other values may be known. If the calculation failes, this will die
|
At that stage not all other values may be known. If the calculation fails, this will die
|
||||||
at status check time.
|
at status check time.
|
||||||
*/
|
*/
|
||||||
return 1;
|
return 1;
|
||||||
|
2
make_gen
2
make_gen
@ -24,7 +24,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
|||||||
hklscan.o xytable.o exebuf.o exeman.o ubfour.o ubcalc.o\
|
hklscan.o xytable.o exebuf.o exeman.o ubfour.o ubcalc.o\
|
||||||
circular.o maximize.o sicscron.o scanvar.o tasublib.o\
|
circular.o maximize.o sicscron.o scanvar.o tasublib.o\
|
||||||
d_sign.o d_mod.o tcldrivable.o stdscan.o diffscan.o\
|
d_sign.o d_mod.o tcldrivable.o stdscan.o diffscan.o\
|
||||||
synchronize.o definealias.o oscillate.o \
|
synchronize.o definealias.o oscillate.o tasdrive.o\
|
||||||
hmcontrol.o userscan.o rs232controller.o lomax.o \
|
hmcontrol.o userscan.o rs232controller.o lomax.o \
|
||||||
fourlib.o motreg.o motreglist.o anticollider.o \
|
fourlib.o motreg.o motreglist.o anticollider.o \
|
||||||
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) \
|
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) \
|
||||||
|
1
mesure.c
1
mesure.c
@ -846,7 +846,6 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
|||||||
self->fRefl = fopen(pFile,"r");
|
self->fRefl = fopen(pFile,"r");
|
||||||
if(!self->fRefl)
|
if(!self->fRefl)
|
||||||
{
|
{
|
||||||
fclose(self->fRefl);
|
|
||||||
sprintf(pBueffel,"ERROR: there is no such measurement at %s",fileroot);
|
sprintf(pBueffel,"ERROR: there is no such measurement at %s",fileroot);
|
||||||
SCWrite(pCon,pBueffel,eError);
|
SCWrite(pCon,pBueffel,eError);
|
||||||
return 0;
|
return 0;
|
||||||
|
2
scan.c
2
scan.c
@ -729,7 +729,7 @@ CountEntry CollectCounterData(pScanData self)
|
|||||||
self->fPreset = fPreset;
|
self->fPreset = fPreset;
|
||||||
|
|
||||||
/* do some preprocessing */
|
/* do some preprocessing */
|
||||||
iRet = PrepareScan(self);
|
iRet = SilentPrepare(self);
|
||||||
if(!iRet)
|
if(!iRet)
|
||||||
{
|
{
|
||||||
self->WriteHeader = HeaderFunc;
|
self->WriteHeader = HeaderFunc;
|
||||||
|
@ -285,7 +285,13 @@
|
|||||||
}
|
}
|
||||||
sprintf(pFile,"%s%1d.log",pFile, iFile);
|
sprintf(pFile,"%s%1d.log",pFile, iFile);
|
||||||
fLogFile = fopen(pFile,"w");
|
fLogFile = fopen(pFile,"w");
|
||||||
assert(fLogFile);
|
if(!fLogFile)
|
||||||
|
{
|
||||||
|
printf("ERROR: cannot open logfile %s for writing\n",
|
||||||
|
pFile);
|
||||||
|
fLogFile = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
iLineCount = 0;
|
iLineCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
415
sicsstat.tcl
415
sicsstat.tcl
@ -1,193 +1,230 @@
|
|||||||
banana CountMode timer
|
exe batchpath ./
|
||||||
banana preset 10.000000
|
exe syspath ./
|
||||||
# Counter counter
|
#---- tasUB module tasub
|
||||||
counter SetPreset 10.000000
|
tasub mono dd 3.350000
|
||||||
counter SetMode Timer
|
tasub mono hb1 1.000000
|
||||||
# Motor tilt
|
tasub mono hb2 1.000000
|
||||||
tilt sign 1.000000
|
tasub mono vb1 1.000000
|
||||||
tilt SoftZero 0.000000
|
tasub mono vb2 1.000000
|
||||||
tilt SoftLowerLim -403.623993
|
tasub mono ss 1
|
||||||
tilt SoftUpperLim 396.376007
|
tasub ana dd 3.350000
|
||||||
tilt Fixed -1.000000
|
tasub ana hb1 1.000000
|
||||||
tilt InterruptMode 0.000000
|
tasub ana hb2 1.000000
|
||||||
tilt AccessCode 2.000000
|
tasub ana vb1 1.000000
|
||||||
# Motor chi
|
tasub ana vb2 1.000000
|
||||||
chi sign 1.000000
|
tasub ana ss 1
|
||||||
chi SoftZero 0.000000
|
tasub cell 1.000000 1.000000 1.000000 90.000000 90.000000 90.000000
|
||||||
chi SoftLowerLim -20.000000
|
tasub clear
|
||||||
chi SoftUpperLim 20.000000
|
tasub const ki
|
||||||
chi Fixed -1.000000
|
tasub ss 1
|
||||||
chi InterruptMode 0.000000
|
tasub setub 1.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 1.000000
|
||||||
chi AccessCode 2.000000
|
tasub setnormal 0.000000 0.000000 0.000000
|
||||||
# Motor ome
|
tasub settarget 0.000000 0.000000 0.000000 0.000000 0.000000
|
||||||
ome sign 1.000000
|
tasub update
|
||||||
ome SoftZero 0.000000
|
scaninfo 0,Unknown,1.0,.1
|
||||||
ome SoftLowerLim -180.000000
|
scaninfo setAccess 0
|
||||||
ome SoftUpperLim 180.000000
|
polfile UNKNOWN
|
||||||
ome Fixed -1.000000
|
polfile setAccess 2
|
||||||
ome InterruptMode 0.000000
|
local UNKNOWN
|
||||||
ome AccessCode 2.000000
|
local setAccess 2
|
||||||
# Motor atz
|
output UNKNOWN
|
||||||
atz sign 1.000000
|
output setAccess 2
|
||||||
atz SoftZero 0.000000
|
lastcommand UNKNOWN
|
||||||
atz SoftLowerLim -3900.000000
|
lastcommand setAccess 2
|
||||||
atz SoftUpperLim 0.000000
|
|
||||||
atz Fixed -1.000000
|
|
||||||
atz InterruptMode 0.000000
|
|
||||||
atz AccessCode 2.000000
|
|
||||||
# Motor az1
|
|
||||||
az1 sign 1.000000
|
|
||||||
az1 SoftZero 0.000000
|
|
||||||
az1 SoftLowerLim -3900.000000
|
|
||||||
az1 SoftUpperLim 0.000000
|
|
||||||
az1 Fixed -1.000000
|
|
||||||
az1 InterruptMode 0.000000
|
|
||||||
az1 AccessCode 2.000000
|
|
||||||
# Motor dv
|
|
||||||
dv sign 1.000000
|
|
||||||
dv SoftZero 0.000000
|
|
||||||
dv SoftLowerLim -14000.000000
|
|
||||||
dv SoftUpperLim 25000.000000
|
|
||||||
dv Fixed -1.000000
|
|
||||||
dv InterruptMode 0.000000
|
|
||||||
dv AccessCode 2.000000
|
|
||||||
# Motor dh
|
|
||||||
dh sign 1.000000
|
|
||||||
dh SoftZero 0.000000
|
|
||||||
dh SoftLowerLim -14000.000000
|
|
||||||
dh SoftUpperLim 16000.000000
|
|
||||||
dh Fixed -1.000000
|
|
||||||
dh InterruptMode 0.000000
|
|
||||||
dh AccessCode 2.000000
|
|
||||||
# Motor dz
|
|
||||||
dz sign 1.000000
|
|
||||||
dz SoftZero 0.000000
|
|
||||||
dz SoftLowerLim 1.050000
|
|
||||||
dz SoftUpperLim 6.000000
|
|
||||||
dz Fixed -1.000000
|
|
||||||
dz InterruptMode 0.000000
|
|
||||||
dz AccessCode 2.000000
|
|
||||||
# Motor sy
|
|
||||||
sy sign 1.000000
|
|
||||||
sy SoftZero 0.000000
|
|
||||||
sy SoftLowerLim -10000.000000
|
|
||||||
sy SoftUpperLim 10000.000000
|
|
||||||
sy Fixed -1.000000
|
|
||||||
sy InterruptMode 0.000000
|
|
||||||
sy AccessCode 2.000000
|
|
||||||
# Motor sx
|
|
||||||
sx sign 1.000000
|
|
||||||
sx SoftZero 0.000000
|
|
||||||
sx SoftLowerLim -10000.000000
|
|
||||||
sx SoftUpperLim 10000.000000
|
|
||||||
sx Fixed -1.000000
|
|
||||||
sx InterruptMode 0.000000
|
|
||||||
sx AccessCode 2.000000
|
|
||||||
# Motor sz
|
|
||||||
sz sign 1.000000
|
|
||||||
sz SoftZero 0.000000
|
|
||||||
sz SoftLowerLim -10000.000000
|
|
||||||
sz SoftUpperLim 10000.000000
|
|
||||||
sz Fixed -1.000000
|
|
||||||
sz InterruptMode 0.000000
|
|
||||||
sz AccessCode 2.000000
|
|
||||||
# Motor om
|
|
||||||
om sign 1.000000
|
|
||||||
om SoftZero 0.000000
|
|
||||||
om SoftLowerLim -10000.000000
|
|
||||||
om SoftUpperLim 10000.000000
|
|
||||||
om Fixed -1.000000
|
|
||||||
om InterruptMode 0.000000
|
|
||||||
om AccessCode 2.000000
|
|
||||||
# Motor tl
|
|
||||||
tl sign 1.000000
|
|
||||||
tl SoftZero 0.000000
|
|
||||||
tl SoftLowerLim -10000.000000
|
|
||||||
tl SoftUpperLim 10000.000000
|
|
||||||
tl Fixed -1.000000
|
|
||||||
tl InterruptMode 0.000000
|
|
||||||
tl AccessCode 2.000000
|
|
||||||
# Motor tu
|
|
||||||
tu sign 1.000000
|
|
||||||
tu SoftZero 0.000000
|
|
||||||
tu SoftLowerLim -10000.000000
|
|
||||||
tu SoftUpperLim 10000.000000
|
|
||||||
tu Fixed -1.000000
|
|
||||||
tu InterruptMode 0.000000
|
|
||||||
tu AccessCode 2.000000
|
|
||||||
# Motor gl
|
|
||||||
gl sign 1.000000
|
|
||||||
gl SoftZero 0.000000
|
|
||||||
gl SoftLowerLim -10000.000000
|
|
||||||
gl SoftUpperLim 10000.000000
|
|
||||||
gl Fixed -1.000000
|
|
||||||
gl InterruptMode 0.000000
|
|
||||||
gl AccessCode 2.000000
|
|
||||||
# Motor gu
|
|
||||||
gu sign 1.000000
|
|
||||||
gu SoftZero 0.000000
|
|
||||||
gu SoftLowerLim -10000.000000
|
|
||||||
gu SoftUpperLim 10000.000000
|
|
||||||
gu Fixed -1.000000
|
|
||||||
gu InterruptMode 0.000000
|
|
||||||
gu AccessCode 2.000000
|
|
||||||
# Motor sc
|
|
||||||
sc sign 1.000000
|
|
||||||
sc SoftZero 0.000000
|
|
||||||
sc SoftLowerLim -2000.000000
|
|
||||||
sc SoftUpperLim 70000.000000
|
|
||||||
sc Fixed -1.000000
|
|
||||||
sc InterruptMode 0.000000
|
|
||||||
sc AccessCode 2.000000
|
|
||||||
# Motor stz
|
|
||||||
stz sign 1.000000
|
|
||||||
stz SoftZero 0.000000
|
|
||||||
stz SoftLowerLim 6500.000000
|
|
||||||
stz SoftUpperLim 20000.000000
|
|
||||||
stz Fixed -1.000000
|
|
||||||
stz InterruptMode 0.000000
|
|
||||||
stz AccessCode 2.000000
|
|
||||||
# Motor stx
|
|
||||||
stx sign 1.000000
|
|
||||||
stx SoftZero 0.000000
|
|
||||||
stx SoftLowerLim -16000.000000
|
|
||||||
stx SoftUpperLim 16000.000000
|
|
||||||
stx Fixed -1.000000
|
|
||||||
stx InterruptMode 0.000000
|
|
||||||
stx AccessCode 2.000000
|
|
||||||
# Motor sr
|
|
||||||
sr sign 1.000000
|
|
||||||
sr SoftZero 0.000000
|
|
||||||
sr SoftLowerLim -10000.000000
|
|
||||||
sr SoftUpperLim 10000.000000
|
|
||||||
sr Fixed -1.000000
|
|
||||||
sr InterruptMode 0.000000
|
|
||||||
sr AccessCode 2.000000
|
|
||||||
sampletable UNKNOWN
|
|
||||||
sampletable setAccess 2
|
|
||||||
starttime 2003-02-13 13:52:54
|
|
||||||
starttime setAccess 2
|
|
||||||
batchroot /afs/psi.ch/user/k/koennecke/src/sics
|
|
||||||
batchroot setAccess 2
|
|
||||||
sample Wurstbroetchen
|
|
||||||
sample setAccess 2
|
|
||||||
adress UNKNOWN
|
|
||||||
adress setAccess 2
|
|
||||||
phone UNKNOWN
|
|
||||||
phone setAccess 2
|
|
||||||
fax UNKNOWN
|
|
||||||
fax setAccess 2
|
|
||||||
email UNKNOWN
|
|
||||||
email setAccess 2
|
|
||||||
samplename KohlSulfid
|
|
||||||
samplename setAccess 2
|
|
||||||
comment UNKNOWN
|
|
||||||
comment setAccess 2
|
|
||||||
environment UNKNOWN
|
|
||||||
environment setAccess 2
|
|
||||||
subtitle UNKNOWN
|
|
||||||
subtitle setAccess 2
|
|
||||||
user Albert von Villigen
|
user Albert von Villigen
|
||||||
user setAccess 2
|
user setAccess 2
|
||||||
title UNKNOWN
|
title UNKNOWN
|
||||||
title setAccess 2
|
title setAccess 2
|
||||||
|
# Counter counter
|
||||||
|
counter SetPreset 10.000000
|
||||||
|
counter SetMode Timer
|
||||||
|
# Motor agl
|
||||||
|
agl sign 1.000000
|
||||||
|
agl SoftZero 0.000000
|
||||||
|
agl SoftLowerLim -10.000000
|
||||||
|
agl SoftUpperLim 10.000000
|
||||||
|
agl Fixed -1.000000
|
||||||
|
agl InterruptMode 0.000000
|
||||||
|
agl precision 0.010000
|
||||||
|
agl AccessCode 2.000000
|
||||||
|
agl movecount 10.000000
|
||||||
|
# Motor sgu
|
||||||
|
sgu sign 1.000000
|
||||||
|
sgu SoftZero 0.000000
|
||||||
|
sgu SoftLowerLim -16.000000
|
||||||
|
sgu SoftUpperLim 16.000000
|
||||||
|
sgu Fixed -1.000000
|
||||||
|
sgu InterruptMode 0.000000
|
||||||
|
sgu precision 0.010000
|
||||||
|
sgu AccessCode 2.000000
|
||||||
|
sgu movecount 10.000000
|
||||||
|
# Motor sgl
|
||||||
|
sgl sign 1.000000
|
||||||
|
sgl SoftZero 0.000000
|
||||||
|
sgl SoftLowerLim -16.000000
|
||||||
|
sgl SoftUpperLim 16.000000
|
||||||
|
sgl Fixed -1.000000
|
||||||
|
sgl InterruptMode 0.000000
|
||||||
|
sgl precision 0.010000
|
||||||
|
sgl AccessCode 2.000000
|
||||||
|
sgl movecount 10.000000
|
||||||
|
# Motor mgl
|
||||||
|
mgl sign 1.000000
|
||||||
|
mgl SoftZero 0.000000
|
||||||
|
mgl SoftLowerLim -10.000000
|
||||||
|
mgl SoftUpperLim 10.000000
|
||||||
|
mgl Fixed -1.000000
|
||||||
|
mgl InterruptMode 0.000000
|
||||||
|
mgl precision 0.010000
|
||||||
|
mgl AccessCode 2.000000
|
||||||
|
mgl movecount 10.000000
|
||||||
|
# Motor atu
|
||||||
|
atu sign 1.000000
|
||||||
|
atu SoftZero 0.000000
|
||||||
|
atu SoftLowerLim -17.000000
|
||||||
|
atu SoftUpperLim 16.879999
|
||||||
|
atu Fixed -1.000000
|
||||||
|
atu InterruptMode 0.000000
|
||||||
|
atu precision 0.010000
|
||||||
|
atu AccessCode 2.000000
|
||||||
|
atu movecount 10.000000
|
||||||
|
# Motor atl
|
||||||
|
atl sign 1.000000
|
||||||
|
atl SoftZero 0.000000
|
||||||
|
atl SoftLowerLim -17.000000
|
||||||
|
atl SoftUpperLim 17.000000
|
||||||
|
atl Fixed -1.000000
|
||||||
|
atl InterruptMode 0.000000
|
||||||
|
atl precision 0.010000
|
||||||
|
atl AccessCode 2.000000
|
||||||
|
atl movecount 10.000000
|
||||||
|
# Motor stu
|
||||||
|
stu sign 1.000000
|
||||||
|
stu SoftZero 0.000000
|
||||||
|
stu SoftLowerLim -30.000000
|
||||||
|
stu SoftUpperLim 30.000000
|
||||||
|
stu Fixed -1.000000
|
||||||
|
stu InterruptMode 0.000000
|
||||||
|
stu precision 0.010000
|
||||||
|
stu AccessCode 2.000000
|
||||||
|
stu movecount 10.000000
|
||||||
|
# Motor stl
|
||||||
|
stl sign 1.000000
|
||||||
|
stl SoftZero 0.000000
|
||||||
|
stl SoftLowerLim -30.000000
|
||||||
|
stl SoftUpperLim 30.000000
|
||||||
|
stl Fixed -1.000000
|
||||||
|
stl InterruptMode 0.000000
|
||||||
|
stl precision 0.010000
|
||||||
|
stl AccessCode 2.000000
|
||||||
|
stl movecount 10.000000
|
||||||
|
# Motor mtu
|
||||||
|
mtu sign 1.000000
|
||||||
|
mtu SoftZero 0.000000
|
||||||
|
mtu SoftLowerLim -17.000000
|
||||||
|
mtu SoftUpperLim 17.000000
|
||||||
|
mtu Fixed -1.000000
|
||||||
|
mtu InterruptMode 0.000000
|
||||||
|
mtu precision 0.010000
|
||||||
|
mtu AccessCode 2.000000
|
||||||
|
mtu movecount 10.000000
|
||||||
|
# Motor mtl
|
||||||
|
mtl sign 1.000000
|
||||||
|
mtl SoftZero 0.000000
|
||||||
|
mtl SoftLowerLim -17.000000
|
||||||
|
mtl SoftUpperLim 17.000000
|
||||||
|
mtl Fixed -1.000000
|
||||||
|
mtl InterruptMode 0.000000
|
||||||
|
mtl precision 0.010000
|
||||||
|
mtl AccessCode 2.000000
|
||||||
|
mtl movecount 10.000000
|
||||||
|
# Motor ach
|
||||||
|
ach sign 1.000000
|
||||||
|
ach SoftZero 0.000000
|
||||||
|
ach SoftLowerLim -0.500000
|
||||||
|
ach SoftUpperLim 11.500000
|
||||||
|
ach Fixed -1.000000
|
||||||
|
ach InterruptMode 0.000000
|
||||||
|
ach precision 0.010000
|
||||||
|
ach AccessCode 2.000000
|
||||||
|
ach movecount 10.000000
|
||||||
|
# Motor sro
|
||||||
|
sro sign 1.000000
|
||||||
|
sro SoftZero 0.000000
|
||||||
|
sro SoftLowerLim 0.000000
|
||||||
|
sro SoftUpperLim 351.000000
|
||||||
|
sro Fixed -1.000000
|
||||||
|
sro InterruptMode 0.000000
|
||||||
|
sro precision 0.010000
|
||||||
|
sro AccessCode 2.000000
|
||||||
|
sro movecount 10.000000
|
||||||
|
# Motor mcv
|
||||||
|
mcv sign 1.000000
|
||||||
|
mcv SoftZero 0.000000
|
||||||
|
mcv SoftLowerLim -9.000000
|
||||||
|
mcv SoftUpperLim 124.000000
|
||||||
|
mcv Fixed -1.000000
|
||||||
|
mcv InterruptMode 0.000000
|
||||||
|
mcv precision 0.010000
|
||||||
|
mcv AccessCode 2.000000
|
||||||
|
mcv movecount 10.000000
|
||||||
|
# Motor a6
|
||||||
|
a6 sign 1.000000
|
||||||
|
a6 SoftZero 0.000000
|
||||||
|
a6 SoftLowerLim -116.000000
|
||||||
|
a6 SoftUpperLim 166.000000
|
||||||
|
a6 Fixed -1.000000
|
||||||
|
a6 InterruptMode 0.000000
|
||||||
|
a6 precision 0.010000
|
||||||
|
a6 AccessCode 2.000000
|
||||||
|
a6 movecount 10.000000
|
||||||
|
# Motor a5
|
||||||
|
a5 sign 1.000000
|
||||||
|
a5 SoftZero 0.000000
|
||||||
|
a5 SoftLowerLim -200.000000
|
||||||
|
a5 SoftUpperLim 200.000000
|
||||||
|
a5 Fixed -1.000000
|
||||||
|
a5 InterruptMode 0.000000
|
||||||
|
a5 precision 0.010000
|
||||||
|
a5 AccessCode 2.000000
|
||||||
|
a5 movecount 10.000000
|
||||||
|
# Motor a4
|
||||||
|
a4 sign 1.000000
|
||||||
|
a4 SoftZero 0.000000
|
||||||
|
a4 SoftLowerLim -135.100006
|
||||||
|
a4 SoftUpperLim 123.400002
|
||||||
|
a4 Fixed -1.000000
|
||||||
|
a4 InterruptMode 0.000000
|
||||||
|
a4 precision 0.010000
|
||||||
|
a4 AccessCode 2.000000
|
||||||
|
a4 movecount 10.000000
|
||||||
|
# Motor a3
|
||||||
|
a3 sign 1.000000
|
||||||
|
a3 SoftZero 0.000000
|
||||||
|
a3 SoftLowerLim -177.300003
|
||||||
|
a3 SoftUpperLim 177.300003
|
||||||
|
a3 Fixed -1.000000
|
||||||
|
a3 InterruptMode 0.000000
|
||||||
|
a3 precision 0.010000
|
||||||
|
a3 AccessCode 2.000000
|
||||||
|
a3 movecount 10.000000
|
||||||
|
# Motor a2
|
||||||
|
a2 sign 1.000000
|
||||||
|
a2 SoftZero 0.000000
|
||||||
|
a2 SoftLowerLim -129.100006
|
||||||
|
a2 SoftUpperLim -22.000000
|
||||||
|
a2 Fixed -1.000000
|
||||||
|
a2 InterruptMode 0.000000
|
||||||
|
a2 precision 0.010000
|
||||||
|
a2 AccessCode 2.000000
|
||||||
|
a2 movecount 10.000000
|
||||||
|
# Motor a1
|
||||||
|
a1 sign 1.000000
|
||||||
|
a1 SoftZero 0.000000
|
||||||
|
a1 SoftLowerLim -87.000000
|
||||||
|
a1 SoftUpperLim 6.100000
|
||||||
|
a1 Fixed -1.000000
|
||||||
|
a1 InterruptMode 0.000000
|
||||||
|
a1 precision 0.010000
|
||||||
|
a1 AccessCode 2.000000
|
||||||
|
a1 movecount 10.000000
|
||||||
|
111
stdscan.c
111
stdscan.c
@ -368,6 +368,28 @@ static char *fixExtension(char *filename)
|
|||||||
self->fd = NULL;
|
self->fd = NULL;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
static int prepareDataFile(pScanData self){
|
||||||
|
char *pPtr = NULL;
|
||||||
|
char pBueffel[512];
|
||||||
|
|
||||||
|
/* allocate a new data file */
|
||||||
|
pPtr = ScanMakeFileName(self->pSics,self->pCon);
|
||||||
|
if(!pPtr)
|
||||||
|
{
|
||||||
|
SCWrite(self->pCon,
|
||||||
|
"ERROR: cannot allocate new data filename, Scan aborted",
|
||||||
|
eError);
|
||||||
|
self->pCon = NULL;
|
||||||
|
self->pSics = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
snprintf(pBueffel,511,"Writing data file: %s ...",pPtr);
|
||||||
|
SCWrite(self->pCon,pBueffel,eWarning);
|
||||||
|
strcpy(self->pFile,pPtr);
|
||||||
|
free(pPtr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
int PrepareScan(pScanData self)
|
int PrepareScan(pScanData self)
|
||||||
{
|
{
|
||||||
@ -377,7 +399,6 @@ static char *fixExtension(char *filename)
|
|||||||
float fVal;
|
float fVal;
|
||||||
char pBueffel[512];
|
char pBueffel[512];
|
||||||
char pMessage[1024];
|
char pMessage[1024];
|
||||||
char *pPtr = NULL;
|
|
||||||
|
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(self->iNP > 0);
|
assert(self->iNP > 0);
|
||||||
@ -426,21 +447,68 @@ static char *fixExtension(char *filename)
|
|||||||
SetCounterPreset((pCounter)self->pCounterData, self->fPreset);
|
SetCounterPreset((pCounter)self->pCounterData, self->fPreset);
|
||||||
self->iCounts = 0;
|
self->iCounts = 0;
|
||||||
|
|
||||||
/* allocate a new data file */
|
if(!prepareDataFile(self)){
|
||||||
pPtr = ScanMakeFileName(self->pSics,self->pCon);
|
|
||||||
if(!pPtr)
|
|
||||||
{
|
|
||||||
SCWrite(self->pCon,
|
|
||||||
"ERROR: cannot allocate new data filename, Scan aborted",
|
|
||||||
eError);
|
|
||||||
self->pCon = NULL;
|
|
||||||
self->pSics = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
snprintf(pBueffel,511,"Writing data file: %s ...",pPtr);
|
|
||||||
SCWrite(self->pCon,pBueffel,eWarning);
|
return 1;
|
||||||
strcpy(self->pFile,pPtr);
|
}
|
||||||
free(pPtr);
|
/*--------------------------------------------------------------------------*/
|
||||||
|
int SilentPrepare(pScanData self)
|
||||||
|
{
|
||||||
|
pVarEntry pVar = NULL;
|
||||||
|
void *pDings;
|
||||||
|
int i, iRet;
|
||||||
|
float fVal;
|
||||||
|
char pBueffel[512];
|
||||||
|
char pMessage[1024];
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
assert(self->iNP > 0);
|
||||||
|
assert(self->pCon);
|
||||||
|
|
||||||
|
/* check boundaries of scan variables and allocate storage */
|
||||||
|
for(i = 0; i < self->iScanVar; i++)
|
||||||
|
{
|
||||||
|
DynarGet(self->pScanVar,i,&pDings);
|
||||||
|
pVar = (pVarEntry)pDings;
|
||||||
|
if(pVar)
|
||||||
|
{
|
||||||
|
/* start value */
|
||||||
|
fVal = ScanVarStart(pVar);
|
||||||
|
iRet = pVar->pInter->CheckLimits(pVar->pObject,
|
||||||
|
fVal,pBueffel,511);
|
||||||
|
if(!iRet)
|
||||||
|
{
|
||||||
|
sprintf(pMessage,"ERROR: %s, scan aborted",pBueffel);
|
||||||
|
SCWrite(self->pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* end value */
|
||||||
|
fVal = pVar->fStart + (self->iNP - 1) * ScanVarStep(pVar);
|
||||||
|
iRet = pVar->pInter->CheckLimits(pVar->pObject,
|
||||||
|
fVal,pBueffel,511);
|
||||||
|
if(!iRet)
|
||||||
|
{
|
||||||
|
sprintf(pMessage,"ERROR: %s, scan aborted",pBueffel);
|
||||||
|
SCWrite(self->pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
InitScanVar(pVar);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SCWrite(self->pCon,
|
||||||
|
"WARNING: Internal error, no scan variable, I try to continue",
|
||||||
|
eWarning);
|
||||||
|
}
|
||||||
|
pVar = NULL;
|
||||||
|
} /* end for */
|
||||||
|
|
||||||
|
/* configure counter */
|
||||||
|
SetCounterMode((pCounter)self->pCounterData,self->iMode);
|
||||||
|
SetCounterPreset((pCounter)self->pCounterData, self->fPreset);
|
||||||
|
self->iCounts = 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -453,7 +521,6 @@ static char *fixExtension(char *filename)
|
|||||||
float fVal;
|
float fVal;
|
||||||
char pBueffel[512];
|
char pBueffel[512];
|
||||||
char pMessage[1024];
|
char pMessage[1024];
|
||||||
char *pPtr = NULL;
|
|
||||||
|
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(self->iNP > 0);
|
assert(self->iNP > 0);
|
||||||
@ -484,21 +551,9 @@ static char *fixExtension(char *filename)
|
|||||||
SetCounterPreset((pCounter)self->pCounterData, self->fPreset);
|
SetCounterPreset((pCounter)self->pCounterData, self->fPreset);
|
||||||
self->iCounts = 0;
|
self->iCounts = 0;
|
||||||
|
|
||||||
/* allocate a new data file */
|
if(!prepareDataFile(self)){
|
||||||
pPtr = ScanMakeFileName(self->pSics,self->pCon);
|
|
||||||
if(!pPtr)
|
|
||||||
{
|
|
||||||
SCWrite(self->pCon,
|
|
||||||
"ERROR: cannot allocate new data filename, Scan aborted",
|
|
||||||
eError);
|
|
||||||
self->pCon = NULL;
|
|
||||||
self->pSics = NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
snprintf(pBueffel,511,"Writing data file: %s ...",pPtr);
|
|
||||||
SCWrite(self->pCon,pBueffel,eWarning);
|
|
||||||
strcpy(self->pFile,pPtr);
|
|
||||||
free(pPtr);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,10 @@
|
|||||||
/**
|
/**
|
||||||
* second version of PrepareScan which does not check scan limits
|
* second version of PrepareScan which does not check scan limits
|
||||||
*/
|
*/
|
||||||
|
int SilentPrepare(pScanData self);
|
||||||
|
/**
|
||||||
|
* third version of PrepareScan which does not create data files but checks
|
||||||
|
*/
|
||||||
int NonCheckPrepare(pScanData self);
|
int NonCheckPrepare(pScanData self);
|
||||||
/**
|
/**
|
||||||
* ScanDrive handles driving to the scan point iPoint.
|
* ScanDrive handles driving to the scan point iPoint.
|
||||||
|
644
tasdrive.c
Normal file
644
tasdrive.c
Normal file
@ -0,0 +1,644 @@
|
|||||||
|
/*---------------------------------------------------------------------
|
||||||
|
SICS interface to the triple axis drivable motors.
|
||||||
|
|
||||||
|
copyright: see file COPYRIGHT
|
||||||
|
|
||||||
|
Mark Koennecke, May 2005
|
||||||
|
--------------------------------------------------------------------*/
|
||||||
|
#include <assert.h>
|
||||||
|
#include "sics.h"
|
||||||
|
#include "tasdrive.h"
|
||||||
|
|
||||||
|
#define ABS(x) (x < 0 ? -(x) : (x))
|
||||||
|
|
||||||
|
#define MOTPREC .01
|
||||||
|
/*------------------- motor indexes in motor data structure ---------
|
||||||
|
WARNING: have to match tasub.c !!!!!
|
||||||
|
--------------------------------------------------------------------*/
|
||||||
|
#define A1 0
|
||||||
|
#define A2 1
|
||||||
|
#define MCV 2
|
||||||
|
#define MCH 3
|
||||||
|
#define A3 4
|
||||||
|
#define A4 5
|
||||||
|
#define SGU 6
|
||||||
|
#define SGL 7
|
||||||
|
#define A5 8
|
||||||
|
#define A6 9
|
||||||
|
#define ACV 10
|
||||||
|
#define ACH 11
|
||||||
|
|
||||||
|
/*============== Drivable Interface functions =====================*/
|
||||||
|
static int TASSetValue(void *pData, SConnection *pCon,
|
||||||
|
float value){
|
||||||
|
ptasMot self = (ptasMot)pData;
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
setTasPar(&self->math->target,self->math->tasMode,self->code,value);
|
||||||
|
self->math->mustDrive = 1;
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------*/
|
||||||
|
static int readTASMotAngles(ptasUB self, SConnection *pCon,
|
||||||
|
ptasAngles ang){
|
||||||
|
int status;
|
||||||
|
float val, theta;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Monochromator
|
||||||
|
*/
|
||||||
|
status = MotorGetSoftPosition(self->motors[A1],pCon,&val);
|
||||||
|
if(status == 0){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
theta = val;
|
||||||
|
status = MotorGetSoftPosition(self->motors[A2],pCon,&val);
|
||||||
|
if(status == 0){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
ang->monochromator_two_theta = val;
|
||||||
|
if(ABS(val/2. - theta) > .1){
|
||||||
|
SCWrite(pCon,"WARNING: theta monochromator not half of two theta",eWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Analyzer
|
||||||
|
*/
|
||||||
|
status = MotorGetSoftPosition(self->motors[A5],pCon,&val);
|
||||||
|
if(status == 0){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
theta = val;
|
||||||
|
status = MotorGetSoftPosition(self->motors[A6],pCon,&val);
|
||||||
|
if(status == 0){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
ang->analyzer_two_theta = val;
|
||||||
|
if(ABS(val/2. - theta) > .1){
|
||||||
|
SCWrite(pCon,"WARNING: theta analyzer not half of two theta",eWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
crystal
|
||||||
|
*/
|
||||||
|
status = MotorGetSoftPosition(self->motors[A3],pCon,&val);
|
||||||
|
if(status == 0){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
ang->a3 = val;
|
||||||
|
status = MotorGetSoftPosition(self->motors[A4],pCon,&val);
|
||||||
|
if(status == 0){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
ang->sample_two_theta = val;
|
||||||
|
status = MotorGetSoftPosition(self->motors[SGU],pCon,&val);
|
||||||
|
if(status == 0){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
ang->sgu = val;
|
||||||
|
status = MotorGetSoftPosition(self->motors[SGL],pCon,&val);
|
||||||
|
if(status == 0){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
ang->sgl = val;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------*/
|
||||||
|
static float TASGetValue(void *pData, SConnection *pCon){
|
||||||
|
ptasMot self = (ptasMot)pData;
|
||||||
|
int status;
|
||||||
|
tasAngles angles;
|
||||||
|
double val;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
if(self->math->mustRecalculate == 1) {
|
||||||
|
status = readTASMotAngles(self->math, pCon, &angles);
|
||||||
|
if(status != 1){
|
||||||
|
return -999.99;
|
||||||
|
}
|
||||||
|
status = calcTasQEPosition(&self->math->machine, angles, &self->math->current);
|
||||||
|
if(status < 0){
|
||||||
|
SCWrite(pCon,"ERROR: out of memory calculating Q-E variables",eError);
|
||||||
|
return -999.99;
|
||||||
|
}
|
||||||
|
self->math->mustRecalculate = 0;
|
||||||
|
}
|
||||||
|
val = getTasPar(self->math->current,self->code);
|
||||||
|
return (float)val;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------*/
|
||||||
|
static float TASQMGetValue(void *pData, SConnection *pCon){
|
||||||
|
ptasMot self = (ptasMot)pData;
|
||||||
|
int status;
|
||||||
|
tasAngles angles;
|
||||||
|
double val;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
if(self->math->mustRecalculate == 1) {
|
||||||
|
status = readTASMotAngles(self->math, pCon, &angles);
|
||||||
|
if(status != 1){
|
||||||
|
return -999.99;
|
||||||
|
}
|
||||||
|
status = calcTasPowderPosition(&self->math->machine, angles, &self->math->current);
|
||||||
|
if(status < 0){
|
||||||
|
SCWrite(pCon,"ERROR: out of memory calculating Q-E variables",eError);
|
||||||
|
return -999.99;
|
||||||
|
}
|
||||||
|
self->math->mustRecalculate = 0;
|
||||||
|
}
|
||||||
|
val = getTasPar(self->math->current,self->code);
|
||||||
|
return (float)val;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
static int TASCheckLimits(void *pData, float fVal, char *error, int iErrLen){
|
||||||
|
/*
|
||||||
|
There is no meaningful implementation here. This gets called when starting the motor.
|
||||||
|
At that stage not all other values may be known. If the calculation fails,
|
||||||
|
this will die at status check time.
|
||||||
|
*/
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
static int TASHalt(void *pData){
|
||||||
|
ptasMot self = (ptasMot)pData;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
for(i = 0; i < 12; i++){
|
||||||
|
if(self->math->motors[i] != NULL){
|
||||||
|
self->math->motors[i]->pDrivInt->Halt(self->math->motors[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int startMotors(ptasMot self, tasAngles angles,
|
||||||
|
SConnection *pCon){
|
||||||
|
float val;
|
||||||
|
double curve;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
/*
|
||||||
|
monochromator
|
||||||
|
*/
|
||||||
|
val = self->math->motors[A1]->pDrivInt->GetValue(self->math->motors[A1],pCon);
|
||||||
|
if(ABS(val - angles.monochromator_two_theta/2.) > MOTPREC){
|
||||||
|
status = self->math->motors[A1]->pDrivInt->SetValue(self->math->motors[A1],
|
||||||
|
pCon,
|
||||||
|
angles.monochromator_two_theta/2.);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = self->math->motors[A2]->pDrivInt->GetValue(self->math->motors[A2],pCon);
|
||||||
|
if(ABS(val - angles.monochromator_two_theta) > MOTPREC){
|
||||||
|
status = self->math->motors[A2]->pDrivInt->SetValue(self->math->motors[A2],
|
||||||
|
pCon,
|
||||||
|
angles.monochromator_two_theta);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(self->math->motors[MCV] != NULL){
|
||||||
|
curve = maCalcVerticalCurvature(self->math->machine.monochromator,
|
||||||
|
angles.monochromator_two_theta);
|
||||||
|
val = self->math->motors[MCV]->pDrivInt->GetValue(self->math->motors[MCV],pCon);
|
||||||
|
if(ABS(val - curve) > MOTPREC){
|
||||||
|
status = self->math->motors[MCV]->pDrivInt->SetValue(self->math->motors[MCV],
|
||||||
|
pCon,
|
||||||
|
curve);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(self->math->motors[MCH] != NULL){
|
||||||
|
curve = maCalcHorizontalCurvature(self->math->machine.monochromator,
|
||||||
|
angles.monochromator_two_theta);
|
||||||
|
val = self->math->motors[MCH]->pDrivInt->GetValue(self->math->motors[MCH],pCon);
|
||||||
|
if(ABS(val - curve) > MOTPREC){
|
||||||
|
status = self->math->motors[MCH]->pDrivInt->SetValue(self->math->motors[MCH],
|
||||||
|
pCon,
|
||||||
|
curve);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
analyzer
|
||||||
|
*/
|
||||||
|
val = self->math->motors[A5]->pDrivInt->GetValue(self->math->motors[A5],pCon);
|
||||||
|
if(ABS(val - angles.analyzer_two_theta/2.) > MOTPREC){
|
||||||
|
status = self->math->motors[A5]->pDrivInt->SetValue(self->math->motors[A5],
|
||||||
|
pCon,
|
||||||
|
angles.analyzer_two_theta/2.);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = self->math->motors[A6]->pDrivInt->GetValue(self->math->motors[A6],pCon);
|
||||||
|
if(ABS(val - angles.analyzer_two_theta) > MOTPREC){
|
||||||
|
status = self->math->motors[A6]->pDrivInt->SetValue(self->math->motors[A6],
|
||||||
|
pCon,
|
||||||
|
angles.analyzer_two_theta);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(self->math->motors[ACV] != NULL){
|
||||||
|
curve = maCalcVerticalCurvature(self->math->machine.analyzer,
|
||||||
|
angles.analyzer_two_theta);
|
||||||
|
val = self->math->motors[ACV]->pDrivInt->GetValue(self->math->motors[ACV],pCon);
|
||||||
|
if(ABS(val - curve) > MOTPREC){
|
||||||
|
status = self->math->motors[ACV]->pDrivInt->SetValue(self->math->motors[ACV],
|
||||||
|
pCon,
|
||||||
|
curve);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(self->math->motors[ACH] != NULL){
|
||||||
|
curve = maCalcHorizontalCurvature(self->math->machine.analyzer,
|
||||||
|
angles.analyzer_two_theta);
|
||||||
|
val = self->math->motors[ACH]->pDrivInt->GetValue(self->math->motors[ACH],pCon);
|
||||||
|
if(ABS(val - curve) > MOTPREC){
|
||||||
|
status = self->math->motors[ACH]->pDrivInt->SetValue(self->math->motors[ACH],
|
||||||
|
pCon,
|
||||||
|
curve);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
crystal
|
||||||
|
*/
|
||||||
|
val = self->math->motors[A3]->pDrivInt->GetValue(self->math->motors[A3],pCon);
|
||||||
|
if(ABS(val - angles.a3) > MOTPREC){
|
||||||
|
status = self->math->motors[A3]->pDrivInt->SetValue(self->math->motors[A3],
|
||||||
|
pCon,
|
||||||
|
angles.a3);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = self->math->motors[A4]->pDrivInt->GetValue(self->math->motors[A4],pCon);
|
||||||
|
if(ABS(val - angles.sample_two_theta) > MOTPREC){
|
||||||
|
status = self->math->motors[A4]->pDrivInt->SetValue(self->math->motors[A4],
|
||||||
|
pCon,
|
||||||
|
angles.sample_two_theta);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = self->math->motors[SGL]->pDrivInt->GetValue(self->math->motors[SGL],pCon);
|
||||||
|
if(ABS(val - angles.sgl) > MOTPREC){
|
||||||
|
status = self->math->motors[SGL]->pDrivInt->SetValue(self->math->motors[SGL],
|
||||||
|
pCon,
|
||||||
|
angles.sgl);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = self->math->motors[SGU]->pDrivInt->GetValue(self->math->motors[SGU],pCon);
|
||||||
|
if(ABS(val - angles.sgu) > MOTPREC){
|
||||||
|
status = self->math->motors[SGU]->pDrivInt->SetValue(self->math->motors[SGU],
|
||||||
|
pCon,
|
||||||
|
angles.sgu);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self->math->mustDrive = 0;
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
static int calculateAndDrive(ptasMot self, SConnection *pCon){
|
||||||
|
tasAngles angles;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = calcAllTasAngles(&self->math->machine, self->math->target,
|
||||||
|
&angles);
|
||||||
|
switch(status){
|
||||||
|
case ENERGYTOBIG:
|
||||||
|
SCWrite(pCon,"ERROR: desired energy to big",eError);
|
||||||
|
return HWFault;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UBNOMEMORY:
|
||||||
|
SCWrite(pCon,"ERROR: out of memory calculating angles",eError);
|
||||||
|
return HWFault;
|
||||||
|
break;
|
||||||
|
case BADRMATRIX:
|
||||||
|
SCWrite(pCon,"ERROR: bad crystallographic parameters or bad UB",eError);
|
||||||
|
return HWFault;
|
||||||
|
break;
|
||||||
|
case TRIANGLENOTCLOSED:
|
||||||
|
SCWrite(pCon,"ERROR: cannot close scattering triangle",eError);
|
||||||
|
return HWFault;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return startMotors(self,angles,pCon);
|
||||||
|
}
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
static int checkMotors(ptasMot self, SConnection *pCon){
|
||||||
|
int i, status;
|
||||||
|
|
||||||
|
self->math->mustRecalculate = 1;
|
||||||
|
for(i = 0; i < 12; i++){
|
||||||
|
if(self->math->motors[i] != NULL){
|
||||||
|
status = self->math->motors[i]->pDrivInt->CheckStatus(self->math->motors[i],pCon);
|
||||||
|
if(status != HWIdle && status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return HWIdle;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------------*/
|
||||||
|
static int TASGetStatus(void *pData, SConnection *pCon){
|
||||||
|
ptasMot self = (ptasMot)pData;
|
||||||
|
int status;
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
if(self->math->mustDrive == 1){
|
||||||
|
status = calculateAndDrive(self,pCon);
|
||||||
|
if(status != OKOK){
|
||||||
|
return HWFault;
|
||||||
|
} else {
|
||||||
|
return HWBusy;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return checkMotors(self, pCon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int startQMMotors(ptasMot self, tasAngles angles,
|
||||||
|
SConnection *pCon){
|
||||||
|
float val;
|
||||||
|
double curve;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
/*
|
||||||
|
monochromator
|
||||||
|
*/
|
||||||
|
val = self->math->motors[A1]->pDrivInt->GetValue(self->math->motors[A1],pCon);
|
||||||
|
if(ABS(val - angles.monochromator_two_theta/2.) > MOTPREC){
|
||||||
|
status = self->math->motors[A1]->pDrivInt->SetValue(self->math->motors[A1],
|
||||||
|
pCon,
|
||||||
|
angles.monochromator_two_theta/2.);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = self->math->motors[A2]->pDrivInt->GetValue(self->math->motors[A2],pCon);
|
||||||
|
if(ABS(val - angles.monochromator_two_theta) > MOTPREC){
|
||||||
|
status = self->math->motors[A2]->pDrivInt->SetValue(self->math->motors[A2],
|
||||||
|
pCon,
|
||||||
|
angles.monochromator_two_theta);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(self->math->motors[MCV] != NULL){
|
||||||
|
curve = maCalcVerticalCurvature(self->math->machine.monochromator,
|
||||||
|
angles.monochromator_two_theta);
|
||||||
|
val = self->math->motors[MCV]->pDrivInt->GetValue(self->math->motors[MCV],pCon);
|
||||||
|
if(ABS(val - curve) > MOTPREC){
|
||||||
|
status = self->math->motors[MCV]->pDrivInt->SetValue(self->math->motors[MCV],
|
||||||
|
pCon,
|
||||||
|
curve);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(self->math->motors[MCH] != NULL){
|
||||||
|
curve = maCalcHorizontalCurvature(self->math->machine.monochromator,
|
||||||
|
angles.monochromator_two_theta);
|
||||||
|
val = self->math->motors[MCH]->pDrivInt->GetValue(self->math->motors[MCH],pCon);
|
||||||
|
if(ABS(val - curve) > MOTPREC){
|
||||||
|
status = self->math->motors[MCH]->pDrivInt->SetValue(self->math->motors[MCH],
|
||||||
|
pCon,
|
||||||
|
curve);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
analyzer
|
||||||
|
*/
|
||||||
|
val = self->math->motors[A5]->pDrivInt->GetValue(self->math->motors[A5],pCon);
|
||||||
|
if(ABS(val - angles.analyzer_two_theta/2.) > MOTPREC){
|
||||||
|
status = self->math->motors[A5]->pDrivInt->SetValue(self->math->motors[A5],
|
||||||
|
pCon,
|
||||||
|
angles.analyzer_two_theta/2.);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = self->math->motors[A6]->pDrivInt->GetValue(self->math->motors[A6],pCon);
|
||||||
|
if(ABS(val - angles.analyzer_two_theta) > MOTPREC){
|
||||||
|
status = self->math->motors[A6]->pDrivInt->SetValue(self->math->motors[A6],
|
||||||
|
pCon,
|
||||||
|
angles.analyzer_two_theta);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(self->math->motors[ACV] != NULL){
|
||||||
|
curve = maCalcVerticalCurvature(self->math->machine.analyzer,
|
||||||
|
angles.analyzer_two_theta);
|
||||||
|
val = self->math->motors[ACV]->pDrivInt->GetValue(self->math->motors[ACV],pCon);
|
||||||
|
if(ABS(val - curve) > MOTPREC){
|
||||||
|
status = self->math->motors[ACV]->pDrivInt->SetValue(self->math->motors[ACV],
|
||||||
|
pCon,
|
||||||
|
curve);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(self->math->motors[ACH] != NULL){
|
||||||
|
curve = maCalcHorizontalCurvature(self->math->machine.analyzer,
|
||||||
|
angles.analyzer_two_theta);
|
||||||
|
val = self->math->motors[ACH]->pDrivInt->GetValue(self->math->motors[ACH],pCon);
|
||||||
|
if(ABS(val - curve) > MOTPREC){
|
||||||
|
status = self->math->motors[ACH]->pDrivInt->SetValue(self->math->motors[ACH],
|
||||||
|
pCon,
|
||||||
|
curve);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
crystal
|
||||||
|
*/
|
||||||
|
val = self->math->motors[A4]->pDrivInt->GetValue(self->math->motors[A4],pCon);
|
||||||
|
if(ABS(val - angles.sample_two_theta) > MOTPREC){
|
||||||
|
status = self->math->motors[A4]->pDrivInt->SetValue(self->math->motors[A4],
|
||||||
|
pCon,
|
||||||
|
angles.sample_two_theta);
|
||||||
|
if(status != OKOK){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self->math->mustDrive = 0;
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
static int calculateQMAndDrive(ptasMot self, SConnection *pCon){
|
||||||
|
tasAngles angles;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = calcTasPowderAngles(&self->math->machine, self->math->target,
|
||||||
|
&angles);
|
||||||
|
switch(status){
|
||||||
|
case ENERGYTOBIG:
|
||||||
|
SCWrite(pCon,"ERROR: desired energy to big",eError);
|
||||||
|
return HWFault;
|
||||||
|
break;
|
||||||
|
case TRIANGLENOTCLOSED:
|
||||||
|
SCWrite(pCon,"ERROR: cannot close scattering triangle",eError);
|
||||||
|
return HWFault;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return startQMMotors(self,angles,pCon);
|
||||||
|
}
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------------*/
|
||||||
|
static int TASQMGetStatus(void *pData, SConnection *pCon){
|
||||||
|
ptasMot self = (ptasMot)pData;
|
||||||
|
int status;
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
if(self->math->mustDrive == 1){
|
||||||
|
status = calculateQMAndDrive(self,pCon);
|
||||||
|
if(status != OKOK){
|
||||||
|
return HWFault;
|
||||||
|
} else {
|
||||||
|
return HWBusy;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return checkMotors(self, pCon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*================== Life and Death =========================================*/
|
||||||
|
static void KillTasMot(void *pData){
|
||||||
|
ptasMot self = (ptasMot)pData;
|
||||||
|
if(self == NULL){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(self->pDes != NULL){
|
||||||
|
DeleteDescriptor(self->pDes);
|
||||||
|
self->pDes == NULL;
|
||||||
|
}
|
||||||
|
if(self->pDriv != NULL){
|
||||||
|
free(self->pDriv);
|
||||||
|
self->pDriv = NULL;
|
||||||
|
}
|
||||||
|
free(self);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void *GetTasInterface(void *pData, int interfaceID){
|
||||||
|
ptasMot self = (ptasMot)pData;
|
||||||
|
|
||||||
|
if(self != NULL && interfaceID == DRIVEID){
|
||||||
|
return self->pDriv;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
int InstallTasMotor(SicsInterp *pSics, ptasUB self, int tasVar, char *name){
|
||||||
|
ptasMot pNew = NULL;
|
||||||
|
|
||||||
|
pNew = (ptasMot)malloc(sizeof(tasMot));
|
||||||
|
if(!pNew){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memset(pNew,0,sizeof(tasMot));
|
||||||
|
pNew->pDes = CreateDescriptor("TasMot");
|
||||||
|
pNew->pDriv = CreateDrivableInterface();
|
||||||
|
if(!pNew->pDes || !pNew->pDriv) {
|
||||||
|
free(pNew);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pNew->pDes->GetInterface = GetTasInterface;
|
||||||
|
pNew->pDriv->Halt = TASHalt;
|
||||||
|
pNew->pDriv->CheckLimits = TASCheckLimits;
|
||||||
|
pNew->pDriv->SetValue = TASSetValue;
|
||||||
|
pNew->pDriv->CheckStatus = TASGetStatus;
|
||||||
|
pNew->pDriv->GetValue = TASGetValue;
|
||||||
|
pNew->math = self;
|
||||||
|
pNew->code = tasVar;
|
||||||
|
|
||||||
|
return AddCommand(pSics,name, TasMot, KillTasMot,pNew);
|
||||||
|
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
int InstallTasQMMotor(SicsInterp *pSics, ptasUB self){
|
||||||
|
ptasMot pNew = NULL;
|
||||||
|
|
||||||
|
pNew = (ptasMot)malloc(sizeof(tasMot));
|
||||||
|
if(!pNew){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memset(pNew,0,sizeof(tasMot));
|
||||||
|
pNew->pDes = CreateDescriptor("TasMot");
|
||||||
|
pNew->pDriv = CreateDrivableInterface();
|
||||||
|
if(!pNew->pDes || !pNew->pDriv) {
|
||||||
|
free(pNew);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pNew->pDes->GetInterface = GetTasInterface;
|
||||||
|
pNew->pDriv->Halt = TASHalt;
|
||||||
|
pNew->pDriv->CheckLimits = TASCheckLimits;
|
||||||
|
pNew->pDriv->SetValue = TASSetValue;
|
||||||
|
pNew->pDriv->CheckStatus = TASQMGetStatus;
|
||||||
|
pNew->pDriv->GetValue = TASQMGetValue;
|
||||||
|
pNew->math = self;
|
||||||
|
pNew->code = QM;
|
||||||
|
|
||||||
|
return AddCommand(pSics,"qm", TasMot, KillTasMot,pNew);
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
int TasMot(SConnection *pCon,SicsInterp *pSics, void *pData,
|
||||||
|
int argc, char *argv[]){
|
||||||
|
ptasMot self = (ptasMot)pData;
|
||||||
|
float value;
|
||||||
|
char pBueffel[132];
|
||||||
|
|
||||||
|
if(argc > 1){
|
||||||
|
strtolower(argv[1]);
|
||||||
|
if(strcmp(argv[1],"target") == 0){
|
||||||
|
snprintf(pBueffel,131,"%s.target = %f",
|
||||||
|
argv[0], getTasPar(self->math->target,self->code));
|
||||||
|
SCWrite(pCon,pBueffel,eValue);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
SCWrite(pCon,"ERROR: tasmot does not understand this subcommand",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
value = self->pDriv->GetValue(self,pCon);
|
||||||
|
snprintf(pBueffel,131,"%s = %f", argv[0], value);
|
||||||
|
SCWrite(pCon,pBueffel,eValue);
|
||||||
|
return 1;
|
||||||
|
}
|
17
tasdrive.h
Normal file
17
tasdrive.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
/*---------------------------------------------------------------------
|
||||||
|
SICS interface to the triple axis drivable motors.
|
||||||
|
|
||||||
|
copyright: see file COPYRIGHT
|
||||||
|
|
||||||
|
Mark Koennecke, May 2005
|
||||||
|
--------------------------------------------------------------------*/
|
||||||
|
#ifndef TASDRIV
|
||||||
|
#define TASDRIV
|
||||||
|
#include "tasub.h"
|
||||||
|
|
||||||
|
int InstallTasMotor(SicsInterp *pSics, ptasUB self, int tasVar, char *name);
|
||||||
|
int InstallTasQMMotor(SicsInterp *pSics, ptasUB self);
|
||||||
|
int TasMot(SConnection *pCon,SicsInterp *pSics, void *pData,
|
||||||
|
int argc, char *argv[]);
|
||||||
|
#endif
|
416
tasub.c
416
tasub.c
@ -10,6 +10,7 @@
|
|||||||
#include "sics.h"
|
#include "sics.h"
|
||||||
#include "lld.h"
|
#include "lld.h"
|
||||||
#include "tasub.h"
|
#include "tasub.h"
|
||||||
|
#include "tasdrive.h"
|
||||||
/*------------------- motor indexes in motor data structure ---------*/
|
/*------------------- motor indexes in motor data structure ---------*/
|
||||||
#define A1 0
|
#define A1 0
|
||||||
#define A2 1
|
#define A2 1
|
||||||
@ -43,8 +44,9 @@ static void saveReflections(ptasUB self, char *name, FILE *fd){
|
|||||||
while(status == 1){
|
while(status == 1){
|
||||||
LLDnodeDataTo(self->reflectionList,&r);
|
LLDnodeDataTo(self->reflectionList,&r);
|
||||||
fprintf(fd,"%s addref %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n",
|
fprintf(fd,"%s addref %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n",
|
||||||
name, r.h, r.k, r.l, r.a3, r.two_theta, r.sgu, r.sgl,
|
name, r.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3, r.angles.sample_two_theta,
|
||||||
KtoEnergy(r.ki), KtoEnergy(r.kf));
|
r.angles.sgu, r.angles.sgl,
|
||||||
|
KtoEnergy(r.qe.ki), KtoEnergy(r.qe.kf));
|
||||||
status = LLDnodePtr2Next(self->reflectionList);
|
status = LLDnodePtr2Next(self->reflectionList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,6 +70,20 @@ static int tasUBSave(void *pData, char *name, FILE *fd){
|
|||||||
fprintf(fd,"%s const kf\n",name);
|
fprintf(fd,"%s const kf\n",name);
|
||||||
}
|
}
|
||||||
fprintf(fd,"%s ss %d\n", name,self->machine.ss_sample);
|
fprintf(fd,"%s ss %d\n", name,self->machine.ss_sample);
|
||||||
|
fprintf(fd," %s setub %f %f %f %f %f %f %f %f %f\n",
|
||||||
|
name,
|
||||||
|
self->machine.UB[0][0], self->machine.UB[0][1], self->machine.UB[0][2],
|
||||||
|
self->machine.UB[1][0], self->machine.UB[1][1], self->machine.UB[1][2],
|
||||||
|
self->machine.UB[2][0], self->machine.UB[2][1], self->machine.UB[2][2]);
|
||||||
|
fprintf(fd," %s setnormal %f %f %f\n",
|
||||||
|
name,
|
||||||
|
self->machine.planeNormal[0][0], self->machine.planeNormal[1][0],
|
||||||
|
self->machine.planeNormal[2][0]);
|
||||||
|
fprintf(fd,"%s settarget %f %f %f %f %f %f\n",
|
||||||
|
name,
|
||||||
|
self->target.qh, self->target.qk, self->target.ql, self->target.qm,
|
||||||
|
self->target.ki, self->target.kf);
|
||||||
|
fprintf(fd,"%s update\n", name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*------------------------------------------------------------------*/
|
/*------------------------------------------------------------------*/
|
||||||
@ -139,58 +155,20 @@ static int readTASAngles(ptasUB self, SConnection *pCon,
|
|||||||
/*
|
/*
|
||||||
Monochromator
|
Monochromator
|
||||||
*/
|
*/
|
||||||
status = MotorGetSoftPosition(self->motors[A1],pCon,&val);
|
|
||||||
if(status == 0){
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
ang->monochromator.theta = val;
|
|
||||||
status = MotorGetSoftPosition(self->motors[A2],pCon,&val);
|
status = MotorGetSoftPosition(self->motors[A2],pCon,&val);
|
||||||
if(status == 0){
|
if(status == 0){
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
ang->monochromator.two_theta = val;
|
ang->monochromator_two_theta = val;
|
||||||
if(self->motors[MCV] != NULL){
|
|
||||||
status = MotorGetSoftPosition(self->motors[MCV],pCon,&val);
|
|
||||||
if(status == 0){
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
ang->monochromator.vertical_curvature = val;
|
|
||||||
}
|
|
||||||
if(self->motors[MCH] != NULL){
|
|
||||||
status = MotorGetSoftPosition(self->motors[MCH],pCon,&val);
|
|
||||||
if(status == 0){
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
ang->monochromator.horizontal_curvature = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Analyzer
|
Analyzer
|
||||||
*/
|
*/
|
||||||
status = MotorGetSoftPosition(self->motors[A5],pCon,&val);
|
|
||||||
if(status == 0){
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
ang->analyzer.theta = val;
|
|
||||||
status = MotorGetSoftPosition(self->motors[A6],pCon,&val);
|
status = MotorGetSoftPosition(self->motors[A6],pCon,&val);
|
||||||
if(status == 0){
|
if(status == 0){
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
ang->analyzer.two_theta = val;
|
ang->analyzer_two_theta = val;
|
||||||
if(self->motors[ACV] != NULL){
|
|
||||||
status = MotorGetSoftPosition(self->motors[ACV],pCon,&val);
|
|
||||||
if(status == 0){
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
ang->analyzer.vertical_curvature = val;
|
|
||||||
}
|
|
||||||
if(self->motors[ACH] != NULL){
|
|
||||||
status = MotorGetSoftPosition(self->motors[ACH],pCon,&val);
|
|
||||||
if(status == 0){
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
ang->analyzer.horizontal_curvature = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
crystal
|
crystal
|
||||||
@ -233,7 +211,12 @@ static int testMotor(ptasUB pNew, SConnection *pCon, char *name, int idx){
|
|||||||
int TasUBFactory(SConnection *pCon,SicsInterp *pSics, void *pData,
|
int TasUBFactory(SConnection *pCon,SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[]){
|
int argc, char *argv[]){
|
||||||
ptasUB pNew = NULL;
|
ptasUB pNew = NULL;
|
||||||
int status = 0;
|
int status = 0, i;
|
||||||
|
char pBueffel[132];
|
||||||
|
char names[][3] = {"ei","ki",
|
||||||
|
"qh","qk","ql",
|
||||||
|
"ef","kf",
|
||||||
|
"en"};
|
||||||
|
|
||||||
if(argc < 2) {
|
if(argc < 2) {
|
||||||
SCWrite(pCon,"ERROR: need name to install tasUB",eError);
|
SCWrite(pCon,"ERROR: need name to install tasUB",eError);
|
||||||
@ -284,9 +267,23 @@ int TasUBFactory(SConnection *pCon,SicsInterp *pSics, void *pData,
|
|||||||
SCWrite(pCon,"ERROR: duplicate tasUB command not created",eError);
|
SCWrite(pCon,"ERROR: duplicate tasUB command not created",eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: install all the virtual motors
|
install virtual motors
|
||||||
*/
|
*/
|
||||||
|
for(i = 0; i < 8; i++){
|
||||||
|
status = InstallTasMotor(pSics,pNew,i+1,names[i]);
|
||||||
|
if(status != 1){
|
||||||
|
snprintf(pBueffel,131,"ERROR: failed to create TAS motor %s", names[i]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
status = InstallTasQMMotor(pSics,pNew);
|
||||||
|
if(status != 1){
|
||||||
|
snprintf(pBueffel,131,"ERROR: failed to create TAS motor qm");
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------------*/
|
/*-----------------------------------------------------------------*/
|
||||||
@ -304,6 +301,10 @@ static int setCrystalParameters(pmaCrystal crystal, SConnection *pCon,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!SCMatchRights(pCon,usMugger)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
strtolower(argv[2]);
|
strtolower(argv[2]);
|
||||||
if(strcmp(argv[2],"dd") == 0){
|
if(strcmp(argv[2],"dd") == 0){
|
||||||
crystal->dd = d;
|
crystal->dd = d;
|
||||||
@ -411,6 +412,11 @@ static int tasReadCell(SConnection *pCon, ptasUB self, int argc, char *argv[]){
|
|||||||
eError);
|
eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!SCMatchRights(pCon,usUser)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
status = Tcl_GetDouble(pTcl,argv[2],&self->cell.a);
|
status = Tcl_GetDouble(pTcl,argv[2],&self->cell.a);
|
||||||
if(status != TCL_OK){
|
if(status != TCL_OK){
|
||||||
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]);
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]);
|
||||||
@ -487,7 +493,8 @@ static void listReflections(ptasUB self, SConnection *pCon){
|
|||||||
count++;
|
count++;
|
||||||
LLDnodeDataTo(self->reflectionList,&r);
|
LLDnodeDataTo(self->reflectionList,&r);
|
||||||
snprintf(line,255,"%3d %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
|
snprintf(line,255,"%3d %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
|
||||||
count, r.h, r.k, r.l, r.a3, r.two_theta, r.sgu, r.sgl, r.ki, r.kf);
|
count, r.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3, r.angles.sample_two_theta,
|
||||||
|
r.angles.sgu, r.angles.sgl, r.qe.ki, r.qe.kf);
|
||||||
Tcl_DStringAppend(&list,line,-1);
|
Tcl_DStringAppend(&list,line,-1);
|
||||||
status = LLDnodePtr2Next(self->reflectionList);
|
status = LLDnodePtr2Next(self->reflectionList);
|
||||||
}
|
}
|
||||||
@ -513,19 +520,24 @@ static int addReflection(ptasUB self, SicsInterp *pSics,
|
|||||||
eError);
|
eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[2],&r.h);
|
|
||||||
|
if(!SCMatchRights(pCon,usUser)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[2],&r.qe.qh);
|
||||||
if(status != TCL_OK){
|
if(status != TCL_OK){
|
||||||
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]);
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]);
|
||||||
SCWrite(pCon,pBueffel,eError);
|
SCWrite(pCon,pBueffel,eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&r.k);
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&r.qe.qk);
|
||||||
if(status != TCL_OK){
|
if(status != TCL_OK){
|
||||||
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]);
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]);
|
||||||
SCWrite(pCon,pBueffel,eError);
|
SCWrite(pCon,pBueffel,eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&r.l);
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&r.qe.ql);
|
||||||
if(status != TCL_OK){
|
if(status != TCL_OK){
|
||||||
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[4]);
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[4]);
|
||||||
SCWrite(pCon,pBueffel,eError);
|
SCWrite(pCon,pBueffel,eError);
|
||||||
@ -533,66 +545,56 @@ static int addReflection(ptasUB self, SicsInterp *pSics,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(argc >= 11){
|
if(argc >= 11){
|
||||||
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[5],&r.a3);
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[5],&r.angles.a3);
|
||||||
if(status != TCL_OK){
|
if(status != TCL_OK){
|
||||||
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[5]);
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[5]);
|
||||||
SCWrite(pCon,pBueffel,eError);
|
SCWrite(pCon,pBueffel,eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[5],&r.a3);
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[6],&r.angles.sample_two_theta);
|
||||||
if(status != TCL_OK){
|
|
||||||
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[5]);
|
|
||||||
SCWrite(pCon,pBueffel,eError);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[6],&r.two_theta);
|
|
||||||
if(status != TCL_OK){
|
if(status != TCL_OK){
|
||||||
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[6]);
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[6]);
|
||||||
SCWrite(pCon,pBueffel,eError);
|
SCWrite(pCon,pBueffel,eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[7],&r.sgu);
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[7],&r.angles.sgu);
|
||||||
if(status != TCL_OK){
|
if(status != TCL_OK){
|
||||||
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[7]);
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[7]);
|
||||||
SCWrite(pCon,pBueffel,eError);
|
SCWrite(pCon,pBueffel,eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[8],&r.sgl);
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[8],&r.angles.sgl);
|
||||||
if(status != TCL_OK){
|
if(status != TCL_OK){
|
||||||
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[8]);
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[8]);
|
||||||
SCWrite(pCon,pBueffel,eError);
|
SCWrite(pCon,pBueffel,eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[9],&r.ki);
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[9],&r.qe.ki);
|
||||||
if(status != TCL_OK){
|
if(status != TCL_OK){
|
||||||
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[9]);
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[9]);
|
||||||
SCWrite(pCon,pBueffel,eError);
|
SCWrite(pCon,pBueffel,eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
r.ki = energyToK(r.ki);
|
r.qe.ki = energyToK(r.qe.ki);
|
||||||
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[10],&r.kf);
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[10],&r.qe.kf);
|
||||||
if(status != TCL_OK){
|
if(status != TCL_OK){
|
||||||
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[10]);
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[10]);
|
||||||
SCWrite(pCon,pBueffel,eError);
|
SCWrite(pCon,pBueffel,eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
r.kf = energyToK(r.kf);
|
r.qe.kf = energyToK(r.qe.kf);
|
||||||
} else {
|
} else {
|
||||||
if(argc > 5){
|
if(argc > 5){
|
||||||
SCWrite(pCon,
|
SCWrite(pCon,
|
||||||
"WARNING: not all angles given on command line, using positions instead",
|
"WARNING: not all angles given on command line, using positions instead",
|
||||||
eWarning);
|
eWarning);
|
||||||
}
|
}
|
||||||
status = readTASAngles(self,pCon,&angles);
|
status = readTASAngles(self,pCon,&r.angles);
|
||||||
if(status != 1){
|
if(status != 1){
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
r.a3 = angles.a3;
|
r.qe.ki = maCalcK(self->machine.monochromator,angles.monochromator_two_theta);
|
||||||
r.two_theta = angles.sample_two_theta;
|
r.qe.kf = maCalcK(self->machine.analyzer,angles.analyzer_two_theta);
|
||||||
r.sgu = angles.sgu;
|
|
||||||
r.sgl = angles.sgl;
|
|
||||||
maCalcK(self->machine.monochromator,angles.monochromator,&r.ki);
|
|
||||||
maCalcK(self->machine.analyzer,angles.analyzer,&r.kf);
|
|
||||||
}
|
}
|
||||||
LLDnodeAppend(self->reflectionList,&r);
|
LLDnodeAppend(self->reflectionList,&r);
|
||||||
Tcl_DStringInit(&list);
|
Tcl_DStringInit(&list);
|
||||||
@ -601,10 +603,12 @@ static int addReflection(ptasUB self, SicsInterp *pSics,
|
|||||||
Tcl_DStringAppend(&list,pBueffel,-1);
|
Tcl_DStringAppend(&list,pBueffel,-1);
|
||||||
snprintf(pBueffel,255,
|
snprintf(pBueffel,255,
|
||||||
" %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
|
" %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
|
||||||
r.h, r.k, r.l, r.a3, r.two_theta, r.sgu, r.sgl, r.ki, r.kf);
|
r.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3, r.angles.sample_two_theta,
|
||||||
|
r.angles.sgu, r.angles.sgl, r.qe.ki, r.qe.kf);
|
||||||
Tcl_DStringAppend(&list,pBueffel,-1);
|
Tcl_DStringAppend(&list,pBueffel,-1);
|
||||||
SCWrite(pCon,Tcl_DStringValue(&list),eValue);
|
SCWrite(pCon,Tcl_DStringValue(&list),eValue);
|
||||||
Tcl_DStringFree(&list);
|
Tcl_DStringFree(&list);
|
||||||
|
SCparChange(pCon);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------------*/
|
/*-----------------------------------------------------------------*/
|
||||||
@ -662,28 +666,30 @@ static void printReflectionDiagnostik(ptasUB self, SConnection *pCon,
|
|||||||
Tcl_DStringAppend(&list,line,-1);
|
Tcl_DStringAppend(&list,line,-1);
|
||||||
snprintf(line,255,
|
snprintf(line,255,
|
||||||
"INPUT %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
|
"INPUT %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
|
||||||
r.h, r.k, r.l, r.a3, r.two_theta, r.sgu, r.sgl, r.ki, r.kf);
|
r.qe.qh, r.qe.qk, r.qe.ql, r.angles.a3,
|
||||||
|
r.angles.sample_two_theta, r.angles.sgu, r.angles.sgl, r.qe.ki, r.qe.kf);
|
||||||
Tcl_DStringAppend(&list,line,-1);
|
Tcl_DStringAppend(&list,line,-1);
|
||||||
qe.ki = r.ki;
|
qe.ki = r.qe.ki;
|
||||||
qe.kf = r.kf;
|
qe.kf = r.qe.kf;
|
||||||
qe.qk = r.h;
|
qe.qh = r.qe.qh;
|
||||||
qe.qk = r.k;
|
qe.qk = r.qe.qk;
|
||||||
qe.ql = r.l;
|
qe.ql = r.qe.ql;
|
||||||
calcAllTasAngles(&self->machine,qe,&angles);
|
calcAllTasAngles(&self->machine,qe,&angles);
|
||||||
snprintf(line,255,
|
snprintf(line,255,
|
||||||
"QE->ANG %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
|
"QE->ANG %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
|
||||||
r.h, r.k, r.l, angles.a3, angles.sample_two_theta,
|
r.qe.qh, r.qe.qk, r.qe.ql,
|
||||||
angles.sgu, angles.sgl, r.ki, r.kf);
|
angles.a3, angles.sample_two_theta,
|
||||||
|
angles.sgu, angles.sgl, r.qe.ki, r.qe.kf);
|
||||||
Tcl_DStringAppend(&list,line,-1);
|
Tcl_DStringAppend(&list,line,-1);
|
||||||
angles.a3 = r.a3;
|
angles.a3 = r.angles.a3;
|
||||||
angles.sample_two_theta = r.two_theta;
|
angles.sample_two_theta = r.angles.sample_two_theta;
|
||||||
angles.sgu = r.sgu;
|
angles.sgu = r.angles.sgu;
|
||||||
angles.sgl = r.sgl;
|
angles.sgl = r.angles.sgl;
|
||||||
calcTasQEPosition(&self->machine,angles,&qe);
|
calcTasQEPosition(&self->machine,angles,&qe);
|
||||||
snprintf(line,255,
|
snprintf(line,255,
|
||||||
"ANG->QE %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
|
"ANG->QE %6.2f %6.2f %6.2f %7.2f %7.2f %6.2f %6.2f %6.2f %6.2f\n",
|
||||||
qe.qh, qe.qk, qe.ql, r.a3, r.two_theta,
|
qe.qh, qe.qk, qe.ql, angles.a3, angles.sample_two_theta,
|
||||||
r.sgu, r.sgl, qe.ki, qe.kf);
|
angles.sgu, angles.sgl, qe.ki, qe.kf);
|
||||||
Tcl_DStringAppend(&list,line,-1);
|
Tcl_DStringAppend(&list,line,-1);
|
||||||
SCWrite(pCon,Tcl_DStringValue(&list),eValue);
|
SCWrite(pCon,Tcl_DStringValue(&list),eValue);
|
||||||
Tcl_DStringFree(&list);
|
Tcl_DStringFree(&list);
|
||||||
@ -714,6 +720,11 @@ static int calcUB(ptasUB self, SConnection *pCon, SicsInterp *pSics,
|
|||||||
eError);
|
eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!SCMatchRights(pCon,usUser)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
status = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&idx);
|
status = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&idx);
|
||||||
if(status != TCL_OK){
|
if(status != TCL_OK){
|
||||||
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]);
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]);
|
||||||
@ -761,6 +772,7 @@ static int calcUB(ptasUB self, SConnection *pCon, SicsInterp *pSics,
|
|||||||
self->machine.planeNormal = calcPlaneNormal(r1,r2);
|
self->machine.planeNormal = calcPlaneNormal(r1,r2);
|
||||||
listUB(UB,pCon);
|
listUB(UB,pCon);
|
||||||
listDiagnostik(self,pCon);
|
listDiagnostik(self,pCon);
|
||||||
|
SCparChange(pCon);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*------------------------------------------------------------------*/
|
/*------------------------------------------------------------------*/
|
||||||
@ -820,19 +832,240 @@ static int calcRefAngles(ptasUB self, SConnection *pCon,
|
|||||||
SCWrite(pCon,"ERROR: Out of memory calculating angles",eError);
|
SCWrite(pCon,"ERROR: Out of memory calculating angles",eError);
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
|
case BADRMATRIX:
|
||||||
|
SCWrite(pCon,"ERROR: bad crystallographic parameters or bad UB",eError);
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
case TRIANGLENOTCLOSED:
|
case TRIANGLENOTCLOSED:
|
||||||
SCWrite(pCon,"ERROR: scattering triangle not closed",eError);
|
SCWrite(pCon,"ERROR: scattering triangle not closed",eError);
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
snprintf(pBueffel,255," %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f",
|
snprintf(pBueffel,255," %8.2f %8.2f %8.2f %8.2f %8.2f %8.2f",
|
||||||
angles.monochromator.theta, angles.monochromator.two_theta,
|
angles.monochromator_two_theta,
|
||||||
angles.a3, angles.sample_two_theta,
|
angles.a3, angles.sample_two_theta,
|
||||||
angles.sgl, angles.sgu,
|
angles.sgl, angles.sgu,
|
||||||
angles.analyzer.theta,angles.analyzer.two_theta);
|
angles.analyzer_two_theta);
|
||||||
SCWrite(pCon,pBueffel,eValue);
|
SCWrite(pCon,pBueffel,eValue);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
static int setUB(SConnection *pCon, SicsInterp *pSics, ptasUB self,
|
||||||
|
int argc, char *argv[]){
|
||||||
|
double value;
|
||||||
|
char pBueffel[256];
|
||||||
|
int status;
|
||||||
|
|
||||||
|
if(argc < 11){
|
||||||
|
SCWrite(pCon,"ERROR: not enough arguments for setting UB",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!SCMatchRights(pCon,usUser)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[2],&value);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->machine.UB[0][0] = value;
|
||||||
|
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&value);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->machine.UB[0][1] = value;
|
||||||
|
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&value);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[4]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->machine.UB[0][2] = value;
|
||||||
|
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[5],&value);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[5]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->machine.UB[1][0] = value;
|
||||||
|
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[6],&value);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[6]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->machine.UB[1][1] = value;
|
||||||
|
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[7],&value);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[7]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->machine.UB[1][2] = value;
|
||||||
|
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[8],&value);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[8]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->machine.UB[2][0] = value;
|
||||||
|
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[9],&value);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[9]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->machine.UB[2][1] = value;
|
||||||
|
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[10],&value);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[10]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->machine.UB[2][2] = value;
|
||||||
|
SCSendOK(pCon);
|
||||||
|
SCparChange(pCon);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
static int setNormal(SConnection *pCon, SicsInterp *pSics, ptasUB self,
|
||||||
|
int argc, char *argv[]){
|
||||||
|
double value;
|
||||||
|
char pBueffel[256];
|
||||||
|
int status;
|
||||||
|
|
||||||
|
if(argc < 5){
|
||||||
|
SCWrite(pCon,"ERROR: not enough arguments for setting plane normal",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!SCMatchRights(pCon,usUser)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[2],&value);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->machine.planeNormal[0][0] = value;
|
||||||
|
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&value);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->machine.planeNormal[1][0] = value;
|
||||||
|
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&value);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[4]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->machine.planeNormal[2][0] = value;
|
||||||
|
SCSendOK(pCon);
|
||||||
|
SCparChange(pCon);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
static int setTarget(SConnection *pCon, SicsInterp *pSics, ptasUB self,
|
||||||
|
int argc, char *argv[]){
|
||||||
|
double value;
|
||||||
|
char pBueffel[256];
|
||||||
|
int status;
|
||||||
|
|
||||||
|
if(argc < 8){
|
||||||
|
SCWrite(pCon,"ERROR: not enough arguments for setting qe target",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!SCMatchRights(pCon,usUser)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[2],&self->target.qh);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&self->target.qk);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&self->target.ql);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[4]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[5],&self->target.qm);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[5]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[6],&self->target.ki);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[6]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[7],&self->target.kf);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[7]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCSendOK(pCon);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
static int tasUpdate(SConnection *pCon, ptasUB self){
|
||||||
|
int status;
|
||||||
|
tasAngles angles;
|
||||||
|
|
||||||
|
status = readTASAngles(self,pCon,&angles);
|
||||||
|
if(status != 1){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
status = calcTasQEPosition(&self->machine, angles, &self->current);
|
||||||
|
if(status < 0){
|
||||||
|
SCWrite(pCon,"ERROR: out of memory calculating Q-E variables",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->mustRecalculate = 0;
|
||||||
|
SCSendOK(pCon);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
/*-------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------*/
|
||||||
int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
|
int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[]){
|
int argc, char *argv[]){
|
||||||
@ -877,6 +1110,14 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
|
|||||||
return calcUB(self,pCon,pSics,argc,argv);
|
return calcUB(self,pCon,pSics,argc,argv);
|
||||||
} else if(strcmp(argv[1],"calcref") == 0){
|
} else if(strcmp(argv[1],"calcref") == 0){
|
||||||
return calcRefAngles(self,pCon,pSics,argc,argv);
|
return calcRefAngles(self,pCon,pSics,argc,argv);
|
||||||
|
} else if(strcmp(argv[1],"setub") == 0){
|
||||||
|
return setUB(pCon,pSics,self,argc,argv);
|
||||||
|
} else if(strcmp(argv[1],"setnormal") == 0){
|
||||||
|
return setNormal(pCon,pSics,self,argc,argv);
|
||||||
|
} else if(strcmp(argv[1],"settarget") == 0){
|
||||||
|
return setTarget(pCon,pSics,self,argc,argv);
|
||||||
|
} else if(strcmp(argv[1],"update") == 0){
|
||||||
|
return tasUpdate(pCon,self);
|
||||||
} else if(strcmp(argv[1],"const") == 0){
|
} else if(strcmp(argv[1],"const") == 0){
|
||||||
if(argc > 2){
|
if(argc > 2){
|
||||||
strtolower(argv[2]);
|
strtolower(argv[2]);
|
||||||
@ -919,6 +1160,7 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
self->machine.ss_sample = newSS;
|
self->machine.ss_sample = newSS;
|
||||||
|
tasUpdate(pCon,self);
|
||||||
SCSendOK(pCon);
|
SCSendOK(pCon);
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
|
15
tasub.h
15
tasub.h
@ -15,9 +15,6 @@
|
|||||||
#include "motor.h"
|
#include "motor.h"
|
||||||
|
|
||||||
/*------------------- defines for tasMode -----------------------------------*/
|
/*------------------- defines for tasMode -----------------------------------*/
|
||||||
#define KICONST 1
|
|
||||||
#define KFCONST 2
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
pObjectDescriptor pDes;
|
pObjectDescriptor pDes;
|
||||||
tasMachine machine;
|
tasMachine machine;
|
||||||
@ -33,16 +30,6 @@
|
|||||||
}tasUB, *ptasUB;
|
}tasUB, *ptasUB;
|
||||||
|
|
||||||
|
|
||||||
/*----------------------- defines for virtual motors -----------------------------*/
|
|
||||||
#define EI 1
|
|
||||||
#define KI 2
|
|
||||||
#define QH 3
|
|
||||||
#define QK 4
|
|
||||||
#define QL 5
|
|
||||||
#define EF 6
|
|
||||||
#define KF 7
|
|
||||||
#define EN 8
|
|
||||||
#define QM 9
|
|
||||||
/*--------------------- the tas virtual motor data structure ---------------------*/
|
/*--------------------- the tas virtual motor data structure ---------------------*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
pObjectDescriptor pDes;
|
pObjectDescriptor pDes;
|
||||||
@ -57,8 +44,6 @@ int TasUBFactory(SConnection *pCon,SicsInterp *pSics, void *pData,
|
|||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
|
int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
int TasMot(SConnection *pCon,SicsInterp *pSics, void *pData,
|
|
||||||
int argc, char *argv[]);
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
33
tasub.w
33
tasub.w
@ -17,9 +17,6 @@ This module handles the calculations typical for a triple axis spectrometer.
|
|||||||
A data structure:
|
A data structure:
|
||||||
@d tasubdat @{
|
@d tasubdat @{
|
||||||
/*------------------- defines for tasMode -----------------------------------*/
|
/*------------------- defines for tasMode -----------------------------------*/
|
||||||
#define KICONST 1
|
|
||||||
#define KFCONST 2
|
|
||||||
/*-----------------------------------------------------------------------------*/
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
pObjectDescriptor pDes;
|
pObjectDescriptor pDes;
|
||||||
tasMachine machine;
|
tasMachine machine;
|
||||||
@ -56,16 +53,6 @@ A data structure:
|
|||||||
|
|
||||||
For the virtual motors, there must be a data structure, too:
|
For the virtual motors, there must be a data structure, too:
|
||||||
@d tasubmotdat @{
|
@d tasubmotdat @{
|
||||||
/*----------------------- defines for virtual motors -----------------------------*/
|
|
||||||
#define EI 1
|
|
||||||
#define KI 2
|
|
||||||
#define QH 3
|
|
||||||
#define QK 4
|
|
||||||
#define QL 5
|
|
||||||
#define EF 6
|
|
||||||
#define KF 7
|
|
||||||
#define EN 8
|
|
||||||
#define QM 9
|
|
||||||
/*--------------------- the tas virtual motor data structure ---------------------*/
|
/*--------------------- the tas virtual motor data structure ---------------------*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
pObjectDescriptor pDes;
|
pObjectDescriptor pDes;
|
||||||
@ -88,8 +75,6 @@ int TasUBFactory(SConnection *pCon,SicsInterp *pSics, void *pData,
|
|||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
|
int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
int TasMot(SConnection *pCon,SicsInterp *pSics, void *pData,
|
|
||||||
int argc, char *argv[]);
|
|
||||||
|
|
||||||
@}
|
@}
|
||||||
|
|
||||||
@ -114,3 +99,21 @@ int TasMot(SConnection *pCon,SicsInterp *pSics, void *pData,
|
|||||||
@<tasubint@>
|
@<tasubint@>
|
||||||
#endif
|
#endif
|
||||||
@}
|
@}
|
||||||
|
@o tasdrive.h @{
|
||||||
|
/*---------------------------------------------------------------------
|
||||||
|
SICS interface to the triple axis drivable motors.
|
||||||
|
|
||||||
|
copyright: see file COPYRIGHT
|
||||||
|
|
||||||
|
Mark Koennecke, May 2005
|
||||||
|
--------------------------------------------------------------------*/
|
||||||
|
#ifndef TASDRIV
|
||||||
|
#define TASDRIV
|
||||||
|
#include "tasub.h"
|
||||||
|
|
||||||
|
int InstallTasMotor(SicsInterp *pSics, ptasUB self, int tasVar, char *name);
|
||||||
|
int InstallTasQMMotor(SicsInterp *pSics, ptasUB self);
|
||||||
|
int TasMot(SConnection *pCon,SicsInterp *pSics, void *pData,
|
||||||
|
int argc, char *argv[]);
|
||||||
|
#endif
|
||||||
|
@}
|
||||||
|
325
tasublib.c
325
tasublib.c
@ -1,13 +1,15 @@
|
|||||||
/**
|
/**
|
||||||
* This is a library of functions and data structures for performing
|
* This is a library of functions and data structures for performing
|
||||||
* triple axis spectrometer angle calculations using the UB-matrix
|
* triple axis spectrometer angle calculations using the UB-matrix
|
||||||
* formalism as described by Mark Lumsden.
|
* formalism as described by Mark Lumsden, to appear in Acta Cryst.
|
||||||
*
|
*
|
||||||
* copyright: see file COPYRIGHT
|
* copyright: see file COPYRIGHT
|
||||||
*
|
*
|
||||||
* Mark Koennecke, April 2005
|
* Mark Koennecke, April 2005
|
||||||
*/
|
*/
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
#include "trigd.h"
|
#include "trigd.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
#include "tasublib.h"
|
#include "tasublib.h"
|
||||||
@ -30,42 +32,53 @@ double KtoEnergy(double k){
|
|||||||
energy = ECONST*k*k;
|
energy = ECONST*k*k;
|
||||||
return energy;
|
return energy;
|
||||||
}
|
}
|
||||||
|
/*-------------------------------------------------------------------*/
|
||||||
|
static double calcCurvature(double B1, double B2, double theta){
|
||||||
|
return B1 + B2/Sind(ABS(theta));
|
||||||
|
}
|
||||||
/*--------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------*/
|
||||||
int maCalcAngles(maCrystal data, pmaAngles angles, double k){
|
int maCalcTwoTheta(maCrystal data, double k, double *two_theta){
|
||||||
double fd;
|
double fd, theta;
|
||||||
|
|
||||||
/* fd = k/(2.*data.dd); */
|
/* fd = k/(2.*data.dd); */
|
||||||
fd = PI/(data.dd*k);
|
fd = PI/(data.dd*k);
|
||||||
if(fd > 1.0) {
|
if(fd > 1.0) {
|
||||||
return ENERGYTOBIG;
|
return ENERGYTOBIG;
|
||||||
}
|
}
|
||||||
angles->theta = Asind(fd)*data.ss;
|
theta = Asind(fd)*data.ss;
|
||||||
angles->two_theta = 2.*angles->theta;
|
*two_theta = 2.*theta;
|
||||||
angles->horizontal_curvature = data.HB1 + data.HB2/Sind(angles->theta);
|
|
||||||
angles->vertical_curvature = data.VB1 + data.VB2/Sind(angles->theta);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------*/
|
||||||
int maCalcK(maCrystal data, maAngles angles, double *k){
|
double maCalcVerticalCurvature(maCrystal data, double two_theta){
|
||||||
|
return calcCurvature(data.VB1,data.VB2, two_theta/2.);
|
||||||
*k = ABS(data.dd * Sind(angles.two_theta/2));
|
}
|
||||||
*k = PI / *k;
|
/*-------------------------------------------------------------------*/
|
||||||
if(ABS(angles.two_theta/2. - angles.theta) > .1) {
|
double maCalcHorizontalCurvature(maCrystal data, double two_theta){
|
||||||
return BADSYNC;
|
return calcCurvature(data.HB1,data.HB2, two_theta/2.);
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
|
double maCalcK(maCrystal data, double two_theta){
|
||||||
|
double k;
|
||||||
|
k = ABS(data.dd * Sind(two_theta/2));
|
||||||
|
if(ABS(k) > .001){
|
||||||
|
k = PI / k;
|
||||||
|
} else {
|
||||||
|
k = .0;
|
||||||
}
|
}
|
||||||
return 1;
|
return k;
|
||||||
}
|
}
|
||||||
/*==================== reciprocal space ==============================*/
|
/*==================== reciprocal space ==============================*/
|
||||||
static MATRIX tasReflectionToHC(tasReflection r, MATRIX B){
|
static MATRIX tasReflectionToHC(tasQEPosition r, MATRIX B){
|
||||||
MATRIX h = NULL, hc = NULL;
|
MATRIX h = NULL, hc = NULL;
|
||||||
|
|
||||||
h = makeVector();
|
h = makeVector();
|
||||||
if(h == NULL){
|
if(h == NULL){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
vectorSet(h,0,r.h);
|
vectorSet(h,0,r.qh);
|
||||||
vectorSet(h,1,r.k);
|
vectorSet(h,1,r.qk);
|
||||||
vectorSet(h,2,r.l);
|
vectorSet(h,2,r.ql);
|
||||||
|
|
||||||
hc = mat_mul(B,h);
|
hc = mat_mul(B,h);
|
||||||
killVector(h);
|
killVector(h);
|
||||||
@ -135,9 +148,9 @@ static MATRIX uFromAngles(double om, double sgu, double sgl){
|
|||||||
static MATRIX calcTasUVectorFromAngles(tasReflection r){
|
static MATRIX calcTasUVectorFromAngles(tasReflection r){
|
||||||
double theta, om;
|
double theta, om;
|
||||||
|
|
||||||
theta = calcTheta(r.ki,r.kf,r.two_theta);
|
theta = calcTheta(r.qe.ki,r.qe.kf,r.angles.sample_two_theta);
|
||||||
om = r.a3 - theta;
|
om = r.angles.a3 - theta;
|
||||||
return uFromAngles(om,r.sgu, r.sgl);
|
return uFromAngles(om,r.angles.sgu, r.angles.sgl);
|
||||||
}
|
}
|
||||||
/*-------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------*/
|
||||||
MATRIX calcPlaneNormal(tasReflection r1, tasReflection r2){
|
MATRIX calcPlaneNormal(tasReflection r1, tasReflection r2){
|
||||||
@ -170,8 +183,8 @@ MATRIX calcTasUBFromTwoReflections(lattice cell, tasReflection r1,
|
|||||||
*errorCode = status;
|
*errorCode = status;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
h1 = tasReflectionToHC(r1,B);
|
h1 = tasReflectionToHC(r1.qe,B);
|
||||||
h2 = tasReflectionToHC(r2,B);
|
h2 = tasReflectionToHC(r2.qe,B);
|
||||||
if(h1 == NULL || h2 == NULL){
|
if(h1 == NULL || h2 == NULL){
|
||||||
*errorCode = UBNOMEMORY;
|
*errorCode = UBNOMEMORY;
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -265,34 +278,33 @@ static MATRIX buildTVMatrix(MATRIX U1V, MATRIX U2V){
|
|||||||
return T;
|
return T;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
static MATRIX tasReflectionToQC(ptasReflection r, MATRIX UB){
|
static MATRIX tasReflectionToQC(tasQEPosition r, MATRIX UB){
|
||||||
MATRIX Q, QC;
|
MATRIX Q, QC;
|
||||||
|
|
||||||
Q = makeVector();
|
Q = makeVector();
|
||||||
if(Q == NULL){
|
if(Q == NULL){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
vectorSet(Q,0,r->h);
|
vectorSet(Q,0,r.qh);
|
||||||
vectorSet(Q,1,r->k);
|
vectorSet(Q,1,r.qk);
|
||||||
vectorSet(Q,2,r->l);
|
vectorSet(Q,2,r.ql);
|
||||||
QC = mat_mul(UB,Q);
|
QC = mat_mul(UB,Q);
|
||||||
killVector(Q);
|
killVector(Q);
|
||||||
return QC;
|
return QC;
|
||||||
}
|
}
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
static MATRIX buildRMatrix(MATRIX UB, MATRIX planeNormal,
|
static MATRIX buildRMatrix(MATRIX UB, MATRIX planeNormal,
|
||||||
ptasReflection r){
|
tasQEPosition qe){
|
||||||
MATRIX U3V, U1V, U2V, TV, TVINV;
|
MATRIX U1V, U2V, TV, TVINV, M;
|
||||||
|
|
||||||
U3V = planeNormal;
|
|
||||||
|
|
||||||
U1V = tasReflectionToQC(r,UB);
|
U1V = tasReflectionToQC(qe,UB);
|
||||||
if(U1V == NULL){
|
if(U1V == NULL){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
normalizeVector(U1V);
|
normalizeVector(U1V);
|
||||||
|
|
||||||
U2V = vectorCrossProduct(U3V,U1V);
|
U2V = vectorCrossProduct(planeNormal,U1V);
|
||||||
if(U2V == NULL){
|
if(U2V == NULL){
|
||||||
killVector(U1V);
|
killVector(U1V);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -305,73 +317,69 @@ static MATRIX buildRMatrix(MATRIX UB, MATRIX planeNormal,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
TVINV = mat_inv(TV);
|
TVINV = mat_inv(TV);
|
||||||
if(TVINV == NULL){
|
|
||||||
killVector(U1V);
|
killVector(U1V);
|
||||||
killVector(U2V);
|
killVector(U2V);
|
||||||
mat_free(TV);
|
mat_free(TV);
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
killVector(U1V);
|
|
||||||
killVector(U2V);
|
|
||||||
mat_free(TVINV);
|
|
||||||
|
|
||||||
return TVINV;
|
return TVINV;
|
||||||
}
|
}
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
int calcTasQAngles(MATRIX UB, MATRIX planeNormal, int ss, ptasReflection r){
|
int calcTasQAngles(MATRIX UB, MATRIX planeNormal, int ss, tasQEPosition qe,
|
||||||
|
ptasAngles angles){
|
||||||
MATRIX R, QC;
|
MATRIX R, QC;
|
||||||
double om, q, theta, cos2t, tmp;
|
double om, q, theta, cos2t, tmp, sq;
|
||||||
|
|
||||||
R = buildRMatrix(UB, planeNormal, r);
|
R = buildRMatrix(UB, planeNormal, qe);
|
||||||
if(R == NULL){
|
if(R == NULL){
|
||||||
return UBNOMEMORY;
|
return UBNOMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
om = Acosd(R[0][0]/sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0]));
|
sq = sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0]);
|
||||||
r->sgl = Acosd(sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0]));
|
if(ABS(sq) < .00001){
|
||||||
r->sgu = Asind(R[2][1]/sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0]));
|
|
||||||
|
|
||||||
/*
|
|
||||||
r->sgl = Asind(-R[2][0]);
|
|
||||||
tmp = sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0]);
|
|
||||||
if(tmp > .001){
|
|
||||||
r->sgu = Acosd(R[2][2]/tmp);
|
|
||||||
} else {
|
|
||||||
return BADRMATRIX;
|
return BADRMATRIX;
|
||||||
}
|
}
|
||||||
*/
|
om = Acosd(R[0][0]/sq);
|
||||||
|
om -= 180.;
|
||||||
|
angles->sgl = Acosd(sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0]));
|
||||||
|
sq = sqrt(R[0][0]*R[0][0] + R[1][0]*R[1][0]);
|
||||||
|
if(ABS(sq) < .00001){
|
||||||
|
return BADRMATRIX;
|
||||||
|
}
|
||||||
|
angles->sgu = Asind(R[2][1]/sq);
|
||||||
|
|
||||||
|
QC = tasReflectionToQC(qe,UB);
|
||||||
QC = tasReflectionToQC(r,UB);
|
|
||||||
if(QC == NULL){
|
if(QC == NULL){
|
||||||
return UBNOMEMORY;
|
return UBNOMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
q = vectorLength(QC);
|
q = vectorLength(QC);
|
||||||
q = 2.*PI*vectorLength(QC);
|
q = 2.*PI*vectorLength(QC);
|
||||||
cos2t = (r->ki*r->ki + r->kf*r->kf - q*q)/(2. * ABS(r->ki) * ABS(r->kf));
|
cos2t = (qe.ki*qe.ki + qe.kf*qe.kf - q*q)/(2. * ABS(qe.ki) * ABS(qe.kf));
|
||||||
if(cos2t > 1.){
|
if(cos2t > 1.){
|
||||||
return TRIANGLENOTCLOSED;
|
return TRIANGLENOTCLOSED;
|
||||||
}
|
}
|
||||||
r->two_theta = ss*Acosd(cos2t);
|
angles->sample_two_theta = ss*Acosd(cos2t);
|
||||||
|
|
||||||
theta = calcTheta(r->ki, r->kf,r->two_theta);
|
theta = calcTheta(qe.ki, qe.kf,angles->sample_two_theta);
|
||||||
|
|
||||||
r->a3 = om + theta;
|
angles->a3 = om + theta;
|
||||||
|
|
||||||
killVector(QC);
|
killVector(QC);
|
||||||
|
mat_free(R);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
int calcTasQH(MATRIX UB, ptasReflection r){
|
int calcTasQH(MATRIX UB, tasAngles angles, ptasQEPosition qe){
|
||||||
MATRIX UBINV = NULL, QV = NULL, Q = NULL;
|
MATRIX UBINV = NULL, QV = NULL, Q = NULL;
|
||||||
double q;
|
double q;
|
||||||
|
tasReflection r;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
UBINV = mat_inv(UB);
|
UBINV = mat_inv(UB);
|
||||||
QV = calcTasUVectorFromAngles(*r);
|
r.angles = angles;
|
||||||
|
r.qe = *qe;
|
||||||
|
QV = calcTasUVectorFromAngles(r);
|
||||||
if(UBINV == NULL || QV == NULL){
|
if(UBINV == NULL || QV == NULL){
|
||||||
return UBNOMEMORY;
|
return UBNOMEMORY;
|
||||||
}
|
}
|
||||||
@ -380,26 +388,23 @@ int calcTasQH(MATRIX UB, ptasReflection r){
|
|||||||
Thereby take into account the physicists magic fudge
|
Thereby take into account the physicists magic fudge
|
||||||
2PI factor
|
2PI factor
|
||||||
*/
|
*/
|
||||||
q = sqrt(r->ki*r->ki + r->kf*r->kf - 2.*r->ki*r->kf*Cosd(r->two_theta));
|
q = sqrt(qe->ki*qe->ki + qe->kf*qe->kf - 2.*qe->ki*qe->kf*Cosd(angles.sample_two_theta));
|
||||||
q /= 2. * PI;
|
q /= 2. * PI;
|
||||||
|
qe->qm = q;
|
||||||
|
|
||||||
for(i = 0; i < 3; i++){
|
for(i = 0; i < 3; i++){
|
||||||
QV[i][0] *= q;
|
QV[i][0] *= q;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
mat_dump(UB);
|
|
||||||
mat_dump(UBINV);
|
|
||||||
mat_dump(QV);
|
|
||||||
*/
|
|
||||||
Q = mat_mul(UBINV,QV);
|
Q = mat_mul(UBINV,QV);
|
||||||
if(Q == NULL){
|
if(Q == NULL){
|
||||||
mat_free(UBINV);
|
mat_free(UBINV);
|
||||||
killVector(QV);
|
killVector(QV);
|
||||||
return UBNOMEMORY;
|
return UBNOMEMORY;
|
||||||
}
|
}
|
||||||
r->h = Q[0][0];
|
qe->qh = Q[0][0];
|
||||||
r->k = Q[1][0];
|
qe->qk = Q[1][0];
|
||||||
r->l = Q[2][0];
|
qe->ql = Q[2][0];
|
||||||
|
|
||||||
killVector(QV);
|
killVector(QV);
|
||||||
killVector(Q);
|
killVector(Q);
|
||||||
@ -413,29 +418,20 @@ int calcAllTasAngles(ptasMachine machine, tasQEPosition qe,
|
|||||||
int status;
|
int status;
|
||||||
tasReflection r;
|
tasReflection r;
|
||||||
|
|
||||||
status = maCalcAngles(machine->monochromator,&angles->monochromator,
|
status = maCalcTwoTheta(machine->monochromator,qe.ki,
|
||||||
qe.ki);
|
&angles->monochromator_two_theta);
|
||||||
if(status != 1){
|
if(status != 1){
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
r.h = qe.qh;
|
|
||||||
r.k = qe.qk;
|
|
||||||
r.l = qe.ql;
|
|
||||||
r.ki = qe.ki;
|
|
||||||
r.kf = qe.kf;
|
|
||||||
status = calcTasQAngles(machine->UB, machine->planeNormal,
|
status = calcTasQAngles(machine->UB, machine->planeNormal,
|
||||||
machine->ss_sample, &r);
|
machine->ss_sample, qe,angles);
|
||||||
if(status != 1){
|
if(status != 1){
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
angles->a3 = r.a3;
|
|
||||||
angles->sample_two_theta = r.two_theta;
|
|
||||||
angles->sgu = r.sgu;
|
|
||||||
angles->sgl = r.sgl;
|
|
||||||
|
|
||||||
status = maCalcAngles(machine->analyzer,&angles->analyzer,
|
status = maCalcTwoTheta(machine->analyzer,qe.kf,&
|
||||||
qe.kf);
|
angles->analyzer_two_theta);
|
||||||
if(status != 1){
|
if(status != 1){
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -445,46 +441,139 @@ int calcAllTasAngles(ptasMachine machine, tasQEPosition qe,
|
|||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
int calcTasQEPosition(ptasMachine machine, tasAngles angles,
|
int calcTasQEPosition(ptasMachine machine, tasAngles angles,
|
||||||
ptasQEPosition qe){
|
ptasQEPosition qe){
|
||||||
int status, retVal = 1;
|
int status;
|
||||||
|
|
||||||
|
qe->ki = maCalcK(machine->monochromator,angles.monochromator_two_theta);
|
||||||
|
qe->kf = maCalcK(machine->analyzer,angles.analyzer_two_theta);
|
||||||
|
|
||||||
|
status = calcTasQH(machine->UB,angles,qe);
|
||||||
|
if(status != 1){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*================== POWDER Implementation ===========================*/
|
||||||
|
int calcTasPowderAngles(ptasMachine machine, tasQEPosition qe,
|
||||||
|
ptasAngles angles){
|
||||||
|
double cos2t;
|
||||||
|
int status;
|
||||||
tasReflection r;
|
tasReflection r;
|
||||||
double k;
|
|
||||||
|
|
||||||
status = maCalcK(machine->monochromator,angles.monochromator,&k);
|
status = maCalcTwoTheta(machine->monochromator,qe.ki,
|
||||||
|
&angles->monochromator_two_theta);
|
||||||
if(status != 1){
|
if(status != 1){
|
||||||
if(status != BADSYNC){
|
return status;
|
||||||
retVal = BADSYNC;
|
}
|
||||||
|
|
||||||
|
cos2t = (qe.ki*qe.ki + qe.kf*qe.kf - qe.qm*qe.qm)/(2. * ABS(qe.ki) * ABS(qe.kf));
|
||||||
|
if(cos2t > 1.){
|
||||||
|
return TRIANGLENOTCLOSED;
|
||||||
|
}
|
||||||
|
angles->sample_two_theta = machine->ss_sample*Acosd(cos2t);
|
||||||
|
|
||||||
|
|
||||||
|
status = maCalcTwoTheta(machine->analyzer,qe.kf,&
|
||||||
|
angles->analyzer_two_theta);
|
||||||
|
if(status != 1){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
int calcTasPowderPosition(ptasMachine machine, tasAngles angles,
|
||||||
|
ptasQEPosition qe){
|
||||||
|
|
||||||
|
int status;
|
||||||
|
|
||||||
|
qe->ki = maCalcK(machine->monochromator,angles.monochromator_two_theta);
|
||||||
|
qe->kf = maCalcK(machine->analyzer,angles.analyzer_two_theta);
|
||||||
|
|
||||||
|
qe->qm = sqrt(qe->ki*qe->ki + qe->kf*qe->kf -
|
||||||
|
2.*qe->ki*qe->kf*Cosd(angles.sample_two_theta));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*====================== Logic implementation =========================*/
|
||||||
|
void setTasPar(ptasQEPosition qe, int tasMode, int tasVar, double value){
|
||||||
|
double et;
|
||||||
|
|
||||||
|
assert(tasMode == KICONST || tasMode == KFCONST);
|
||||||
|
|
||||||
|
switch(tasVar){
|
||||||
|
case KF:
|
||||||
|
qe->kf = value;
|
||||||
|
break;
|
||||||
|
case EF:
|
||||||
|
qe->kf = energyToK(value);
|
||||||
|
break;
|
||||||
|
case KI:
|
||||||
|
qe->ki = value;
|
||||||
|
break;
|
||||||
|
case EI:
|
||||||
|
qe->ki = energyToK(value);
|
||||||
|
break;
|
||||||
|
case QH:
|
||||||
|
qe->qh = value;
|
||||||
|
break;
|
||||||
|
case QK:
|
||||||
|
qe->qk = value;
|
||||||
|
break;
|
||||||
|
case QL:
|
||||||
|
qe->ql = value;
|
||||||
|
break;
|
||||||
|
case EN:
|
||||||
|
if(tasMode == KICONST){
|
||||||
|
et = KtoEnergy(qe->ki) - value;
|
||||||
|
qe->kf = energyToK(et);
|
||||||
|
} else if(tasMode == KFCONST){
|
||||||
|
et = KtoEnergy(qe->kf) + value;
|
||||||
|
qe->ki = energyToK(et);
|
||||||
} else {
|
} else {
|
||||||
return status;
|
assert(0);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case QM:
|
||||||
|
qe->qm = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
qe->ki = k;
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
status = maCalcK(machine->analyzer,angles.analyzer,&k);
|
double getTasPar(tasQEPosition qe, int tasVar){
|
||||||
if(status != 1){
|
switch(tasVar){
|
||||||
if(status != BADSYNC){
|
case EI:
|
||||||
retVal = BADSYNC;
|
return KtoEnergy(qe.ki);
|
||||||
} else {
|
break;
|
||||||
return status;
|
case KI:
|
||||||
|
return qe.ki;
|
||||||
|
break;
|
||||||
|
case EF:
|
||||||
|
return KtoEnergy(qe.kf);
|
||||||
|
break;
|
||||||
|
case KF:
|
||||||
|
return qe.kf;
|
||||||
|
break;
|
||||||
|
case QH:
|
||||||
|
return qe.qh;
|
||||||
|
break;
|
||||||
|
case QK:
|
||||||
|
return qe.qk;
|
||||||
|
break;
|
||||||
|
case QL:
|
||||||
|
return qe.ql;
|
||||||
|
break;
|
||||||
|
case EN:
|
||||||
|
return KtoEnergy(qe.ki) - KtoEnergy(qe.kf);
|
||||||
|
break;
|
||||||
|
case QM:
|
||||||
|
return qe.qm;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
qe->kf = k;
|
|
||||||
|
|
||||||
|
|
||||||
r.sgu = angles.sgu;
|
|
||||||
r.sgl = angles.sgl;
|
|
||||||
r.a3 = angles.a3;
|
|
||||||
r.two_theta = angles.sample_two_theta;
|
|
||||||
r.ki = qe->ki;
|
|
||||||
r.kf = qe->kf;
|
|
||||||
status = calcTasQH(machine->UB,&r);
|
|
||||||
if(status != 1){
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
qe->qh = r.h;
|
|
||||||
qe->qk = r.k;
|
|
||||||
qe->ql = r.l;
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
187
tasublib.h
187
tasublib.h
@ -17,6 +17,64 @@
|
|||||||
#define UBNOMEMORY -702
|
#define UBNOMEMORY -702
|
||||||
#define TRIANGLENOTCLOSED -703
|
#define TRIANGLENOTCLOSED -703
|
||||||
#define BADRMATRIX -704
|
#define BADRMATRIX -704
|
||||||
|
/*========================== defines for tasMode ====================*/
|
||||||
|
#define KICONST 1
|
||||||
|
#define KFCONST 2
|
||||||
|
/*=========================== TAS Variables =========================*/
|
||||||
|
#define EI 1
|
||||||
|
#define KI 2
|
||||||
|
#define QH 3
|
||||||
|
#define QK 4
|
||||||
|
#define QL 5
|
||||||
|
#define EF 6
|
||||||
|
#define KF 7
|
||||||
|
#define EN 8
|
||||||
|
#define QM 9
|
||||||
|
/*=========================== data structures =======================*/
|
||||||
|
/**
|
||||||
|
* data structure describing a monochromator or analyzer crystal
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
double dd; /* lattice spacing */
|
||||||
|
int ss; /* scattering sense */
|
||||||
|
double HB1, HB2; /* horizontal curvature parameters */
|
||||||
|
double VB1, VB2; /* vertical curvature parameters */
|
||||||
|
} maCrystal, *pmaCrystal;
|
||||||
|
/**
|
||||||
|
* the machine parameters of a triple axis spectrometer
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
maCrystal monochromator, analyzer;
|
||||||
|
MATRIX UB;
|
||||||
|
MATRIX planeNormal;
|
||||||
|
int ss_sample; /* scattering sense sample */
|
||||||
|
}tasMachine, *ptasMachine;
|
||||||
|
/**
|
||||||
|
* a position in Q - Energy space
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
double ki, kf;
|
||||||
|
double qh,qk,ql;
|
||||||
|
double qm;
|
||||||
|
}tasQEPosition, *ptasQEPosition;
|
||||||
|
/**
|
||||||
|
* A triple axis angle position
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
double monochromator_two_theta;
|
||||||
|
double a3;
|
||||||
|
double sample_two_theta;
|
||||||
|
double sgl;
|
||||||
|
double sgu;
|
||||||
|
double analyzer_two_theta;
|
||||||
|
}tasAngles, *ptasAngles;
|
||||||
|
/**
|
||||||
|
* a full triple axis reflection
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
tasQEPosition qe;
|
||||||
|
tasAngles angles;
|
||||||
|
}tasReflection, *ptasReflection;
|
||||||
/*================= Monochromator/Analyzer stuff =====================*/
|
/*================= Monochromator/Analyzer stuff =====================*/
|
||||||
/**
|
/**
|
||||||
* convert an energy in meV to Ki, Kf type values
|
* convert an energy in meV to Ki, Kf type values
|
||||||
@ -32,46 +90,35 @@ double energyToK(double energy);
|
|||||||
double KtoEnergy(double k);
|
double KtoEnergy(double k);
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
/**
|
/**
|
||||||
* data structure describing a monochromator or analyzer crystal
|
* calculate two_theta for k
|
||||||
|
* @param data The crystals parameter
|
||||||
|
* @param k The input K value to calculate
|
||||||
|
* @param two_theta The resulting two_theta
|
||||||
|
* @return 1 on success, a negative error code on failure
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
int maCalcTwoTheta(maCrystal data, double k, double *two_theta);
|
||||||
double dd; /* lattice spacing */
|
|
||||||
int ss; /* scattering sense */
|
|
||||||
double HB1, HB2; /* horizontal curvature parameters */
|
|
||||||
double VB1, VB2; /* vertical curvature parameters */
|
|
||||||
} maCrystal, *pmaCrystal;
|
|
||||||
/**
|
/**
|
||||||
* data structure for the angles of a mono/ana calculation
|
* calculate the value for the vertical curvature
|
||||||
|
* @param data The input crystal parameters
|
||||||
|
* @param two_theta The tow theta value for which to calculate the curvature.
|
||||||
|
* @return A new value for the curvature.
|
||||||
*/
|
*/
|
||||||
typedef struct{
|
double maCalcVerticalCurvature(maCrystal data, double two_theta);
|
||||||
double theta;
|
|
||||||
double two_theta;
|
|
||||||
double horizontal_curvature;
|
|
||||||
double vertical_curvature;
|
|
||||||
}maAngles, *pmaAngles;
|
|
||||||
/*-----------------------------------------------------------------------*/
|
|
||||||
/**
|
/**
|
||||||
* calculate the angles for the wavelength or K value k
|
* calculate the value for the horizontal curvature
|
||||||
|
* @param data The input crystal parameters
|
||||||
|
* @param two_theta The tow theta value for which to calculate the curvature.
|
||||||
|
* @return A new value for the curvature.
|
||||||
|
*/
|
||||||
|
double maCalcHorizontalCurvature(maCrystal data, double two_theta);
|
||||||
|
/**
|
||||||
|
* calculate the value of the K vector from the angle
|
||||||
* @param data The crystals constants
|
* @param data The crystals constants
|
||||||
* @param angles output angles
|
* @param two_theta The two theta read from the motor
|
||||||
* @param k The wavelength or k value to calculate
|
* @return The k value calculated from two_theta and the parameters.
|
||||||
* @return 1 on success, a negative error code on failure.
|
|
||||||
*/
|
*/
|
||||||
int maCalcAngles(maCrystal data, pmaAngles angles, double k);
|
double maCalcK(maCrystal data, double two_theta);
|
||||||
/**
|
|
||||||
* calculate the value of the K vector from angles
|
|
||||||
* @param data The crystals constants
|
|
||||||
* @param angles The current angles
|
|
||||||
* @param k The output K vector
|
|
||||||
* @return 1 on success, a negative error code on failure.
|
|
||||||
*/
|
|
||||||
int maCalcK(maCrystal data, maAngles angles, double *k);
|
|
||||||
/*======================= reciprocal space =============================*/
|
/*======================= reciprocal space =============================*/
|
||||||
typedef struct {
|
|
||||||
double h,k,l;
|
|
||||||
double a3, two_theta, sgu, sgl;
|
|
||||||
double ki, kf;
|
|
||||||
}tasReflection, *ptasReflection;
|
|
||||||
/**
|
/**
|
||||||
* calculate a UB from two reflections and the cell.
|
* calculate a UB from two reflections and the cell.
|
||||||
* @param cell The lattice constant of the crystal
|
* @param cell The lattice constant of the crystal
|
||||||
@ -97,41 +144,22 @@ MATRIX calcPlaneNormal(tasReflection r1, tasReflection r2);
|
|||||||
* @param UB The UB matrix to use
|
* @param UB The UB matrix to use
|
||||||
* @param planeNormal The normal to the scattering plane to use
|
* @param planeNormal The normal to the scattering plane to use
|
||||||
* @param ss The scattering sense at the sample
|
* @param ss The scattering sense at the sample
|
||||||
* @param r The input/output reflection
|
* @param qe The desired Q Energy position
|
||||||
|
* @param angles The resulting angles.
|
||||||
* @return 1 on success, a negative error code when errors are encountered
|
* @return 1 on success, a negative error code when errors are encountered
|
||||||
*/
|
*/
|
||||||
int calcTasQAngles(MATRIX UB, MATRIX planeNormal,
|
int calcTasQAngles(MATRIX UB, MATRIX planeNormal,
|
||||||
int ss, ptasReflection r);
|
int ss, tasQEPosition qe,
|
||||||
|
ptasAngles angles);
|
||||||
/**
|
/**
|
||||||
* calculate QH, QK, QL from the angles given
|
* calculate QH, QK, QL from the angles given
|
||||||
* @param UB The UB matrix to use
|
* @param UB The UB matrix to use
|
||||||
* @param r The reflection to proecess. The angles and ki, kf have to be set
|
* @param angles The angles as read from the motors
|
||||||
* to appropriate values before this can work properly.
|
* @param qe The resulting Q Energy positions
|
||||||
* @return 1 on success, a negative error code on failures.
|
* @return 1 on success, a negative error code on failures.
|
||||||
*/
|
*/
|
||||||
int calcTasQH(MATRIX UB, ptasReflection r);
|
int calcTasQH(MATRIX UB, tasAngles angles, ptasQEPosition qe);
|
||||||
/*======================== pulling it together.. =======================*/
|
/*======================== pulling it together.. =======================*/
|
||||||
typedef struct {
|
|
||||||
maCrystal monochromator, analyzer;
|
|
||||||
MATRIX UB;
|
|
||||||
MATRIX planeNormal;
|
|
||||||
int ss_sample; /* scattering sense sample */
|
|
||||||
tasReflection r;
|
|
||||||
}tasMachine, *ptasMachine;
|
|
||||||
/*---------------------------------------------------------------------*/
|
|
||||||
typedef struct {
|
|
||||||
maAngles monochromator;
|
|
||||||
double a3;
|
|
||||||
double sample_two_theta;
|
|
||||||
double sgl;
|
|
||||||
double sgu;
|
|
||||||
maAngles analyzer;
|
|
||||||
}tasAngles, *ptasAngles;
|
|
||||||
/*-------------------------------------------------------------------*/
|
|
||||||
typedef struct {
|
|
||||||
double ki, kf;
|
|
||||||
double qh,qk,ql;
|
|
||||||
}tasQEPosition, *ptasQEPosition;
|
|
||||||
/**
|
/**
|
||||||
* calculate all the tas target angles for a position in Q-Energy space.
|
* calculate all the tas target angles for a position in Q-Energy space.
|
||||||
* @param machine The machine description
|
* @param machine The machine description
|
||||||
@ -151,4 +179,45 @@ int calcAllTasAngles(ptasMachine machine, tasQEPosition qe,
|
|||||||
*/
|
*/
|
||||||
int calcTasQEPosition(ptasMachine machine, tasAngles angles,
|
int calcTasQEPosition(ptasMachine machine, tasAngles angles,
|
||||||
ptasQEPosition qe);
|
ptasQEPosition qe);
|
||||||
|
/*======================== POWDER MODE =================================
|
||||||
|
Powder mode is driving only QM, A3, SGGU, SGL will not be touched,
|
||||||
|
only energy and sample two theta will be driven.
|
||||||
|
========================================================================*/
|
||||||
|
/**
|
||||||
|
* calculate the angles for a specified energy and qm position (in qe).
|
||||||
|
* @param machine The machine constants of the spectrometer
|
||||||
|
* @param qe The energy, qm position desired.
|
||||||
|
* @param angles The angles for this qe position. Please ignore a3, sgu, sgl
|
||||||
|
* @return 1 on success, a negative error code else
|
||||||
|
*/
|
||||||
|
int calcTasPowderAngles(ptasMachine machine, tasQEPosition qe,
|
||||||
|
ptasAngles angles);
|
||||||
|
/**
|
||||||
|
* calculate the current energy qm position from angles.
|
||||||
|
* @param machine The spectrometer parameters.
|
||||||
|
* @param angles The angles as read from the motors
|
||||||
|
* @param qe The resulting qe position
|
||||||
|
* @return 1 on success, a negative error code on errors
|
||||||
|
*/
|
||||||
|
int calcTasPowderPosition(ptasMachine machine, tasAngles angles,
|
||||||
|
ptasQEPosition qe);
|
||||||
|
/*======================= TAS Logic =====================================*/
|
||||||
|
/**
|
||||||
|
* set triple axis parameters, thereby taking the tasMode into account
|
||||||
|
* @param qe The Q Energy variable set to update
|
||||||
|
* @param tasMode The triple axis mode to apply
|
||||||
|
* @param tasVar The TAS variable to handle. This MUST be one of the
|
||||||
|
* defines at the top of this file.
|
||||||
|
* @param value The value to set for tasPar
|
||||||
|
*/
|
||||||
|
void setTasPar(ptasQEPosition qe, int tasMode, int tasVar, double value);
|
||||||
|
/**
|
||||||
|
* calculates the value of a TAS parameter from qe.
|
||||||
|
* @param qe The Q Energy psoition to extract data from
|
||||||
|
* @parm tasVar The TAS variable to extract. This MUST be one of the
|
||||||
|
* defines given at the top of this file.
|
||||||
|
* @return The value of the TAS variable.
|
||||||
|
*/
|
||||||
|
double getTasPar(tasQEPosition qe, int tasVar);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user