SICS-720 Add autofocussing on Taipan using the following energy relations,

Avfocus = 115 + 2.13 * Ef
Mvfocus = 102.2 + 1.78 * Ei

Ahfocus = 45.68 - (-105.7) * (0.945) ^ Ef
Mhfocus = 184.42 - (60.1) * (0.951) ^ Ei

NOTE: Parameters are set via tasub mono/ana  VB1/VB2/HB1/HB2/HB3
This commit is contained in:
Ferdi Franceschini
2014-03-10 14:05:46 +11:00
parent 879a573e05
commit 9b19ddf4e6
5 changed files with 96 additions and 32 deletions

View File

@ -39,9 +39,9 @@
static long TASSetValue(void *pData, SConnection * pCon, float value) static long TASSetValue(void *pData, SConnection * pCon, float value)
{ {
ptasMot self = (ptasMot) pData; ptasMot self = (ptasMot) pData;
assert(self);
int qcodes[] = {3,4,5,8}; /* qh,qk,ql, en */ int qcodes[] = {3,4,5,8}; /* qh,qk,ql, en */
int i; int i;
assert(self);
if (self->code > 5 && self->math->tasMode == ELASTIC) { if (self->code > 5 && self->math->tasMode == ELASTIC) {
SCWrite(pCon, "ERROR: cannot drive this motor in elastic mode", SCWrite(pCon, "ERROR: cannot drive this motor in elastic mode",
@ -328,9 +328,9 @@ static int startMotors(ptasMot self, tasAngles angles,
self->math->busy[A2] = 1; self->math->busy[A2] = 1;
} }
if (self->math->motors[MCV] != NULL) { if (self->math->motors[MCV] != NULL && self->math->autofocus) {
curve = maCalcVerticalCurvature(self->math->machine.monochromator, curve = maCalcVerticalCurvature(self->math->machine.monochromator,
angles.monochromator_two_theta); angles.monochromator_two_theta, getTasPar(self->math->target, EI), self->math->focusfn);
status = startTASMotor(self->math->motors[MCV], pCon, self->math->motname[MCV], status = startTASMotor(self->math->motors[MCV], pCon, self->math->motname[MCV],
curve, silent,stopFixed); curve, silent,stopFixed);
if (status != OKOK) { if (status != OKOK) {
@ -341,9 +341,9 @@ static int startMotors(ptasMot self, tasAngles angles,
} }
} }
if (self->math->motors[MCH] != NULL) { if (self->math->motors[MCH] != NULL && self->math->autofocus) {
curve = maCalcHorizontalCurvature(self->math->machine.monochromator, curve = maCalcHorizontalCurvature(self->math->machine.monochromator,
angles.monochromator_two_theta); angles.monochromator_two_theta, getTasPar(self->math->target, EI), self->math->focusfn);
status = startTASMotor(self->math->motors[MCH], pCon, self->math->motname[MCH], status = startTASMotor(self->math->motors[MCH], pCon, self->math->motname[MCH],
curve, silent,stopFixed); curve, silent,stopFixed);
if (status != OKOK) { if (status != OKOK) {
@ -374,9 +374,9 @@ static int startMotors(ptasMot self, tasAngles angles,
self->math->busy[A6] = 1; self->math->busy[A6] = 1;
} }
if (self->math->motors[ACV] != NULL) { if (self->math->motors[ACV] != NULL && self->math->autofocus) {
curve = maCalcVerticalCurvature(self->math->machine.analyzer, curve = maCalcVerticalCurvature(self->math->machine.analyzer,
angles.analyzer_two_theta); angles.analyzer_two_theta, getTasPar(self->math->target, EF), self->math->focusfn);
status = startTASMotor(self->math->motors[ACV], pCon, self->math->motname[ACV], status = startTASMotor(self->math->motors[ACV], pCon, self->math->motname[ACV],
curve, silent,stopFixed); curve, silent,stopFixed);
if (status != OKOK) { if (status != OKOK) {
@ -386,9 +386,9 @@ static int startMotors(ptasMot self, tasAngles angles,
self->math->busy[ACV] = 1; self->math->busy[ACV] = 1;
} }
} }
if (self->math->motors[ACH] != NULL) { if (self->math->motors[ACH] != NULL && self->math->autofocus) {
curve = maCalcHorizontalCurvature(self->math->machine.analyzer, curve = maCalcHorizontalCurvature(self->math->machine.analyzer,
angles.analyzer_two_theta); angles.analyzer_two_theta, getTasPar(self->math->target, EF), self->math->focusfn);
status = startTASMotor(self->math->motors[ACH], pCon, self->math->motname[ACH], status = startTASMotor(self->math->motors[ACH], pCon, self->math->motname[ACH],
curve, silent,stopFixed); curve, silent,stopFixed);
if (status != OKOK) { if (status != OKOK) {
@ -666,9 +666,9 @@ static int startQMMotors(ptasMot self, tasAngles angles,
self->math->busy[A2] = 1; self->math->busy[A2] = 1;
} }
if (self->math->motors[MCV] != NULL) { if (self->math->motors[MCV] != NULL && self->math->autofocus) {
curve = maCalcVerticalCurvature(self->math->machine.monochromator, curve = maCalcVerticalCurvature(self->math->machine.monochromator,
angles.monochromator_two_theta); angles.monochromator_two_theta, getTasPar(self->math->target, EI), self->math->focusfn);
status = startTASMotor(self->math->motors[MCV], pCon, self->math->motname[MCV], status = startTASMotor(self->math->motors[MCV], pCon, self->math->motname[MCV],
curve, silent,stopFixed); curve, silent,stopFixed);
if (status != OKOK) { if (status != OKOK) {
@ -678,9 +678,9 @@ static int startQMMotors(ptasMot self, tasAngles angles,
} }
} }
if (self->math->motors[MCH] != NULL) { if (self->math->motors[MCH] != NULL && self->math->autofocus) {
curve = maCalcHorizontalCurvature(self->math->machine.monochromator, curve = maCalcHorizontalCurvature(self->math->machine.monochromator,
angles.monochromator_two_theta); angles.monochromator_two_theta, getTasPar(self->math->target, EI), self->math->focusfn);
status = startTASMotor(self->math->motors[MCH], pCon, self->math->motname[MCH], status = startTASMotor(self->math->motors[MCH], pCon, self->math->motname[MCH],
curve, silent,stopFixed); curve, silent,stopFixed);
if (status != OKOK) { if (status != OKOK) {
@ -709,9 +709,9 @@ static int startQMMotors(ptasMot self, tasAngles angles,
self->math->busy[A6] = 1; self->math->busy[A6] = 1;
} }
if (self->math->motors[ACV] != NULL) { if (self->math->motors[ACV] != NULL && self->math->autofocus) {
curve = maCalcVerticalCurvature(self->math->machine.analyzer, curve = maCalcVerticalCurvature(self->math->machine.analyzer,
angles.analyzer_two_theta); angles.analyzer_two_theta, getTasPar(self->math->target, EF), self->math->focusfn);
status = startTASMotor(self->math->motors[ACV], pCon, self->math->motname[ACV], status = startTASMotor(self->math->motors[ACV], pCon, self->math->motname[ACV],
curve, silent,stopFixed); curve, silent,stopFixed);
if (status != OKOK) { if (status != OKOK) {
@ -720,9 +720,9 @@ static int startQMMotors(ptasMot self, tasAngles angles,
self->math->busy[ACV] = 1; self->math->busy[ACV] = 1;
} }
} }
if (self->math->motors[ACH] != NULL) { if (self->math->motors[ACH] != NULL && self->math->autofocus) {
curve = maCalcHorizontalCurvature(self->math->machine.analyzer, curve = maCalcHorizontalCurvature(self->math->machine.analyzer,
angles.analyzer_two_theta); angles.analyzer_two_theta, getTasPar(self->math->target, EF), self->math->focusfn);
status = startTASMotor(self->math->motors[ACH], pCon, self->math->motname[ACH], status = startTASMotor(self->math->motors[ACH], pCon, self->math->motname[ACH],
curve, silent,stopFixed); curve, silent,stopFixed);
if (status != OKOK) { if (status != OKOK) {

51
tasub.c
View File

@ -173,6 +173,8 @@ static ptasUB MakeTasUB()
pNew->actualEn = .0; pNew->actualEn = .0;
pNew->outOfPlaneAllowed = 1; pNew->outOfPlaneAllowed = 1;
pNew->mustRecalculate = 1; pNew->mustRecalculate = 1;
pNew->autofocus = 0;
pNew->focusfn = THETA_FN;
return pNew; return pNew;
} }
@ -381,6 +383,10 @@ int TasUBFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
eError); eError);
return 0; return 0;
} }
if (pNew->motors[MCV] != NULL && pNew->motors[MCH] != NULL &&
pNew->motors[ACV] != NULL && pNew->motors[ACH] != NULL) {
pNew->autofocus = 1;
}
status = AddCommand(pSics, argv[1], TasUBWrapper, KillTasUB, pNew); status = AddCommand(pSics, argv[1], TasUBWrapper, KillTasUB, pNew);
if (status != 1) { if (status != 1) {
@ -453,6 +459,11 @@ static int setCrystalParameters(pmaCrystal crystal, SConnection * pCon,
SCSendOK(pCon); SCSendOK(pCon);
SCparChange(pCon); SCparChange(pCon);
return 1; return 1;
} else if (strcmp(argv[2], "hb3") == 0) {
crystal->HB3 = d;
SCSendOK(pCon);
SCparChange(pCon);
return 1;
} else if (strcmp(argv[2], "vb1") == 0) { } else if (strcmp(argv[2], "vb1") == 0) {
crystal->VB1 = d; crystal->VB1 = d;
SCSendOK(pCon); SCSendOK(pCon);
@ -493,6 +504,11 @@ static int getCrystalParameters(pmaCrystal crystal, SConnection * pCon,
crystal->HB2); crystal->HB2);
SCWrite(pCon, pBueffel, eValue); SCWrite(pCon, pBueffel, eValue);
return 1; return 1;
} else if (strcmp(argv[2], "hb3") == 0) {
snprintf(pBueffel, 131, "%s.%s.hb3 = %f", argv[0], argv[1],
crystal->HB3);
SCWrite(pCon, pBueffel, eValue);
return 1;
} else if (strcmp(argv[2], "vb1") == 0) { } else if (strcmp(argv[2], "vb1") == 0) {
snprintf(pBueffel, 131, "%s.%s.vb1 = %f", argv[0], argv[1], snprintf(pBueffel, 131, "%s.%s.vb1 = %f", argv[0], argv[1],
crystal->VB1); crystal->VB1);
@ -2200,6 +2216,41 @@ int TasUBWrapper(SConnection * pCon, SicsInterp * pSics, void *pData,
SCWrite(pCon, pBueffel, eValue); SCWrite(pCon, pBueffel, eValue);
return 1; return 1;
} }
} else if (strcmp(argv[1], "autofocus") == 0) {
if (argc > 2) {
status = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &(self->autofocus));
if (status != TCL_OK) {
SCWrite(pCon, "ERROR: failed to convert argument to number",
eError);
return 0;
}
} else {
snprintf(pBueffel, 131, "%s.autofocus = %d", argv[0], self->autofocus);
SCWrite(pCon, pBueffel, eValue);
return 1;
}
} else if (strcmp(argv[1], "focusfn") == 0) {
if (argc > 2) {
strtolower(argv[2]);
if (strcmp(argv[2], "theta") == 0) {
self->focusfn = THETA_FN;
} else if (strcmp(argv[2], "energy") == 0) {
self->focusfn = ENERGY_FN;
} else {
SCWrite(pCon, "ERROR: Arguments should be theta or energy", eError);
}
} else {
switch (self->focusfn) {
case ENERGY_FN:
snprintf(pBueffel, 131, "%s.focusfn = %s", argv[0], "energy");
break;
case THETA_FN:
snprintf(pBueffel, 131, "%s.focusfn = %s", argv[0], "theta");
break;
}
SCWrite(pCon, pBueffel, eValue);
return 1;
}
} else { } else {
snprintf(pBueffel, 131, "ERROR: subcommand %s to %s not defined", snprintf(pBueffel, 131, "ERROR: subcommand %s to %s not defined",
argv[1], argv[0]); argv[1], argv[0]);

View File

@ -24,6 +24,8 @@
tasQEPosition current; tasQEPosition current;
int tasMode; int tasMode;
int outOfPlaneAllowed; int outOfPlaneAllowed;
int autofocus;
int focusfn;
double targetEn, actualEn; double targetEn, actualEn;
int mustRecalculate; int mustRecalculate;
int mustDrive; int mustDrive;

View File

@ -40,14 +40,22 @@ double KtoEnergy(double k)
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
static double calcCurvature(double B1, double B2, double theta, int ori) static double calcCurvature(double B1, double B2, double B3, double theta, double energy, int ori, int focusfn)
{ {
assert(ori == VERT || ori == HOR); assert(ori == VERT || ori == HOR);
if (focusfn == ENERGY_FN) {
if (ori == VERT) {
return B1 + B2 * energy;
} else {
return B1 + B2 * pow(B3, energy);
}
} else {
if (ori == VERT) { if (ori == VERT) {
return B1 + B2 / Sind(ABS(theta)); return B1 + B2 / Sind(ABS(theta));
} else { } else {
return B1 + B2 * Sind(ABS(theta)); return B1 + B2 * Sind(ABS(theta));
} }
}
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
@ -66,15 +74,15 @@ int maCalcTwoTheta(maCrystal data, double k, double *two_theta)
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
double maCalcVerticalCurvature(maCrystal data, double two_theta) double maCalcVerticalCurvature(maCrystal data, double two_theta, double energy, int focusfn)
{ {
return calcCurvature(data.VB1, data.VB2, two_theta / 2., VERT); return calcCurvature(data.VB1, data.VB2, 1, two_theta / 2., energy, VERT, focusfn);
} }
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
double maCalcHorizontalCurvature(maCrystal data, double two_theta) double maCalcHorizontalCurvature(maCrystal data, double two_theta, double energy, int focusfn)
{ {
return calcCurvature(data.HB1, data.HB2, two_theta / 2., HOR); return calcCurvature(data.HB1, data.HB2, data.HB3, two_theta / 2., energy, HOR, focusfn);
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/

View File

@ -22,6 +22,9 @@
#define KICONST 1 #define KICONST 1
#define KFCONST 2 #define KFCONST 2
#define ELASTIC 3 #define ELASTIC 3
/*========================== defines for focusfn ====================*/
#define ENERGY_FN 1
#define THETA_FN 2
/* /*
* in elastic mode A5, A5 will be disregarded and ki = kf at all times * in elastic mode A5, A5 will be disregarded and ki = kf at all times
*/ */
@ -42,7 +45,7 @@
typedef struct { typedef struct {
double dd; /* lattice spacing */ double dd; /* lattice spacing */
int ss; /* scattering sense */ int ss; /* scattering sense */
double HB1, HB2; /* horizontal curvature parameters */ double HB1, HB2, HB3; /* horizontal curvature parameters */
double VB1, VB2; /* vertical curvature parameters */ double VB1, VB2; /* vertical curvature parameters */
} maCrystal, *pmaCrystal; } maCrystal, *pmaCrystal;
/** /**
@ -109,14 +112,14 @@ int maCalcTwoTheta(maCrystal data, double k, double *two_theta);
* @param two_theta The tow theta value for which to calculate the curvature. * @param two_theta The tow theta value for which to calculate the curvature.
* @return A new value for the curvature. * @return A new value for the curvature.
*/ */
double maCalcVerticalCurvature(maCrystal data, double two_theta); double maCalcVerticalCurvature(maCrystal data, double two_theta, double energy, int focusfn);
/** /**
* calculate the value for the horizontal curvature * calculate the value for the horizontal curvature
* @param data The input crystal parameters * @param data The input crystal parameters
* @param two_theta The tow theta value for which to calculate the curvature. * @param two_theta The tow theta value for which to calculate the curvature.
* @return A new value for the curvature. * @return A new value for the curvature.
*/ */
double maCalcHorizontalCurvature(maCrystal data, double two_theta); double maCalcHorizontalCurvature(maCrystal data, double two_theta, double energy, int focusfn);
/** /**
* calculate the value of the K vector from the angle * calculate the value of the K vector from the angle
* @param data The crystals constants * @param data The crystals constants