next up previous
Next: Turning Movements Now Also on Up: EMME/2 News 6 July 1988 Previous: Annotation Files

Enhanced Macro Commands - Some Examples of Their Use

Since the introduction of the enhanced macro commands with Release 3.0, several users have suggested that in addition to the information made available in the User's Manual and in previous issues of EMME/2 News, it would be useful to illustrate these new macro commands by means of small example macro files. The following is an attempt to do just that.

We do not repeat here the description and syntax of the macro commands. These can be found in section III-2.2 of the User's Manual (assuming that you have updated your copy of the manual with the replaced pages that were sent out with Release 3.0), as well as in the February issue of EMME/2 News. It might be helpful to have these references handy for understanding fully the examples that follow.

As a first simple example, using the standard link subset selection, we would like to select all links that are contained entirely in a given rectangular network window. The window is specified by its lower left and upper right x/y coordinates. For the window LL=480/100 UR=880/400, this can be done without using a macro as follows:

Enter: Desired link types or attributes (from,to)
= xi=480,880
= and xj=480,880
= and yi=100,400
= and yj=100,400
=

If this type of selection occurs often within an application, it might be a good idea to define a macro called window in the following way

Enter: Desired link types or attributes (from,to)
= ~>window 480 100 880 400
  xi=%1%,%3%  
= and xj=%1%,%3%
= and yi=%2%,%4%
= and yj=%2%,%4%
= 
= ~>

The values 480, 100, 880 and 400 are the initial values for the macro parameters %1%, %2%, %3% and %4%, to be used during the saving phase of the macro. The so saved macro can from now on be recalled for any other window, just by calling the macro with the new window coordinates, e.g. entering

~<window 330 145 370 175

will generate the dialog using these new window coordinates

Enter: Desired link types or attributes (from,to)
= < xi=330,370
= < and xj=330,370
= < and yi=145,175
= < and yj=145,175
= <
= <~<

This demonstrates how to create and recall macros using parameters. The macro file created in this way is an ordinary sequential text file called "window" which contains the lines as they were entered, i.e.

xi=%1%,%3%  
and xj=%1%,%3%
and yi=%2%,%4%
and yj=%2%,%4%

It is a good practice to include comments and tests into macros, that are used for production purposes. As an example, here is a more complete version of the same macro window, which is commented and which checks that it is indeed called at the level of an Enter-question and that there are four parameters specified:

~/ ----------------------------------------------------------------
~/ window - select links that are within a specified network window
~/ usage:  window <xll> <yll> <xur> <yur>               88-07-01 HS
~/ ----------------------------------------------------------------
~?q>0             / Is it really an enter question?
~$error
~x=%0%            / At least 4 arguments?
~?x<4
~$error
xi=%1%,%3%        / Select link subset.
and xj=%1%,%3%
and yi=%2%,%4%
and yj=%2%,%4%

~$end
~:error
~/ usage:  window <xll> <yll> <xur> <yur> 
~:end

While the above macro may be more complex than needed, given the simplicity of the task it performs, it illustrates well some of the more elaborate macro commands. The "~/" lines are simply comments. The "~?q>0" tests if the current question is of the Enter variety or not. If not (q>0), the "~$error" command branches to the label "~:error" and displays an appropriate error message. If the type of question is correct, the macro proceeds to check the number of arguments, contained in the read-only register %0%. The "~x=%0%" command sets the register x to the number of arguments, which is then tested to be at least 4 by means of the command "~?x<4" (if not branching again to the "~:error" label).

In the second example, we look at the task of punching out several matrices with a single macro invocation. Module 3.14 allows the punching of one matrix only at a time and for a large application this task is quite time consuming. Having a macro "punchmat" that punches out all the matrices given as arguments saves waiting in front of the terminal for the individual punches to be completed. Here is one way to accomplish this task:

~/ -----------------------------------------------------------------
~/ punchmat - punch the matrices specified as arguments  88-07-01 HS
~/ -----------------------------------------------------------------
3.14           / call module 3.14
~y=0           / reset register y
~:next
3              / punch
%1%            / matrix identifier
~?q=1
no             / not the same constraint matrix
               / no constraint matrix
~?q=1
no             / no aggregation by origin
~?q=1
no             / no aggregation by destination
~?q=1
no             / no submatrix
~%             / shift macro arguments one to the left
~y+1           / count number of matrices punched so far
~x=%0%         / x is now the number of arguments left
~?x>0          / branch if still work to do
~$next
q              / back to main menu
~/ Matrix punch complete, %y% matrices punched ^G^G^G^G

Note that this macro contains already some "bells and whistles" that are not absolutely necessary, but make its use more easy. We will not explain the macro line by line, but rather point out some interesting details. (See section IV-3.14-3 of the EMME/2 User's Manual for the details of the dialog this macro is running through.)

a)
Note that some of the questions that appear in the dialog are dependent on the context. The question "Same constraint matrix (...)?" is not asked the very first time after the module is called. The test "~?q=1" will insert the answer "no" only if the question is indeed asked, i.e. if the current question is of the type Yes/No. The same method is used for the questions "Aggregation by origins?" (asked only for matrices of types mo and mf), "Aggregation by destination?" (asked only for matrices of types md and mf) and "Submatrix?" (not asked for scalar matrices).
b)
The register y is used to count the matrices that have been punched so far. At the beginning it is set to zero by "~y=0" and every time a matrix has been successfully punched, it is incremented with the command "~y+1". It is used to generate a message at the end that displays the number of matrices that have been punched. This type of message is very useful at the end of a macro that might take too much time for the user to wait in front of the terminal. When he returns, the screen will display this message reminding him of the task that was performed and confirming that no problems were encountered. The message can also contain BELL characters (^G in the above example) which produce a high-pitched sound when sent to the terminal, informing the user that the macro has terminated.
c)
The "punchmat" macro can have any number of matrix identifiers as command arguments. Only the first is actually handled explicitly, the subsequent ones are looped through (by branching to label :next) after having performed a "parametershift" command "~%" which discards the current parameter %1% (which has already been handled) and shifts down all remaining parameters by one, leaving the next in row as %1%. The number of parameters left is contained in %0%, which is copied into the x register where it can be tested to find out if the job is done.
d)
The macro can conveniently be commented by using the EMME/2 free format convention that anything after a slash "/" (that is not part of a text item, such as in titles or algebraic expressions) is considered as a comment. Note that this method of commenting a macro should not be used on label and branching commands "~$..." and "~:...".

The third example performs a task similar to the one we just saw. Instead of punching a set of specified matrices, we now want the macro to punch out all matrices of certain types gif. It is called "punchall" and takes as arguments any combination of the type identifiers "ms", "mo", "md" and "mf".

~/  --------------------------------------------------------------
~/  punchall - punch all matrices of the given types   88-06-24 HS
~/
~/  This macro will punch out all matrices of the specified type
~/  E.g. "~<punchall md" will punch out all destination matrices,
~/  whereas "~<punchall ms md mo mf" will punch out all existing
~/  matrices in the data base.
~/  --------------------------------------------------------------
3.14 c='punchall %1% %2% %3% %4%' / call mod 3.14 - use log book comment
~x=0           / reset register x (will loop through matrix numbers)
~y=0           / reset register y (number of matrices punched so far)
3              / punch
~:next
~x+1           / set next matrix number
~?x>25         / all matrices tested? (max number of matrices is here 25)
~$ntype
%1%%x%         / matrix identifier
~?e
~$next
~?q=1
no             / not the same constraint matrix
               / no constraint matrix
~?q=1
no             / no aggregation by origin
~?q=1
no             / no aggregation by destination
~?q=1
no             / no submatrix
~y+1           / count number of matrices punched so far
3              / punch
~$next
~:ntype
~%             / shift macro arguments one to the left
~z=%0%         / z is now the number of arguments left
~x=0           / reset register x to prepare for new matrix type
~?z>0          / branch if still work to do
~$next
               / no more matrix to punch
q              / back to main menu, display message
~/ Matrix punch complete, %y% matrices punched

Of course, the notes a) to d) given in the last example are also valid here, but there are some more points that merit special attention:

e)
When module 3.14 is called, a comment is placed into the log book documenting the operation that is being performed.
f)
The register x is used to loop through all possible matrix numbers, in this case from 1 to 25 (this number should be replaced with the actual data base dimension of the given application), while parameter %1% contains the matrix type. For matrices that are not defined, entering the identifier at the line %1%%x% will cause an error. Usually, when any error condition is detected the macro processing is immediately terminated with the message "<ERROR!<". In this case, however, the line "~?e" tests if an error has occurred, thus preventing the macro from aborting prematurely.

The only macro command that we have not encountered in any of the above examples, is the read line command "~*". It can be used to take the input to a given question not from the macro file, but have the user enter it from the terminal. As very simple example, consider the following small macro file named newtitle:

1.23       / call module 1.23, "modify titles and units"
1          / change project title
~*         / <<<< the title is entered here by the user
q          / back to the main menu

This last example shows how the "~*" command could be used to write macros that answer some of the questions automatically, leaving some others to the user to enter interactively.


next up previous
Next: Turning Movements Now Also on Up: EMME/2 News 6 July 1988 Previous: Annotation Files


Heinz Spiess, EMME/2 Support Center, Thu Jun 6 14:16:08 MET DST 1996