I. Язык процедур MIDAS

Слово MIDAS будет ниже означать ESO-MIDAS, что расшифровывается как Munich Image Data Analysis System - Мюнхенская система для обработки изображений, созданная и поддерживаемая European Southern Observatory (т.е. Европейской Южной Обсерваторией). Эта система включает специальные средства для обработки изображений и редукции данных с акцентом на астрономические приложения.

1. Процедуры MIDAS

MIDAS может работать в интерактивном и пакетном режимах. В первом случае вы просто даете команды этой системы одну за другой, во втором - собираете эти команды в файл, называемый процедурой, и затем выполняете ее. Эффект будет один и тот же.

Очевидно, что существует ряд дополнительных команд, помогающих организовать такие процедуры. Эти команды образуют язык процедур MIDAS, называемый MIDAS Command Language или сокращенно MCL. Во многих аспектах этот язык очень напоминает обычный Фортран.

2. Операторы процедур

В MIDAS не надо никаких специальных операторов, чтобы начать или закончить процедуру. Существуют, правда, операторы, которые желательно помещать в начало процедур, например операторы, определяющие параметры процедуры.

Внутри процедур можно использовать любые команды MIDAS, включая, конечно, команды языка MCL.

3. Переменные - ключевые слова

Начнем с простого вида данных в MIDAS - ключевых слов. Как и массивы в Фортране или Си, они имеют имя, тип и размер.

Имя не может быть длиннее 15 символов. 
Тип может быть real, integer, character или double precision. 
Размер означает число элементов и в принципе не ограничен.

4. Локальные ключевые слова

По умолчанию ключевые слова являются глобальными, т.е. сохраняющими свое значение при переходе из одной процедуры в другую. Зачастую это нежелательно, и тогда ключевые слова определяют как локальные переменные, т.е. переменные, которые функционируют только внутри данной процедуры. Например следующие определения четырех ключевых слов:
  DEFINE/LOCAL kx/D/1/1 0.1000000000000001
  DEFINE/LOCAL werter/I/1/4 2,0,1
  DEFINE/LOCAL kxa/R/2/4 2.0,3.0
  DEFINE/LOCAL aw/C/1/5 abba

Здесь I, R, D и C означают integer, real, double precision и character соответственно; два числа после этих букв и наклонной черты показывают индекс первого элемента и количество элементов ключевого слова, начиная с него; и, наконец, после пробела числа (символы), разделенные запятой, - это начальные значения. 
 
Таким образом, выше мы определили 4 локальных ключевых слова:
===========================================================================
имя       тип        длина      начальные значения
---------------------------------------------------------------------------
kx        double pr.   1        kx(1) = 0.1000000000000001
werter    integer      4        werter(1) = 2; werter(2) = 0; werter(3) = 1
kxa       real         5        kxa(2) = 2.0; kxa(3) = 3.0
aw        character    5        aw = abba 
===========================================================================

Следует сделать несколько замечаний:

1) описанные элементы, которым не присвоены начальные значения (например, werter(4)), по умолчанию получают значение, равное нулю;

2) каким бы ни был индекс первого элемента в операторе, ключевое слово всегда включает элементы, начиная с первого, т.е. kxa(1) фактически определен также (и согласно вышесказанному его значение есть ноль);

3) очевидно различие "числовых" (например, werter) и "нечисловых" (aw) ключевых слов при определении начальных значений.

Кстати заметим, что одно только имя ключевого слова по умолчанию означает первый элемент, т.е. werter и werter(1) представляют собой одно и то же для MIDAS.

5. Имя и значение переменной

Только что выше мы присвоили начальные значения нескольким переменным (ключевым словам). Важно различать имена переменных и их значения. Если мы пишем {kxa}, то это вызывает значение переменной; а если kxa, то ее имя. Необходимость различия будет очевидной в следующем пункте.

6. Ввод и вывод значений переменных

Напечатать что-либо на экране можно, используя следующую команду MIDAS:
  WRITE/OUT <список_вывода>
где <список_вывода> может включать все, что возможно.

Например оператор
  WRITE/OUT kx = {kx}
выдаст на экран строку
  kx = 1.00000E+00

Отметим еще раз, что здесь kx без скобок {} было интерпретировано как имя переменной, а {kx} - как ее значение.

7. Как присвоить значение переменной

Значение ключевому слову можно присвоить, используя команду WRITE/KEYWORD. Например, оператор
  WRITE/KEYWORD kxa/R/3/2 2.7,3.2
присвоит значение 2.7 третьему элементу ключевого слова kxa, а 3.2 - четвертому.

При подобном присвоении нельзя выходить за пределы изначально определенной длины ключевого слова; так для kxa невозможно указать пятый и последующие элементы, поскольку они не определены.

Кроме задания начального значения, ключевому слову можно присвоить значение и иным образом, например такой командой:
  werter(2) = 2 

Здесь в левой части равенства следует помещать имена переменных, а в правой - значения переменных (имена в фигурных скобках) и константы, а также любые включающие их алгебраические выражения.

8. Глобальные ключевые слова

Команда имеет еще одну важную функцию - она может быть использована для того, чтобы определить глобальное ключевое слово. Например
  WRITE/KEYWORD kk/I/1/3 1,4,9
порождает новое глобальное ключевое слово с начальными значениями kk(1)=1, kk(2)=4, kk(3)=9. При этом определять его командой DEFINE/LOCAL не нужно и не должно.

9. Алгебраические выражения

В MIDAS можно использовать стандартные математические операции: + - * / и скобки (), чтобы менять порядок операций. Например
  kxa = (5.6 * ({kxa} + 4) - 1 ) / 3.1   

10. Математические функции

Большинство стандартных математических функций реализовано в виде встроенных подпрограмм.

M$LN (arg1)   натуральный логарифм  real/double как arg1
M$LOG (arg1)  десятичный логарифм   real/double как arg1
M$EXP (arg1)  экспонента            real/double как arg1
M$SIN (arg1)  синус                 real/double как arg1
M$COS (arg1)  косинус               real/double как arg1
M$TAN (arg1)  тангенс               real/double как arg1
M$ASIN (arg1) арксинус              real/double как arg1
M$ACOS (arg1) арккосинус            real/double как arg1
M$ATAN (arg1) арктангенс            real/double как arg1
M$SQRT (arg1) корень квадратный     real/double как arg1
M$ABS (arg1)  абсолютная величина   integer/real/double как arg1
M$NINT (arg1) ближайшее целое       integer при real/double arg1

При этом в тригонометрических функциях углы измеряются в градусах!

Реализовано также несколько нематематических функций. О них пойдет речь на следующих занятиях.

11. Циклы

Циклы весьма похожи на фортрановские. Используется конструкция
  DO <счетчик> = <начало> <конец> <шаг>
  <команды>
  ENDDO
где DO и ENDDO - это служебные слова, <счетчик> - целое (integer) ключевое слово, <начало>, <конец>, <шаг> - целые выражения, <команды> - любые команды MIDAS.

Например, следующие операторы дадут значения a = 5.0:
  DEFINE/LOCAL  n/I/1/1 0
  DEFINE/LOCAL  a/R/1/1 0.0
  DO n = 1 2+2 2
  a = {a} + 2.5
  ENDDO

Заметим, что между n и =, а также между = и 1 в третьей строке должен быть пробел, а переменная-счетчик должна быть обязательно описана (в отличие от Фортрана).

Следует помнить, что цикл в MIDAS всегда исполняется 1 раз, даже если <начало> больше <конец>!

12. Условные операторы

Эти операторы сходны с аналогичными операторами в Фортране и возможны в трех вариантах:
 
а) IF <условие> <команда>

б) IF <условие> THEN
   <команда>
   ...
   ENDIF

в) IF <условие> THEN
   ...
   ELSEIF <условие> THEN
   ...
   ELSE
   ...
   ENDIF

Разрешается использовать до 8 уровней вложения операторов IF. Обратите внимание на необычное слово ELSEIF.

В вышеприведенных конструкциях <условие> формируется логическими операциями
.EQ. (равно)       .NE. (не равно)
.LT. (меньше)      .LE. (меньше равно)
.GT. (больше)      .GE. (больше равно)

Например, если i равно 5, то следующие операторы дадут b = 7.
  IF i .EQ. 5 THEN
  b = 7
  ENDIF

Отметим, что пробелы до и после .EQ. и т.п. необходимы.

13. Комментарии

Все символы в строке после знака ! считаются комментарием и не обрабатываются MIDAS.

Два примера:
  ! this is a comment
  WRITE/OUT kxa ! this is a comment too (i.e. everything after kxa in the line)

Здесь также необходим пробел перед ! во второй строке.

14. Связь с операционной системой

MIDAS работает в операционных системах типа UNIX (включая Linux). Некоторые часто используемые команды Linux были даны в Приложении А.

Когда вы работаете в MIDAS, то можете давать команды операционной системы, например посмотреть, сколько свободного места осталось на диске. Такие команды должны следовать за знаком $ и могут быть в принципе использованы и в MIDAS-процедурах.

Следует подчеркнуть, что если вы хотите изменить текущую директорию, например, чтобы вводить и выводить файлы из другой, команда $cd не поможет. В этом случае следует использовать команду MIDAS CHANGE/DIRECTORY.

15. Параметры процедуры

Если ваша процедура должна иметь параметры, их нужно описать в начале процедуры так:
  DEFINE/PARAMETER P1 <нач_значение> <тип> <промпт> <мин_значение>,<макс_значение>
где <тип> может быть N (number), C (character), T (table), I (image) или F (fit file), что, заметим, отличается от типов переменных (ключевых слов)!

Число параметров может контролироваться самой системой MIDAS, например
  DEFINE/MAXPAR 2
будет проверять, сопровождаете ли вы вызов процедуры добавлением двух и только двух параметров. В ином случае вы получите сообщение с предупреждением.

Вы можете отказаться от присвоения начальных значений и заставить MIDAS всегда проверять, подставляете ли вы параметры описанного типа, когда стартуете процедуру. Для этого нужно поставить знак + вместо <нач_значение>. 

Остальные параметры команды DEFINE/PARAMETER практически не будут использоваться нами.

16. Вызов процедуры

Чтобы выполнить процедуру, следует набрать @@, пробел и имя процедуры (имя соответствующего файла) с последующими параметрами разделенными пробелом (см. следующий пункт в качестве примера).

17. Пример процедуры

Напишем простую процедуру, использующую некоторые MCL-команды, обсуждавшиеся выше. Процедура вычисляет z = x**y и имеет два очевидных входных параметра x и y.

  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  ! exm1.prg - procedure to calculate z = x**y
  ! CROSSREF x y   ! a useful command
  ECHO/FULL
  ! SET/FORMAT I6             ! a useful command
  ! SET/FORMAT F16.8,F24.16   ! as well
  DEFINE/PARAMETER p1 +  NUMBER "Enter x: "  
  DEFINE/PARAMETER p2 +  NUMBER "Enter y: " 
  DEFINE/MAXPAR 2  
  DEFINE/LOCAL x/d/1/1 
  DEFINE/LOCAL y/d/1/1
  DEFINE/LOCAL z/d/1/1
  WRITE/KEYWORD z1/d/1/1
  WRITE/KEYWORD x {p1}
  WRITE/KEYWORD y {p2}
  WRITE/OUT x = {x} y = {y}
  IF x .EQ. 0d0 THEN
  z = 0.0 
  ELSE
  z = M$EXP ({y} * M$LN ({x}))
  ENDIF
  WRITE/OUT z = {z}
  z1 = {z}
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Если вы вошли в MIDAS и вызываете эту процедуру для исполнения посредством
  @@ exm1.prg 2 2
то получите в результате ее работы среди нескольких прочих строк следующую:
  z = 4.00000E+00

18. Список команд MCL

Для справки приведем все команды язык процедур MIDAS.

BRANCH var comparisons labels   

CROSSREF label1 ... label8

DEFINE/LOCAL keyword data all_flag level_flag

DEFINE/PARAMETER par def type prompt limits

DO loopvar = begin end step
... command body ...
ENDDO 

ENTRY proc

GOTO label

IF par1 op par2 command

IF par1 op par2 THEN
... if-sequence ...
ELSEIF par3 op par4 THEN
... else if-sequence ...
ELSE
... else-sequence ...
ENDIF

INQUIRE/KEYWORD keyword prompt-string

label:

RETURN par1 ... par3

PAUSE

DEFINE/MAXPAR no_par

ECHO/qualif levela,levelb

COMPUTE/KEYWORD reskeyword = expression

SET/FORMAT format_specs

WRITE/OUT text

! comment