diff --git a/doc/user/mesure.htm b/doc/user/mesure.htm
index a18035ee..84e97de6 100644
--- a/doc/user/mesure.htm
+++ b/doc/user/mesure.htm
@@ -5,65 +5,72 @@
Reflection List Processor
-This section describes the means for doing a standard single counter four
-circle diffractometer measurement with SICS. A prerequisite for that is a
-file with a list of reflections to measure. This is a simple file with
-three floating point values per line giving the HKL of the reflection to
-measure. Do not forget to put standard reflections into that file any now
-and then. Another prerequisite is, that the UB-matrix had been determined
-beforehand and that SICS has the updated values. Also check the value of
-lambda in the hkl-object.
-
-
-The measurement procedure is rather simple: If a reflection is accessible
-the diffractometer is positioned on that reflection. Then a scan is done for
-the reflection and data written to file. The scans all run with a fixed scan
-widths, counter preset and countmode. There is a choice of omega scan or
-omega two theta scan. It is known that there are more sophisticated
-measurement schemes for four circle diffraction, but as TRICS is only
-temporarily operated with a single counter not much optimisation seemed
-necessary.
+This module performs four circle diffractometer measurements with a single
+ counter . In a first view this
+module takes a list of reflections as input, drive to each reflection in the list
+ and performs a scan for each reflection. Some more feautures are supported:
+
+- Two different input file formats are supported: the simplest contains a three
+ values for H,K,L per line. Some users prefer to perform the angle calculations
+ themselves; for such cases the input list can contain four values: two theta, omega, chi
+ and phi per line.
+
- This module supports phi scans: the reflection list must then contain H,K,L and phi
+ per line.
+
- Both measurements in normal bisecting mode and normal beam mode are supported.
+
- Optionally weak reflections can be remeasured with the preset multiplied by 5.
+
- Optionally scans are performed in fastscan mode: Between steps, the motor and the
+ counter are started at the same time. The step is finished when both operations terminate.
+
- The module maintains a table of two theta ranges and scan step widths and scan
+ variables. This allows to perform scans with varying step widths with two theta and to
+ switch between omega and omega - two theta scan mode.
+
-Three files will be written starting from a root such as tricsnumberyear.
-For instance trics05601998 means file number 560 in 1998. The file ending in
+Three files will be written starting from a root such as tricsyearnnumber.
+For instance trics1998n000560 means file number 560 in 1998. The file ending in
.log will contain the console log. This is extremely verbose. Another file
ending with .col will contain the reflection, diffractometer settings and
the measured profile. The third file, ending with .rfl will contain for each
refelction, the HKL, the diffractometer settings and the intensity and sigma
-intensity as calculated by the SICS internal integration routine. It does
-a Grant Gabe integration (see J.Appl. Cryst (1978), 11, 114-120).
+intensity as calculated by the SICS internal integration routine. A
+ Grant Gabe integration (see J.Appl. Cryst (1978), 11, 114-120) is performed.
For the purpose of the command description it is assumed, that this facility
-is accessible as object mess within SICS.
+is accessible as object dataset within SICS.
Interaction with this object happens through the following commands:
-- mess start
+
- dataset start
- Creates a new set of files and writes some header info.
-
- mess measure filename iSkip
+
- dataset measure filename iSkip
- Starts a measurement. Reads reflections from the file filename. iSkip is
an optional parameter which allows to skip iSkip lines in the file. This
is for recovery in cases of accidental or purposeful interruption
of the measurement.
-
- mess genlist filename iSkip
+
- dataset genlist filename iSkip
- Mesures reflection from filename. The file is expected to have been
created by hklgen and to include all the angle settings. The optional
parameter iSkip determines the number of lines to skip in the file. This
feature allows to continue measurement on not fully processed files.
-
- mess reopen filename
+
- dataset reopen filename
- Reopens an already existing file set for appending. Only the file root
without directory info or endings needs to be given.
-
- mess close
+
- dataset close
- Closes the current data file set.
-
- mess file
+
- dataset file
- Prints the current data file name.
+
- dataset list
+
- prints the current parameters.
+
- dataset calc file
+
- Tries to calculate all the reflections listen in file and prints an estimate how
+ many reflections are within limits. As file format only a H,K,L type file is
+ supported.
Then there are a few parameter commands. They follow the general scheme:
-- mess parameter
+
- dataset parameter
- Prints the current value of the parameter
-
- mess parameter value
+
- dataset parameter value
- Sets the parameter to the new value.
This object knows about the following parameters:
@@ -72,9 +79,6 @@ This object knows about the following parameters:
The counting mode to use. Possible values are timer or monitor.
preset
The preset to use for counting
-mode
-The measurement mode. Posssible values are omega for omega scans and
-omega2theta for omega two theta scans.
np
number of points to collect for each profile.
step
@@ -82,16 +86,41 @@ omega2theta for omega two theta scans.
compact
Determines if the scan data output to the SICS is in normal
(compact = 0) or condensed (compact = 1) form. The default is 1.
+weak
+0 or 1: switches on special processing of weak reflections.
+weakthreshold
+The threshold used to decide what constitues a weak reflection. The test is:
+ max count in scan - 2* min count in scan.
+fastscan
+0 or 1: switches fastscan mode.
-mess supports two geometries: the first is the usual bisecting geometry. The
+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
+commands are supported:
+
+- dataset table list
+
- prints the content of the table.
+
- dataset table add start end scanmode step
+
- configures two theta range. start and end define the two theta range. scanmode can either
+ be om for omega scans or o2t for omega 2 theta scans. step is the step width to use.
+
- dataset table del num
+
- deletes the entry num from the table. Counting starts with 0!
+
- dataset table clear
+
- clears the whole table.
+
+When there is no two theta range configured for a given two theta value, the omega scan
+ mode applies with the step width given as a parameter to dataset.
+
+
+dataset supports two geometries: the first is the usual bisecting geometry. The
second is the normal beam geometry where the detector is moved out of plane.
This si accounted for by two switches:
-- mess bi
+
- dataset bi
- switches into bissectiong mode. This is the default.
-
- mess nb
+
- dataset nb
- switches into normal beam mode.
@@ -102,19 +131,19 @@ files and continuation of reflection processing at a point way down the
reflection file is supported. Consequently the start of a new experiment
requires the following steps:
-- Create a new set of files with mess start.
+
- Create a new set of files with dataset start.
- Configure the scans with the parameter commands.
-
- Start processing a reflection file with either the mess genlist
- or mess measure commands.
+
- Start processing a reflection file with either the dataset genlist
+ or dataset measure commands.
If you need to continue reflection file processing after an abort or after
solving a problem the following steps are required:
- Determine the file number you were working at and the line number in the
reflection file where you wish to continue processing.
-
- Set the file root with the mess reopen command.
+
- Set the file root with the dataset reopen command.
- Configure the scan parameters again.
-
- Restart the measurement with either mess genlist or mess
+
- Restart the measurement with either dataset genlist or dataset
measure but specify the iSkip parameter according to the position in
the reflection file where processing should continue.
diff --git a/evcontroller.c b/evcontroller.c
index 05d0cd52..456a4e1a 100644
--- a/evcontroller.c
+++ b/evcontroller.c
@@ -1442,6 +1442,7 @@ static pEVControl InstallCommonControllers(SicsInterp *pSics,
if (FindCommandData(pSics, argv[2], "Environment Controller")) {
if (strcmp(argv[1], "replace") == 0) {
RemoveCommand(pSics, argv[2]);
+ EVUnregister(FindEMON(pSics),argv[2]);
} else {
sprintf(pBueffel,
"ERROR: environment device %s already installed, delete first",
diff --git a/fourtable.c b/fourtable.c
new file mode 100644
index 00000000..a5fe4bd0
--- /dev/null
+++ b/fourtable.c
@@ -0,0 +1,231 @@
+/*---------------------------------------------------------------------------
+ F O U R T A B L E
+
+ A SICS object which holds the variation of scan parameters for four circle
+ reflection list measurements.
+ copyright: see copyright.h
+
+ Mark Koennecke, February 2005
+---------------------------------------------------------------------------*/
+#include
+#include
+#include "sics.h"
+#include "fortify.h"
+#include "lld.h"
+#include
+#include "splitter.h"
+#include "fourtable.h"
+/*====================== table entry ===================================*/
+typedef struct {
+ double twoThetaStart;
+ double twoThetaEnd;
+ double step;
+ char scanVar[30];
+}FourTableEntry, *pFourTableEntry;
+/*==================== functions =======================================*/
+int MakeFourCircleTable(){
+ return LLDcreate(sizeof(FourTableEntry));
+}
+/*-----------------------------------------------------------------------*/
+void DeleteFourCircleTable(int handle){
+ LLDdelete(handle);
+}
+/*------------------------------------------------------------------------*/
+static void clearTable(int handle){
+ int status;
+
+ status = LLDnodePtr2First(handle);
+ while(status == 1) {
+ LLDnodeDelete(handle);
+ status = LLDnodePtr2Next(handle);
+ }
+}
+/*------------------------------------------------------------------------*/
+static void printList(int handle, SConnection *pCon){
+ FourTableEntry entry;
+ char pBueffel[132];
+ int status, printed = 0;
+ Tcl_DString list;
+
+ Tcl_DStringInit(&list);
+ status = LLDnodePtr2First(handle);
+ while(status == 1) {
+ LLDnodeDataTo(handle,&entry);
+ snprintf(pBueffel,131,"%8.3f %8.3f %s %8.3f\n", entry.twoThetaStart, entry.twoThetaEnd,
+ entry.scanVar,entry.step);
+ Tcl_DStringAppend(&list,pBueffel,-1);
+ printed = 1;
+ status = LLDnodePtr2Next(handle);
+ }
+ if(printed == 0){
+ Tcl_DStringAppend(&list,"table is empty",-1);
+ }
+ SCWrite(pCon,Tcl_DStringValue(&list), eValue);
+ Tcl_DStringFree(&list);
+}
+/*-----------------------------------------------------------------------*/
+static int addToList(int handle, SConnection *pCon, int argc, char *argv[]){
+ FourTableEntry entry;
+ char pBueffel[132];
+
+ if(argc < 7){
+ SCWrite(pCon,"ERROR: not enough arguments to table add",eError);
+ return 0;
+ }
+
+ if(isNumeric(argv[3])){
+ entry.twoThetaStart = atof(argv[3]);
+ } else {
+ snprintf(pBueffel,131,"ERROR: expected numeric argument, received %s", argv[3]);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+ if(isNumeric(argv[4])){
+ entry.twoThetaEnd = atof(argv[4]);
+ } else {
+ snprintf(pBueffel,131,"ERROR: expected numeric argument, received %s", argv[4]);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+ strncpy(entry.scanVar,argv[5],29);
+ if(isNumeric(argv[6])){
+ entry.step = atof(argv[6]);
+ } else {
+ snprintf(pBueffel,131,"ERROR: expected numeric argument, received %s", argv[6]);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+ LLDnodePrependFrom(handle,&entry);
+
+ return 1;
+}
+/*-----------------------------------------------------------------------*/
+static void delEntry(int handle, int index){
+ int count = 0, status;
+
+ status = LLDnodePtr2First(handle);
+ while(status == 1) {
+ if(count == index){
+ LLDnodeDelete(handle);
+ break;
+ } else {
+ count++;
+ status = LLDnodePtr2Next(handle);
+ }
+ }
+}
+/*------------------------------------------------------------------------*/
+int HandleFourCircleCommands(int handle, SConnection *pCon,
+ int argc, char *argv[], int *err){
+ *err = 1;
+
+ /*
+ test if this is for us
+ */
+ if(argc >= 3){
+ strtolower(argv[1]);
+ if(strcmp(argv[1],"table") != 0){
+ return 0;
+ }
+ } else {
+ return 0;
+ }
+
+ /*
+ what are we supposed to do?
+ */
+ strtolower(argv[2]);
+ if(strcmp(argv[2],"clear") == 0){
+ if(!SCMatchRights(pCon,usUser)){
+ *err = 0;
+ return 1;
+ }
+ clearTable(handle);
+ SCSendOK(pCon);
+ } else if (strcmp(argv[2],"list") == 0){
+ printList(handle,pCon);
+ } else if(strcmp(argv[2],"add") == 0){
+ if(!SCMatchRights(pCon,usUser)){
+ *err = 0;
+ return 1;
+ }
+ *err = addToList(handle,pCon,argc,argv);
+ if(*err != 0)
+ {
+ SCSendOK(pCon);
+ }
+ } else if(strcmp(argv[2],"del") == 0){
+ if(!SCMatchRights(pCon,usUser)){
+ *err = 0;
+ return 1;
+ }
+ if(argc < 4){
+ SCWrite(pCon,"ERROR: insufficnet number of arguments to table del",eError);
+ *err = 0;
+ } else {
+ if(isNumeric(argv[3])){
+ delEntry(handle, atoi(argv[3]));
+ SCSendOK(pCon);
+ } else {
+ SCWrite(pCon,"ERROR: bad argument: expected numeric argument to table del",eError);
+ *err = 0;
+ }
+ }
+ } else {
+ SCWrite(pCon,"ERROR: subcommand to table not known",eError);
+ *err = 0;
+ }
+
+ return 1;
+}
+/*-----------------------------------------------------------------------*/
+static FourTableEntry findEntry(int handle, double two_theta){
+ int status;
+ FourTableEntry entry;
+
+ status = LLDnodePtr2First(handle);
+ while(status == 1) {
+ LLDnodeDataTo(handle,&entry);
+ if(two_theta > entry.twoThetaStart && two_theta <= entry.twoThetaEnd){
+ return entry;
+ }
+ status = LLDnodePtr2Next(handle);
+ }
+ strcpy(entry.scanVar,"NOT FOUND");
+ return entry;
+}
+/*------------------------------------------------------------------------*/
+char *GetFourCircleScanVar(int handle, double two_theta){
+ FourTableEntry entry;
+
+ entry = findEntry(handle,two_theta);
+ return strdup(entry.scanVar);
+}
+/*------------------------------------------------------------------------*/
+double GetFourCircleStep(int handle, double two_theta){
+ FourTableEntry entry;
+
+ entry = findEntry(handle,two_theta);
+ if(strcmp(entry.scanVar,"NOT FOUND") == 0){
+ return -999.99;
+ } else {
+ return entry.step;
+ }
+}
+/*------------------------------------------------------------------------*/
+int SaveFourCircleTable(int handle, char *objName, FILE *fd){
+ FourTableEntry entry;
+ int status;
+
+ fprintf(fd,"%s table clear\n",objName);
+ status = LLDnodePtr2Last(handle);
+ while(status != 0) {
+ LLDnodeDataTo(handle,&entry);
+ fprintf(fd,"%s table add %f %f %s %f\n",objName,
+ entry.twoThetaStart, entry.twoThetaEnd,entry.scanVar,
+ entry.step);
+ status = LLDnodePtr2Prev(handle);
+ }
+ return 1;
+}
+
diff --git a/fourtable.h b/fourtable.h
new file mode 100644
index 00000000..37d2d33f
--- /dev/null
+++ b/fourtable.h
@@ -0,0 +1,22 @@
+
+/*---------------------------------------------------------------------------
+ F O U R T A B L E
+
+ A SICS object which holds the variation of scan parameters for four circle
+ reflection list measurements.
+ copyright: see copyright.h
+
+ Mark Koennecke, February 2005
+---------------------------------------------------------------------------*/
+#ifndef FOURTABLE
+#define FOURTABLE
+
+ int MakeFourCircleTable();
+ void DeleteFourCircleTable(int handle);
+ int HandleFourCircleCommands(int handle, SConnection *pCon,
+ int argc, char *argv[], int *err);
+ char *GetFourCircleScanVar(int handle, double two_theta);
+ double GetFourCircleStep(int handle, double two_theta);
+ int SaveFourCircleTable(int handle, char *objName, FILE *fd);
+
+#endif
diff --git a/hkl.c b/hkl.c
index d86d5a74..c7ac0dee 100644
--- a/hkl.c
+++ b/hkl.c
@@ -282,6 +282,12 @@
}
return 1;
}
+/*-------------------------------------------------------------------------*/
+void SetHKLScanTolerance(pHKL self, float fVal)
+{
+ assert(self);
+ self->scanTolerance = fVal;
+}
/*-------------------------------------------------------------------------*/
int SetWavelengthManual(pHKL self, float fVal)
{
diff --git a/hkl.w b/hkl.w
index 31d8f583..1685e17f 100644
--- a/hkl.w
+++ b/hkl.w
@@ -87,6 +87,7 @@ module:
/*------------------------------------------------------------------------*/
int SetWavelengthVariable(SConnection *pCon, pHKL self, pSelVar pVar);
int SetWavelengthManual(pHKL self, float fVal);
+ void SetHKLScanTolerance(pHKL self, float value);
int SetUB(pHKL self, float fUB[9]);
int GetUB(pHKL self, float fUB[9]);
int SetNOR(pHKL self, int iNOB);
diff --git a/make_gen b/make_gen
index 7ee43f56..a0edc873 100644
--- a/make_gen
+++ b/make_gen
@@ -21,7 +21,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
danu.o nxdict.o varlog.o stptok.o nread.o \
scan.o fitcenter.o telnet.o token.o wwildcard.o hklmot.o\
tclev.o hkl.o integrate.o optimise.o dynstring.o nxutil.o \
- mesure.o uubuffer.o commandlog.o udpquieck.o \
+ mesure.o uubuffer.o commandlog.o udpquieck.o fourtable.o\
rmtrail.o help.o nxupdate.o confvirtualmot.o \
simchop.o choco.o chadapter.o trim.o scaldate.o \
hklscan.o xytable.o exebuf.o exeman.o\
diff --git a/makefile_slinux b/makefile_slinux
new file mode 100644
index 00000000..86e230c9
--- /dev/null
+++ b/makefile_slinux
@@ -0,0 +1,44 @@
+#---------------------------------------------------------------------------
+# Makefile for SICS
+# machine-dependent part for Redhat Linux with AFS at PSI
+#
+# Mark Koennecke 1996-2001
+# Markus Zolliker, March 2003
+#==========================================================================
+# assign if the National Instrument GPIB driver is available
+SINQDIR=/afs/psi.ch/project/sinq
+NI= -DHAVENI
+NIOBJ= nigpib.o
+NILIB=$(SINQDIR)/linux/lib/cib.o
+
+# The variable SRC is needed for the case, where source and objects are
+# separated. In the case where objects are mixed up with sources, SRC
+# is assumed to be empty and does not harm. I case of problems
+# please ask Markus Zolliker.
+
+include $(SRC)sllinux_def
+
+CC = gcc
+CFLAGS = -I$(HDFROOT)/include -DHDF4 -DHDF5 $(NI) \
+ -I$(SRC)psi/hardsup -I$(SRC). \
+ -fwritable-strings -DCYGNUS -DNONINTF -g $(DFORTIFY)
+
+BINTARGET = bin
+EXTRA=nintf.o
+SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \
+ psi/tecs/libtecsl.a
+LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\
+ -ltcl8.3 $(HDFROOT)/lib/libhdf5.a \
+ $(HDFROOT)/lib/libmfhdf.a $(HDFROOT)/lib/libdf.a \
+ $(HDFROOT)/lib/libjpeg.a -lsz -ldl -lz -lm -lc
+
+include $(SRC)make_gen
+
+
+
+
+
+
+
+
+
diff --git a/mesure.c b/mesure.c
index 7c29ffac..85bff41a 100644
--- a/mesure.c
+++ b/mesure.c
@@ -1,12 +1,13 @@
/*-------------------------------------------------------------------------
M E S U R E
- An object for doing simple four circle diffractometer measurements with
+ An object for doing four circle diffractometer measurements with
a single counter.
copyright: see copyright.h
Mark Koennecke, April 1998
+ heavily reworked: Mark Koennecke, February-March 2005
---------------------------------------------------------------------------*/
#include
#include
@@ -19,6 +20,7 @@
#include "o2t.h"
#include "scan.h"
#include "scan.i"
+#include "stdscan.h"
#include "danu.h"
#include "integrate.h"
#include "hkl.h"
@@ -26,6 +28,7 @@
#include "evcontroller.h"
#include "mesure.h"
#include "nxscript.h"
+#include "fourtable.h"
#include "lld.h"
extern void SNXFormatTime(char *pBueffel, int iLen);
@@ -50,7 +53,6 @@
and reflection driving */
pMotor pOmega; /* motor for omega scans */
char *pCOmega; /* name of omega motor */
- char *pO2T; /* name of omega 2 theta virtual motor */
char *pFileRoot; /* where to write files */
pDataNumber pDanu; /* where to get data file number */
FILE *fRefl; /* reflection profile file */
@@ -63,24 +65,77 @@
int np; /* number of scan points */
float fPreset; /* counting preset */
float fStep; /* omega step widths */
- int iMode; /* omega or omega 2 theta scan flag */
long *lCounts; /* array to store counting values */
float fPosition[4]; /* the real positions after driving */
int iCompact; /* true if compact scan ouput. */
- int psiMode; /* 1 for psi scan mode, 0 else */
- int stepList; /* a list of stepwidth ranges */
+ int weak; /* weak flag: remeasure weak reflections */
+ long weakThreshold; /* threshold when a peak is so weak that is has to
+ remeasured */
+ int fastScan; /* flag for using fastscans for scanning reflections */
+ int psiMode; /* 1 for psi scan mode, 0 else */
+ int stepTable; /* mapping of two theta ranges to step width and
+ variable to scan */
} Mesure;
-/*---------------------------------------------------------------------
- Entries for the stepwidth range list
- ----------------------------------------------------------------------*/
-typedef struct {
- float start;
- float end;
- float stepWidth;
-}StepEntry;
+/*-------------------------------------------------------------------------*/
+static int SaveMesure(void *pData, char *name, FILE *fd)
+{
+ pMesure self = (pMesure)pData;
+
+ fprintf(fd,"#Four Circle Dataset Module %s\n",name);
+ if(self->CountMode == eTimer)
+ {
+ fprintf(fd,"%s countmode timer\n",name);
+ }
+ else
+ {
+ fprintf(fd,"%s countmode monitor\n",name);
+ }
+ fprintf(fd,"%s np %d\n", name, self->np);
+ fprintf(fd,"%s preset %f\n", name, self->fPreset);
+ fprintf(fd,"%s step %f\n", name, self->fStep);
+ fprintf(fd,"%s weakthreshold %f\n", name, self->weakThreshold);
+ fprintf(fd,"%s compact %d\n", name, self->iCompact);
+ fprintf(fd,"%s weak %d\n", name, self->weak);
+ fprintf(fd,"%s fastscan %d\n", name, self->fastScan);
+ SaveFourCircleTable(self->stepTable,name,fd);
+ return 1;
+}
+/*-------------------------------------------------------------------------*/
+static void ListMesure(pMesure self, char *name, SConnection *pCon)
+{
+ Tcl_DString list;
+ char pBuffer[132];
+
+ Tcl_DStringInit(&list);
+ if(self->CountMode == eTimer)
+ {
+ snprintf(pBuffer,131,"%s.countmode timer\n",name);
+ }
+ else
+ {
+ snprintf(pBuffer,131,"%s.countmode monitor\n",name);
+ }
+ Tcl_DStringAppend(&list,pBuffer,-1);
+ snprintf(pBuffer,131,"%s.np %d\n", name, self->np);
+ Tcl_DStringAppend(&list,pBuffer,-1);
+ snprintf(pBuffer,131,"%s.preset %f\n", name, self->fPreset);
+ Tcl_DStringAppend(&list,pBuffer,-1);
+ snprintf(pBuffer,131,"%s.step %f\n", name, self->fStep);
+ Tcl_DStringAppend(&list,pBuffer,-1);
+ snprintf(pBuffer,131,"%s.weakthreshold %f\n", name, self->weakThreshold);
+ Tcl_DStringAppend(&list,pBuffer,-1);
+ snprintf(pBuffer,131,"%s.compact %d\n", name, self->iCompact);
+ Tcl_DStringAppend(&list,pBuffer,-1);
+ snprintf(pBuffer,131,"%s.weak %d\n", name, self->weak);
+ Tcl_DStringAppend(&list,pBuffer,-1);
+ snprintf(pBuffer,131,"%s.fastscan %d\n", name, self->fastScan);
+ Tcl_DStringAppend(&list,pBuffer,-1);
+ SCWrite(pCon,Tcl_DStringValue(&list),eValue);
+ Tcl_DStringFree(&list);
+}
/*--------------------------------------------------------------------------*/
pMesure CreateMesure(pHKL pCryst, pScanData pScanner, pMotor pOmega,
- char *pOm, char *po2t, char *pFileRoot,
+ char *pOm, char *pFileRoot,
pDataNumber pDanu)
{
pMesure pNew = NULL;
@@ -100,6 +155,7 @@ typedef struct {
memset(pNew,0,sizeof(Mesure));
pNew->pDes = CreateDescriptor("Mesure");
+ pNew->pDes->SaveStatus = SaveMesure;
pNew->pCall = CreateCallBackInterface();
if( !pNew->pDes || !pNew->pCall)
{
@@ -112,7 +168,6 @@ typedef struct {
pNew->pCryst = pCryst;
pNew->pOmega = pOmega;
pNew->pCOmega = strdup(pOm);
- pNew->pO2T = strdup(po2t);
pNew->pFileRoot = strdup(pFileRoot);
pNew->pDanu = pDanu;
pNew->iCount = 0;
@@ -120,14 +175,16 @@ typedef struct {
pNew->np = 50;
pNew->fStep = 0.05;
pNew->fPreset = 2;
- pNew->iMode = 0;
pNew->iCompact = 1;
+ pNew->weak = 0;
+ pNew->weakThreshold = 99999;
+ pNew->fastScan = 0;
pNew->psiMode = 0;
#ifdef MESSDEBUG
pNew->lCounts = (long *)malloc(90*sizeof(long));
#endif
pNew->lCounts = (long *)malloc(50*sizeof(long));
- pNew->stepList = LLDcreate(sizeof(StepEntry));
+ pNew->stepTable = MakeFourCircleTable();
return pNew;
}
/*------------------------------------------------------------------------*/
@@ -151,13 +208,11 @@ typedef struct {
free(self->pFileRoot);
if(self->pCOmega)
free(self->pCOmega);
- if(self->pO2T)
- free(self->pO2T);
if(self->fRefl)
MesureClose(self);
if(self->lCounts)
free(self->lCounts);
- LLDdelete(self->stepList);
+ DeleteFourCircleTable(self->stepTable);
free(self);
}
/*------------------------------------------------------------------------*/
@@ -179,9 +234,9 @@ typedef struct {
assert(pSics);
/* check no of parameters
- inicom name hkl scan omega o2t root danu
+ inicom name hkl scan omega root danu
*/
- if(argc < 8)
+ if(argc < 7)
{
SCWrite(pCon,
"ERROR: Insufficient number of parameters to MesureFactory",eError);
@@ -237,28 +292,8 @@ typedef struct {
return 0;
}
- /* o2t */
- pCom = FindCommand(pSics,argv[5]);
- if(pCom)
- {
- pDum = (pDummy)pCom->pData;
- if(pDum)
- {
- if(strcmp(pDum->pDescriptor->name,"Omega2Theta") == 0)
- {
- pO2T = (pSicsO2T)pCom->pData;
- }
- }
- }
- if(!pO2T)
- {
- sprintf(pBueffel,"ERROR: %s is no omega 2 theta object",argv[5]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
-
/* Data Number */
- pCom = FindCommand(pSics,argv[7]);
+ pCom = FindCommand(pSics,argv[6]);
if(pCom)
{
pDum = (pDummy)pCom->pData;
@@ -272,13 +307,13 @@ typedef struct {
}
if(!pDanu)
{
- sprintf(pBueffel,"ERROR: %s is no DataNumber object",argv[7]);
+ sprintf(pBueffel,"ERROR: %s is no DataNumber object",argv[6]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
/* finally create the thing */
- pNew = CreateMesure(pCryst,pScan,pMot,argv[4],argv[5],argv[6],pDanu);
+ pNew = CreateMesure(pCryst,pScan,pMot,argv[4],argv[5],pDanu);
if(!pNew)
{
SCWrite(pCon,"ERROR: no memory in MesureFactory",eError);
@@ -359,201 +394,220 @@ typedef struct {
return 1;
}
-/*------------------------------------------------------------------------*/
-static void addStepRange(pMesure self, float start, float end, float step)
+/*-------------------------------------------------------------------------
+ This is slightly tricky: the crystallography module has a scan tolerance.
+ This is supposed to be automatically set. In order to do so, I need
+ the step width which in turn is dependent on two theta. Therefore I calculate
+ two times: the first time with a scan tolerance of 0 to get two theta, the
+ second time with teh scan tolerance ste to a decent value to get the
+ real thing.
+ ---------------------------------------------------------------------------*/
+static int MesureCalculateSettings(pMesure self, float fHKL[3], float fSet[4],
+ float fPsi, SConnection *pCon)
{
- StepEntry se;
- assert(self != NULL);
-
- se.start = start;
- se.end = end;
- se.stepWidth = step;
- LLDnodeAppendFrom(self->stepList,&se);
-}
-/*------------------------------------------------------------------------*/
-static float determineStepWidth(pMesure self, float two_theta)
-{
- float stepWidth;
- StepEntry se;
- int iRet;
-
- assert(self != NULL);
-
- stepWidth = self->fStep;
- iRet = LLDnodePtr2First(self->stepList);
- while(iRet != 0)
+ int status;
+ float step, tolerance;
+
+ SetHKLScanTolerance(self->pCryst,.0);
+ status = CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon);
+ if(!status)
{
- LLDnodeDataTo(self->stepList,&se);
- if(two_theta > se.start && two_theta < se.end)
- {
- stepWidth = se.stepWidth;
- break;
- }
- iRet = LLDnodePtr2Next(self->stepList);
+ return status;
}
- return stepWidth;
+ step = GetFourCircleStep(self->stepTable, fSet[0]);
+ if(step < -900.){
+ step = self->fStep;
+ }
+ tolerance = (step * (float)self->np)/2. + .2;
+ SetHKLScanTolerance(self->pCryst,tolerance);
+ return CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon);
}
/*--------------------------------------------------------------------------*/
int MesureReflection(pMesure self, float fHKL[3], float fPsi,
SConnection *pCon)
{
- int iRet, i;
- float fStart, stepWidth;
- float fDelta, fSet[4];
- char pBueffel[132];
+ int iRet;
+ float fSet[4];
assert(self);
-
- /* drive to reflection */
- iRet = DriveHKL(self->pCryst,fHKL,fPsi,0,pCon);
+
+ iRet = MesureCalculateSettings(self,fHKL,fSet,fPsi,pCon);
if(!iRet)
{
return iRet;
}
+ return MesureGenReflection(self,fHKL,fSet,pCon);
+ }
+/*-----------------------------------------------------------------------*/
+static int DriveToReflection(pMesure self, float fSet[4], SConnection *pCon)
+{
+ int iRet, i;
+ float fDelta;
+ char pBueffel[132];
- /* store achieved position for reporting */
- iRet = GetCurrentPosition(self->pCryst,pCon,self->fPosition);
- if(iRet != 1)
- {
- return iRet;
- }
+ iRet = DriveSettings(self->pCryst,fSet,pCon);
+ if(!iRet)
+ {
+ return iRet;
+ }
- /*
- check if we are really there.
- */
- CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon);
- for(i = 0; i < 4; i++)
- {
- fDelta = fSet[i] - self->fPosition[i];
- if(fDelta < 0.)
- fDelta = -fDelta;
- if(fDelta > ANGERR)
- {
- sprintf(pBueffel,
- "ERROR: angle %d positioned badly, aborting Reflection",
- i);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- }
-
- /* calculate scan start */
- iRet = MotorGetSoftPosition(self->pOmega,pCon,&fStart);
- if(!iRet)
- {
- return iRet;
- }
- stepWidth = determineStepWidth(self,self->fPosition[0]);
- if(stepWidth != self->fStep)
- {
- snprintf(pBueffel,130,"Using stepwidth %f",stepWidth);
- SCWrite(pCon,pBueffel,eWarning);
- }
- fStart -= (self->np/2)*stepWidth;
-
- /* set the scan up */
- ClearScanVar(self->pScanner);
- if(self->iMode == 0)
- {
- AddScanVar(self->pScanner, pServ->pSics,pCon,self->pCOmega,
+ /* store achieved position for reporting */
+ iRet = GetCurrentPosition(self->pCryst,pCon,self->fPosition);
+ if(iRet != 1)
+ {
+ return iRet;
+ }
+
+ /*
+ check if we are really there.
+ */
+ for(i = 0; i < 4; i++)
+ {
+ fDelta = fSet[i] - self->fPosition[i];
+ if(fDelta < 0.)
+ fDelta = -fDelta;
+ if(fDelta > ANGERR)
+ {
+ snprintf(pBueffel,131,
+ "ERROR: angle %d positioned badly, aborting Reflection",
+ i);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+ }
+ return 1;
+}
+/*-----------------------------------------------------------------------
+ test if this scan has to be remeasured because it is weak
+ ------------------------------------------------------------------------*/
+int weakScan(pMesure self)
+{
+ int i;
+ long low = 99999, high = -99999;
+
+ /*
+ ths scan is always OK if we do not test for weak conditions
+ */
+ if(self->weak == 0){
+ return 0;
+ }
+ GetScanCounts(self->pScanner,self->lCounts,self->np);
+ for(i = 0; i < self->np; i++)
+ {
+ if(self->lCounts[i] < low)
+ {
+ low = self->lCounts[i];
+ }
+ if(self->lCounts[i] > high)
+ {
+ high = self->lCounts[i];
+ }
+ }
+ /*
+ I am using the weakest point here as a rough estimate of
+ the background
+ */
+ if(high - 2 * low > self->weakThreshold)
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+/*------------------------------------------------------------------------*/
+static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
+{
+ float fStart, stepWidth;
+ int iRet;
+ char pBueffel[132];
+ char *scanVar = NULL;
+
+ /* calculate scan start */
+ iRet = MotorGetSoftPosition(self->pOmega,pCon,&fStart);
+ if(!iRet)
+ {
+ return iRet;
+ }
+ scanVar = GetFourCircleScanVar(self->stepTable,(double)twoTheta);
+ if(strcmp(scanVar,"NOT FOUND") == 0)
+ {
+ free(scanVar);
+ scanVar = strdup(self->pCOmega);
+ stepWidth = self->fStep;
+ } else {
+ stepWidth = GetFourCircleStep(self->stepTable,(double)twoTheta);
+ }
+
+ if(stepWidth != self->fStep)
+ {
+ snprintf(pBueffel,130,"Using stepwidth %f",stepWidth);
+ SCWrite(pCon,pBueffel,eWarning);
+ }
+ fStart -= (self->np/2)*stepWidth;
+
+ /* set the scan up */
+ ClearScanVar(self->pScanner);
+ AddScanVar(self->pScanner, pServ->pSics,pCon,scanVar,
fStart, stepWidth);
+ free(scanVar);
+
+ /* do the scan */
+ if(self->iCompact)
+ {
+ self->pScanner->CollectScanData = CompactScanData;
+ }
+ if(self->fastScan >= 1)
+ {
+ self->pScanner->ScanDrive = ScanFastDrive;
+ }
+ iRet = SilentScan(self->pScanner,self->np,self->CountMode,
+ self->fPreset,pServ->pSics,pCon);
+ if(weakScan(self))
+ {
+ /*
+ look for interrupts before restarting scan
+ */
+ if(iRet == 0)
+ {
+ if(SCGetInterrupt(pCon) >= eAbortBatch)
+ {
+ return 0;
}
else
{
- AddScanVar(self->pScanner, pServ->pSics,pCon,self->pO2T,
- fStart, stepWidth);
+ SCSetInterrupt(pCon,eContinue);
}
-
- /* do the scan */
- if(self->iCompact)
- {
- self->pScanner->CollectScanData = CompactScanData;
- }
- iRet = SilentScan(self->pScanner,self->np,self->CountMode,
- self->fPreset,pServ->pSics,pCon);
+ }
+ /*
+ redo scan with preset * 5
+ */
+ SCWrite(pCon,"Remeasuring weak reflection",eWarning);
+ iRet = SilentScan(self->pScanner,self->np,self->CountMode,
+ self->fPreset*5.,pServ->pSics,pCon);
- ResetScanFunctions(self->pScanner);
-
- return iRet;
- }
+ }
+ ResetScanFunctions(self->pScanner);
+ return iRet;
+}
/*------------------------------------------------------------------------*/
int MesureGenReflection(pMesure self, float fHKL[3], float fSet[4],
SConnection *pCon)
{
int iRet, i;
- float fStart, fDelta, stepWidth;
char pBueffel[132];
assert(self);
- /* drive to reflection */
- iRet = DriveSettings(self->pCryst,fSet,pCon);
+ iRet = DriveToReflection(self,fSet,pCon);
if(!iRet)
{
- return iRet;
+ return iRet;
}
- /* store achieved position for reporting */
- iRet = GetCurrentPosition(self->pCryst,pCon,self->fPosition);
- if(iRet != 1)
- {
- return iRet;
- }
-
- /*
- check if we are really there.
- */
- for(i = 0; i < 4; i++)
- {
- fDelta = fSet[i] - self->fPosition[i];
- if(fDelta < 0.)
- fDelta = -fDelta;
- if(fDelta > ANGERR)
- {
- sprintf(pBueffel,
- "ERROR: angle %d positioned badly, aborting Reflection",
- i);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- }
-
- /* calculate scan start */
- iRet = MotorGetSoftPosition(self->pOmega,pCon,&fStart);
- if(!iRet)
- {
- return iRet;
- }
- stepWidth = determineStepWidth(self,self->fPosition[0]);
- if(stepWidth != self->fStep)
- {
- snprintf(pBueffel,130,"Using stepwidth %f",stepWidth);
- SCWrite(pCon,pBueffel,eWarning);
- }
- fStart -= (self->np/2)*stepWidth;
-
- /* set the scan up */
- ClearScanVar(self->pScanner);
- if(self->iMode == 0)
- {
- AddScanVar(self->pScanner, pServ->pSics,pCon,self->pCOmega,
- fStart, stepWidth);
- }
- else
- {
- AddScanVar(self->pScanner, pServ->pSics,pCon,self->pO2T,
- fStart, stepWidth);
- }
-
- /* do the scan */
- if(self->iCompact)
- {
- self->pScanner->CollectScanData = CompactScanData;
- }
- iRet = SilentScan(self->pScanner,self->np,self->CountMode,
- self->fPreset,pServ->pSics,pCon);
- ResetScanFunctions(self->pScanner);
+ iRet = ScanReflection(self,fSet[0],pCon);
return iRet;
}
@@ -976,6 +1030,65 @@ static float determineStepWidth(pMesure self, float two_theta)
fclose(fd);
return 1;
}
+/*------------------------------------------------------------------------*/
+ int TestFile(pMesure self, char *pFile, SConnection *pCon)
+ {
+ FILE *fd = NULL;
+ char pBueffel[512], pError[256];
+ int i, iRet;
+ float fHKL[3], fSet[4], fPsi = .0;
+ int count = 0, good = 0;
+
+ assert(self);
+ assert(pCon);
+
+ /* well before doing a thing, open the list file */
+ fd = fopen(pFile,"r");
+ if(!fd)
+ {
+ sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);
+ SCWrite(pCon,pBueffel,eError);
+ return 0;
+ }
+
+ if(self->psiMode > 0){
+ SCWrite(pCon,"WARNING: measuring in psi mode",eWarning);
+ }
+
+ /* loop through space and test! */
+ while(fgets(pBueffel,510,fd) != NULL)
+ {
+ for(i = 0; i < 3;i++)
+ fHKL[i] = 0.;
+ if(self->psiMode > 0){
+ iRet = sscanf(pBueffel,"%f%f%f%f",
+ &fHKL[0],&fHKL[1],&fHKL[2],&fPsi);
+ if(iRet != 4){
+ snprintf(pError,255,"WARNING: skipping bad line %s",pBueffel);
+ SCWrite(pCon,pError,eWarning);
+ continue;
+ }
+ } else {
+ iRet = sscanf(pBueffel,"%f%f%f",&fHKL[0],&fHKL[1],&fHKL[2]);
+ if(iRet != 3){
+ snprintf(pError,255,"WARNING: skipping bad line %s",pBueffel);
+ SCWrite(pCon,pError,eWarning);
+ continue;
+ }
+ }
+ count++;
+ iRet = MesureCalculateSettings(self,fHKL,fSet,fPsi,pCon);
+ if(iRet == 1)
+ {
+ good++;
+ }
+ }
+ fclose(fd);
+ snprintf(pBueffel,511,"Of %d reflections on file, %d are good and %d are rotten",
+ count,good,count-good);
+ SCWrite(pCon,pBueffel,eValue);
+ return 1;
+ }
/*------------------------------------------------------------------------*/
int MesureGenFile(pMesure self, char *pFile, int iSkip, SConnection *pCon)
{
@@ -1078,23 +1191,16 @@ static float determineStepWidth(pMesure self, float two_theta)
self->fStep = fVal;
return 1;
}
+ else if(strcmp(name,"weakthreshold") == 0)
+ {
+ self->weakThreshold = (long)nintf(fVal);
+ return 1;
+ }
else if(strcmp(name,"preset") == 0)
{
self->fPreset = fVal;
return 1;
}
- else if(strcmp(name,"mode") == 0)
- {
- if(fVal <= 0)
- {
- self->iMode = 0;
- }
- else
- {
- self->iMode = 1;
- }
- return 1;
- }
else if(strcmp(name,"countmode") == 0)
{
if(fVal < 0.05)
@@ -1119,6 +1225,30 @@ static float determineStepWidth(pMesure self, float two_theta)
}
return 1;
}
+ else if(strcmp(name,"weak") == 0)
+ {
+ if(fVal >= 1.)
+ {
+ self->weak = 1;
+ }
+ else
+ {
+ self->weak = 0;
+ }
+ return 1;
+ }
+ else if(strcmp(name,"fastscan") == 0)
+ {
+ if(fVal >= 1.)
+ {
+ self->fastScan = 1;
+ }
+ else
+ {
+ self->fastScan = 0;
+ }
+ return 1;
+ }
else if(strcmp(name,"psimode") == 0)
{
if(fVal >= 1.)
@@ -1149,9 +1279,9 @@ static float determineStepWidth(pMesure self, float two_theta)
*fVal = self->fStep;
return 1;
}
- else if(strcmp(name,"mode") == 0)
+ else if(strcmp(name,"weakthreshold") == 0)
{
- *fVal = self->iMode;
+ *fVal = (float)self->weakThreshold;
return 1;
}
else if(strcmp(name,"preset") == 0)
@@ -1176,6 +1306,16 @@ static float determineStepWidth(pMesure self, float two_theta)
*fVal = self->iCompact;
return 1;
}
+ else if(strcmp(name,"fastscan") == 0)
+ {
+ *fVal = (float)self->fastScan;
+ return 1;
+ }
+ else if(strcmp(name,"weak") == 0)
+ {
+ *fVal = (float)self->weak;
+ return 1;
+ }
else if(strcmp(name,"psimode") == 0)
{
*fVal = self->psiMode;
@@ -1190,7 +1330,7 @@ static float determineStepWidth(pMesure self, float two_theta)
int MesureAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
- int iRet, iSkip;
+ int iRet, iSkip, err;
char pBueffel[1024];
pMesure self = NULL;
double d;
@@ -1206,6 +1346,15 @@ static float determineStepWidth(pMesure self, float two_theta)
SCWrite(pCon,pBueffel,eError);
return 0;
}
+
+ /*
+ catch table processing commands
+ */
+ iRet = HandleFourCircleCommands(self->stepTable,pCon,argc,argv,&err);
+ if(iRet == 1)
+ {
+ return err;
+ }
strtolower(argv[1]);
/*------ start */
@@ -1222,6 +1371,11 @@ static float determineStepWidth(pMesure self, float two_theta)
}
return iRet;
}
+/*----------- list*/
+ else if(strcmp(argv[1],"list") == 0)
+ {
+ ListMesure(self,argv[0],pCon);
+ }
/*------ file */
else if(strcmp(argv[1],"file") == 0)
{
@@ -1317,6 +1471,17 @@ static float determineStepWidth(pMesure self, float two_theta)
}
return iRet;
}
+/*------- calc */
+ else if(strcmp(argv[1],"calc") == 0)
+ {
+ if(argc < 3)
+ {
+ SCWrite(pCon,"ERROR: expected list file name as parameter for measure ",eError);
+ return 0;
+ }
+ iRet = TestFile(self,argv[2],pCon);
+ return iRet;
+ }
/*------- genlist */
else if(strcmp(argv[1],"genlist") == 0)
{
@@ -1398,98 +1563,6 @@ static float determineStepWidth(pMesure self, float two_theta)
return 1;
}
}
-/*------- mode */
- if(strcmp(argv[1],"mode") == 0)
- {
- if(argc > 2) /* set case */
- {
- /* check rights */
- if(!SCMatchRights(pCon,usUser))
- {
- SCWrite(pCon,"ERROR: You are not aurhorised to do this!",eError);
- return 0;
- }
- if(strcmp(argv[2],"omega") == 0)
- {
- fVal = 0.;
- }
- else if(strcmp(argv[2],"omega2theta") == 0)
- {
- fVal = 1.;
- }
- else
- {
- SCWrite(pCon,"ERROR: Invalid parameter for mode",eError);
- return 0;
- }
- MesureSetPar(self,"mode",fVal);
- SCSendOK(pCon);
- return 1;
- }
- else /* get case */
- {
- MesureGetPar(self,"mode",&fVal);
- if(fVal < 0.05)
- {
- sprintf(pBueffel,"%s.countmode = omega",argv[0]);
- }
- else
- {
- sprintf(pBueffel,"%s.countmode = omega2theta", argv[0]);
- }
- SCWrite(pCon,pBueffel,eValue);
- return 1;
- }
- }
- else if(strcmp(argv[1],"addrange") == 0)
- {
- if(argc < 5)
- {
- SCWrite(pCon,"ERROR: not enough arguments to addrange",eError);
- return 0;
- }
- if(!SCMatchRights(pCon,usUser))
- {
- return 0;
- }
- iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&d);
- if(iRet != TCL_OK)
- {
- snprintf(pBueffel,131,
- "ERROR: expected numeric value but got %s",argv[2]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- start = (float)d;
- iRet = Tcl_GetDouble(pSics->pTcl,argv[3],&d);
- if(iRet != TCL_OK)
- {
- snprintf(pBueffel,131,
- "ERROR: expected numeric value but got %s",argv[3]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- end = (float)d;
- iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&d);
- if(iRet != TCL_OK)
- {
- snprintf(pBueffel,131,
- "ERROR: expected numeric value but got %s",argv[4]);
- SCWrite(pCon,pBueffel,eError);
- return 0;
- }
- step = (float)d;
- addStepRange(self,start,end,step);
- SCSendOK(pCon);
- return 1;
- }
- else if(strcmp(argv[1],"clearrange") == 0)
- {
- LLDdelete(self->stepList);
- self->stepList = LLDcreate(sizeof(StepEntry));
- SCSendOK(pCon);
- return 1;
- }
/*------ can be other pars */
else
{
@@ -1539,11 +1612,3 @@ static float determineStepWidth(pMesure self, float two_theta)
}
}
}
-
-
-
-
-
-
-
-
diff --git a/mesure.h b/mesure.h
index 8bcf388b..aaad2ec7 100644
--- a/mesure.h
+++ b/mesure.h
@@ -2,12 +2,13 @@
/*----------------------------------------------------------------------------
M E S U R E
- A SICS object for doing simple four circle measurements with a single
+ A SICS object for doing four circle measurements with a single
counter.
copyright: see copyright.h
- Mark Koenencke, April 1998
+ Mark Koennecke, April 1998
+ Heavily reworked: Mark Koennecke, February-March 2005
---------------------------------------------------------------------------*/
#ifndef SICSMESURE
#define SICSMESURE
@@ -15,7 +16,7 @@
typedef struct __Mesure *pMesure;
/*--------------------- live & death --------------------------------------*/
pMesure CreateMesure(pHKL pCryst, pScanData pScanner,
- pMotor pOmega, char *pom, char *po2t,
+ pMotor pOmega, char *pom,
char *pFileRoot,pDataNumber pDanu);
void DeleteMesure(void *pData);
diff --git a/mesure.tex b/mesure.tex
index 6b63596d..68dd6121 100644
--- a/mesure.tex
+++ b/mesure.tex
@@ -1,15 +1,22 @@
\subsection{Four Circle Single Counter Measurement Object}
-This object implements a basic single counter reflection measurement routine
+This object implements a single counter reflection measurement routine
for four circle diffractometers. This object is able to read a reflection
listing, drive to each reflection in the list, do a scan on it, integrate
-the scan results and write the results to ASCII files. Nothing sophisticated
-such as optimised measurement procedures and special background measurement
-programs. Three files will be created as output: one file with the ending
+the scan results and write the results to ASCII files.
+Three files will be created as output: one file with the ending
.rfl which contains the reflection profiles for each reflection, a file .asc
which contains a summary in form of HKL, I, sigma(I) for each reflection
and a file ending .err which contains all the error messages obtained during
the run.
+This module has evolved to support the following mode advanced feautures:
+\begin{itemize}
+\item Vary step width and scanned variable in dependence on two theta
+\item Calculation mode in order to determine the number of reflections which
+can actually be measured from a given list.
+\item Remeasuring of weak reflections.
+\item Fast scans.
+\end{itemize}
The interface to this object consists of these functions:
@@ -22,7 +29,7 @@ $\langle$mesureint {\footnotesize ?}$\rangle\equiv$
\mbox{}\verb@ typedef struct __Mesure *pMesure;@\\
\mbox{}\verb@/*--------------------- live & death --------------------------------------*/@\\
\mbox{}\verb@ pMesure CreateMesure(pHKL pCryst, pScanData pScanner, @\\
-\mbox{}\verb@ pMotor pOmega, char *pom, char *po2t,@\\
+\mbox{}\verb@ pMotor pOmega, char *pom,@\\
\mbox{}\verb@ char *pFileRoot,pDataNumber pDanu);@\\
\mbox{}\verb@ void DeleteMesure(void *pData);@\\
\mbox{}\verb@@\\
@@ -95,13 +102,57 @@ Mesure supports the following parameters:
\item[preset] The preset value for counting.
\item[countmode] the counting mode, can be 0 for timer or 1 for monitor
mode.
-\item[mode] can be 0 for omega 2theta scans or 1 for omega scans.
-\item[step] the scan step widths. This is allways in omega, in omega 2theta
-mode 2theta is always the double of this.
\end{description}
+
+\subsubsection{Four Circle Table}
+In order to support the variation of scan parameters with two theta a table is needed which
+holds the necessary parameters. This table is implemented in a separate module. The
+interface to this module is:
\begin{flushleft} \small
\begin{minipage}{\linewidth} \label{scrap2}
+$\langle$fourtableint {\footnotesize ?}$\rangle\equiv$
+\vspace{-1ex}
+\begin{list}{}{} \item
+\mbox{}\verb@@\\
+\mbox{}\verb@ int MakeFourCircleTable();@\\
+\mbox{}\verb@ void DeleteFourCircleTable(int handle);@\\
+\mbox{}\verb@ int HandleFourCircleCommands(int handle, SConnection *pCon, @\\
+\mbox{}\verb@ int argc, char *argv[], int *err);@\\
+\mbox{}\verb@ char *GetFourCircleScanVar(int handle, double two_theta);@\\
+\mbox{}\verb@ double GetFourCircleStep(int handle, double two_theta);@\\
+\mbox{}\verb@ int SaveFourCircleTable(int handle, char *objName, FILE *fd);@\\
+\mbox{}\verb@@$\diamond$
+\end{list}
+\vspace{-1ex}
+\footnotesize\addtolength{\baselineskip}{-1ex}
+\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
+\item Macro referenced in scrap ?.
+\end{list}
+\end{minipage}\\[4ex]
+\end{flushleft}
+Many functions takes as the first argument a handle to the four circle table as
+ created by MakeFourCircleTable.
+\begin{description}
+\item[MakeFourCircleTable] creats a four circle table. Returns a handle with which
+the table can be referred to later.
+\item[DeleteFourCircleTable] removes a four circle table. The single argument is
+ a handle to a four circle tbale as created by MakeFourCircle.
+\item[HandleFourCircleCommands] handles interpreter commands which allow to
+ edit or list the table described by handle. pCon is used for output. argc, argv are
+ the arguments to the command. The returns 1 when the command was handled, 0 else.
+ If there was an error, err is set to 0.
+\item[GetFourCircleScanVar] retrieves the scan variable to use for the two theta
+ value given.
+\item[GetFourCircleStep] retrieves the step width to use for the two theta
+ value given.
+\item[SaveFourCircleTable] saves the configuration of the table into fd. objName is the
+name of the object to which this table belongs.
+\end{description}
+
+
+\begin{flushleft} \small
+\begin{minipage}{\linewidth} \label{scrap3}
\verb@"mesure.h"@ {\footnotesize ? }$\equiv$
\vspace{-1ex}
\begin{list}{}{} \item
@@ -109,12 +160,13 @@ mode 2theta is always the double of this.
\mbox{}\verb@/*----------------------------------------------------------------------------@\\
\mbox{}\verb@ M E S U R E@\\
\mbox{}\verb@@\\
-\mbox{}\verb@ A SICS object for doing simple four circle measurements with a single@\\
+\mbox{}\verb@ A SICS object for doing four circle measurements with a single@\\
\mbox{}\verb@ counter. @\\
\mbox{}\verb@@\\
\mbox{}\verb@ copyright: see copyright.h@\\
\mbox{}\verb@@\\
-\mbox{}\verb@ Mark Koenencke, April 1998@\\
+\mbox{}\verb@ Mark Koennecke, April 1998@\\
+\mbox{}\verb@ Heavily reworked: Mark Koennecke, February-March 2005 @\\
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
\mbox{}\verb@#ifndef SICSMESURE@\\
\mbox{}\verb@#define SICSMESURE@\\
@@ -125,3 +177,27 @@ mode 2theta is always the double of this.
\vspace{-2ex}
\end{minipage}\\[4ex]
\end{flushleft}
+\begin{flushleft} \small
+\begin{minipage}{\linewidth} \label{scrap4}
+\verb@"fourtable.h"@ {\footnotesize ? }$\equiv$
+\vspace{-1ex}
+\begin{list}{}{} \item
+\mbox{}\verb@@\\
+\mbox{}\verb@/*---------------------------------------------------------------------------@\\
+\mbox{}\verb@ F O U R T A B L E@\\
+\mbox{}\verb@@\\
+\mbox{}\verb@ A SICS object which holds the variation of scan parameters for four circle@\\
+\mbox{}\verb@ reflection list measurements.@\\
+\mbox{}\verb@ copyright: see copyright.h@\\
+\mbox{}\verb@@\\
+\mbox{}\verb@ Mark Koennecke, February 2005@\\
+\mbox{}\verb@---------------------------------------------------------------------------*/@\\
+\mbox{}\verb@#ifndef FOURTABLE@\\
+\mbox{}\verb@#define FOURTABLE@\\
+\mbox{}\verb@@$\langle$fourtableint {\footnotesize ?}$\rangle$\verb@@\\
+\mbox{}\verb@#endif@\\
+\mbox{}\verb@@$\diamond$
+\end{list}
+\vspace{-2ex}
+\end{minipage}\\[4ex]
+\end{flushleft}
diff --git a/mesure.w b/mesure.w
index 3eb3d37d..4a0d9b83 100644
--- a/mesure.w
+++ b/mesure.w
@@ -1,15 +1,22 @@
\subsection{Four Circle Single Counter Measurement Object}
-This object implements a basic single counter reflection measurement routine
+This object implements a single counter reflection measurement routine
for four circle diffractometers. This object is able to read a reflection
listing, drive to each reflection in the list, do a scan on it, integrate
-the scan results and write the results to ASCII files. Nothing sophisticated
-such as optimised measurement procedures and special background measurement
-programs. Three files will be created as output: one file with the ending
+the scan results and write the results to ASCII files.
+Three files will be created as output: one file with the ending
.rfl which contains the reflection profiles for each reflection, a file .asc
which contains a summary in form of HKL, I, sigma(I) for each reflection
and a file ending .err which contains all the error messages obtained during
the run.
+This module has evolved to support the following mode advanced feautures:
+\begin{itemize}
+\item Vary step width and scanned variable in dependence on two theta
+\item Calculation mode in order to determine the number of reflections which
+can actually be measured from a given list.
+\item Remeasuring of weak reflections.
+\item Fast scans.
+\end{itemize}
The interface to this object consists of these functions:
@@ -17,7 +24,7 @@ The interface to this object consists of these functions:
typedef struct __Mesure *pMesure;
/*--------------------- live & death --------------------------------------*/
pMesure CreateMesure(pHKL pCryst, pScanData pScanner,
- pMotor pOmega, char *pom, char *po2t,
+ pMotor pOmega, char *pom,
char *pFileRoot,pDataNumber pDanu);
void DeleteMesure(void *pData);
@@ -82,24 +89,72 @@ Mesure supports the following parameters:
\item[preset] The preset value for counting.
\item[countmode] the counting mode, can be 0 for timer or 1 for monitor
mode.
-\item[mode] can be 0 for omega 2theta scans or 1 for omega scans.
-\item[step] the scan step widths. This is allways in omega, in omega 2theta
-mode 2theta is always the double of this.
\end{description}
+
+\subsubsection{Four Circle Table}
+In order to support the variation of scan parameters with two theta a table is needed which
+holds the necessary parameters. This table is implemented in a separate module. The
+interface to this module is:
+@d fourtableint @{
+ int MakeFourCircleTable();
+ void DeleteFourCircleTable(int handle);
+ int HandleFourCircleCommands(int handle, SConnection *pCon,
+ int argc, char *argv[], int *err);
+ char *GetFourCircleScanVar(int handle, double two_theta);
+ double GetFourCircleStep(int handle, double two_theta);
+ int SaveFourCircleTable(int handle, char *objName, FILE *fd);
+@}
+Many functions takes as the first argument a handle to the four circle table as
+ created by MakeFourCircleTable.
+\begin{description}
+\item[MakeFourCircleTable] creats a four circle table. Returns a handle with which
+the table can be referred to later.
+\item[DeleteFourCircleTable] removes a four circle table. The single argument is
+ a handle to a four circle tbale as created by MakeFourCircle.
+\item[HandleFourCircleCommands] handles interpreter commands which allow to
+ edit or list the table described by handle. pCon is used for output. argc, argv are
+ the arguments to the command. The returns 1 when the command was handled, 0 else.
+ If there was an error, err is set to 0.
+\item[GetFourCircleScanVar] retrieves the scan variable to use for the two theta
+ value given.
+\item[GetFourCircleStep] retrieves the step width to use for the two theta
+ value given.
+\item[SaveFourCircleTable] saves the configuration of the table into fd. objName is the
+name of the object to which this table belongs.
+\end{description}
+
+
@o mesure.h @{
/*----------------------------------------------------------------------------
M E S U R E
- A SICS object for doing simple four circle measurements with a single
+ A SICS object for doing four circle measurements with a single
counter.
copyright: see copyright.h
- Mark Koenencke, April 1998
+ Mark Koennecke, April 1998
+ Heavily reworked: Mark Koennecke, February-March 2005
---------------------------------------------------------------------------*/
#ifndef SICSMESURE
#define SICSMESURE
@
#endif
@}
+
+@o fourtable.h @{
+/*---------------------------------------------------------------------------
+ F O U R T A B L E
+
+ A SICS object which holds the variation of scan parameters for four circle
+ reflection list measurements.
+ copyright: see copyright.h
+
+ Mark Koennecke, February 2005
+---------------------------------------------------------------------------*/
+#ifndef FOURTABLE
+#define FOURTABLE
+@
+#endif
+@}
\ No newline at end of file
diff --git a/scan.tex b/scan.tex
index bb502b97..20677a38 100644
--- a/scan.tex
+++ b/scan.tex
@@ -474,6 +474,12 @@ $\langle$stdscan {\footnotesize ?}$\rangle\equiv$
\mbox{}\verb@ */ @\\
\mbox{}\verb@ int ScanDrive(pScanData self, int iPoint);@\\
\mbox{}\verb@ /**@\\
+\mbox{}\verb@ * ScanFastDrive starts driving to the scan point iPoint, but@\\
+\mbox{}\verb@ * does not wait. Use this for implementing slightly faster@\\
+\mbox{}\verb@ * scans.@\\
+\mbox{}\verb@ */ @\\
+\mbox{}\verb@ int ScanFastDrive(pScanData self, int iPoint);@\\
+\mbox{}\verb@ /**@\\
\mbox{}\verb@ * ScanCount is called at each scan step to do the counting.@\\
\mbox{}\verb@ */@\\
\mbox{}\verb@ int ScanCount(pScanData self, int iPoint);@\\
diff --git a/scan.w b/scan.w
index c214690e..083c22e7 100644
--- a/scan.w
+++ b/scan.w
@@ -419,6 +419,12 @@ documentation.
* ScanDrive handles driving to the scan point iPoint.
*/
int ScanDrive(pScanData self, int iPoint);
+ /**
+ * ScanFastDrive starts driving to the scan point iPoint, but
+ * does not wait. Use this for implementing slightly faster
+ * scans.
+ */
+ int ScanFastDrive(pScanData self, int iPoint);
/**
* ScanCount is called at each scan step to do the counting.
*/
diff --git a/scanvar.h b/scanvar.h
index d8e59150..93303639 100644
--- a/scanvar.h
+++ b/scanvar.h
@@ -40,7 +40,7 @@
*name, float start, float step);
/**
* InitScanVar clears the list of scan points
- * @param pvar The scan variable to clear
+ * @param pvar The scna variable to clear
*/
void InitScanVar(pVarEntry pVar);
/**
diff --git a/stdscan.c b/stdscan.c
index 8b20e44d..b39f9414 100644
--- a/stdscan.c
+++ b/stdscan.c
@@ -574,6 +574,25 @@
}
return status;
}
+/*------------------------------------------------------------------------*/
+ int ScanFastDrive(pScanData self, int iPoint)
+ {
+ int iRet;
+ long lTask;
+ int status;
+
+ iRet = StartToDrive(self,iPoint);
+ if(!iRet)
+ {
+ SCWrite(self->pCon,"ERROR: Cannot Drive, Scan aborted",eError);
+ status = 0;
+ }
+ else
+ {
+ status = 1;
+ }
+ return status;
+ }
/*--------------------------------------------------------------------------*/
int ScanCount(pScanData self, int iPoint)
{
diff --git a/stdscan.h b/stdscan.h
index f2cd1369..135ffbe7 100644
--- a/stdscan.h
+++ b/stdscan.h
@@ -34,6 +34,12 @@
* ScanDrive handles driving to the scan point iPoint.
*/
int ScanDrive(pScanData self, int iPoint);
+ /**
+ * ScanFastDrive starts driving to the scan point iPoint, but
+ * does not wait. Use this for implementing slightly faster
+ * scans.
+ */
+ int ScanFastDrive(pScanData self, int iPoint);
/**
* ScanCount is called at each scan step to do the counting.
*/