esrf

Beamline Instrument Software Support
SPEC Macro documentation: [ Macro Index | BCU Home ]

#%TITLE% cen.mac
#%NAME%
#  Centering macros. OBSOLETE.
#
#%CATEGORY% Scans, obsolete
#
#%DESCRIPTION%
#  This macro set is OBSOLETE. Kept here as example
#
#  This set of macros will try to find the center of a reflection in the
#  angle sequence specified by the user. 
#  It will do a scan in the first angle, go to the center of the peak found,
#  do a scan in the next angle, and so on.
#  Initially it takes a user supplied scan width, but after the first cycle,
#  it adjusts the scan width depending on FWHM found.
#  The sequence is repeated until either convergence or a max 
#  number of cycles is found. %BR%
#  This routine can be used in conjunction with the SEARCH routine, either
#  directly inside, or from the search results file.
#
#%EXAMPLE%
#  %PRE%
#  %B%cen_seq%B%
#    Defines the centering sequence -  Angle names and convergence criteria
#     Angle number 1
#       Name?: [ 0 to end]:  (0)? th 
#       Give data for: th
#        Initial scan width: (1)? 1.5
#        Initial scan step size:  (0)? .1
#        Minimum step size: (0)? 0.05
#        Max shift to define convergence:  (0)? 0.02
#        Recenter if already converged (NO)? YES 
#     Angle number 2
#       Name?: [ 0 to end]:  (0)? chi
#       Give data for: chi
#        Initial scan width: (3)? 6
#        Initial scan step size:  (0)? .25
#        Minimum step size: (0)? .2
#        Max shift to define convergence:  (0)? .05
#        Recenter if already converged (NO)? YES
#     Angle number 3
#       Name?: [ 0 to end]:  (0)? 0
#    2 angles in sequence -  th chi
#  %B%cen_here%B%
#    The centering will start from the current angles.
# %PRE%
#
#%LOG%
#
#  $Revision: 3.1 $
#
#  $Log: cen.mac,v $
#  Revision 3.1  2008/02/27 13:19:36  rey
#  documentation changes
#
#%END%

##############################################################################
#This routine does the centering cycles

#%IU%     
#%MDESC%
#    This routine does the real centering

def cen_do_it '{
global CENANAME CENMOTCYC CENSSEQ CEN_START_ANG BESTANG I_CYC FOUND
global CONV CENWIDTH COUNTTIME CENSHIFT THIS TRY1 TRY2 BEST_CPS
global START STOP STEP COUNT NPT
local cen_ok done
#set up initial parameters for first cycle
COUNT = CENITIME ; BEST_CPS=0
for (THIS=0;THIS<CENMOTCYC;THIS++) {
  CENWIDTH[THIS]=CENIWIDTH[THIS]
  BESTANG[THIS]=CEN_START_ANG[THIS]
  CONV[THIS]=0		# set converged false
  cen_ok[THIS]=0		# set skip false.
 }
#make sure starting angles are setup
cen_mv 
#
for (I_CYC=0,n=0;I_CYC<CENNCYC;I_CYC++) { # MAX NUMBER OF CENTERING CYCLES
  for (THIS=0;THIS<CENMOTCYC;THIS++) { # NUMBER OF ANGLES IN EACH CYCLE
    n++
    if (cen_ok[THIS]==0) {		# IF WE SHOULD DO THIS ONE
       if (I_CYC == 0) 			# SCAN WIDTH/STEP WHETHER 1ST OR SUBS
        STEP=CENISTEP[THIS]
      else {
        STEP = CENWIDTH[THIS]/(CENNPTS-1)
        if (STEP < CENSTEP[THIS]) STEP=CENSTEP[THIS]
      }
      START = BESTANG[THIS] - CENWIDTH[THIS]/2
      STOP  = BESTANG[THIS] + CENWIDTH[THIS]/2      
      TRY1=0;TRY2=0
      for (FOUND=0;FOUND == 0;) {
        cen_scan THIS
        cen_what_next
        cen_mv 		
      }			
      if (FOUND != -1)  {
        printf (\
         "New: %8.4f shift: %8.4f  width: %7.4f maxcps: %5d count: %7.1f\n",\
         BESTANG[THIS],CENSHIFT,pl_FWHM,C_maxc/COUNT,COUNT)
        CEN_FWHM[THIS]=pl_FWHM
        if (CONV[THIS]) {
          printf("shift less than %7.4f - so converged\n",CENMSHIFT[THIS])
          if (!CENMCYC[THIS]) {
            printf("Converged at cycle %d - enough said\n",I_CYC+1)
            cen_ok[THIS]=1
          }
        } else {
          printf("shift more than %7.4f - NOT converged\n",CENMSHIFT[THIS])
          cen_ok[THIS]=0
        }
# at end of second cycle, look at all angles to see if all converged
        done=0
        printf ("look for convergence:- ")
        for (conv=1,ii=0;ii<CENMOTCYC;ii++) {
          printf ("%d  ",CONV[ii])
          if (CONV[ii] == 0) conv=0
        }
        if (conv == 1) {
          printf ("CONVERGED\n")
          done=1
	  break
        } else {
          printf ("not yet\n")
        }
      } else # if FOUND != -1
        break
    } # if cen_ok[THIS]=0 IF IT DID THE SCAN
    if (FOUND == -1 || done == 1) break
  } # ONE ANGLE SCAN
  if (FOUND == -1 || done == 1) break
} # FULL CYCLE
# decide whether converged:
if (FOUND == -1)
  printf ("\n**Abandon ship**!!\n")
else {
  if (done == 0)
    printf("This is getting boring - Had enuf\n")
  else
    printf("done sufficient for a big happiness\n")
  if (conv == 1)
    printf ("**CONVERGED: ")
  else 
    printf ("UNconverged: ")
}

# write the results to the terminal
printf ("best angles: ")
for (ii=0;ii<CENMOTCYC;ii++) {
  printf("%s:%9.4f ",motor_mne(CENMINDX[ii]),A[CENMINDX[ii]])
}
printf (" with cps: %8d\n",BEST_CPS)

# move to best angles
printf (" I move to this angles\n")
cen_mv

# and append to the file
cen_savetofile
}'


###########################################################################
# THIS ROUTINE LOOKS AT THE SCAN AND DECIDES WHAT TO DO

#%IU%  
#%MDESC%
#    decides whether to give up (maxc < CENMINC), scan further, 
#    or prepares the next angles.
def cen_what_next '{
global C_maxc
FOUND=1
C_maxc=data_anal(0,0,0,1,1,"max") ;C_maxa=data_anal(0,0,0,0,0,"max")
C_minc=data_anal(0,0,0,1,1,"min")
C_fwhm=data_anal(0,0,0,1,1,"fwhm")
C_c1 = data_get (0,0,1) ; C_c2 = data_get (0,NPT-1,1)
C_c=CEN
#
#H.G. check on max. counts per seconds i.s.o. maximum counts.

if (C_maxc/COUNT < CENMINC) {
  printf ("Max count only: %d - give up\n\n",C_maxc/COUNT)
  FOUND=-1
}
#
if (C_maxc/COUNT  > BEST_CPS) BEST_CPS=C_maxc/COUNT
if ( FOUND != -1 && C_c1 > C_maxc/2) {
  printf ("not found lhs  ")
  TRY1=TRY1+1
  if (TRY1==2) {
    printf("give up\n")
    FOUND=-1
  } else {
    printf ("Add a scan width to LHS\n")
    START = START - CENWIDTH[THIS]
    FOUND=0
  }
}
if ( FOUND !=-1 && C_c2 > C_maxc/2) {
  printf ("not found rhs  ")
  TRY2=TRY2+1
  if (TRY2==2) {
    printf("give up\n")
    FOUND=-1
  } else {
    printf ("Add a scan width to RHS\n")
    STOP = STOP + CENWIDTH[THIS]
    FOUND=0
  }
}
if (FOUND == 1) {
  C_central=C_c
  CENSHIFT=fabs(BESTANG[THIS]-C_central)
  if (fabs(CENSHIFT) <= CENMSHIFT[THIS]) CONV[THIS]=1
  CENWIDTH[THIS]=pl_FWHM*CENFWHMFAC
  BESTANG[THIS]=C_central
}
}'

###############################################################################
#%IU%  <center-angle-index>
#%MDESC%

def cen_scan '{
_m[0] = CENMINDX[$1]			# scan angle number
if (START != STOP) {
  _s[0] = START			# scan starting position
  _f[0] = STOP                  # scan end
  _n1 = int (fabs(STOP-START)/STEP)
  if (_n1 < CENNPTS) _n1 = CENNPTS
  NPT = _n1 +1  ; _ctime = COUNT ; _nm = 1
  printf ("\n\nCycle %d - Scan %s   Best %8.3f  Width: %7.2f pts: %d\n",\
            I_CYC+1,motor_mne(_m[0]),BESTANG[THIS],CENWIDTH[THIS],NPT)
  _ascan
} else {
  printf ("Zero width demanded for %s\n",motor_mne(_m[0]))
}
}'

###############################################################################
#setup parameters for centering times etc
#%IU%  
#%MDESC%
#%PRE%
#    Number of points in the scan : 15
#    Maximum number of cycles allowed :5 
#    Initial counting time in secs :1
#    Max permitted counting time :10  (not implemented yet)
#    Minimum counts to define a peak :200 (better will be a peak/bkgd ratio)
#%PRE%
def cen_par '
{
global CENNPTS CENNCYC CENITIME CENMTIME CENMINC
  CENNPTS=getval("Number of points in the scan ",CENNPTS)
  CENNCYC=getval("Maximum number of cycles allowed ",CENNCYC)
  CENITIME=getval("Initial counting time in secs ",CENITIME)
  CENMTIME=getval("Max permitted counting time ",CENMTIME)
  CENMINC=getval("Minimum counts to define a peak ",CENMINC)
}'

#%IU%
#%MDESC%
# Sets defaults for angles to write, output format ,...
# This is done in this way to allow other macros to use the centering 
# for more general scans (like beamline alignment)

def cen_defaults '
{
global CEN_SAV_NUM CEN_SAV_ANG CEN_FWHM CEN_SAVFWHM CEN_FORMAT CENFWHMFAC
global CEN_SAVHKL
CEN_SAV_NUM=4
#CEN_SAV_ANG[0]=mot_num(tth) ; CEN_SAV_ANG[1]=mot_num(th)  
#CEN_SAV_ANG[2]=mot_num(chi) ; CEN_SAV_ANG[3]=mot_num(phi) 
#h.g. ugly fix
CEN_SAV_ANG[0]=0 ; CEN_SAV_ANG[1]=4
CEN_SAV_ANG[2]=5 ; CEN_SAV_ANG[3]=6
if ((CEN_SAV_ANG[0]<0)||(CEN_SAV_ANG[1]<0)||(CEN_SAV_ANG[2]<0)||\
	(CEN_SAV_ANG[3]<0)) {
  printf ("Can not work - at least one motor missing (tth th chi phi)\n")
  exit
}
CEN_SAVFWHM=0
CEN_SAVHKL=1
CEN_FORMAT=" %9.4f "
CENFWHMFAC=3
}'

###############################################################################
#setup parameters for the centering sequence
#%UU%  
#%MDESC%
# You will be ask the filename for results and other general paramters
# (see %B% cen_par %B%). For every angle you like to center you have
# to answer the following questions:
#%UL%
#%LI%  Name?: [ 0 to end]  : Enter the motor mnemonic 
#%LI%      Initial scan width : 
#%LI%      Initial scan step size : Just give enough to be sure not
#to miss your peak. The step width will be adjusted for the
#consecutive scans.
#%LI%      Minimum step size : A scan will not be made with smaller
#step size even if you ask for more points in the scan (see general setup)
#%LI%      Max shift to define convergence 
#%LI%      Recenter if already converged : NO will stop doing scans
#with this motor if it is converged. YES will recenter this angle even
#if it is converged. (ex: the angles dependent on each other). 
#%XUL%
def cen_seq '{
global CENIWIDTH CENMSHIFT CENMCYC 
global CENANAME CENMOTCYC CENISTEP CENSTEP 
global CENFILE CENMINDX CEN_NUM CENOLDF
global CEN_SAV_NUM CEN_SAV_ANG CEN_FWHM CEN_SAVFWHM
global CEN_FORMAT
local uu line
# Some global settings
CENOLDF = CENFILE
if ((CENFILE = getval("File name to write results",CENFILE))!=CENOFILE) {
  if (!unix(sprintf("test -r %s",CENFILE))) {
    getline(CENFILE,"open")
    for (CEN_NUM=0,line=getline(CENFILE);line!="-1";line=getline(CENFILE)){
      sscanf (line,"%d",CEN_NUM)
    }
  } else {
    CEN_NUM = 0
  }
}
cen_par

if (CEN_SAV_NUM == 0) {
  cen_defaults
}

printf ("Defines the centering sequence -  Angles and convergence criteria\n")
for (CENMOTCYC=0;;) {
  printf ("Angle number %d\n",CENMOTCYC+1)
  if ((CENANAME[CENMOTCYC]=getval("   Name?: [ 0 to end]: ",\
	CENANAME[CENMOTCYC])) ==0) {
    printf ("%d angles in sequence - ",CENMOTCYC)
    for (uu=0;uu<CENMOTCYC;uu++) printf (" %s ",CENANAME[uu])
    printf ("\n")
    break
  } else {
    if ((CENMINDX[CENMOTCYC]=motor_num(CENANAME[CENMOTCYC])) == -1) {
      printf ("%s is not a recognised motor name!\n",CENANAME[uu])
      continue
    }
    printf ("   Give data for: %s\n",CENANAME[CENMOTCYC])
    CENIWIDTH[CENMOTCYC] =getval("     Initial scan width:",\
                                       CENIWIDTH[CENMOTCYC])
    CENISTEP[CENMOTCYC]  =getval("     Initial step size: ",\
                                       CENISTEP[CENMOTCYC])
    CENSTEP[CENMOTCYC]   =getval("     Minimum step size:",\
                                       CENSTEP[CENMOTCYC]) 
    CENMSHIFT[CENMOTCYC] =getval("     Max shift to define convergence: ",\
                                       CENMSHIFT[CENMOTCYC])
    CENMCYC[CENMOTCYC]   =yesno("     Recenter if already converged ",\
                                       CENMCYC[CENMOTCYC])
    CENMOTCYC++
    }
  }
}'


##############################################################################
# set up CEN_START_ANG from current positions
#%UU% 

#%MDESC%
#  This initiates the centering algorithm from current angles\n")
def cen_here'{
local uu ok mini_more
if (!CENMOTCYC) {
  printf("No angles to center\n")
  exit
}
printf ("\nThis initiates the centering algorithm from current angles\n")
waitmove
get_angles
printf ("\n")
printf ("Centering sequence: %d angles: ",CENMOTCYC)
for (ii=0;ii<CENMOTCYC;ii++) 
  printf (" %s (%9.4f) ",CENANAME[ii],A[CENMINDX[ii]])
printf ("\n")
for (uu=0;uu<CENMOTCYC;uu++) {
  CEN_START_ANG[uu]=A[CENMINDX[uu]]
}
cen_do_it
}'

#############################################################
#%IU%  
#%MDESC%
#    does the moving in the centering - uses the BESTANG array
def cen_mv '
{
local uu tonk
waitmove
get_angles
for (uu=0;uu<CENMOTCYC;uu++) {
  A[CENMINDX[uu]]  =  BESTANG[uu]+0
  }
move_em
waitmove
}
'  

#%IU%  
#%MDESC%
# This macro saves the results to a file. This has been separated 
# to allow other macro sets to redefine it.
def cen_savetofile  '
{
local ii
if (open(CENFILE)== 0) {
  fprintf(CENFILE,"%5d  ",++CEN_NUM)
  if (CEN_SAVHKL) {
    calcHKL
    fprintf (CENFILE,"%6.2f %6.2f %6.2f ",H,K,L)
  }
#h.g. fix get the real angles
  sync; get_angles
  for (ii=0;ii<CEN_SAV_NUM;ii++) {
    if ((mn =CEN_SAV_ANG[ii]) == -1) {
      if (ii >= CENMOTCYC) {
	continue
      } else {
        mn = CENMINDX[ii]
      }
    }
    fprintf(CENFILE,CEN_FORMAT,A[mn])
  }
  if (CEN_SAVFWHM) 
    for (ii=0;ii<CENMOTCYC;ii++) {
      fprintf(CENFILE,CEN_FORMAT,CEN_FWHM[ii])
    }
#  fprintf(CENFILE,"%2d %8d\n",conv, BEST_CPS)
  fprintf(CENFILE,"%8d %s\n",BEST_CPS,conv?"*C****AC":"*C****A*")
  close (CENFILE)
} else 
  printf ("CANNOT WRITE TO %s\n",CENFILE)
} '

#%MACROS%
#%IMACROS%
#%ATTENTION%
# 
#%DEPENDENCIES%
#  - The file cen.mac has to be read in (qdo'd)      !done by: startup script
#%AUTHOR%
#  JA 1st trimestre .94 , modified by JK (6.94)
#%TOC%