- Removed -fwritable-string
SKIPPED: psi/dornier2.c psi/ecbdriv.c psi/el734hp.c psi/libpsi.a psi/make_gen psi/makefile_linux psi/pimotor.c psi/pipiezo.c psi/sinqhttp.c psi/tcpdornier.c psi/velodornier.c
This commit is contained in:
356
cone.c
Normal file
356
cone.c
Normal file
@ -0,0 +1,356 @@
|
||||
/*----------------------------------------------------------------------
|
||||
SICS cone module for cone scans. Form more details see conescan.tex
|
||||
and cone.tex.
|
||||
|
||||
COPYRIGHT: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, March 2006
|
||||
------------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "cone.h"
|
||||
#include "hkl.i"
|
||||
#include "vector.h"
|
||||
#include "fourlib.h"
|
||||
/*=================== Object Descriptor Interface ===================================================*/
|
||||
static void *ConeGetInterface(void *pData, int iID){
|
||||
pConeData self = NULL;
|
||||
|
||||
self = (pConeData)pData;
|
||||
if(self == NULL){
|
||||
return NULL;
|
||||
}
|
||||
if(iID == DRIVEID){
|
||||
return self->pDriv;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*---------------------------------------------------------------------------------------------------*/
|
||||
static void ConeSaveStatus(void *data, char *name, FILE *fd){
|
||||
pConeData self = (pConeData)data;
|
||||
if(self == NULL){
|
||||
return;
|
||||
}
|
||||
fprintf(fd,"%s center %d\n", name,self->center);
|
||||
fprintf(fd,"%s target %f %f %f\n", name, self->target.h,
|
||||
self->target.k, self->target.l);
|
||||
}
|
||||
/*=================== Drivable Interface ============================================================*/
|
||||
static int ConeHalt(void *pData){
|
||||
pConeData self = NULL;
|
||||
|
||||
self = (pConeData)pData;
|
||||
assert(self != NULL);
|
||||
|
||||
self->pHkl->pTheta->pDrivInt->Halt(self->pHkl->pTheta);
|
||||
self->pHkl->pOmega->pDrivInt->Halt(self->pHkl->pOmega);
|
||||
self->pHkl->pChi->pDrivInt->Halt(self->pHkl->pChi);
|
||||
self->pHkl->pPhi->pDrivInt->Halt(self->pHkl->pPhi);
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------------------------*/
|
||||
static int ConeCheckLimits(void *self, float fVal, char *error, int errLen){
|
||||
/*
|
||||
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 MATRIX makeCsToPsiMatrix(reflection center, double lambda){
|
||||
MATRIX psiToCs = NULL, csToPsi = NULL, t1, t2;
|
||||
double z1[3], u;
|
||||
|
||||
psiToCs = makeInstToConeVectorMatrix(center,lambda);
|
||||
if(psiToCs == NULL){
|
||||
return NULL;
|
||||
}
|
||||
csToPsi = mat_inv(psiToCs);
|
||||
/*
|
||||
* this is debugging code: remove together with variables
|
||||
*/
|
||||
z1FromAngles(lambda,center.s2t,center.om,center.chi,center.phi,z1);
|
||||
t1 = makeVectorInit(z1);
|
||||
t2 = mat_mul(psiToCs,t1);
|
||||
normalizeVector(t2);
|
||||
t1[0][0] = .0;
|
||||
t1[1][0] = .0;
|
||||
t1[2][0] = 1.;
|
||||
u = angleBetween(t1,t2);
|
||||
|
||||
mat_free(psiToCs);
|
||||
return csToPsi;
|
||||
}
|
||||
/*----------------------------------------------------------------------------------------------------
|
||||
* I am lazy in this function: I calculate anew from all the data. This saves
|
||||
* me a lot of trouble keeping track of parameter changes in UBCALC etc.
|
||||
* ---------------------------------------------------------------------------*/
|
||||
static long ConeSetValue(void *pData, SConnection *pCon, float fVal){
|
||||
pConeData self = NULL;
|
||||
float fSet[4];
|
||||
double openingAngle, length, testAngle;
|
||||
MATRIX csToPsi = NULL, B = NULL, newScat = NULL, cent;
|
||||
int status;
|
||||
reflection center;
|
||||
char buffer[131];
|
||||
double z1[3];
|
||||
|
||||
if(!SCMatchRights(pCon,usUser)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
self = (pConeData)pData;
|
||||
assert(self != NULL);
|
||||
|
||||
/*
|
||||
* calculate opening angle
|
||||
*/
|
||||
B = mat_creat(3,3,UNIT_MATRIX);
|
||||
status = calculateBMatrix(self->ubi->direct,B);
|
||||
if(status < 0){
|
||||
SCWrite(pCon,"ERROR: cell has no volume",eError);
|
||||
return 0;
|
||||
}
|
||||
center = getReflection(self->ubi,self->center);
|
||||
openingAngle = angleBetweenReflections(B,center,self->target);
|
||||
|
||||
/*
|
||||
* calculate conversion matrix from cone system to PSI system
|
||||
*/
|
||||
csToPsi = makeCsToPsiMatrix(center,self->ubi->hkl->fLambda);
|
||||
if(csToPsi == NULL){
|
||||
SCWrite(pCon,"ERROR: bad parameters: failed to generate conversion matrix",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* calculate scattering vector on cone and make its length
|
||||
* match the length of the apropriate scattering vector
|
||||
*/
|
||||
length = scatteringVectorLength(B,self->target);
|
||||
newScat = calcConeVector(openingAngle, fVal, length, csToPsi);
|
||||
if(newScat == NULL){
|
||||
SCWrite(pCon,"ERROR: fails to calculate cone vector",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* this is debugging code
|
||||
*/
|
||||
length = vectorLength(newScat);
|
||||
z1FromAngles(self->ubi->hkl->fLambda,center.s2t,center.om,center.chi,
|
||||
center.phi,z1);
|
||||
cent = makeVectorInit(z1);
|
||||
testAngle = angleBetween(cent,newScat);
|
||||
snprintf(buffer,131,"OpeningAngle = %f, testAngle = %f, length = %f",
|
||||
openingAngle,testAngle,length);
|
||||
SCWrite(pCon,buffer,eWarning);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* try to find setting angles for this vector
|
||||
*/
|
||||
status = findAllowedBisecting(self->pHkl->fLambda,newScat, fSet,
|
||||
hklInRange, self->pHkl);
|
||||
/*
|
||||
* clean up matrices
|
||||
*/
|
||||
mat_free(B);
|
||||
mat_free(newScat);
|
||||
mat_free(csToPsi);
|
||||
if(status != 1){
|
||||
SCWrite(pCon,"ERROR: cannot get cone vector into scattering position",
|
||||
eError);
|
||||
SCSetInterrupt(pCon,eAbortOperation);
|
||||
return 0;
|
||||
}
|
||||
self->lastConeAngle = fVal;
|
||||
/*
|
||||
* start motors
|
||||
*/
|
||||
return startHKLMotors(self->pHkl, pCon,fSet);
|
||||
}
|
||||
/*---------------------------------------------------------------------------------------------------*/
|
||||
static int checkMotors(pConeData self, SConnection *pCon){
|
||||
int status;
|
||||
|
||||
status = self->pHkl->pTheta->pDrivInt->CheckStatus(self->pHkl->pTheta, pCon);
|
||||
if(status != HWIdle && status != OKOK){
|
||||
return status;
|
||||
}
|
||||
status = self->pHkl->pOmega->pDrivInt->CheckStatus(self->pHkl->pOmega, pCon);
|
||||
if(status != HWIdle && status != OKOK){
|
||||
return status;
|
||||
}
|
||||
status = self->pHkl->pChi->pDrivInt->CheckStatus(self->pHkl->pChi, pCon);
|
||||
if(status != HWIdle && status != OKOK){
|
||||
return status;
|
||||
}
|
||||
status = self->pHkl->pPhi->pDrivInt->CheckStatus(self->pHkl->pPhi, pCon);
|
||||
if(status != HWIdle && status != OKOK){
|
||||
return status;
|
||||
}
|
||||
return HWIdle;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------------------------*/
|
||||
static int ConeCheckStatus(void *pData, SConnection *pCon){
|
||||
pConeData self = NULL;
|
||||
int status;
|
||||
|
||||
self = (pConeData)pData;
|
||||
assert(self != NULL);
|
||||
return checkMotors(self,pCon);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------------------------*/
|
||||
static float ConeGetValue(void *pData, SConnection *pCon){
|
||||
pConeData self = NULL;
|
||||
float fVal[3];
|
||||
int status;
|
||||
|
||||
self = (pConeData)pData;
|
||||
assert(self != NULL);
|
||||
|
||||
return self->lastConeAngle;
|
||||
}
|
||||
/*=============================== Live and Death ====================================*/
|
||||
static pConeData MakeConeMot(pUBCALC u){
|
||||
pConeData self = NULL;
|
||||
|
||||
assert(u != NULL);
|
||||
|
||||
self = (pConeData)malloc(sizeof(coneData));
|
||||
if(self == NULL){
|
||||
return NULL;
|
||||
}
|
||||
memset(self,0,sizeof(coneData));
|
||||
self->pDes = CreateDescriptor("Cone");
|
||||
self->pDriv = CreateDrivableInterface();
|
||||
if(self->pDes == NULL || self->pDriv == NULL){
|
||||
free(self);
|
||||
return NULL;
|
||||
}
|
||||
self->pDes->GetInterface = ConeGetInterface;
|
||||
self->pDriv->Halt = ConeHalt;
|
||||
self->pDriv->CheckLimits = ConeCheckLimits;
|
||||
self->pDriv->SetValue = ConeSetValue;
|
||||
self->pDriv->CheckStatus = ConeCheckStatus;
|
||||
self->pDriv->GetValue = ConeGetValue;
|
||||
self->ubi = u;
|
||||
self->pHkl = u->hkl;
|
||||
return self;
|
||||
}
|
||||
/*----------------------------------------------------------------------------------*/
|
||||
static void KillConeMot(void *pData){
|
||||
pConeData self = NULL;
|
||||
|
||||
self = (pConeData)pData;
|
||||
if(self == NULL){
|
||||
return;
|
||||
}
|
||||
if(self->pDes != NULL){
|
||||
DeleteDescriptor(self->pDes);
|
||||
}
|
||||
if(self->pDriv){
|
||||
free(self->pDriv);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
/*=============================== Interpreter Interface ============================*/
|
||||
int ConeAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){
|
||||
pConeData self = NULL;
|
||||
float value;
|
||||
int id;
|
||||
char pBuffer[132];
|
||||
|
||||
self = (pConeData)pData;
|
||||
assert(self != NULL);
|
||||
|
||||
if(argc > 1) {
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"center") == 0){
|
||||
if(argc > 2){
|
||||
if(!SCMatchRights(pCon,usUser)){
|
||||
return 0;
|
||||
}
|
||||
id = atoi(argv[2]);
|
||||
if(id < 0 || id > 2 ){
|
||||
SCWrite(pCon,"ERROR: id must be between 0 - 3",eError);
|
||||
return 0;
|
||||
}
|
||||
self->center = id;
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
snprintf(pBuffer,131,"%s.center = %d", argv[0], self->center);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
return 1;
|
||||
}
|
||||
} else if (strcmp(argv[1],"target") == 0){
|
||||
if(argc >= 5){
|
||||
if(!SCMatchRights(pCon,usUser)){
|
||||
return 0;
|
||||
}
|
||||
self->target.h = atof(argv[2]);
|
||||
self->target.k = atof(argv[3]);
|
||||
self->target.l = atof(argv[4]);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
snprintf(pBuffer,131,"%s.target = %f %f %f", argv[0],
|
||||
self->target.h, self->target.k, self->target.l);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
SCWrite(pCon,"ERROR: subcommand to cone not known",eError);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* default: print value
|
||||
*/
|
||||
value = self->pDriv->GetValue(self,pCon);
|
||||
if(value < -9000.){
|
||||
snprintf(pBuffer,131,"ERROR: failed to read %s",argv[0]);
|
||||
SCWrite(pCon,pBuffer,eError);
|
||||
return 0;
|
||||
}
|
||||
snprintf(pBuffer,131,"%s = %f", argv[0], value);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------------------------*/
|
||||
int MakeCone(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){
|
||||
pUBCALC ubi = NULL;
|
||||
pConeData pMot = NULL;
|
||||
char pBuffer[131];
|
||||
int status;
|
||||
|
||||
if(argc < 3){
|
||||
SCWrite(pCon,"ERROR: insuffient number of arguments to MakeCone",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ubi = FindCommandData(pSics,argv[2],"UBcalc");
|
||||
if(ubi == NULL){
|
||||
snprintf(pBuffer,131,"ERROR: %s is no UBcalc object" , argv[2]);
|
||||
SCWrite(pCon,pBuffer,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pMot = MakeConeMot(ubi);
|
||||
if(pMot == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory creating cone virtual motor",eError);
|
||||
return 0;
|
||||
}
|
||||
status = AddCommand(pSics,argv[1],ConeAction,KillConeMot,pMot);
|
||||
if(status != 1){
|
||||
SCWrite(pCon,"ERROR: failed to create duplicate cone motor",eError);
|
||||
}
|
||||
return status;
|
||||
|
||||
}
|
Reference in New Issue
Block a user