NAME
     MAC - NMRPipe Macro Interpreter

SYNOPSIS
     nmrPipe -fn MAC -macro macFile] [-var  vList]  [-str  sList]
     [-all]

     M [macFileList] [-var vList] [-str sList] [-quit]


SPECIAL NOTE
     The  nmrPipe  MAC  function,  and  the  corresponding  macro
     language   M  are  both  under  active  development.   Their
     features may change substantially, and  macros  created  for
     the  current  versions may not always be forward-compatible.
     This manual page is also still under development.

DESCRIPTION
     MAC is a macro interpreter which executes  the  contents  of
     the  given  macro  file  once for each 1D vector in the data
     stream.  It is used to create  custom  processing  functions
     and  data  shuffling  schemes.  The macro language, which is
     called M,  is  based  on  a  subset  of  the  C  programming
     language,  augmented  by  a  collection of vector processing
     functions.  In addition to use as a processing  function  of
     nmrPipe,  the  macro language R". also be used interactively
     via the stand-alone program "M
     When a macro is invoked via the nmrPipe  MAC  function,  the
     arrays  rdata[]  and  idata[] will contain the real and ima-
     ginary parts of the current 1D vector.  After the  macro  is
     executed, the contents of arrays rdata[] and idata[] will be
     written to the output stream automatically by nmrPipe.

     The macro language allows data to be manipulated directly on
     a  point-by-point basis, or by use of vector functions.  For
     example, this 6-line macro would swap  the  reals  and  ima-
     ginaries on a point-by-point basis:

        for( i = 0; i < size; i++ )
           {
            temp     = rdata[i];
            rdata[i] = idata[i];
            idata[i] = temp;
           }

     whereas this one-line macro would perform the same task more
     quickly using a built-in vector function:

        (void) vvSwap( rdata, idata, size );

     The macro language includes special  pre-defined  variables,

     overall data and the current data vector.   Other  variables
     are  created  automatically when used, such as variables "i"
     and "temp" in the example above.

     Once a macro is entered into a text file, it can be used  to
     process  data  in  the  same way as other nmrPipe processing
     functions.  For example, if either macro  above  is  entered
     into  the  text  file  "swap.M", a scheme like the following
     could be used to exchange real and imaginary data  before  a
     Fourier transform:


        nmrPipe -in test.fid            \
        | nmrPipe -fn MAC -macro swap.M \
        | nmrPipe -fn FT                \
          -out test.ft1 -verb -ov

     As the examples above imply, the  macro  language  has  many
     similarities  to  the C programming language.  Some of these
     include:

         Variable names are case-sensitive.
         Statements are terminated by the ';' character.
         Array subscripts are enclosed by '[' and ']'.
         Statement lists are enclosed by '{' and '}'.

     More details are given below.  In the outlines  that  follow
     var  is scalar variable or a subscripted array variable, and
     expr is a mathematical expression.

VARIABLES
     In the current implementation, the macro  language  supports
     three types of variables:

       1. Scalar variables, as double-precision floats.
       2. One-dimensional arrays, as single-precision floats.
       3. Character arrays.

     Array index values start at zero, as in C.

     Array variables of a specific length can be created using  a
     "float" statement, such as:

        float gReal[size*4], gImag[size*4];
        char  outName[256];

     Scalar variables are created automatically when  used.   The
     value of an uninitialized variable is undefined.

READING AND WRITING DATA
     Some macro applications may require the option of reading or

     1D  vector  at  a  time.   In  these  cases,  the  automatic
     read/write  performed by nmrPipe can be suppressed by use of
     the arguments -noRd and -noWr.  In these  cases,  the  macro
     will be responsible for performing its own reading and writ-
     ing, via functions such as dReadB() and  dWrite()  described
     below.

HEADER VALUES
     The pre-defined array fdata[512] contains  the  file  header
     information  from the current data.  The functions getParm()
     and setParm() can be used  to  get  or  set  values  in  the
     header.   For example, some macro applications may alter the
     size of the output data.  In these cases it will  be  neces-
     sary  to  adjust  the  output file header accordingly before
     processing to indicate the new size.

     When the -all flag is used, the macro will be invoked  twice
     before any processing is required, to provide an opportunity
     to perform initialization such as  updating  the  header  if
     needed.   If  the  -all flag is used, the macro will also be
     invoked once after all processing is finished.   The  action
     to  perform  at  any  given  invocation will be indicated by
     variable "sliceCode" (see below).  If the -all flag  is  not
     used,  the  macro will only be called to process data, never
     to perform initialization or exit procedures.

PREDEFINED VARIABLES
     rdata[size]
          Real part of current 1D vector.

     idata[size]
          Imaginary part of current 1D vector, if any.

     fdata[512]
          Header array from current data.

     xSize
          Size of current X-Axis, complex points.

     ySize
          Size of current Y-Axis, total points  for  hypercomplex
          data, complex points otherwise.

     zSize
          Size of current Z-Axis, total points.

     aSize
          Size of current A-Axis, total points.

     size Same as "xSize"


          Same as "ySize"

     quadState
          If this value is 1, the current dimension is being read
          as  real-only data, and therefore the idata[size] array
          has no imaginary contents.

          If this value is 2,  the  current  dimension  is  being
          treated  as complex, and the array idata[size] contains
          the imaginary data.

     sliceCode
          1D Vector number or code number (see  below).  A  value
          greater  than zero indicates that a 1D vector should be
          processed.  A value less than zero  indicates  that  an
          initialization or shutdown step should be performed.

     sliceCount
          Total 1D slices to process.

     yLoc Location of current 1D slice in Y-Axis.

     zLoc Location of current 1D slice in Z-Axis.

     aLoc Location of current 1D slice in A-Axis.

     inUnit
          File ID for current 1D input data.

     outUnit
          File ID for current output data.

SPECIAL CONSTANTS
     BUFLEN
          Default array length (1024).

     wordLen
          Number of bytes per word (4).

     PI   The constant pi.

     E    The constant e.

     CUR_XDIM
          Used to define dimCode for getParm/setParm below (=1).

     CUR_YDIM
          Used to define dimCode for getParm/setParm below (=2).

     CUR_ZDIM
          Used to define dimCode for getParm/setParm below (=3).

          Used to define dimCode for getParm/setParm below (=4).

     NDSIZE
          Code for  SIZE  parameter  in  header,  as  taken  from
          "fdatap.h";  used  as  a  parmCode  for getParm/setParm
          below.  Other predefined parameter codes will be  added
          in  future implementations; in the mean time, parameter
          codes can be defined "manually" in a macro using values
          listing in "fdatap.h" or in the fdatap manual page.

VALUES FOR SLICECODE
     The following codes will only be used when the  -all  option
     is specified:

     CODE_ARGS
          When sliceCode == CODE_ARGS, the macro is being invoked
          to  extract  any  command  line arguments required.  At
          this  stage,   the   data   arrays   (rdata[size]   and
          idata[size) and the header array (fdata[512]) cannot be
          accessed.

     CODE_INIT
          When sliceCode == CODE_INIT, the macro is being invoked
          to  perform any initialization required for processing.
          At this time, the header should be updated by the macro
          if needed.

     CODE_DONE
          When sliceCode == CODE_DONE,  the  processing  is  fin-
          ished.   The  macro  should perform any exit procedures
          (final summary, etc.) needed.  At this stage, the  data
          arrays (rdata[size] and idata[size) cannot be accessed.

ASSIGNMENT OPERATORS
        var   = expr;   Assignment
        var  += expr;   Increment var by expr.
        var  -= expr;   Decrement var by expr.
        var  *= expr;   Multiple var by expr.
        var  /= expr;   Divide var by expr.


MATH OPERATORS
     Note that unlike C, this implementation defines an  exponen-
     tiation operator '^':


        expr + expr   Addition
        expr - expr   Subtraction
        expr * expr   Multiplication
        expr / expr   Division
        expr % expr   Modulus


        -expr         Negative

        ++var         Increment var, return new value.
        var++         Increment var, return original value.
        --var         Decrement var, return new value.
        var--         Decrement var, return original value.


LOGICAL OPERATORS
     In the current implementation, both sides of binary  logical
     operators  are  always  evaluated,  unlike C, where only the
     left-side argument may be evaluated.


        expr >  expr  Greater than
        expr >= expr  Greater than or equal to
        expr <  expr  Less than
        expr <= expr  Less than or equal to
        expr == expr  Equal to
        expr != expr  Not equal to

        expr && expr  Logical AND
        expr || expr  Logical OR
        !expr         Logical NOT


SPECIAL ITEMS
     (void)
          Ignore (don't print) function return  value.   If  this
          prefix   is  not  used  before  a  function  call,  the
          function's return value will be printed.

     exit( expr );
          Exit the macro with the given status.

     print printList;
          Print the given list of data; printList is  a  list  of
          comma-separated variables or string constants.

     float arrayList;
          Define and allocate the given arrays;  arrayList  is  a
          list of comma-separated arrays with subscripts defining
          their sizes.

     near( x1, x2, d );
          Returns 1 if the absolute difference between x1 and  x2
          is less than the absolute value of d.

LOOP STATEMENTS
     Loop statements  in  the  macro  language  must  have  their


        while( condition )
           {
            statementList
           }

        for( initExpr; condition; incrExpr )
           {
            statementList
           }


CONDITIONAL STATEMENTS
     Conditional statements in the macro language differ  from  C
     in two ways;  first, the statement bodies in the "if" state-
     ment must be enclosed by '{' and '}'; second, the if  state-
     ment must be terminated by a ';' character:


        if (condition)
           {
            statementList;
           };

        if (condition)
           {
            statementList;
           }
        else
           {
            statementList;
           };

        if (condition1)
           {
            statementList;
           }
        else if (condition2)
           {
            statementList;
           }
        else
           {
            statementList;
           };


SCALAR FUNCTIONS
        sin()      Sine
        cos()      Cosine
        tan()      Tangent

        acos()     Inverse Cosine
        atan()     Inverse Tangent
        log()      Log Base-e
        log10()    Log Base-10
        exp()      Exponential
        erf()      Error function
        sqrt()     Square root
        integer()  Truncate to integer
        abs()      Absolute value
        randX()    Uniform random number
        gRandX()   Gaussian random number
        rseed()    Sets random number seed
        readV()    Read a variable
        debug()    Set debug mode


SELECTED VECTOR AND FUNCTION CALLS
     printf( string );
          Print the given  string,  as  with  the  C  version  of
          printf().

     printf( formatString, argList );
          Print  the  given  data,  as  with  the  C  version  of
          printf(); Note Well: in the current implementation, all
          variables are treated by this printf as C type "float",
          so  fomat  statements  must  be  specified accordingly.
          fprintf( fileID, string ); Print the given string to  a
          file,  as  with the C version of fprintf().  The fileID
          should be a value returned by dOpen().

     fprintf( fileID, formatString, argList );
          Print  the  given  data,  as  with  the  C  version  of
          fprintf();  Note  Well:  in the current implementation,
          all variables are treated by  this  printf  as  C  type
          "float",  so fomat statements must be specified accord-
          ingly.  The  fileID  should  be  a  value  returned  by
          dOpen().  sprintf( charArray, string ); Print the given
          string into the given character array, as  with  the  C
          version  of  sprintf().  The  character array should be
          created using the "char" statement.

     sprintf( charArray, formatString, argList );
          Print  the  given  data,  as  with  the  C  version  of
          sprintf();  Note  Well:  in the current implementation,
          all variables are treated by  this  printf  as  C  type
          "float",  so fomat statements must be specified accord-
          ingly.  The character array should be created using the
          "char" statement.

     strcpy( charArray, string );
          Copy the string to the given character array,  as  with

          be created using the "char" statement.

     strcat( charArray, string );
          Catenate the string to the given  character  array,  as
          with  the  C  version of strcat().  The character array
          should be created using the "char" statement.

     strcmp( string1, string2 );
          Compare the given strings, as with  the  C  version  of
          strcmp().  The value returned is either negative, zero,
          or positive depending on whether string1  is  lexically
          less than, equal to, or greater than string2.

     strcasecmp( string1, string2 );
          Compare the given strings, in case-insensitive mode, as
          with the C version of strcasecmp().  The value returned
          is either negative,  zero,  or  positive  depending  on
          whether  string1  is  lexically less than, equal to, or
          greater than string2.

     strexpr( string, regexpr );
          Return 1 if the given string matches the given  regular
          expression  "regexpr".   The  usual  rules  of  regular
          expression matching apply.

     strcpy( charArray, string );
          Copy the string to the given character array,  as  with
          the  C version of strcpy().  The character array should
          be created using the "char" statement.

     argTest( string );
          True if string was found in argv[] command line list.

     argVal( string );
          Returns the value following string  in  argv[]  command
          line list.

     getParm( fdata, parmCode, dimCode );
          Gets a parameter from the given file header array fdata
          according  to  its  parameter  code and dimension code.
          Values of parmCode are listed  in  the  file  fdatap.h;
          values of dimCode are listed above.

     setParm( fdata, parmCode, value, dimCode );
          Sets a parameter in the header array fdata according to
          its  parameter  code  and  dimension  code.   Values of
          parmCode are listed in the  file  fdatap.h;  values  of
          dimCode are listed above.

     pnt2spec( fdata, dimCode, pntVal, unitString );
          Returns a location in spectral units  corresponding  to

          varies from 1 to N, where N is the number of points  in
          the  given  dimension  (dimCode).   The  spectral units
          (unitString) are specified as "ppm",  "hz",  "pts",  or
          "%".

     spec2pnt( fdata, dimCode, specString );
          Returns a location in points corresponding to the given
          spectral  location.  The spectral location is specified
          as a string (specString) which contains a position with
          a spectral units label, such as "7.4ppm".

     dOpen( fileName, modeString );
          Opens the give file, and returns a file ID for  reading
          or writing, using the open() UNIX system call.  If mode
          is "r", the file will be opened read-only.  If mode  is
          "w",  the  file will be created if needed, truncated to
          zero length, and opened for writing. If mode  is  "rw",
          the  file  will be opened for both reading and writing.
          Alternatively, the mode string can contain combinations
          of  the  following  characters  to use as flags for the
          open() UNIX system call:


             ooooooooo     oooooooooooooooo
             Character     UNIX open() Flag
             ooooooooo     oooooooooooooooo
                r             O_RDONLY
                w             O_WRONLY
                d             O_NDELAY
                y             O_NOCTTY
                s             O_SYNC
                a             O_APPEND
                c             O_CREAT
                t             O_TRUNC
                e             O_EXCL
             ooooooooo     oooooooooooooooo



     dClose( fileID );
          Closes the given file.

     dSeek( fileID, byteLoc );
          Positions the given file; this cannot be used for pipe-
          line data.

     vvCopy( destArray, srcArray, length );
          Copy contents of srcArray to destArray.

     vvCopyOff( destArray, srcArray, length, destOffset, srcOffset );
          Copy srcArray[srcOffset...] to destArray[destOffset...]

          Read given byte count from the given file.

     dWrite( fileID, array, byteCount );
          Write given byte count from the given file.

     dReadB( fileID, array, byteCount );
          Read given byte count from  the  given  file  (blocking
          version,  which  waits  until all data have been read).
          Use this function to read data from a pipeline.

     dWriteB( fileID, array, byteCount );
          Write given byte count from the  given  file  (blocking
          version, which waits until all data have been written).

     vvAdd( array1, array2, length );
          array1 = array1 + array2

     vvSub( array1, array2, length );
          array1 = array1 - array2

     vvMult( array1, array2, length );
          array1 = array1 * array2

     vvDiv( array1, array2, length );
          array1 = array1 / array2

     vvSwap( array1, array2, length );
          Swap contents of array1 and array2

     vsAdd( array, length, val );
          array = array + val

     vsMult( array, length, val );
          array = array * val

     vsSet( array, length, val );
          array = val

     lShift( array, length, lsVal );
          Left-shift array by lsVal points.

     rShift( array, length, rsVal );
          Right-shift array by lsVal points.

     vShow( array, length );
          Print contents of array.

     vNeg( array, length );
          Negate contents of array.

     reverse( array, length );


     phase( realArray, imaginaryArray, length, p0, p1 );
          Apply a phase correction.

OPTIONS
     -macro macroFile
          Specifies the macro file to execute,  relative  to  the
          current directory.  This is a required argument.

     -var vList
          Specifies  a  space-separated  list  of  variable/value
          pairs,  which allows variables to be initialized at the
          command line before the macro is executed.  -str  sList
          Specifies  a  space-separated  list  of variable/string
          pairs, which allows character arrays to be created  and
          initialized  at  the  command  line before the macro is
          executed.

     -all (nmrPipe only) If this flag is used, the macro will  be
          invoked  to  perform initialization and exist steps, as
          well as processing steps.  If the -all is not used, the
          macro  will  only be invoked for processing steps.  The
          action that the macro is expected to perform  is  indi-
          cated  by  the  variable  "sliceCode", explained above.
          -quit (M stand-alone interpreter only).  If  this  flag
          is  included, the stand-alone program M will exit after
          all macro files on the command line have been executed.
          If  the flag is not included, the program will enter an
          interactive mode after all macro files have  been  exe-
          cuted.

EXAMPLES
     For examples, see the following nmrPipe macros:

        skew.M     Applies a custom window function.
        ranceY.M   Rance-Kay mode 2D gradient shuffling.
        ranceZ.M   Rance-Kay mode 3D gradient shuffling.
        shuf3D.M   Adjust non-standard 3D acquisition order.
        rrii.M     Adjust non-standard Chemagnetics data.

     as well as the following stand-alone M macros:

        xz.M       Extract XZ 2D Plane from 3D/4D data.
        xa.M       Extract XA 2D Plane from 4D data.