next up previous contents index
Next: DO Loops Up: MIDAS Command Language Previous: Passing Parameters in MIDAS

     
Symbol Substitution in Command Procedures

As mentioned before, the Monitor performs symbol substitutions on MIDAS command lines in the first pass by replacing symbol names in the command line with their current value. For character symbols just the string is put in; for symbols of other types the binary data are converted to ASCII using the formats specified in the SET/FORMAT command. This substitution is iterated until no more symbol substitutions are possible. Keywords, descriptors, pixel values of an image or elements of a table are valid symbols in the MIDAS command language.
  
The following syntax for substitution is used to distinguish among keywords , descriptors , pixel  values and table elements : $\{$star$\}$ is a string representing the value stored in the keyword star
If star is not a character keyword, the numerical value of star will be converted to an ASCII string according to the format defined via the SET/FORMAT command. Therefore, take care, you may lose precision if an inadequate format is chosen. $\{$galaxy,disk$\}$ is a string representing the value stored in descriptor disk of the image frame galaxy.bdf
If disk is not a character descriptor, the numerical value of disk will be converted to an ASCII string according to  ... 

$\{$galaxy[x,y]$\}$ is a string representing the value of the image pixel at coordinate x,y of the 2-dimensional frame galaxy.bdf.
This value will always be converted to an ASCII string according to  ... 

$\{$dust,:particles,$7\}$ is a string representing the element of the table dust.tbl in the column labeled :particles and row #7
If the table element is not of type character, the numerical value will be converted to an ASCII string according to  ... 

$\{$dust,#2,$77\}$ is a string representing the element of the table dust.tbl in the second column and row 77   
Elements of numerical keywords with more than one element are specified like elements in a FORTRAN vector, e.g. INPUTR(7), that also means that the first element has the index 1 (not 0). Also substrings of character keywords are indicated as in FORTRAN, e.g. INPUTC(2:5). These features are also implemented for descriptors but not for table entries (yet).
  
Since the outcome of symbol substitution is a character string, it can be used in place of any operand of a Midas command, like the command, qualifier or parameters, e.g. WRITE/OUT $\{\{$P1$\}$,STEP(1)$\}$.
  
It's with the the command COMPUTE/KEYWORD and its short form variable = expression (called direct assignment), with variable any of keyword, descriptor, image-pixel or table-element that symbol substitution gets a bit more complex. Therefore, we shall elaborate on that in some more detail.
  
First, the result (left hand side) keyword, descriptor, table element, etc. is specified WITHOUT the brackets, i.e Midas > compute/keyw dust,#2,77 = inputr(6)*m$sin(inputr(12))
or Midas > dust,#2,77 = inputr(6)*m$sin(inputr(12))
  
Any algebraic expression using the operators +, -, *, /  and parentheses ( , ) and constants as well as any variable explained above is supported by the command COMPUTE/KEYWORD (and direct assignments). However, since keywords are the ``objects" of the right-hand expression in this command they don't have to be enclosed in curly brackets unless we need a conversion from character keywords to numerical data. If a keyword name is found as operand in the COMPUTE/KEYWORD command, automatically its content is taken (character strings have to be enclosed in double quotes). Using curly brackets always and thus substitution at the parsing stage of the Midas command line introduces dependency on the SET/FORMAT command and thus the possible danger of loss of precision for numerical keywords.
But this is only true for keywords - all other variables like descriptors, table elements, etc. have to to be either converted to ASCII strings via the curly brackets (or accessed via the M$VALUE function)!

Midas > inputd = image,step(2)+outputd(5)
is WRONG. Whereas,

Midas > outputr(12) = outputr(1)-inputi(12)+$\{$galaxy,step(2)$\})$
is O.K.
  
Also the commands DO, IF and BRANCH operate on keywords or constants only. So again, the name of a keyword indicates already to use it's contents, whereas character strings have to be enclosed in double quotes.   
Inside a Midas procedure the line: if $\{$inputi$\}$ .eq. 22 then
is not wrong, but: if inputi .eq. 22 then
is better, since inputi is an integer keyword and needs therefore no conversion from character string to numerical value.
However, if e.g. parameter P3 contains a number, then if p3 .eq. 22 then
is WRONG, instead: if $\{$p3$\}$ .eq. 22 then
has to be used, since the parameters are implemented as character keywords.
  
Let us look at another examples:

!+
! Example 6, MIDAS procedure exa6.prg
!+
DEFINE/PARAM P1 ? N "Enter alpha value: " -88.5,912.4
DEFINE/PARAM P2 ? N "Enter loop_count: " 1,999
DEFINE/MAXPAR 2
! max. 2 parameters expected
WRITE/KEYWORD VAR/R/1/1 0.
! init key VAR
VAR =
$\{$P1$\}$ * 3.3 ! see remark a
WRITE/DESCR myframe rval/r/1/2 0.0,0.0 !
LOOP:
! declare label LOOP
VAR = 1.+VAR
! see remark b
myframe,rval(2) = var+12.99
WRITE/OUT
$\{$myframe,rval(2)$\}$
myframe[@10,@20] = 20.0-
$\{$myframe,rval(2)$\}$
WRITE/OUT
$\{$myframe[@10,@20]$\}$
mytable,:DEC,@7 =
$\{$myframe[@10,@20]$\}$*2.0
WRITE/OUT
$\{$mytable,:DEC,@7$\}$
WRITE/OUT " "
IF VAR .LE.
$\{$P2$\}$ GOTO LOOP ! go to label LOOP, if VAR $\leq$ contents of P2
Then the command @@ exa6 1.0 5.2 will yield:
1.72900E+01
2.71000E+00
5.42000E+00

1.82900E+01
1.71000E+00
3.42000E+00
  
Remark A:
Parameter P1 is implemented as a character keyword. Therefore, we have to use $\{$P1$\}$ * 3.3 in the expression to convert the character data in P1 to numerical data (both operands must be numeric).
If we had written VAR = P1 * 3.3, MIDAS would have protested because in the righthand expression we would have tried to multiply a char. string with a float.
  
Remark B:
Here we use keyword VAR directly (i.e. without curly brackets) since ist's a float keyword, so both operands of the righthand expression are of numeric type.
  
Note
For character keywords COMPUTE/KEYWORD only supports character concatenation (`//'). If you want to write a character string into a character keyword, use WRITE/KEYWORD instead.
  
To recapitulate it you must use curly brackets with keywords in COMPUTE/KEYWORD if you need to convert a character keyword to a numeric constant - but no conversion problems (like loss of precision) here. This is, for example, the case when you want to use the contents of the (character) parameters P1, ..., P8 in a numeric expression, e.g.:
outputr(3) = {p1}*outputr(12)
This line would be translated to:
outputr(3) = 0026*outputr(12)
in the first pass over the command line, so the right hand side contains a numerical constant and a keyword - a valid numerical expression.
However, the Midas command line:
outputr(3) = p1*outputr(12)
would involve a char. and real keyword in the evaluation of the right hand side and is therefore illegal syntax.
  
Since symbols may be tested in conditional statements and thus change the control flow of a MIDAS procedure, they provide the link between application programs and the MIDAS command language.
The number of characters used in the ASCII representation of a numerical symbol is controlled via the command SET/FORMAT format for integer symbols and
SET/FORMAT rformat,dformat for real (rformat) and double (dformat) precision symbols. Similar to FORTRAN the I-format (with leading zeroes not suppressed) is used for integer symbols and real or double precision symbols use the E-format, G-format or F-format:
!+
! Example 7, MIDAS procedure exa7.prg
!+
WRITE/KEYWORD INPUTI 12
! set INPUTI(1) to 12
WRITE/KEYWORD INPUTR 12.345
! set INPUTR(1) to 12.345
! and set INPUTD(1) to 123456.98765432
WRITE/KEYWORD INPUTD 123456.98765432
WRITE/OUT
$\{$inputi(1)$\}$$\{$inputr(1)$\}$$\{$inputd(1)$\}$
SET/FORMAT I2
! use format I2.2 for integer symbols
! and use format E12.8 and G22.8 for real and double symbols
SET/FORMAT E12.8,G22.8
WRITE/OUT
$\{$inputi(1)$\}$$\{$inputr(1)$\}$$\{$inputd(1)$\}$
SET/FORMAT i5
! use format I5.5 for integer symbols
! and use format F12.4 and E22.13 for real and double symbols
SET/FORMAT f12.4,e22.13
WRITE/OUT
$\{$inputi(1)$\}$$\{$inputr(1)$\}$$\{$inputd(1)$\}$
The command @@ exa7 will yield:
0012 1.23450E+01 1.23457E+05 default is I4 and E15.5,E15.5
12 1.23450003E+01 1.23456988E+05
uses I2 and E12.8,G22.8
00012 12.345 1.2345698765432E+05
uses I5 and F12.4,E22.13
If you want to omit any leading zeroes for integer symbols use SET/FORMAT I1, then only the necessary digits will be displayed.
Note
Use SET/FORMAT f-format to only change the format for real symbols and SET/FORMAT ,f-format to only change the format for double symbols.
  
The format which is specified via the SET/FORMAT command must be set individually in the body of each procedure. For backward compatibility the default is SET/FORMAT I4 E15.5,E15.5 (format I4 for integer values, E15.5 for real and double precision values).

This represents a hidden danger with numeric (especially double precision) data because you might loose precision. Consider the following example:

!+
! Example 7a, MIDAS procedure exa7a.prg
!+
inputd = 1234.55667701
write/keyword outputd/d/1/1
$\{$inputd$\}$
set/format ,f20.10
write/out
$\{$outputd(1)$\}$

When executing @@ exa7a you will get 1234.5601 instead of 1234.55677701 even though you used the large format f20.10 for the representation of keyword OUTPUTD. What happened? Well, let's show the substitutions, so we do
Midas > echo/full
Midas > @@ exa7a   
and we get:

1 > inputd = 1234.55667701
1 > write/keyword outputd/d/1/1
$\{$inputd$\}$
write/keyword outputd/d/1/1 1.23456E+03
1 > SET/FORMAT ,f20.10
1 > WRITE/OUT
$\{$outputd$\}$
WRITE/OUT 1234.5601
1234.5601
  
So keyword OUTPUTD got the contents of INPUTD formatted according to the default format for double precision values (e15.5), which yields 1234.560 ...
  
If we change to:
!+
! Example 7b, MIDAS procedure exa7b.prg
!+
set/format ,f20.10
inputd = 1234.55667701
write/keyword outputd/d/1/1
$\{$inputd$\}$
write/out
$\{$outputd$\}$
(and turn the echo off) we get from @@ exa7b the output 1234.55677701 as expected.

So it's good practice to always put SET/FORMAT into the begin of your procedure if you use substitutions.
  
However, the best would be to use no substitution at all via:

!+
! Example 7c, MIDAS procedure exa7c.prg
!+
inputd = 1234.55667701
outputd = inputd
SET/FORMAT ,f20.10
WRITE/OUT
$\{$outputd$\}$
Now, we get from @@ exa7c the output 1234.55677701 as expected and we don't have to worry about the SET/FORMAT command.
  
Substitution begins inside the curly brackets, starting at the deepest nested level:
WRITE/OUT $\{$IN_A$\}$$\{$INPUTC(1:3)$\}$
will display SPIRALABC on the terminal, if key IN_A contains the string SPIRAL and key INPUTC(1:3) the string ABC.
It is sometimes necessary to substitute symbols in a nested order:
!+
! Example 8, MIDAS procedure exa8.prg
!+
DEFINE/PARAM P1 myframe IMA "Enter name for input frame: "
SET/FORMAT F5.1
WRITE/OUT
$\{$$\{$P1$\}$,STEP(1)$\}$
the command @@ exa8 will force the Monitor to substitute the last command line in exa8.prg first to:   WRITE/OUT $\{$myframe,STEP(1)$\}$ and then yield:   20.5
assuming that descriptor STEP of myframe.bdf contains 20.5 as first element. This example also illustrates the concept of recursive substitution .
  
You may want to use symbol substitutions for sending the output of a MIDAS command to an ASCII file or to the terminal depending upon the contents of e.g., the character keyword mykey.
Setting keyword mykey once to ">outfile" or ">terminal" if you want output to a file or not together with the command line WRITE/TABLE mytab $\{$mykey$\}$  in your procedure will not work!
For, the check for the output redirection is done at the very first parsing of the command line before any symbols in that line are replaced...
Instead, setting mykey to "outfile" or "terminal" and changing the command line to:   WRITE/TABLE mytab >$\{$mykey$\}$
will do the intended switching of output to a file or terminal.
  


next up previous contents index
Next: DO Loops Up: MIDAS Command Language Previous: Passing Parameters in MIDAS
Petra Nass
1999-06-09