Functions
The most basic way to group lines of Macro code is into a function. Let's write a function to compute wind speed given its U and V vector components.
We've already written code to compute wind speed:
speed = sqrt(u*u + v*v)
We can easily create a function around this code, taking u
and v
as input parameters. Create a new Macro icon and call it wind_speed
. Enter the following into it:
function wind_speed(u, v) speed = sqrt(u*u + v*v) return speed end wind_speed
Within the same macro, read in some wind data and call the function, plotting the result:
u = read('wind_u.grib') v = read('wind_v.grib') speed = wind_speed(u,v) plot(speed)
Note that it does not matter where the function is defined in the macro - it will be found.
Notice that the function does not restrict the type of variables coming into it - they could be fieldsets, numbers, geopoints or any other data type which is compatible with the operations being performed by the function (square root, multiplication and addition). Try calling the function with plain numbers:
print(wind_speed(3, 4))
We could restrict the function so that it only accepts fieldset parameters:
function wind_speed(u:fieldset, v:fieldset)
This can be useful in some cases, but for this particular example the functionality is so general that it will work with fieldsets, geopoints, numbers and vectors - so we can leave this restriction out. See the supplied Syntax Sheet for more examples of how to define functions.
Including Other Macros
Now split the macro into two separate files: the wind_speed macro should have the function definition, and the call_wind_speed macro should read the GRIB data, call the function and plot the data (it should not work now, because it cannot find the function).
The include
command literally includes the text of any macro at the insertion point. In our current example to make the function available to the call_wind_speed
macro, it is enough to add the line:
include "wind_speed"
anywhere in the macro.
The included macro is read at the point where the include
instruction is found. You can specify absolute or relative path names (relative to the position of the macro being run).
In this way you can place small libraries of functions in macro files, stored in a folder of your choice, ready for inclusion.
Inclusion does not require the included macro to be a self contained program or function - any partial fragment of code can be included, for example some variable declarations.
include
statement is interpreted before the macro is run. This means that you cannot, for instance, use a dynamically generated path to find the file to be included.Functions in a User/System Library
This is the method that can be really described as building a library of functions. Its principle is very simple - place macro functions in a particular folder which is searched by the function look-up procedure so they can be called from any macro program without the need for an include
statement.
In our case, simply drag the wind_speed macro icon to the folder ~/metview/System/Macros
. From then on you can call this function from within any of your macros. Note that this only works when the name of the macro file is the same as the name of the function it contains. Remove the include
statement from your call_wind_speed macro and see if it still works (it should). If you rename the wind_speed macro, or the function inside it, it should no longer work.
This allows you to build your own personal function library. For a function to be available to other users, you can place the macros with the functions into shared folder on the file system; all users will need to set the environment variable METVIEW_MACRO_PATH
to this location before starting Metview.
Extending the Macro Language
It is possible to write your own C/C++/Fortran code and interface it with Metview Macro. In this way we can write functions in another language and call them directly from a macro, passing variables such as vectors, numbers and fieldsets between them. This is beyond the scope of this training course, but be aware that it is possible! It is currently documented in the 2014 Metview training course, and examples are given in the solutions folder if you'd like to have a look.