input graph.mp;
warningcheck :=0;

input latexmp.mp

% read two columns from a file,
% need to specify filename, the target
% path name, and two columns,
% if there's only one column, take 1---size(column)
% as default x ---- well, dont' know how to do it yet now
numeric n_paths; %number of paths I have read so far
numeric n_line; % lines I have already plotted out
numeric g_w, g_h;       % global width and height of plotting area
g_w=5in;
g_h=4in;

numeric  mtfontsize, gridfontsize, lgdfontsize;
mtfontsize:=14;
gridfontsize:=12;
lgdfontsize:=10;

vardef pttoinch(expr p)=p/72 enddef;

string wantgrid;
numeric d[][], count[];
% d is the raw data I have seen,
% p is the paths to be plotted

picture line_patterns[], line_markers[];
color line_colors[];
numeric line_widths[];
% the four basic properties of each line,
% needs to be remembered so that I can draw them in the legend box



def rdata(expr filename)% a string
%       (suffix d)% an array of paths
       (expr column)% i is column number in the datafile
=
       begingroup
       string s[];
       numeric row;
       row:=0;
       gdata(filename, s,
                       d[n_paths][row]:=Mlog_str(s[column]);
                       row:=row+1;
       );
       count[n_paths]:=row-1;
       n_paths:=n_paths+1;
       endgroup;
enddef;



% create a path from two "raw paths", which only have
% meaningful x part
vardef combine_paths(expr p, q)=
       (d[p][0],d[q][0])
       for i=1 upto  min(count[p], count[q]):
               -- (d[p][i],d[q][i])
       endfor
enddef;




input string.mp

% style specification:
% the first two are column numbers,
% then following are specifications
% seperated by whitespace,
% the "linewdith" number should be preceded by
% "linewidth" , color is started by "c", pattern is started by
% "p"
% add a one line from existing data repository into
% the set of paths  to be printed, p. also parse the
% line style, etc.
def mtplot(expr cmd)=
begingroup
       numeric x,y;
       string style;
       path p;
       string ss;
       numeric marker_idx;

       ss:=cmd;

       % now use default setting if not specified
       line_widths[n_line]:=1;
       line_patterns[n_line] := patterns[n_line mod (patterns.count+1)].d;
       line_colors[n_line] := colors[n_line mod ( colors.count+1)].d;
       marker_idx := 0;
       % X and Y column index
       x := scantokens(loptok ss );
       y := scantokens(loptok ss );
       p := combine_paths(x,y);

       forever : exitif ss="";
       style := loptok(ss);
       if ( style = "linewidth" ) :
               line_widths[n_line]:= scantokens( loptok(ss));
       else :
               if ( (substring(0,1) of  style)
                       = "c" ):
                       line_colors[n_line]:=searchdefault.colors(style);
               else:
                       if ( ( substring(0,1) of style )
                               = "p" ):
                               line_patterns[n_line]:= searchdefault.patterns(style);
                       else:
                               if ( ( substring(0,1) of style )
                                       = "m" ):
                                       marker_idx := searchdefault.markers(style);
                               fi % t spec
                       fi % p spec
               fi% color spec
       fi % width spec
       endfor;

       line_markers[n_line]:=markersp(marker_idx,
                       withpen pencircle scaled line_widths[n_line]
                        withcolor line_colors[n_line]
                       );


       gdraw p
               withpen pencircle scaled line_widths[n_line]
               withcolor line_colors[n_line]
               dashed line_patterns[n_line] scaled line_widths[n_line]
               % scaled is important, so width and length of dashes are
               % proportional
               ;

       gdraw p plot line_markers[n_line];
       n_line := n_line+1;
endgroup;
enddef;


vardef ttt primary a = (1=1) enddef;


%search color or pattern from default table
vardef searchdefault@#(expr query)=
       %take the substring from the second char upward
       string sss;
       sss:=( substring (1,cspan(query,ttt))
                       of query);
       searchdefault_rec@#(0,sss)
enddef;

% a recursive definition
vardef searchdefault_rec@#(expr idx, query )=
if ( @#[idx].name = query ):
                @#[idx].d
elseif ( idx = @#.count):
        @#[0].d        % at the last choice, have to use it
else:
                        searchdefault_rec@#(idx+1, query)
fi
enddef;




%default color table

string colors[].name;
color  colors[].d;
numeric colors.count;
colors[0].name:="k"; colors[0].d:=black;
colors[1].name:="r"; colors[1].d:=red;
colors[2].name:="g"; colors[2].d:=green;
colors[3].name:="b"; colors[3].d:=blue;
colors[4].name:="y"; colors[4].d:=red+green;
colors[5].name:="o"; colors[5].d:=1.5*red+ 0.5*green;
colors[6].name:="p"; colors[6].d:=red+blue;
colors.count:=6;

%default dash patterns
string patterns[].name;
picture patterns[].d;
numeric patterns.count;
patterns[0].name:="solid"; patterns[0].d:=nullpicture;
patterns[1].name:="dash"; patterns[1].d:=evenly;
patterns[2].name:="dot";
       patterns[2].d:=dashpattern( on 0 off 1.5 );
patterns[3].name:="dashdot";
       patterns[3].d:=dashpattern(on 4 off 2 on 1 off 2) ;
patterns[4].name:="dddash";
       patterns[4].d:=dashpattern(on 1 off 2 on 1 off 2 on 4
       off 2);
patterns[5].name:="dddot";
       patterns[5].d:=dashpattern(
               on 4 off 2 on 4 off 2 on 1 off 2 );
patterns.count:=5;


%default markers
string markers[].name;
numeric markers[].d;
numeric markers.count;
picture temppic;
markers[0].name:="o";
markers[1].name:="x";
markers[2].name:="*";
markers[3].name:="d";
markers[4].name:="s";
% just to make the function "searchdefault()" return the index
markers[0].d:=0;
markers[1].d:=1;
markers[2].d:=2;
markers[3].d:=3;
markers[4].d:=4;

markers.count=4;

numeric markersize;
markersize:=3bp;
% a wacky trick to paste the options
% (withpen, etc) that is to be supplied later onto
% the marker picture
% markers_picture or "markers_paths"
def markeritem(text s)=
       hide(
%               save tmp_pic;
               picture tmp_pic;
               tmp_pic:=nullpicture;
               s;
               )
       tmp_pic
enddef;


def markerset(text opt)=

       markeritem( trash:=1; ), %nothing

       markeritem(     % "X"
               addto tmp_pic doublepath
                               ( (-1,-1) -- (1, 1) ) scaled markersize opt;
               addto tmp_pic doublepath
                               ( (-1, 1) -- (1,-1) ) scaled markersize opt;
       ) ,
       markeritem(     % "*"
               for i=1, 2 , 3:
                       addto tmp_pic doublepath
                               ( dir(i*120) -- dir(i*120+180) )
                                       scaled markersize  opt;
               endfor;
       ),

       markeritem(   % diamond "d"
               addto tmp_pic doublepath
                       unitsquare shifted (-.5, -.5)
                       rotated 45
                       scaled markersize opt;
       ),

       markeritem(     % square "s"
               addto tmp_pic doublepath
                       unitsquare shifted ( -.5 , -.5)
                       opt;
       )
enddef;

def markersp(expr idx)(text opt)=
       hide (
                       numeric i;
                       picture result,j;
               i:=0;
               for j=markerset(opt):   % list out all possible markers
                       if ( i=idx):
                               result:=j;
                       fi
                       i:=i+1;
               endfor
               if (  unknown result ):
                       result:=j;      % just last marker
               fi
       )
       result
enddef;



def xlabel(expr l)=
       glabel.bot(textext("{\mtfont " & l & " } ") ,  OUT );
enddef;

def ylabel(expr l)=
       glabel.lft(textext("{\mtfont " & l & " } ")
               rotated 90, OUT);
enddef;



%draw the legend, do calculation on the legend box size
% need lgdfontsize, how many lines to draw, etc,
% also use the remembered line properties
vardef legend(expr x, y)(text tags)=
       numeric lgd_w, lgd_h, lgd_x, lgd_y;     % size of legend box
       picture lgd, tmp_lgd;
       string s,tagstr[];
       numeric i,j;

 % parse the tags first, put them into an array,
       i:=0;
       for s=tags:
        tagstr[i]:=s;
        i:=i+1;
       endfor
       for j=i upto n_line -1:
        tagstr[i]:=decimal(j);
       endfor

       tmp_lgd:=nullpicture;
       lgd:=nullpicture;

 %first draw the legend box into picture, then
       % draw it and shift it
       margin:=(lgdfontsize/2);
       for i = 0 upto n_line -1:
               % draw the sample line in legend box
               addto tmp_lgd doublepath
                       (( (0,0)
                               --
                        ((g_w /10),0))
                        shifted  ( margin , 2margin+ lgdfontsize *i*1.5  )
                       )
                                withpen pencircle scaled line_widths[i]
                                withcolor line_colors[i]
                                dashed line_patterns[i]
                               scaled line_widths[i];

               % add anotation to the sample line
               addto tmp_lgd also thelabel.rt(
                               textext("{\lgdfont "& tagstr[i] & "}"),
                       ( (margin+g_w/10+margin)
                               ,(2margin+ lgdfontsize *i*1.5))
               );

               % draw marker mark on sample line
               addto tmp_lgd also      line_markers[i]
               shifted (
                               ((g_w/20),0)
                               +
                                ( (margin), (2margin+ lgdfontsize *i*1.5))
               );
       endfor;

       path box;
       box:=bbox(tmp_lgd);
       lgd_w:= xpart(point 1 of box) + margin;
       lgd_h:= n_line * lgdfontsize *1.5 + 2margin;

       addto lgd contour (0,0)--(lgd_w,0)--(lgd_w,lgd_h)--(0,lgd_h)--cycle
               withcolor .95 white;    % fill the background of legend box with white
       addto lgd doublepath (0,0)--(lgd_w,0)--(lgd_w,lgd_h)--(0,lgd_h)--cycle
                       withpen pencircle;
       addto lgd also tmp_lgd;

       % now calculate position of legend box
       if ( x = 1 ):
        lgd_x := (g_w/20);
       elseif( x= 2):
               lgd_x:=(g_w/2-(lgd_w)/2);
       else:
               lgd_x:=(g_w*19/20) - lgd_w;
       fi

       if ( y=1):
        lgd_y:=(g_h/10);
       elseif (y=2):
           lgd_y:=(g_h/2-(lgd_h)/2);
       else:
           lgd_y:=(g_h*9/10)- lgd_h;
       fi

%finally draw the legend box
       draw lgd shifted (lgd_x, lgd_y);

enddef;


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

defaultfont:="Helvetica";


% initialization
def begingrf(expr w, h)=
hide(
string tempstr;
tempstr:=
       "\font\mtfont=" & defaultfont & " at " & decimal(mtfontsize) &"pt  "
       & " \font\lgdfont=" & defaultfont & " at " &decimal(lgdfontsize) & "pt "
       & " \font\gridfont=" & defaultfont & "  at " &decimal(gridfontsize) &"pt "
       ;       %legend font, use normal 10pt
setupLaTeXMP(preamble=tempstr);
)
begingraph(w,h);
init_numbers(btex$-$etex,
               textext("{\gridfont 1}"),
               %btex$1$etex,
       btex ${\times}10$ etex,
       btex${}^-$etex,
       btex${}^2$etex);
Gtemplate.itick := origin -- (w/100,0);
Gtemplate.otick := origin -- (-w/100,0);
interim Gpaths:=log;
n_line:=0;
n_paths:=0;
wantgrid:="yes";
enddef;


% plot out everyting else
def finishgrf =
autogrid(itick.bot,itick.lft) withpen pencircle scaled 1.5;
if ( wantgrid = "yes" ):
autogrid(grid.bot,grid.lft) withpen pencircle scaled 0.5 dashed evenly;
fi
frame withpen pencircle scaled 1;
endgraph;
enddef;