The Macro Tech-Tips column is aimed at EMME/2 users which are already familiar with EMME/2 macro writing, but want to further improve their general macro writing skills.
In this issue, we first look at some methods to improve the general robustness and efficiency of macros. In the second part, we take a closer look at the new g-registers and show how these can be used to efficiently perform some quite elaborate tasks.
Suppressing Pauses during Macro Execution
Whenever a message is displayed on the screen and might immediately
be followed by a clear screen command, EMME/2 pauses for a second or two
in order to give the user enough time to look at the message before
the screen is erased. This happens in particular each time a report has
been sent to the print file (message ``x pages sent to print file'').
While this pause is very useful when running EMME/2 interactively,
it is in general not necessary when running a macro. Thus, macros that
generate many small reports can often be sped up significantly by
suppressing these pauses. This is done by activating bit 5 of the
o-register, i.e. by adding the line ~o|32
at the beginning of
the macro.
Avoiding format errors by limiting text length
EMME/2 is quite strict regarding the maximum size of text and alphanumeric
items, and will usually generate a format error when an attempt is made
to enter a string which is too long. Macros often construct strings
(such as descriptions of matrices, scalars, zone group ensembles or
extra attributes) according to the current context or from user
supplied parameters.
In order to avoid such macros becoming ``time-bombs'', it is
necessary to take special precautions to ensure that the maximum
string length is not exceeded. Since text register substitution allows
access to substrings, this can be done by first storing the entire
title or description in a text register and then passing only the properly
limited substring to the program, e.g. as is done in the following result
matrix specification dialog:
mf66 / active demand yes / change matrix header actdem / matrix name ~t1=Active Demand (sel-lk %1% %2% %3%) '%t1.40%' / matrix description (limit to max. 40 chars) ~?q=1 y / initialize data 0 / to zero
Testing for batch input errors
Errors which are detected when reading batch input files are usually
warnings. As macro processing only stops automatically on fatal errors,
but not on warnings, batch input errors occurring within a macro will
often slip through unnoticed at the time they happen and are
-if at all- only detected much later. To avoid the danger associated
with such errors, any macro which performs batch input operations should
be able to detect batch input errors, so that, if they happen,
appropriate measures can be taken right away. Tracking this type of
warning errors is best done by checking the global parameter NLERR
(documented on page C-6 of the EMME/2 User Manual) which can be
accessed by setting the value of the p-register to the corresponding index
32 and reading its contents.
As this parameter is composed of the total number
of errors of both types as well as the number of the last
error detected, its value will only change during a batch
input operation if errors were detected. The following
small macro sequence shows the principle
of how such a test can be implemented:
... ~p=32 ~x=%p% ... (perform batch input operations here) ~x-%p% ~?!x=0 ~/Batch input error detected! ...An example of a more elaborate implementation of checking the NLERR parameter can be found in the macro
errchk.mac
, which is
available on our web site.
Using the g-registers for computing histograms and distributions
Since the introduction of Release 8, the size of the put()/get()
stack of
EMME/2's expression parser has been increased to 250 and the stack values
can be accessed directly from macros via the new floating point
registers g1 - g250, both for reading and writing.
This opens up many new possibilities for direct interactions of
macros with function evaluations, as well as network and matrix
calculations. One such possibility is to efficiently compute
network histograms, i.e. sum up the value of some network expression
(e.g. vehicle-hours) by some arbitrary classification (e.g. district).
While in previous releases such a computation had to be done rather
inefficiently on a class-by-class basis,
it can now be done for up to 250 classes
simultaneously with a single expression of the
type
put(get(puti(
class))+
expr)
where class is an arbitrary sub-expression defining the classes
(giving values in the range 1 to 250) and expr defines the
quantity to be accumulated. Once the computation is performed, the
results are contained in the registers g1 - g250 from
where they can be accessed directly by the macro. The following
macro sequence computes and displays the vehicle-hours per district
(assumed in @distr
):
~+;2.41;1;n;put(get(puti(@distr))+volau*timau/60.);;all;5 ~+;~x+1;~?!gx=0;~/District %%%x_3%%%:%%%gx.2_10%%% vhrs;~?x<250;~$The macro
nethist.mac
(available on our web site)
uses the above technique to compute, display and plot
arbitrary network histograms.