% @(#)batche.alq 17.1.1.1 (ESO-IPG) 01/25/02 17:43:17 Some guidelines for writing Midas batches ----------------------------------------- This document is a short guide to writing correct and robust Midas batches (procedures) which are able to survive the installation of future Midas versions. Please, note, that this is NOT a comprehensive description of the Midas command language. Instead, chapter 3 of the Midas User's Guide, Volume A, gives a detailed account of that. The Midas User's Guide, volume A and B, are now not only available in printed form, but also under Mosaic directly from the La Silla home page. Click on the item `Manuals' in the `Documentation' section of the home page. In the page `La Silla Manuals' click on the item `Midas Document' to get it (direct URL is: http://lw10.ls.eso.org/manuals/midas/html/midas.html). In chapter 3 (Vol. A) the Midas command language is described in detail and many examples are provided which illustrate the concepts of the language. Instead, this is a collection of suggestions and comments resulting from the browsing and editing of quite a few Midas procedures written at La Silla and Garching. The numbering of these suggestions is rather arbitrary and does not indicate any ordering according to importance. There is interactive help (as well as printed, Volume C) available for all Midas commands which will be mentioned here. It is strongly recommend to use the Graphical User Interface to the Midas help facility, because it supports searching, browsing and cross referencing via the mouse. Inside Midas you activate the GUI via the Midas command "CREATE/GUI help". Outside Midas use the command `helpmidas' to start up that GUI. 1) Midas procedures are ASCII files which must be readable by anybody, it is not necessary/recommended to make them executable like, e.g. shell scripts in Unix. 2) Even though empty lines are o.k. and treated like comment lines by the Midas monitor, we suggest to use instead the Midas syntax, i.e to begin a comment line with an exclamation mark (!). 3) Make heavy use of comments, not just full comment lines but also adding comments to the end of a Midas command, e.g.: inputi = m$existk("lola") !check, if keyword `lola' exists 4) Procedures are interpreted by Midas, i.e. there is no compilation step involved. The execution of procedures is done in two steps: a - the procedure is read into memory, all comments are stripped off and programming constructs like e.g. IF, DO commands are translated into an intermediate code; furthermore all symbol substitutions (see 11)) are performed on the command line b - the code is executed by passing each command line to the Midas monitor which processes it exactly as if entered interactively 5) Midas commands consist of a command and a qualifier, separated by a slash (/), like e.g. WRITE/KEYWORD. They may be abbreviated to only the significant no. of characters to avoid ambiguity with other commands. This feature is intended to ease the interactive input of commands (minimum typing). However, command abbreviation must be avoided in Midas batches, instead all commands in a procedure should be as complete as possible, which is at most 6 characters for the command protion and at most 4 chaaracters for the qualifier portion. This ensures that the command will not be affected by any new commands which may be added to Midas in the future. Also avoid relying on the defaults of parameters which are described in the help of a command. For with the command CREATE/DEFAULT one can change these defaults dynamically. Instead write full command lines specifying all parameters in your batches. 6) Keywords serve as variables for the Midas command language, there are global and local keywords, which are created via write/keyw lola/i/1/3 1,2,3 or define/local lola/i/1/3 1,2,3 When a keyword (variable) is only needed inside a batch one should use local keywords. When a keyword may be used later on by other commands or procedures a global keyword is necessary. Keywords may be single values or arrays, they may be of type integer, real, double precision or character. The first element of a keyword array is element no. 1 (like in Fortran). 7) Always provide as many initial values to a keyword as you define in e.g. the "define/local" command. define/local lola/r/1/6 0 usually works as intended i.e. all elements of keyword `lola' are filled with 0, but depending upon the computer and operating system the contents of lola(2,...,6) may be unpredictable. So, use define/local lola/r/1/6 0 all in order to fill all elements of keyword lola with 0. 8) The command "SET/MIDAS output=..." should be used instead of directly manipulating the keyword LOG for controlling the output on the terminal. Thus any possible changes in the low level handling of e.g. keyword LOG will not affect the procedure. 9) Midas batches stop automatically after the last command in the file. Therefore, the command RETURN is not needed as last command of a Midas batch. 10) Use always {,} and not the apostrophes (now outdated) anymore to indicate symbol substitution 11) Probably the most complicated feature in Midas procedures is the symbol substitution which will provide the contents of any Midas data structure as ASCII string. Thus, e.g. keyword, descriptors or table elements can be accessed directly from a Midas procedure: {star} is a string representing the value stored in the keyword `star'; if `star' is not a character keyword, the numeric value of `star' will be converted to an ASCII string according to the format defined via the SET/FORMAT command. Therefore, one may lose precision if not an adequate format is chosen... {galaxy,disk} is a string representing the value stored in the descriptor `disk' of frame `galaxy.bdf'; if `disk' is not a character descriptor, the numeric value of `disk' will be converted to an ASCII string according to the format defined via the SET/FORMAT command. {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 be converted to an ASCII string according to the format defined via the SET/FORMAT command. {dust,:particles,7} is a string representing the element of the table `dust.tbl' in column labeled :particles and row 7; if the table element is not of type character, the numeric value will be converted to an ASCII string according to the format defined via SET/FORMAT. {dust,#2,77} is a string representing the element of the table `dust.tbl' in the second column and row 77; Since the outcome of symbol substitution is a char. string, it can be used in place of any operand of a Midas command, like the command, the qualifier or the parameters, e.g. "WRITE/OUT {{P1},STEP(1)}". There are 2 exceptions to this rule: The first exeception concerns the command COMPUTE/KEYWORD, where 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)) Remember, that you can omit the command name COMPUTE/KEYW in the beginning of the command line (then it's also called an immediate command). The other exception is with the specific keyword based commands COMPUTE/KEYWORD, DO, IF and BRANCH where the main operands of the commands are keywords, so the name of a keyword indicates already to use it's contents (char. strings have to be enclosed in brackets). But this is only true for keywords - all other data structures 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! E.g.: Midas > inputd = image,step(2)+outputd(5) is WRONG. Whereas, Midas > outputr(12) = outputr(1)-inputi(12)+{galaxy,step(2)} is O.K. as well as Midas > outputr(12) = outputr(1)-inputi(12)+m$value(galaxy,step(2)) is O.K. (different numeric keyword types, like integer, real can be mixed). Unless the data element is of type character it is preferable to use the M$VALUE function, because it provides the binary value of the data element instead of an ASCII string resulting from the curly brackets' usage. And that string is generated via the format specified (or defaulted) in the SET/FORMAT command... And as another example, do NOT use "if {inputi} .eq. 22 then" but "if inputi .eq. 22 then" instead, in a procedure. The last complication comes from the fact that you must use curly brackets with keywords also in the commands mentioned above, 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 (cf. 4), 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. 12) The format which is specified via the SET/FORMAT command must be set individually in the body of each procedure. For (backward) compatibility reasons the default is like Midas > SET/FORMAT I4 E15.5,E15.5 . Format I4 for integer values, E15.5 for real and double precision values. And this represents a hidden danger with numeric (especially double precision) data (keywords, descriptors,...): With the default format you might loose precision. Consider the following example procedure `test.prg' : inputd = 1234.55667701 outputd = {inputd}+0.0001 set/format ,f20.10 write/out {outputd} when executing: Midas > @@ test you will get 1234.5601 instead of 1234.55677701 even though you used the `large' format f20.10 for the representation of outputd(1). What happened? Well, let's show the substitutions, so we do Midas > echo/full Midas > @@ test and we get: 1 > inputd = 1234.55667701 1 > outputd = {inputd}+0.0001 outputd = 1.23456E+03+0.0001 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 is 1234.560 ... If we change `test.prg' to inputd = 1234.55667701 outputd = inputd+0.0001 set/format ,f20.10 write/out {outputd} (and turn the echo off) we get from: Midas > @@ test 1234.55677701 as expected. Sometimes you have to use curly brackets, e.g. if you have a character keyword containing a number on the right hand side of the expression. For character data there is no problem because the full string is used. So, if we change `test.prg' to define/param p1 ? Number "Enter no.:" inputd = {p1} !{p1} needed, cause p1 is char. keyword outputd = inputd+0.0001 set/format ,f20.10 write/out {outputd} then Midas > @@ test 1234.55667701 yields (with echo on): 1 > DEFINE/PARAM p1 ? Number "Enter no.:" 1 > inputd = {p1} inputd = 1234.55667701 1 > outputd = inputd+0.0001 1 > SET/FORMAT ,f20.10 1 > WRITE/OUT {outputd} WRITE/OUT 1234.55677701 1234.55677701 the correct answer. If we use a descriptor in the right side of the expression we either use curly brackets and must then ensure an adequate format in the procedure. Or (preferably) we use the M$VALUE function and don't have to worry about SET/FORMAT. For example, if we change `test.prg' to: crea/image lola 1,200 0.0,100.00123 set/format ,f20.10 !large format outputd = {lola,step(1)}+0.0001 write/out {outputd} we get from: Midas > @@ test 100.00133 the correct result. But we better rewrite `test.prg' to get: crea/image lola 1,200 0.0,100.00123 outputd = m$value(lola,step(1))+0.0001 !use binary value of STEP(1) set/format ,f20.10 write/out {outputd} which will also produce: 100.00133 .