A batinclude file "matplot" is provided that allows you to use MATLAB for plotting plots directly from GAMS. This package assumes that GAMS is the client and MATLAB is the server, ie you just run GAMS and this sets up and runs MATLAB for you.
The simplest usage is via the syntax: $libinclude matplot A
In this case, A is a one or two dimensional parameter. The first index runs over the points to be plotted on a given line. The second index runs over the different lines to be superimposed on the plot.
The libinclude creates a file "matplot.m" containing all the commands needed to create the plot, and executes these commands using a "matlab engine". The "matplot.m" file is left in the current directory allowing modification and direct running from MATLAB at a later time if required.
The examples and mechanism for carrying this out are adapted from the GNUPLOT plotting interface to GAMS written by Tom Rutherford. He deserves much credit for this interface.
1. A machine running both GAMS and MATLAB
2. GAMS version 2.25.089 or later (released in October, 1996).
1. Ensure that the GAMS system directory is on your system path.
2. Copy matplot.zip into your GAMS
system directory and run unzip matplot
If you are on a SOLARIS box or a PC box, you are done.
3. If you are not running on a SOLARIS box or a PC box, then you need
to (mex)-compile the file matplot.c that is now in your GAMS system
directory. The details are platform specific and can be found on
pages 6-14 - 6-18 of the MATLAB API Guide.
In GAMS, an environment variable is set with a statement such as:
$setglobal variable value
This passes a variable with a specified value to MATLAB. The following variables are understood:
domain | Specifies the domain on the x-axis of data which are to be displayed. (Note: this parameter may be specified as the second argument on the $libinclude call.) |
series | Specifies the data series (individual output plots) which are to be displayed. (Note: this parameter may be specified as the third argument on the $libinclude call.) |
labels | Subset of X axis labels to be displayed on graph. |
xvalue | Specifies a parameter or column containing the x-axis values -- included to permit generating graphs with unequal intervals. (The package first looks to see if there is a parameter named %xvalue%. If there is no parameter with that name, it then looks for a datacolumn with that name.) |
batch | Specifying $setglobal batch yes indicates that MATPLOT should be called in batch mode. When this switch is omitted, MATPLOT awaits the user's click before closing the graph window. |
The following extra environment variables can be used as well.
gp_figure: Specifies the number of a new figure to be created. gp_key: This specifies the location of the legend on the plot 0 = Automatic "best" placement (least conflict with data, default) 1 = Upper right-hand corner 2 = Upper left-hand corner 3 = Lower left-hand corner 4 = Lower right-hand corner -1 = To the right of the plot [Note: can change location with mouse after the plot is drawn]. gp_xscale: This gives the scaling of the x axis within the figure (typical value less than or equal to 1, default 1. gp_yscale: This gives the scaling of the y axis within the figure, default = xscale. [Note: can use mouse to change the size of figure after plot is drawn]. gp_opt0: string to pass additional MATLAB commands to the plotting routine. This is put into matplot.m before the plot is issued. gp_opt1,gp_opt2,....,gp_opt19: strings to pass additonal MATLAB commands to the plotting routine. These are added to the end of matplot.m in the order specified by their numbering.
$title Example 0: Plot a one dimensional vector to the screen set t /1990*2030/; parameter a(t) Example 0: Generic output to the screen (default invocation); a("1990") = 1; loop(t, a(t+1) = a(t) * (1 + 0.04 * uniform(0.2,1.8)); ); * I know that a() is defined over set t. The plotting package * knows that the argument has one dimension, but it does not know * what set defines those entry. Three ways to pass the domain: * (i) Let GAMS figure out which elements of A are nonzero (not a problem * here because the parameter is dense: $libinclude matplot A * (ii) Pass GAMS the domain on the call: $libinclude matplot A t * (iii) Pass GAMS the domain in an environment vaiable: $setglobal domain t $libinclude matplot A
$title Example 1: Generic Invocation of MATPLOT set t /1990*2030/, j /a,b,c,d/; parameter a(t,j) Example 1: Generic output to the screen (default invocation); a("1990",j) = 1; loop(t, a(t+1,j) = a(t,j) * (1 + 0.04 * uniform(0.2,1.8)); ); $setglobal gp_key 2 $libinclude matplot A
$title Example 2: Directing MATPLOT Output to File set t /1990*2030/, j /a,b,c,d/; parameter a(t,j) Random time series with a trend; a("1990",j) = 1; loop(t, a(t+1,j) = a(t,j) * (1 + 0.04 * uniform(0.2,1.8)); ); $setglobal gp_figure 1 $setglobal gp_key 4 $setglobal gp_opt1 $libinclude matplot A $setglobal batch yes $setglobal gp_opt1 "print -dpsc ex2.ps" $libinclude matplot A $setglobal gp_opt1 "print -depsc -epsi ex2.eps" $libinclude matplot A $setglobal gp_xscale 0.8 $setglobal gp_opt1 "print -djpeg ex2.jpg" $libinclude matplot A
The JPEG file generated by ex2.gms:
$title Example 3: Graphs with Labels and Titles set t /0*40/, j /a,b,c,d/; * Note: where we specify descriptive text for subset elements, * it is then displayed in place of the subset index on the * graph -- i.e. 1990,2000 etc. are displayed, not 0,10,... set decade(t) / 0 1990, 10 2000, 20 2010, 30 2020, 40 2030/; parameter a(t,j) Example 3: Labels and Titles; a("0",j) = 1; loop(t, a(t+1,j) = a(t,j) * (1 + 0.04 * uniform(0.2,1.8)); ); * --------------------------- * Generic plotting commands: $setglobal labels decade * --------------------------- * PLOT commands: $setglobal gp_figure 2 $setglobal gp_opt1 "title('Graph of Random Time Series');" $setglobal gp_opt2 "xlabel('Year -- time step annual');" $setglobal gp_opt3 "ylabel('Value');" $libinclude matplot A $setglobal gp_xscale 0.6 $setglobal gp_opt4 "print -djpeg ex3.jpg" $libinclude matplot A
The JPEG file generated by ex3.gms:
$title Example 4: Changes the graph size, y range and location of key: set t /1990*2030/, j /a,b,c,d/; set decade(t) / 1990 'michael', 2000, 2010, 2020, 2030/; parameter a(t,j) Example 4: Changing graph size and scaling ; a("1990",j) = 1; loop(t, a(t+1,j) = a(t,j) * (1 + 0.04 * uniform(0.2,1.8)); ); $setglobal labels decade $setglobal gp_key 1 $setglobal gp_xscale 0.8 $setglobal gp_opt1 "xlabel('Year -- time step annual');" $setglobal gp_opt2 "ylabel('Value');" $setglobal gp_opt3 "grid" $setglobal gp_opt4 "v = axis; v(3:4) = [0 3]; axis(v);" $libinclude matplot A $setglobal batch yes $setglobal gp_opt5 "print -djpeg ex4.jpg" $libinclude matplot A
The JPEG file generated by ex4.gms:
$title Example 5: Unequally spaced data set t /0*40/, j /a,b,c,d/; parameter a(t,j) Example 5: Missing data represented by NA; a("0",j) = 1; loop(t, a(t+1,j) = a(t,j) * (1 + 0.04 * uniform(0.2,1.8)); ); set decade(t) / 0 1990, 10 2000, 20 2010, 30 2020, 40 2030/; parameter year(t); year(t) = 1989 + ord(t); * Omit some data points randomly, indicating these as missing * by assigning values equal to na: a(t,j)$(uniform(0,1) le 0.25) = na; $setglobal labels decade $setglobal xvalue year $setglobal gp_key 0 $setglobal gp_figure 1 $setglobal gp_opt1 "set(gp.plot,'Marker','x');" $setglobal gp_opt2 "xlabel('Year -- time step annual');" $setglobal gp_opt3 "ylabel('Value');" $libinclude matplot A $setglobal gp_xscale 0.9 $setglobal gp_yscale 0.7 $setglobal gp_opt4 "print -djpeg ex5.jpg" $libinclude matplot A
The JPEG file generated by ex5.gms:
$title Example 6: Dealing with Zero Rows and Zero Columns set i evaluation points /1990*2000/ j various time seris /a, b, c, d/; $setglobal labels i table time_path(i,j) Time series with holes a b c d 1990 0 2 0 0 1991 1 2 1 0 1992 2 3 4 0 1993 3 4 0 0 1994 4 0 2 0 1995 0 0 0 0 1996 1 2 3 0 1997 2 3 4 0 1998 3 4 5 0 1999 4 5 6 0 2000 5 1 7 0; * Note that time series d is all zeros, and * all of the time series equals zero in 1995. * Problem: Get matplot.gms to pass zero files * through to the plotting package. $setglobal gp_key 2 $setglobal gp_xscale 0.9 $setglobal gp_yscale 0.6 $setglobal gp_opt1 "title('Problem: 1995 and series D are both zero.');" $libinclude matplot time_path $setglobal batch yes $setglobal gp_opt2 "print -djpeg ex6a.jpg" $libinclude matplot time_path $setglobal gp_opt2 $setglobal batch no * Define an explicit domain and series: $setglobal domain i $setglobal series j $setglobal gp_opt1 "title('One solution: define domain and series');" $libinclude matplot time_path $setglobal batch yes $setglobal gp_opt2 "print -djpeg ex6b.jpg" $libinclude matplot time_path $setglobal gp_opt2 $setglobal batch no * Drop the domain and series definition: $setglobal domain $setglobal series * Method 2: replace zero by eps time_path(i,j)$(not time_path(i,j)) = eps; $setglobal gp_opt1 "title('Another solution: replace zero by eps.');" $libinclude matplot time_path $setglobal batch yes $setglobal gp_opt2 "print -djpeg ex6c.jpg" $libinclude matplot time_path $setglobal gp_opt2 $setglobal batch noJPEG files generated by ex6.gms:
$title Example 7: Plotting Multiple Independent Series set i observation counts /1*4/, g graphs /a, b, c/; table data(i,*,g) x.a y.a x.b y.b x.c y.c 1 1 1 0 2 1 6 2 2 2 3 2 2 4 3 4 3 5 5 3 3 4 10 4 7 6 4 1; * First define a set which can hold 4 observations x * 3 plot series: set p plot points /1*12/ set pp(p); pp("1") = yes; parameter x X coordinate for a given point, y Series values for points; * The next statement is crucial -- initialize * all plot points to NA (missing). The package * will then only plot those items which are * specified. y(p,g) = na; loop(g, loop(i, x(pp) = data(i,"x",g); y(pp,g) = data(i,"y",g); pp(p+1)$pp(p) = yes; pp(p)$pp(p+1) = no; ); ); display x, y; $setglobal domain p $setglobal xvalue x $setglobal gp_opt1 "grid;" $setglobal gp_opt2 "set(gca,'TickDir','out');" $libinclude matplot y * The X coordinates may also be passed as a column in the matrix. y(p,"xv") = x(p); $setglobal xvalue xv $libinclude matplot y $setglobal gp_xscale 0.7 $setglobal gp_yscale 0.6 $setglobal gp_opt3 "print -djpeg ex7.jpg" $libinclude matplot yJPEG file generated by ex7.gms:
$title Example 8: Plotting Two-Dimensional Series set i Commodities /i1*i3/, r Regions /r1*r3/, t Time periods /2000*2100/ s(i,r) Plot series; s(i,r) = yes; parameter prices(t,i,r) Commodity prices; prices(t,i,r) = 1; loop(t, prices(t+1,i,r) = prices(t,i,r) * (1 + 0.04 * uniform(0.2,1.8)); ); $setglobal domain t $setglobal gp_key 2 $setglobal series s * before matplot option: give 9 different colors to lines $setglobal gp_opt0 "set(0,'DefaultAxesColorOrder',rand(9,3));" * remove border around legend box $setglobal gp_opt1 "h = findobj('type', 'axes'); set(h(1), 'visible', 'off');" $libinclude matplot prices $setglobal gp_xscale 0.9 $setglobal gp_yscale 0.8 * before matplot option: cycle through line styles $setglobal gp_opt0 "set(0,'DefaultAxesColorOrder',[0 0 0]); set(0,'DefaultAxesLineStyleOrder','-|:|-.|--|x|o|+|d|v')" $setglobal gp_opt2 "print -djpeg ex8.jpg" $libinclude matplot pricesJPEG file generated by ex8.gms:
$title Example 9: Contour Plotting Example set i /1*20/; alias (i,j); parameter a(i,j) Evaluation of xy x(i) Ages of individuals y(j) Number of individuals; x(i) = ord(i) - 10; y(j) = ord(j) - 10; loop((i,j), a(i,j) = x(i) * y(j); ); $setglobal gp_opt1 "xlabel('value of X');" $setglobal gp_opt2 "ylabel('value of Y');" $setglobal gp_opt3 "title('Evaluation of xy');" $libinclude contour a i j $setglobal batch yes $setglobal gp_opt4 "print -dpsc -epsi ex9.ps" $libinclude contour a i j $setglobal gp_opt4 "print -djpeg ex9.jpg" $libinclude contour a i jJPEG file generated by ex9.gms:
Frequently asked questions about using MATPLOT with GAMS:
How can I move MATPLOT output into a paper or presentation?
Figures may be copied to the Windows clipboard (use Edit -> Copy Figure, or the MATLAB commands "print -dmeta" or "print -dbitmap"). This provides a Windows-compatible image which can be pasted into any number of applications.
Alternative, you can produce publication-quality figures by loading MATPLOT output into LaTeX. The graphicx package can be used in association with EPSI files generated using "print -depsc -epsi figname.ps". Several examples are given above. Also see the MATLAB command "help print".
How do I represent missing values?
MATPLOT.GMS uses use the special GAMS numeric value "NA" to represent missing data.
Can I regenerate a plot using MATPLOT independent of GAMS?
Yes. If you look at files matplot.m and GNUPLOT.DAT after GAMS has exited, you will find that these contain all the MATLAB commands and data required to generate the last plot from your GAMS code. To reproduce the graph, execute matplot.m within MATLAB. Can I make MATLAB the cleint?
A more complete interface between GAMS and MATLAB (that makes MATLAB the client and GAMS the server) can be obtained from MATLAB for visualization.