If your research relies on simulations, then you typically have parameters that you need to change for every simulation you run. If you use a software platform like MATLAB, then you can try getting away with changing parameter values directly via the command line. Generally, though, it’s a lot more flexible if you assign parameters in a function or script that runs your simulation. An even more flexible strategy is to use a function wrapper. This post is an introduction to using function wrappers in MATLAB.
What is a wrapper? A wrapper is a function or script whose implementation is only to call another function. I realize that this doesn’t sound very useful at first. Why bother with another layer of abstraction? Here are some advantages:
- Different wrappers can call the same simulation with different parameters
- The simulation and the wrapper can be modified independently (as long as the arguments are the same!)
- Keeping different wrappers is one way to keep track of what simulations you have
Let’s consider this simple simulation script as an example:
We generate the myOutput row vector, which is an array of Gaussian random variables with the specified mean and variance. The “simulation” here is just one line (the call to randn), but this could easily be much longer and/or involve multiple files. The other lines in this example are defining input arguments. We could easily change any of the parameter values and re-run the script, but we lose the record of what the parameters used to be.
If we re-write the script into a function then we get this:
Now if we call this function from the command line, then at least the command line history will keep a record of what the calls were. But it’s not a good idea to rely on the command line history, especially if you run the code from different machines. Here’s one way that a wrapper comes in handy. The simple wrapper looks like this:
At first glance, it doesn’t look like we’ve changed much, since this is almost identical to the original script. But now we can make multiple copies of this file and change the parameters in each one. Independently, we can change the simulation function and not have to worry about updating the wrappers.
Wrappers don’t need to be limited to a single function call. If the underlying function can support it, then we can use one wrapper to repeat a simulation many times. Let’s modify our function so that it also saves its output to a file whose name is based on the input parameter values:
(Note that in the call to num2str we can specify the formatting of the number, but here we leave it as the basic call)
Do we still need a wrapper? Any call to this function will save the input arguments with the simulation output. But now we can re-write the wrapper to call the simulation multiple times:
This wrapper will run our simulation 11 times (based on the current values of the input arguments) and generate 11 output files. Even though this wrapper is no longer associated with one simulation, the output file names and contents of those files list the arguments that were used to generate the output.
So that’s the basic idea of function wrappers. They can really improve the workflow and organization of your code, and can guide you if you need to re-visit your work after a few months (or years!).