- Fixed a normalisation problem in diffscan when the first value
did not have enough counts - Reduced polling frequency in emon - Fixed a scriptcontext bug which would cause it to dump core in SctTransact on interrupts - Fixed an issue with missing <nl> at the end of batch files - Added a feature which does not call halt when counting stops in hmcontrol.c This is necessary for the BOA CCD - Initalized doNotFree properly in hipadaba.c - Added the travelling salesman reflection measurement algorithm - Added another component to amorset - Removed old SicsWait from nserver.c - Added a means to nxscript to write 16 bit data for BOA - Modified tasub to accept a drivabel as a motor and not only a motor. This became necessary to make EIGER work as A2 on EIGER is a virtual motor SKIPPED: psi/amorcomp.h psi/amordrive.h psi/amorset.c psi/amorset.h psi/amorset.tex psi/amorset.w psi/el734hp.c psi/el737hpdriv.c psi/make_gen psi/pardef.c psi/polterwrite.c psi/psi.c psi/sinqhttpopt.c
This commit is contained in:
204
fourmess.c
204
fourmess.c
@ -34,6 +34,9 @@
|
||||
#include "scanvar.h"
|
||||
#include "scan.i"
|
||||
#include "sdynar.h"
|
||||
#include "lld.h"
|
||||
|
||||
extern char *trim(char *);
|
||||
|
||||
extern void SNXFormatTime(char *pBueffel, int iLen);
|
||||
|
||||
@ -797,12 +800,15 @@ static int hklCompare(const void *h1, const void *h2)
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/*----------------------------------------------------------------------------
|
||||
* This sorts on two theta only.
|
||||
-----------------------------------------------------------------------------*/
|
||||
static int SortRef(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar)
|
||||
{
|
||||
double *sortlist, d, lambda, om, hkl[4], ang[4];
|
||||
const double *cell;
|
||||
double *hklc;
|
||||
int nRefl, i, j;
|
||||
MATRIX B, H, Z1;
|
||||
lattice direct;
|
||||
@ -860,7 +866,195 @@ static int SortRef(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------
|
||||
* Sorting reflection is actually a variant of the traveling salesman
|
||||
* problem. Optimal solutions for this are computationally expensive.
|
||||
* Optimise for the shortest path between reflections. Not all motors
|
||||
* are equal though. Om and phi move quick whereas stt and chi go slow.
|
||||
* As a compromise, what I try here is sorting by a weighted addition of
|
||||
* stt and chi.
|
||||
----------------------------------------------------------------------------*/
|
||||
static int SortRefNew(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar)
|
||||
{
|
||||
double *sortlist, d, lambda, om, hkl[4], ang[4];
|
||||
const double *cell;
|
||||
double *hklc;
|
||||
int nRefl, i, j, status, count;
|
||||
SingleXModes mode;
|
||||
pFourMess priv = self->pPrivate;
|
||||
pSingleDiff diffi = NULL;
|
||||
|
||||
diffi = SXGetDiffractometer();
|
||||
mode = SXGetMode();
|
||||
if(diffi == NULL){
|
||||
SCWrite(pCon,"ERROR: not initialized, no diffractometer", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nRefl = ReflectionListCount(priv->messList);
|
||||
sortlist = malloc(nRefl * 4 * sizeof(double));
|
||||
if (sortlist == NULL) {
|
||||
SCWrite(pCon, "ERROR: out of memory in SortRef", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* I am using hkl[3] for storing the sort value to sort for! */
|
||||
for (i = 0, count = 0; i < nRefl; i++) {
|
||||
GetRefIndex(priv->messList, i, hkl);
|
||||
status = diffi->calculateSettings(diffi,hkl,ang);
|
||||
if(status == 1){
|
||||
if(mode == Bisecting){
|
||||
hkl[3] = ang[0] + 0.5* ang[2];
|
||||
if(ang[2] < 0){
|
||||
SCWrite(pCon,"WARNING: chi < 0!", eWarning);
|
||||
}
|
||||
} else if(mode == NB){
|
||||
/*
|
||||
* sort for nu in the first place. In order to cope with negativity, add
|
||||
* 10.
|
||||
*/
|
||||
hkl[3] = ang[2]+10 + 0.1 * ang[0];
|
||||
} else {
|
||||
hkl[3] = ang[0];
|
||||
}
|
||||
memcpy(sortlist + count * 4, hkl, 4 * sizeof(double));
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
qsort(sortlist, count, 4 * sizeof(double), hklCompare);
|
||||
|
||||
ClearReflectionList(priv->messList);
|
||||
for (i = 0; i < count; i++) {
|
||||
hklc = sortlist+i*4;
|
||||
hklc[3] = .0; /* otherwise this will be interpreted as psi! */
|
||||
status = diffi->calculateSettings(diffi,hklc,ang);
|
||||
AddRefIdxAng(priv->messList, sortlist+i*4,ang);
|
||||
/* AddRefIdx(priv->messList, sortlist + i * 4); */
|
||||
}
|
||||
free(sortlist);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------
|
||||
* Write a reflection list in the TSPLIB format for running a traveling
|
||||
* salesman algorithm against it.
|
||||
----------------------------------------------------------------------------- */
|
||||
static int WriteTSP(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar)
|
||||
{
|
||||
double hkl[4], ang[4];
|
||||
int nRefl, i, j, status, count;
|
||||
SingleXModes mode;
|
||||
pFourMess priv = self->pPrivate;
|
||||
pSingleDiff diffi = NULL;
|
||||
FILE *fd = NULL;
|
||||
|
||||
if(nPar < 1) {
|
||||
SCWrite(pCon,"ERROR: need a filename parameter", eError);
|
||||
return 0;
|
||||
}
|
||||
fd = fopen(trim(par[0]->value.v.text),"w");
|
||||
if(fd == NULL){
|
||||
SCPrintf(pCon,eError,"ERROR: failed to open %s for writing", par[0]->value.v.text);
|
||||
return 0;
|
||||
}
|
||||
|
||||
diffi = SXGetDiffractometer();
|
||||
mode = SXGetMode();
|
||||
if(diffi == NULL){
|
||||
SCWrite(pCon,"ERROR: not initialized, no diffractometer", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nRefl = ReflectionListCount(priv->messList);
|
||||
/*
|
||||
* smear header...
|
||||
*/
|
||||
fprintf(fd,"NAME : %s\n", par[0]->value.v.text);
|
||||
fprintf(fd,"TYPE : TSP\n");
|
||||
fprintf(fd,"DIMENSION : %d\n", nRefl);
|
||||
fprintf(fd,"EDGE_WEIGHT_TYPE : EUC_3D\n");
|
||||
fprintf(fd,"NODE_COORD_SECTION\n");
|
||||
|
||||
|
||||
for (i = 0, count = 0; i < nRefl; i++) {
|
||||
GetRefIndex(priv->messList, i, hkl);
|
||||
status = diffi->calculateSettings(diffi,hkl,ang);
|
||||
if(status == 1){
|
||||
if(mode == Bisecting){
|
||||
fprintf(fd,"%d %e %e %e\n",i+1,ang[0]*3*100,ang[2]*2*100,ang[3]*100);
|
||||
} else if(mode == NB){
|
||||
fprintf(fd,"%d %e %e %e\n",i,ang[2]*4*100,ang[0]*3*100,ang[1]*100);
|
||||
} else {
|
||||
fprintf(fd,"%d %e %e %e\n",i,ang[0]*3*100,ang[2]*2*100,ang[3]*2*100);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(fd);
|
||||
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------
|
||||
* read a tour file as generated by LKH or other TSP solvers and
|
||||
* reorder the reflection list accordingly.
|
||||
-----------------------------------------------------------------------------*/
|
||||
static int ReadTour(pSICSOBJ self, SConnection * pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar)
|
||||
{
|
||||
FILE *fd = NULL;
|
||||
char buffer[132];
|
||||
double hkl[4], ang[4];
|
||||
int idx, tour;
|
||||
pFourMess priv = self->pPrivate;
|
||||
pSingleDiff diffi = NULL;
|
||||
|
||||
|
||||
if(nPar < 1) {
|
||||
SCWrite(pCon,"ERROR: need name of a tour file to read", eError);
|
||||
return 0;
|
||||
}
|
||||
fd = fopen(par[0]->value.v.text,"r");
|
||||
if(fd == NULL){
|
||||
SCPrintf(pCon,eError,"ERROR: failed to open tour file %s for reading",
|
||||
par[0]->value.v.text);
|
||||
return 0;
|
||||
}
|
||||
tour = LLDcreate(sizeof(hkl));
|
||||
diffi = SXGetDiffractometer();
|
||||
assert(diffi != NULL);
|
||||
|
||||
/* skip header */
|
||||
while(fgets(buffer,sizeof(buffer),fd) != NULL){
|
||||
if(strstr(buffer,"TOUR_SECTION") != NULL){
|
||||
break;
|
||||
}
|
||||
}
|
||||
while(fscanf(fd,"%d",&idx) == 1){
|
||||
if(idx < 0){
|
||||
break;
|
||||
}
|
||||
GetRefIndex(priv->messList,idx-1,hkl);
|
||||
LLDnodeAppendFrom(tour,hkl);
|
||||
}
|
||||
fclose(fd);
|
||||
|
||||
idx = LLDnodePtr2First(tour);
|
||||
ClearReflectionList(priv->messList);
|
||||
while(idx == 1){
|
||||
LLDnodeDataTo(tour,hkl);
|
||||
hkl[3] = 0;
|
||||
diffi->calculateSettings(diffi,hkl,ang);
|
||||
AddRefIdxAng(priv->messList, hkl,ang);
|
||||
idx = LLDnodePtr2Next(tour);
|
||||
}
|
||||
LLDdelete(tour);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int FourMessSave(void *data, char *name, FILE * fd)
|
||||
{
|
||||
@ -982,7 +1176,15 @@ void InstallFourMess(SConnection * pCon, SicsInterp * pSics)
|
||||
cmd =
|
||||
AddSICSHdbPar(pNew->objectNode, "indsort", usUser,
|
||||
MakeSICSFunc(SortRef));
|
||||
cmd =
|
||||
AddSICSHdbPar(pNew->objectNode, "writetsp", usUser,
|
||||
MakeSICSFunc(WriteTSP));
|
||||
AddSICSHdbPar(cmd, "filename", usUser, MakeHdbText("Unknown"));
|
||||
|
||||
cmd =
|
||||
AddSICSHdbPar(pNew->objectNode, "readtour", usUser,
|
||||
MakeSICSFunc(ReadTour));
|
||||
AddSICSHdbPar(cmd, "filename", usUser, MakeHdbText("Unknown"));
|
||||
|
||||
cmd =
|
||||
AddSICSHdbPar(pNew->objectNode, "template", usMugger,
|
||||
|
Reference in New Issue
Block a user