#%TITLE% id9eds.mac
#%NAME% Macros for Energy dispersive scattering
#%CATEGORY% Scans, Beamlines
#%DESCRIPTION%
# This macro set is used on beamline ID9 for High Pressure Work for
# the moment. The reciprocal space is searched for reflections.
# Utilities to index this reflections and find other reflections are provided
#%OVERVIEW%
#%DL%
#%DT% Initializing the macro package %DD%
# %UL%
# %LI% You initialize the eds macros with %B%edssetup%B%
# %XUL%
#%DT% Searching for reflections %DD%
# %UL%
# %LI% Searching for reflections in the chi , theta space can be
# done with %B%edssearch%B%
# %XUL%
#%DT% Entering the crystal parameters %DD%
# %UL%
# %LI% You can enter the crystal parameters by hand with %B%setlat%B%
# %LI% You can calculate the lattice and OM with %B%autoindex%B%
# %XUL%
#%DT% Finding the OM %DD%
# %UL%
# %LI% You can create an index file by hand with %B%editlist%B%
# %LI% Calculate the OM and put it into spec with %B%indexcell%B%
# %XUL%
# Another posibility is to enter the OM by hand
# %UL%
# %LI% Enter the OM by hand with %B%enterUB%B%
# %LI% List the OM with %B%listUB%B%
# %XUL%
#%DT% Refining the OM %DD%
# %UL%
# %LI% You can refine the OM with %B%leastsquares%B%
# %XUL%
#%DT% Working with the OM %DD%
# %UL%
# %LI% You can go to an angle specified by hkl with %B%angles%B%.
# %LI% You can calculate hkl for a specific set of angles with %B%hkl%B%.
# %LI% You can index a complete reflection file with %B%indexfile%B%
# %LI% You can create all the accessible reflections and put them
# into a file with %B%calcall%B%
# %LI% You can move to all these reflections easily with
# %B%nextref%B%
# %XUL%
#%DT% File format %DD%
# The following file format for reflection files is used : %BR%
# %5d %5.2f %5.2f %5.2f %7.2f %10.4f %10.4f %10.4f %7d %6.3f %1d %3d %BR%
# <Reflection number> , <H> , <K> , <L> , <Energy in keV>, <Omega in degree>,
# <Chi in degree>, <Phi in degree>, <Intensity in integr. counts>,
# <FWHM in keV> <Flag for multiplett> <flag if selected> %BR%
# Reflections have flag=1 after search procedure, flag=16 means
# that the reflaction is selected.
#%XDL%
#%ATTENTION%
# Do not forget to select reflections (flag set to 16), for those reflections
# you would like to use in the different external programs (like
# calculating the OM , auoindexing, ...)
#
#%UU% [two-theta minth maxth]
#%MDESC% This macro initializes the global variables and ask the user
# for some values which will not change later. It has to be called
# before doing anything else. The user is asked to enter the two-theta
# angle, where he would like to carry out the measurement and limits
# for the theta movement.
def edssetup '
{
global EDSSEARCHFILE EDSAN0 EDSAN1 EDSAN2 EDSMNE EDSSPEED
global EDSOLDSPEED EDSOLDBASE EDS_WA EDS_WB EDSSNO EDSMNE EDS_LINES EDS_MAXNO
global EDS_RESGROUP EDS_ED EDS_TTH EDS_COMMENT EDSMNO
global EDS_INDth EDS_INDtth EDS_INDchi
global EDS_MINC EDS_MAXC EDS_PEAKS
global MIN_EN MAX_EN MIN_INT EDSREFLFILE
global EDS_IPR EDS_MINTHT EDS_MAXTHT EDSREFLECTIONS
# Initialize global variables
EDS_IPR=12 # Number of items per data record
EDS_MINC=0 # min channel to read
EDS_MAXC=4095 # max channel
double array EDS_RES[2048][EDS_IPR]
EDSMNO = 2 ; EDSMNE[0]="mchi" ; EDSMNE[1]="mth" ; EDSMNE[2]="twot"
if ($# != 3) {
EDS_TTH=getval("Two Theta",EDS_TTH)
EDS_MINTHT=getval("Minimum Value of theta",EDS_MINTHT)
EDS_MAXTHT=getval("Maximum Value of theta",EDS_MAXTHT)
} else {
EDS_TTH=$1 ; EDS_MINTHT=$2 ; EDS_MAXTHT=$3
}
EDS_ED=12.398/2/sin(EDS_TTH/2*PI/180)
EDS_INDchi = motor_num(EDSMNE[0]) ; EDS_INDth = motor_num(EDSMNE[1])
EDS_INDtth = motor_num(EDSMNE[2])
if ((EDS_INDchi == -1) || (EDS_INDth == -1) || (EDS_INDtth == -1)) {
printf ("ERROR: %s, %s and %s must be defined!\n",\
EDSMNE[0],EDSMNE[1],EDSMNE[2])
exit
}
EDSOLDSPEED=motor_par(EDS_INDth,"velocity")
EDSOLDBASE=motor_par(EDS_INDth,"base_rate")
}
'
#%IU%
#%MDESC%
# This macro is called from edssearch to ask the user for the parameters
# of the search to be carried out.
def edssearchinput '
{
local range
EDSSEARCHFILE=getval("Filename of the search result file",EDSSEARCHFILE)
EDSSPEED=getval("Theta scan speed in seconds per degree ",EDSSPEED)
printf("FWHM = sqr[a^2 + b*E + (c*E)^2]\n")
EDS_WA=getval("Term (a) in keV",EDS_WA)
EDS_WB=getval("Term (b) in keV",EDS_WB)
EDS_WC=getval("Term (c) ",EDS_WC)
MIN_EN=getval("Minimum Energy to save",MIN_EN)
MAX_EN=getval("Maximum Energy to save",MAX_EN)
MIN_INT=getval("Minimum Intensity to save",MIN_INT)
for (ii=0;ii<EDSMNO;ii++) {
EDSAN0[ii]=getval(sprintf("From %s",EDSMNE[ii]),EDSAN0[ii])
EDSAN1[ii]=getval(sprintf("To %s",EDSMNE[ii]),EDSAN1[ii])
EDSAN2[ii]=getval(sprintf("Step size %s",EDSMNE[ii]),EDSAN2[ii])
}
# Prepare file EDSSEARCHFILE (delete if user wants to and write header
# for new file
EDSSNO=0
if (!unix(sprintf("test -r %s",EDSSEARCHFILE))) {
edsreadfile EDSSEARCHFILE 1
EDSSNO =EDS_MAXNO+1
if (yesno(sprintf("Delete the existing file %s",EDSSEARCHFILE),0)) {
close(EDSSEARCHFILE)
unix(sprintf("/bin/rm -f %s",EDSSEARCHFILE))
EDSSNO = 0
}
}
if (!EDSSNO) {
EDS_COMMENT=getval("Enter Description of Experiment ",EDS_COMMENT)
eds_fileheader EDSSEARCHFILE "edssearch" 1
}
}'
#%IU%
#%MDESC% Move eds two theta motor to EDS_TTH
def eds_movetth '
waitmove ; eds_getangles ; A[EDS_INDtth] = EDS_TTH ; move_em ; waitmove
'
#%IU%
#%MDESC% Move eds theta motor to EDS_AN0[1] and chi to EDS_AN0[0]+nchi*chistep
def eds_movechi '
waitmove ; eds_getangles
A[EDS_INDchi] = EDSAN0[0]+nchi*chistep ; A[EDS_INDth] = EDSAN0[1]
move_em ; waitmove
'
#%IU%
#%MDESC% Starts the theta motor
def eds_startmoveth '
waitmove ; eds_getangles ; A[EDS_INDth] = EDSAN0[1]+nth*thstep ; move_em
'
#%IU%
#%MDESC% Calculates thcen and thdelta. In the old version the search
#subdivided the th steps to get better resolution. As this was not
#used it is removed in this version
def eds_getthdth '
thcen = A[EDS_INDth] - thstep/2
thdelta = thstep/2
'
#%IU%
#%MDESC%
# A get_angles with printing the motor positions on the screen.
#
def eds_getangles '
get_angles
printf ("Chi: %10.4f Theta: %10.4f\r",A[EDS_INDchi],A[EDS_INDth])
'
#%IU%
#%MDESC%
# Moves theta motor slowly and aquires data on the mca
def eds_searchth '
{
waitmove
eds_slow
eds_mcaacqstart
eds_startmoveth
# This part counts on the MCA during motor movement
eds_mcaacqstop
eds_fast
}'
#%IU%
#%MDESC%
# Searches for peaks in the energy spectrum, plots the spectrum and
# writes the result into the file and on the screen.
def eds_findpeak '
eds_psearch
eds_plotspectrum
eds_writeinfile
'
#%UU%
#%MDESC% This macro initiates the actual search procedure. The user
# is asked to specify the necessary parameters and the search is
# started. The following questions are asked:
# %PRE%
# Filename of the search result file All output will go to this file
# Theta scan speed in seconds per degree
# FWHM = sqr[a^2 + b*E + (c*E)^2] These parameters are used for
# Term (a) in keV the peak search (in the Energy
# Term (b) in keV spectrum).
# Term (c)
# Minimum Energy to save These parameter allow to
# Maximum Energy to save restrict the peaks which will
# Minimum Intensity to save be accepted
# and for every angle
# From <angle> A step scan in chi and a continous
# To <angle> scan in theta will be carried
# Step size <angle> out.
# %PRE%
# The following procedure is used to search for scans :
# %UL%
# %LI% Move two theta angle to the user specified value
# %LI% Make a step scan in chi
# %LI% At every point in chi move theta slowly (speed asked above)
# to the next theta point. During this time acquire on the MCA.
# %LI% If peaks in the energy spectrum are found which satisfy the
# user conditions, they are written to the file
# %XUL%
def edssearch '
{
local manchi chistep manth
edssearchinput
eds_fast
eds_initmca
# Calculate nb of steps and stepsize for chi (manchi,chistep) ,
# and th (manth,thstep)
manchi=int(fabs(EDSAN1[0]-EDSAN0[0])/EDSAN2[0])+1
chistep = (EDSAN1[0]-EDSAN0[0]) / (manchi-1)
manth=int(fabs(EDSAN1[1]-EDSAN0[1])/EDSAN2[1])+1
thstep = (EDSAN1[1]-EDSAN0[1]) / (manth-1)
# The main loop
eds_movetth
for (nchi=0; nchi<manchi; nchi++) {
eds_movechi
for (nth=1; nth<manth; nth++) {
eds_searchth
eds_findpeak
}
}
}
'
#%IU%
#%MDESC% Sets the velocity and base rate of the theta motor to the
# saved normal speeds EDSOLDSPEED and EDSOLDBASE
def eds_fast '
motor_par(EDS_INDth,"velocity",EDSOLDSPEED)
motor_par(EDS_INDth,"base_rate",EDSOLDBASE)
'
#%IU%
#%MDESC% Sets the velocity and base rate to the slow EDSSPEED (in
# s/degree)
def eds_slow '
{
stepsize=fabs(motor_par(EDS_INDth,"step_size"))
motor_par(EDS_INDth,"velocity",stepsize/EDSSPEED)
motor_par(EDS_INDth,"base_rate",stepsize/EDSSPEED)
}
'
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Attention this parts uses mca macros
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
def eds_mcaacqstart '
mcaclear
mcastart 0
'
def eds_mcaacqstop '
while (chk_move) {
mca_read EDS_MINC EDS_MAXC
}
mcastop
mca_read EDS_MINC EDS_MAXC
'
def eds_initmca '
# prepare step scans
# Turn ON energy Mode if calibrated
if (MCA_EB <= 0) {
p "ERROR: MCA is not calibrated in Energy - You have to do that first"
exit
}
MCA_ENERGY=1
'
def eds_plotspectrum '
mca_plotit MCA_AUTO MCA_AUTO MCA_AUTO MCA_AUTO
'
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Attention - this part uses the psearch macros
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
def eds_psearch '
mca_tops # Will update PS_EA PS_EB PS_EC calibration parameters from interface
EDS_PEAKS = pssearch (MCA_DATA[][1],0,MCA_MEMGRPSIZE, \
EDS_WA, EDS_WB, EDS_WC, 1, MIN_INT,0)
'
def eds_getpeakvalue '
{
idx = $1
if (idx < EDS_PEAKS) {
p_energy = PS_PEAKS[idx][5] # [1] is the position in channels
p_intens = PS_PEAKS[idx][2]
p_fwhm = PS_PEAKS[idx][6] # [3] is the fwhm in channels
p_multi = PS_PEAKS[idx][4] ? 1 : 0 ;
p_no_more_peaks = 0
} else {
p_no_more_peaks = 1
}
}'
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# File in/output
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#%IU%
#%MDESC% Writes the result from the peak search together with the
# current angles to the search file
def eds_writeinfile '
waitmove ; eds_getangles
for(jj=0;;jj++) {
local p_energy p_fwhm p_multi p_intens
local omega thcen thdelta
eds_getpeakvalue jj
if (p_no_more_peaks) break;
eds_getthdth
omega = thcen - A[EDS_INDtth]/2
if ((p_energy > MIN_EN) && (!MAX_EN || p_energy < MAX_EN) \
&& (!MIN_INT || p_intens > MIN_INT)) {
printf(\
"%5d %7.2f %10.4f %10.4f %5.2f %7d %6.3f %1d \n",\
++EDSSNO,p_energy,thcen,A[EDS_INDchi],0.,\
p_intens,p_fwhm,p_multi)
fprintf(EDSSEARCHFILE,\
"%5d %5.2f %5.2f %5.2f %7.2f %10.4f %10.4f %10.4f %7d %6.3f %1d %3d\n",\
EDSSNO,0,0,0,p_energy,omega,A[EDS_INDchi],0.,\
p_intens,p_fwhm,p_multi,1)
}
}'
#%IU% [filename] [print-flag]
#%MDESC% Reads file with EDS_IPR items per line and comment lines
# in the array EDS_RES. If print-flag is true, every line will
# be printed on the screen. %BR%
# EDS_LINES will hold the number of data lines and EDS_MAXNO will have
# the maximum value in the first column (The peak number).
def edsreadfile '
{
local _f
if ($# > 0) {_f=$1} else {_f=getval("Filename to read reflections","")}
if (file_info(_f,"-r") == 1) {
# array_read dows not return the number of lines just ignore
# EDS_LINES=array_read(_f, EDS_RES)
EDS_RES[][0]=0
array_read(_f, EDS_RES)
EDS_LINES=array_op("sum",(EDS_RES[][0] != 0))
EDS_MAXNO=array_op("max",EDS_RES[:EDS_LINES][0])
printf("%d datapoints read from file %s\n",EDS_LINES,_f)
} else {
print "File ",_f,"does not exist"
exit
}
}'
#%IU% [filename] [macro name for comment]
#%MDESC% Writes file with reflections with data from EDS_RES
# EDS_LINES holds the number of data lines.
#
def edswritefile '{
local _f cnt
if ($# > 0) {
_f=$1
} else {
_f=getval("Filename to save reflections","")
}
if (file_info(_f,"-r") == 1) {
close (_f)
unix(sprintf("mv %s %s.bak",_f,_f))
}
# Save group to file with comments
eds_fileheader _f "$2"
# Format: no H K L E/tth omega chi phi I fwhm multi flag
for(ii=0,cnt=1; ii<EDS_LINES; ii++) {
if (EDS_RES[ii][0]) fprintf(_f,\
"%5d %5.2f %5.2f %5.2f %7.2f %10.4f %10.4f %10.4f %7d %6.3f %1d %3d\n",\
cnt++,EDS_RES[ii][1],EDS_RES[ii][2],EDS_RES[ii][3], \
EDS_RES[ii][4],EDS_RES[ii][5],EDS_RES[ii][6],EDS_RES[ii][7], \
EDS_RES[ii][8],EDS_RES[ii][9],EDS_RES[ii][10],EDS_RES[ii][11])
}
close(_f)
} '
def eds_listrefl '{
local ii
for(ii=0;ii<EDS_LINES;ii++) {
if (EDS_RES[ii][0])
printf(\
"%5d %5.2f %5.2f %5.2f %7.2f %10.4f %10.4f %10.4f %7d %6.3f %1d %3d\n",\
EDS_RES[ii][0],EDS_RES[ii][1],EDS_RES[ii][2],EDS_RES[ii][3], \
EDS_RES[ii][4],EDS_RES[ii][5],EDS_RES[ii][6],EDS_RES[ii][7], \
EDS_RES[ii][8],EDS_RES[ii][9],EDS_RES[ii][10],EDS_RES[ii][11])
}
}'
#%IU% <filename> <macro name for comment> [no geo parameters]
#%MDESC% Saves information in the file header for reflection list and
#other files, The header includes USER, SPEC, date(), EDS_COMMENT,
#lattice const, UB. The third parameter can be set to 1 if no
#geometric parameters like OM and lattice should be in the header.
def eds_fileheader ' {
local _fn
_fn = $1
fprintf(_fn,"#C %20s %20s %30s\n","User","Version","Date")
fprintf(_fn,"#H %20s %20s %30s\n",USER,SPEC,date())
fprintf(_fn,"#U Description: %-55s\n",EDS_COMMENT)
if ($3 == 0) {
fprintf(_fn,"#U Lattice Constants: %8.4f %8.4f %8.4f %7.3f %7.3f %7.3f\n",\
g_aa,g_bb,g_cc,g_al,g_be,g_ga)
fprintf(_fn,"#U OM1: %10.6f %10.6f %10.6f\n",UB[0]/PI2,UB[3]/PI2,UB[6]/PI2)
fprintf(_fn,"#U OM2: %10.6f %10.6f %10.6f\n",UB[1]/PI2,UB[4]/PI2,UB[7]/PI2)
fprintf(_fn,"#U OM3: %10.6f %10.6f %10.6f\n",UB[2]/PI2,UB[5]/PI2,UB[8]/PI2)
}
fprintf(_fn,"#C Created by : $2\n")
fprintf(_fn,"#C Two Theta : %f Theta Limits: %f - %f\n", \
EDS_TTH,EDS_MINTHT,EDS_MAXTHT)
fprintf(_fn,"#C No H K L E Omega Chi Phi I FWHM Multi Flag\n")
} '
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# This section is for the geometric calculations
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#%IU%
#%MDESC% This macro does something very tricky
# be able to load the OM into SPEC. The problem is that SPEC has a
# Flag set either if it starts up or if somebody calls calcG that the
# OM should be recalculated on the next calcA from the primary and
# secondary orientations. So all what I can think of is to force a
# recalculation before loading the matrix.
def eds_preloadmatrix '
H=1; K=0; L=0; calcA
'
#%UU% [E chi th]
#%MDESC% This macros calculates the HKL for a given E,th,chi pair.
def hkl '{
local l_chi l_E l_om l_thy
if ($#) {
l_E = $1
l_chi = $2
l_th = $3
} else {
get_angles
l_E = getval("Energy of the reflection [keV]",35)
l_chi = getval("Chi of the reflection",A[EDS_INDchi])
l_th = getval("Theta of the reflection",A[EDS_INDth])
}
l_om = l_th - EDS_TTH/2
eds_eds2hkl l_E l_om l_chi
printf("H K L = %.5g %.5g %.5g\n",H,K,L)
printf("\n%9.9s %9.9s %9.9s\n","E","chi","th")
printf("%9.4f %9.4f %9.4f\n",l_E,l_chi,l_th)
}'
#%UU%
#%MDESC% Indexes a reflection list by using spec`s orientation matrix.
#The old hkl from the reflection list will be deleted from the file.
def indexlist '
{
local ii
EDSINDEXFILE = getval("Name of the file to index",EDSINDEXFILE)
edsreadfile EDSINDEXFILE 0
for (ii=0;ii<EDS_LINES;ii++) {
eds_eds2hkl EDS_RES[ii][4] EDS_RES[ii][5] EDS_RES[ii][6]
EDS_RES[ii][1] = H ; EDS_RES[ii][2] = K ;EDS_RES[ii][3] = L
}
edswritefile EDSINDEXFILE "indexlist"
printf("Indexing completed.\n")
}'
#%IU% <E> <omega> <chi>
#%MDESC% This macro calculates the fourc angles from the eds "angles"
# E omega chi. The fourc values are returned in the variables
# ftth, fth, fchi, and fphi. It uses the LAMBDA and EDS_ED.
def eds_eds2fourc '
{
fphi = 0
fchi = $3
ftth = asin(LAMBDA*0.5/EDS_ED*$1)*360/PI
fth = $2+0.5*ftth
} '
#%IU% <E> <omega> <chi>
#%MDESC% This macro calculates hkl given in H K L from the eds
# "angles" E omega chi
def eds_eds2hkl '
{
local ftth fth fchi fphi
eds_eds2fourc $1 $2 $3
get_angles ; A[tth]=ftth ; A[th]=fth ; A[chi]=fchi ; A[phi]=fphi
calcHKL
} '
#********************************************************
#%UU%
#%MDESC%
# Asks user to enter the Orientation matrix in the UB array
# Rows have to be entered, separated by space.
def enterUB ' {
local x
print "Enter Orientation Matrix by Row"
eds_preloadmatrix
x = getval("Row 1:",sprintf("%f %f %f",UB[0]/PI2,UB[3]/PI2,UB[6]/PI2))
sscanf(x,"%f %f %f",UB[0],UB[3],UB[6])
x = getval("Row 2:",sprintf("%f %f %f",UB[1]/PI2,UB[4]/PI2,UB[7]/PI2))
sscanf(x,"%f %f %f",UB[1],UB[4],UB[7])
x = getval("Row 3:",sprintf("%f %f %f",UB[2]/PI2,UB[5]/PI2,UB[8]/PI2))
sscanf(x,"%f %f %f",UB[2],UB[5],UB[8])
eds_multUB2PI
}'
#%IU%
#%MDESC% Multiplies Spec UB by 2 * PI
def eds_multUB2PI '
{
local ii
for (ii=0;ii<9;ii++) {
UB[ii] *= PI2
}
}'
def PI2 '(PI*2)'
#********************************************************
#%UU%
#%MDESC%
# Prints the UB matrix on the screen
def listUB '
{
print "Orientation Matrix by Row:"
print ""
printf("Row 1: %10.5f %10.5f %10.5f\n",UB[0]/PI2,UB[3]/PI2,UB[6]/PI2)
printf("Row 2: %10.5f %10.5f %10.5f\n",UB[1]/PI2,UB[4]/PI2,UB[7]/PI2)
printf("Row 3: %10.5f %10.5f %10.5f\n",UB[2]/PI2,UB[5]/PI2,UB[8]/PI2)
}
'
#%UU%
#%MDESC%
# This macro calls the external program refine_cell_spec to do a least
# square fit on all the selected (with flag bit 0x10 set to 1) reflections
# in a file.
def leastsquares '
{
global EDSINDEXFILE
local res ftemp lat ff
EDSINDEXFILE=getval("Index file name (for least square fit)",EDSINDEXFILE)
res=data_pipe("refine_cell_spec",sprintf("%s %f",EDSINDEXFILE,EDS_ED),0,0)
if (split(res,ftemp) == 15) {
eds_preloadmatrix
for (i=0;i<9;i++) {
UB[i]=ftemp[i]*PI2 # det(OM) = 2 Pi in spec , 1 in calc_om_spec
}
for (i=9;i<15;i++) {
ff[i-9]=ftemp[i]+0.0
}
setlat ff[0] ff[1] ff[2] ff[3] ff[4] ff[5]
} else {
print "Error in refining cell"
}
}
'
#%UU%
#%MDESC%
# This macro calls the external program autoindex_spec to try to find
# the indexes of the selected (with flag bit 0x10 set to 1) reflections
# in a file.
def autoindex '
{
global EDSINDEXFILE
local res ftemp lat ff
EDSINDEXFILE=getval("Index file name (for least square fit)",EDSINDEXFILE)
res=data_pipe("autoindex_spec",sprintf("%s %f",EDSINDEXFILE,EDS_ED),0,0)
if (split(res,ftemp) == 15) {
eds_preloadmatrix
for (i=0;i<9;i++) {
UB[i]=ftemp[i]*PI2 # det(OM) = 2 Pi in spec , 1 in calc_om_spec
}
for (i=9;i<15;i++) {
ff[i-9]=ftemp[i]+0.0
}
setlat ff[0] ff[1] ff[2] ff[3] ff[4] ff[5]
} else {
print "Error in autoindexing"
}
}
'
#********************************************************
#%UU%
#%MDESC% The macro calls the external program calc_om_spec to
# calculate the orientation matrix from reflections in a file
# (default EDSINDEXFILE). The user selects the reflections and enters
# at the keyboard the hkl values. The orientation matrix is calculated
# and inserted into spec.
def indexcell '
{
global EDS_UB EDSINDEXFILE
local i ii file ftemp lat
lat=sprintf("%f %f %f %f %f %f %f",EDS_ED,g_aa,g_bb,g_cc,g_al,g_be,g_ga)
EDSINDEXFILE = getval("Index file name (to calc. OM)",EDSINDEXFILE)
res = data_pipe("calc_om_spec",sprintf("%s %s",EDSINDEXFILE,lat),0,0)
if (split(res,ftemp) == 9) {
eds_preloadmatrix
for (i=0;i<9;i++) {
UB[i]=ftemp[i]*PI2 # det(OM) = 2 Pi in spec , 1 in calc_om_spec
}
} else {
print "Error in indexing cell"
}
}
'
#%UU% <h> <k> <l>
#%MDESC% Calculates E, theta (omega), chi for the given h k l and
# offers the user a choice to move the motors to this position
def angles '
{
local ftemp h k l v_omega v_chi v_energy v_theta
h=$1 ; k=$2 ; l=$3
if ($# < 3) {
printf("Usage: angles h k l\n")
exit
}
eds_calcangles h k l
if (v_theta > EDS_MAXTHT || v_theta < EDS_MINTHT ) {
printf("Out of Bounds (%f < th < %f)\n",EDS_MINTHT,EDS_MAXTHT)
} else {
printf(" Energy: %10.4f; Theta: %10.4f; Chi: %10.4f\n" \
,v_energy,v_theta,v_chi)
if (yesno("Drive to Position",0)) {
get_angles
A[EDS_INDth] = v_theta
A[EDS_INDchi] = v_chi
move_em
_update2 EDS_INDth EDS_INDchi
}
}
}
'
#%UU%
#%MDESC% Add reflections to a list of reflection, edit reflection
# list. Very primitive for the moment. Should be replaced with an
# editor later. For the moment you can enter the following commands:
# %DL%
# %DT% L %DD% List all reflections. This is the default action when you
# just type ENTER.
# %DT% D %DD% Delete one reflection. You will be asked for a reflection
# number. The reflections will be renumbered only when written
# to disk.
# %DT% A %DD% Add a reflection by hand. You will be asked to enter the
# energy, th and chi where you found the reflection.
# %DT% M %DD% Mark a reflection so it will be used by further programs (like
# autoindexing, least square fitting or index cell). Marked
# lines will have a 16 in the last column.
# %DT% M %DD% Restore all reflections from the index file. All your changes
# will be lost.
# %DT% E %DD% Call the editor (specified in the global variable EDITOR) to
# edit the reflection list. You will not be editing the index
# file directly , but a temporary file. Only when you write
# the changes back to the index file when you quit, will you make
# your changes permanent.
# %DT% Q %DD% Quit the editor. You will be asked if you want to save your
# changes. The default answer is yes. If you do not save your
# changes, then they will be lost.
# %XDL%
def editlist '{
global EDS_UB EDSINDEXFILE
local _f ii idx g v_ene v_chi v_theta i
global EDS_GR_MOD
rdef cleanup \'
undef cleanup
eds_savegroup
\'
EDS_GR_MOD=0
EDSINDEXFILE = getval("Index file name (to edit)",EDSINDEXFILE)
if (file_info(EDSINDEXFILE,"-r") == 1) {
edsreadfile EDSINDEXFILE 1
} else {
p "File",EDSINDEXFILE,"does not exit (will be created)"
EDS_LINES = 0
}
while (1) {
cho = getval(\
"(L)ist (D)elete (A)dd (M)ark Refl., (R)estore, (E)dit, (Q)uit","l");
if (cho == "x" || cho == "q")
break;
if (cho == "l") {
eds_listrefl
continue;
}
if (cho == "r") {
edsreadfile EDSINDEXFILE 0
EDS_GR_MOD=0
}
if (cho == "e") {
tempf = sprintf("/tmp/,editl_%s_%s.tmp",SPEC,USER)
unix (sprintf("/bin/rm -f %s",tempf))
edswritefile tempf "editlist"
unix (sprintf("%s %s",EDITOR,tempf))
edsreadfile tempf 0
EDS_GR_MOD=1
}
if (cho == "m") {
rno = getval("Enter reflection number to mark",rno)
for (idx = -1, ii=0; ii<EDS_LINES; ii++)
if (EDS_RES[ii][0] == rno) {
idx = ii;
break;
}
if (idx != -1) {
EDS_RES[ii][EDS_IPR-1] = 16
EDS_GR_MOD=1
}
}
if (cho == "d") {
rno = getval("Enter reflection number to delete",rno)
for (idx = -1, ii=0; ii<EDS_LINES; ii++)
if (EDS_RES[ii][0] == rno) {
idx = ii;
break;
}
if (idx != -1) {
EDS_RES[ii][0] = 0
EDS_GR_MOD=1
}
}
if (cho == "a") {
ii=EDS_LINES++
# ask user
v_ene=getval("Energy of peak",v_ene)
v_chi=getval("Chi of peak",A[EDS_INDchi])
v_theta=getval("Theta of peak",A[EDS_INDth])
# Put in array
v_omega=v_theta-EDS_TTH/2
for(i=0;i<EDS_IPR;i++) {
EDS_RES[ii][i] = 0
}
EDS_RES[ii][0] = EDS_LINES
EDS_RES[ii][EDS_IPR-1] = 16 # select this peak for calc_om and ....
EDS_RES[ii][4] = v_ene; EDS_RES[ii][5] = v_omega; EDS_RES[ii][6] = v_chi
EDS_GR_MOD=1
}
}
}
cleanup
'
#%IU%
#%MDESC% Saves group into file if EDS_GR_MOD is true. Will be called
#from cleanup. Used in editlist.
def eds_savegroup '
if (EDS_GR_MOD) {
if (yesno(sprintf("Save your changes to file (%s)",EDSINDEXFILE),1)) {
print "Saving modified group to file .. "
edswritefile EDSINDEXFILE "editlist"
}
}
'
#%UU%
#%MDESC% Calculates all possible reflections up to a certain energy.
# Only reflections are included which can not be divided by 2 or 3.
# (These reflections are at the same chi/th with twice (three times)
# the energy)
def calcall '
{
global EDSREFLECTIONS EDS_REF_FILE_OPEN EDS_EMAX
local ftemp h k l _f emax ihmax ikmax ilmax dinv energy chi omega
local ncalc ninrange hdiv_2 hdiv_3 hkdiv_2 hkdiv_3 hkldiv_2 hkldiv_3
printf("Generate Entire Reflection List\n")
EDSREFLECTIONS = getval("Enter Name of Reflection File",EDSREFLECTIONS)
_f = EDSREFLECTIONS
if (open(_f)) {
} else {
close(_f)
unix(sprintf("mv %s %s.bak",_f,_f))
}
eds_fileheader EDSREFLECTIONS "calcall"
EDS_EMAX=getval("Maximum Reflection Energy to Generate",EDS_EMAX)
# h,k,l max from length of col vector of UB (/2Pi because of spec convent)
efund=EDS_ED*sqrt((UB[0]*UB[0]+UB[3]*UB[3]+UB[6]*UB[6]))/PI2
ihmax=int(EDS_EMAX/efund)+1
efund=EDS_ED*sqrt((UB[1]*UB[1]+UB[4]*UB[4]+UB[7]*UB[7]))/PI2
ikmax=int(EDS_EMAX/efund)+1
efund=EDS_ED*sqrt((UB[2]*UB[2]+UB[5]*UB[5]+UB[8]*UB[8]))/PI2
ilmax=int(EDS_EMAX/efund)+1
ncalc=0 ; ninrange=0 # numb. of refl calculated and numb. in th range
# triple loop : loop 0<h<ihmax , -ikmax<k<ikmax , -ilmax<l<ilmax
for (h=0; h<=ihmax; h++) {
hdiv_2 = h%2 ; hdiv_3 = h%3 # true if h can not be divided by 2 (3)
for (k=-ikmax; k<=ikmax; k++) {
hkdiv_2= hdiv_2 ? 1 : fabs(k)%2 ; hkdiv_3= hdiv_3 ? 1 : fabs(k)%3 ;
for (l=-ilmax; l<ilmax; l++) {
hkldiv_2 = hkdiv_2 ? 1:fabs(l)%2 ; hkldiv_3 = hkdiv_3 ? 1:fabs(l)%3 ;
# if hkl can be divided by 2 (3) then do not include
if ( hkldiv_2 == 0 || hkldiv_3 == 0 ) continue
if (h == 0 && k == 0 && l == 0) continue
eds_calcangles h k l
if (v_energy > 0 && v_energy <= EDS_EMAX) {
ncalc++
dobs = EDS_ED/v_energy
if (v_theta > EDS_MAXTHT || v_theta < EDS_MINTHT) {
} else {
fprintf(_f,\
"%5d %5.2f %5.2f %5.2f %7.2f %10.4f %10.4f %10.4f %7d %6.3f %1d %3d\n",\
ninrange+1,h,k,l,v_energy,v_omega,v_chi,0.,0.,0.,0,0)
ninrange++
}
}
}
}
}
close(_f)
printf("%7d Refl. within Energy range. (E < %f)\n",ncalc,EDS_EMAX)
printf("%7d Refl. within Theta Limits. (%f < t < %f) \n",ninrange,\
EDS_MINTHT,EDS_MAXTHT)
EDS_REF_FILE_OPEN = 0
}
'
#%IU% h k l
#%MDESC% Used to calculate chi, omega, and theta from h k l
# The output variable names are fixed to v_chi, v_omega v_theta v_energy
def eds_calcangles '
ftemp[0]=(UB[0]*$1 + UB[1]*$2 + UB[2]*$3)/PI2
ftemp[1]=(UB[3]*$1 + UB[4]*$2 + UB[5]*$3)/PI2
ftemp[2]=(UB[6]*$1 + UB[7]*$2 + UB[8]*$3)/PI2
dinv = sqrt(ftemp[0]*ftemp[0]+ftemp[1]*ftemp[1]+ftemp[2]*ftemp[2])
v_energy = EDS_ED * dinv
if (ftemp[0] == 0) {
v_chi = 0
} else {
v_chi=atan(ftemp[2]/ftemp[0])*180/PI
if (ftemp[0] <0) {v_chi=v_chi-180}
if (v_chi < -180) { v_chi=v_chi+360}
}
v_omega=asin(ftemp[1]/dinv)*180/PI
v_theta=v_omega+EDS_TTH/2
'
#%UU% [force_new_file_flag]
#%MDESC% This macro goes to the next reflection from a user specified
# reflection file. The angles are calculated from (hkl) in the file.
# If a parameter is given, it will ask the file name , otherwise it will
# ask the file name only the first time it is called.
def nextref'
{
global EDSREFLECTIONS EDS_NEXTREFL EDS_REF_FILE_OPEN
local _f line ftemp hh kk ll
if ($# != 0 || EDS_REF_FILE_OPEN == 0) {
EDSREFLECTIONS = getval("Enter Name of Reflection File",EDSREFLECTIONS)
edsreadfile EDSREFLECTIONS 0
EDS_NEXTREFL = 0
EDS_REF_FILE_OPEN = 1
}
if (EDS_NEXTREFL >= EDS_LINES) {
printf("End of Reflection file (%s) reached\n",EDSREFLECTIONS)
EDS_REF_FILE_OPEN = 0
exit
}
hh = EDS_RES[EDS_NEXTREFL][1]
kk = EDS_RES[EDS_NEXTREFL][2]
ll = EDS_RES[EDS_NEXTREFL][3]
printf("** Reflection %d from file %s\n",++EDS_NEXTREFL,EDSREFLECTIONS)
angles hh kk ll
} '
#%MACROS%
#%IMACROS%
#%BUGS%
# There are some bugs or questions to be fixed
# %PRE%
# * Why are all the reflections ignored which can be divided by 2 or 3
# in calcall. Not all people might want to have that.
# * Autoindexing finds sometimes no suitable cr. and put metric tensor
# to 0
# * the interaction with psearch and mca has been isolated but that is
# probably not good enough
# %PRE%
#%AUTHOR% Larry Finger, Jorg Klora 93/94/95/96
#%TOC%
|