1### Copyright (c) 2007, Tyzx Corporation. All rights reserved. 2function g = g_ez (varargin) 3### g = g_ez (command, args,...) - Single-command plotting function 4### 5### This function allows to do basic plots with a single function call, i.e. 6### like octave's plot() commant. 7### 8### If no output argument is required, the plot is shown and all data created 9### for this plot is deleted. Otherwise use, g_plot(g) to plot g. 10### 11### Commands: 12### --------- 13### "plot", <PLOT_DATA>, where the plotted data can be 2D points or images 14### 2D data can be specified by a two-column matrix of 2D points, 15### optionnally followed by a cell array of label strings 16### 17### "plot", x, y, fmt,... : Reads arguments like in octave's plot (x,y,fmt,...) 18### fmt can be an octave-like formatting, e.g. "-;My Key;", see 19### _g_parse_oct_fmt(). 20### or "img", which may be followed by "range", "xrange", "yrange", 21### "colormap" options. See _g_image_cmd(). 22### "geometry",[w,h] : Set gnuplot window geometry 23### "FILE.(eps|fig)" : Plot to FILE.eps or FILE.fig file. 24### "xrange", [min,max] : Set horizontal range 25### "yrange", [min,max] : Set vertical range 26### "xlabel", str : Set x label 27### "ylabel", str : Set y label 28### "title", str : Set title 29### "cmd", str : Insert command str. 30### "grid", : Same as "cmd","set grid" 31### "xgrid", 32### "ygrid" : Same as "cmd","set grid x" 33### "xtics", arg : If arg is a non-empty string, then this adds the 34### command ["set xtics " arg]. If arg is empty, same as 35### "unset xtics". 36### "ytics", arg : Same as "cmd","set ytics " arg 37### "color", yesno 38### "display", yesno 39### 40### TODO: "hist", "mesh" etc ... 41 42 ## args = struct(); 43 args.cmds = {}; 44 filename = ""; 45 46 # Read arguments and put them in args. 47 48 cnt = 1; # Arg counter 49 nplots = 0; # Plot counter 50 plotcmds = ""; # arguments to plot 51 step = zeros(1,0); # Number of points per "plot" curve 52 stop = {}; 53 N = length (varargin); 54 plots = {}; # Plotted data 55 names = {}; # Names of data files 56 labels = {}; # Labels of each dataset 57 dataLabels = {}; # Labels attached to individual data points 58 do_color = 1; 59 do_wait = 1; 60 do_display = 1; 61 labpos = zeros(0,2); 62 img_indices = zeros(1,0); 63 64 args.xmap = args.ymap = args.map = []; 65 66 while cnt < N 67 cmd = varargin{cnt}; 68 if !ischar (cmd) 69 error ("Expecting string, got a '%s' as %ith argument",\ 70 typeinfo(cmd),cnt); 71 end 72 73 # It's a filename 74 if length (cmd) > 3 \ 75 && (strcmp (cmd(end-3:end), ".eps") \ 76 || strcmp (cmd(end-3:end), ".fig")\ 77 || strcmp (cmd(end-3:end), ".png")) 78# || strcmp (cmd(end-3:end), ".ppm")\ 79# || strcmp (cmd(end-3:end), ".pgm")\ 80# || strcmp (cmd(end-3:end), ".jpg")) 81 filename = cmd; 82 cnt++; 83 continue 84 endif 85 86 switch cmd 87 88 case {"title", "xlabel", "ylabel", "x2label", "y2label"}, 89 str = varargin{++cnt}; 90 if !ischar (str), 91 error ("Option '%s' requires a char argument; got a %s",\ 92 cmd, typeinfo (str)); 93 endif 94 #str = strrep (str,"%","\\%") 95 args.(cmd) = str; 96 97 case "color" 98 do_color = varargin{++cnt}; 99 100 case {"display", "-display"} 101 do_display = varargin{++cnt}; 102 103 case "label" 104 105 str = varargin{++cnt}; 106 if !ischar (str), 107 error ("Option '%s' requires a char argument; got a %s",\ 108 cmd, typeinfo (str)); 109 endif 110 pos = varargin{++cnt}; 111 if !isnumeric (pos), 112 error ("Option '%s' requires a 1 x 2 matrix argument; got a %s",\ 113 cmd, typeinfo (pos)); 114 endif 115 if length (pos) != 2 116 error ("Option '%s' requires a 1 x 2 matrix argument; got %s",\ 117 cmd, sprintf("%i x",size (pos))(1:end-2)); 118 endif 119 labels = {labels{:},str}; 120 labpos = [labpos;pos]; 121 #str = strrep (str,"%","\\%") 122 case {"geometry", "xrange", "yrange", "x2range", "y2range"}, 123 args.(cmd) = varargin{++cnt}; 124 125 case {"range"}, 126 args.xrange = args.yrange = varargin{++cnt}; 127 128 case "grid" 129 args.grid = ""; 130 case "xgrid" 131 args.grid = "x"; 132 case "ygrid" 133 args.grid = "y"; 134 135 case "xmap" 136 args.xmap = varargin{++cnt}; 137 case "ymap" 138 args.ymap = varargin{++cnt}; 139 140 case "plot" 141 do # Add following datasets 142 nplots++; 143 144 foundLabels = {}; # Labels for datapoints 145 146 data = varargin{++cnt}; 147 if !isnumeric (data) 148 error ("Argument after 'plot' should be numeric. Got '%s'.",\ 149 typeinfo(data)); 150 endif 151 orig_data_size = size (data); 152 if rows (data) == 1, data = data'; endif 153 ##nplots 154 ##step 155 ##rows(data) 156 ##keyboard 157 step(1,nplots) = rows (data); 158 159 if cnt < length (varargin) 160 if isnumeric (varargin{cnt+1}) # x and y are separate args 161 tmp = varargin{++cnt}; 162 if prod (size (tmp)) != prod (size (data)) 163 if rows (data) != rows (tmp) 164 if rows (data) == columns (tmp) 165 tmp = tmp'; 166 end 167 end 168 if rows (data) == rows (tmp) \ 169 && columns (data) == 1 170 data = data*ones(1,columns(tmp)); # Replicate abscissa data 171 else 172 error ("First 'plot' arg is %i x %i, while 2nd is %i x %i\n",\ 173 orig_data_size, size (tmp)); 174 endif 175 endif 176 if !xor (isuint(data), isuint(tmp)) # Octave's stupid bug 177 data = [data(:), tmp(:)]; 178 else 179 data = [double(data(:)),double(tmp(:))]; 180 end 181 else 182 if columns(data) == 1 183 data = [(1:rows(data))', data]; 184 end 185 endif # EOF x and y are separate args 186 else 187 if columns(data) == 1 188 data = [(1:rows(data))', data]; 189 end 190 end 191 # Transpose data, if needed. 192 if rows(data)==2 && columns(data)>2, data = data'; endif 193 194 names{nplots} = sprintf ("data%i",nplots); 195 # Determine how to plot it 196 try_arg = []; 197 if cnt < N 198 try_arg = varargin{cnt+1}; 199 endif 200 # Labels passed as a vector: turn into a cell 201 if isnumeric (try_arg) && ! isempty (try_arg) 202 if numel (try_arg) > rows (data) 203 error (["Don't know what to do with third numeric argument of size",\ 204 sprintf(" %i",size(try_arg)),". Plot has has %i points"],\ 205 rows(data)); 206 end 207 try_arg = num2cell (try_arg); 208 end 209 ##foundLabels 210 if iscell (try_arg) # user-specified labels 211 foundLabels = try_arg; 212 cnt++; 213 try_arg = 0; 214 if cnt < N 215 try_arg = varargin{cnt+1}; 216 endif 217 end 218 if ischar (try_arg) && strcmp (try_arg, "img") 219 220 zrange = [min(data(:)), max(data(:))]; 221 ##data = floor (255.999*(data - zrange(1))/diff(zrange)); 222 223 [imFmt, extra, nImArgs,zrange] = _g_image_cmd (size (data), zrange, args, {varargin{cnt+2:end}}); 224 225 cnt += nImArgs + 1; 226 227 data = floor (255.999*(data - zrange(1))/diff(zrange)); 228 data(data < 0) = 0; 229 data(data > 255) = 255; 230 data(isnan (data)) = 0; 231 232 if length (size (data)) == 3 && size(data)(3) == 3 233 data = [data(:,:,1)'(:),data(:,:,2)'(:),data(:,:,3)'(:)]'; 234 else 235 data = data'; 236 end 237 plotcmds = [plotcmds,"'", names{nplots},"' ",imFmt,", "]; 238 img_indices = [img_indices, nplots]; 239 args.cmds = {args.cmds{:}, extra{:}}; 240 241 # EOF "img" 242 elseif ischar (try_arg) && strcmp (try_arg, "box") # Unused for now 243 244 interlaced = prod (orig_data_size) == rows (data) 245 if !interlaced 246 nbox = prod (orig_data_size); 247 datlen = rows (data)/nbox; 248 data1 = data(1:datlen,1); 249 data2 = reshape (data(:,2), nbox, datlen)'; 250 else 251 datindices = data(:,1); 252 #data1 = create_set (data(:,1)); 253 data1 = unique (data(:,1)); 254 nbox = length (data1); 255 data2 = data(:,2); 256 end 257 data = zeros(0,2); 258 stops = zeros(1,0); 259 260 for i = 1:nbox 261 if !interlaced, the_data = data2(:,i); 262 else the_data = data2(data1(i) == datindices); 263 end 264 boxData = boxplot_data (the_data); 265 boxWid = 0.1; 266 data = [data;\ 267 [ data1(i)+boxWid*[1 -1 -1 1 1 -1 -1]/2;\ 268 boxData.quantiles([3 3 2 2 4 4 3])']';\ 269 [ data1(i)*[1 1 1 1];\ 270 boxData.quantiles([1 2 4 5])']';]; 271 stops = [stops, [7 9 11]+11*(i-1)]; 272 end 273 274 cnt += 1; 275 plotcmds = [plotcmds, "'", names{nplots},"' ","w l title '' , "]; 276 stop{nplots} = stops; 277 278 # EOF "box" 279 else # Plain N x 2 data 280 281 [isFmt, fmtContents, wantLabel] = _g_parse_oct_fmt (try_arg, nplots,foundLabels); 282 283 cnt += isFmt; 284 if wantLabel 285 dataLabels{nplots} = 1; 286 else 287 dataLabels{nplots} = 0; 288 end 289 if !isempty (foundLabels) 290 dataLabels{nplots} = foundLabels; 291 end 292 plotcmds = [plotcmds,"'",names{nplots},"' ",fmtContents,", "]; 293 if wantLabel 294 plotcmds = [plotcmds,"'",names{nplots},"' ",wantLabel,", "]; 295 end 296 end 297 plots{nplots} = data; 298 # Determine how to plot it 299 300 # EOF read datasets 301 until (cnt >= N) || !isnumeric (varargin{cnt+1}); 302 303 # EOF case plot 304 case "cmd" 305 args.cmds = {args.cmds{:}, varargin{++cnt}}; 306 307 case "wait" 308 do_wait = varargin{++cnt}; 309 310 case {"xtics","ytics", "x2tics", "y2tics", "tics"}, 311 t = varargin{++cnt}; 312 args.(cmd) = t; 313 314 otherwise 315 error ("Unknown command '%s'", cmd); 316 endswitch 317 cnt++; 318 endwhile # EOF Read arguments and put in struct 319 320 # Transform args in a gnuplot_object 321 322 if struct_contains (args, "geometry"), g = g_new ("geometry", args.geometry); 323 else g = g_new (); 324 endif 325 326 # Special case: quote title 327 #if struct_contains (args, "title"), args.title = ["'",args.title,"'"]; endif 328 329 if length (args.cmds), g = g_cmd (g, args.cmds{:}); endif 330 331 # set all in g.cmds 332 tmp = {"title", \ 333 "xrange", "yrange", "y2range", "x2range", \ 334 "xlabel", "ylabel", "x2label", "y2label", \ 335 "grid", "xgrid", "ygrid"}; 336 for i = 1:length(tmp) 337 if struct_contains (args, tmp{i}) 338 value = args.(tmp{i}); 339 val_str = _g_stringify (tmp{i}, value); 340 g = g_cmd (g,["set ",tmp{i}," ",val_str,""]); 341 endif 342 endfor 343 for i = 1:length(labels) 344 g = g_cmd (g,"pr:3:set label %i \"%s\" at screen %g,%g",i,labels{i},labpos(i,:)); 345 endfor 346 347 if nplots 348 349 for j = 1:3 350 351 Z = {"x","y",""}{j}; 352 Zmap = [Z,"map"]; 353 Ztics = [Z,"tics"]; 354 Zrange = [Z,"range"]; 355 356 if ! isempty (args.(Zmap)) && ! struct_contains (args,Ztics) # Must figure tics for map 357 358 if struct_contains(args,Zrange) # Determine range 359 rng = args.(Zrange); 360 else 361 rng = [inf,-inf]; 362 for i = 1:nplots 363 if all (img_indices != i) 364 rng = [min(rng(1), min (plots{i}(:,1))), \ 365 max(rng(2), max (plots{i}(:,1)))]; 366 end 367 end 368 assert (all (isfinite (rng))) 369 end 370 args.(Ztics) = _g_default_tics (rng); 371 end 372 if struct_contains(args,Ztics) 373 374 if isempty (args.(Ztics)) # No tics 375 376 g = g_cmd (g,["unset ",Ztics]); 377 378 # Explicit command tics 379 elseif ischar (args.(Ztics)) 380 381 g = g_cmd (g, ["set ", Ztics, " ", args.(Ztics)]); 382 383 # Numerical tics 384 else 385 Zmajor = {}; 386 if any (isnan (args.(Ztics))) # FIXME only works for vector args.(Ztics) 387 imajor = find(isnan (args.(Ztics))); 388 imajor -= cumsum(isnan (args.(Ztics)))(imajor) - 1; 389 Zmajor = {"major",imajor}; 390 args.(Ztics) = args.(Ztics)(! isnan (args.(Ztics))); 391 end 392 if ! isempty (args.(Zmap)) && isvector (args.(Ztics)) 393 args.(Ztics) = [_g_map(args.(Zmap), args.(Ztics)(:)'); args.(Ztics)(:)']; 394 g = g_cmd (g, _g_tics (args.(Ztics)(1,:), args.(Ztics)(2,:), Z, Zmajor{:})); 395 else 396 g = g_cmd (g, _g_tics (args.(Ztics), args.(Ztics), Z, Zmajor{:})); 397 end 398 end 399 end 400 end # EOF loop over x, y 401 402 for i = 1:nplots 403 404 if all (img_indices != i) 405 406 plots{i}(:,1) = _g_map (args.xmap, plots{i}(:,1)); 407 plots{i}(:,2) = _g_map (args.ymap, plots{i}(:,2)); 408 if length (stop) >= i && ! isempty (stop{i}) 409 pre_args = {"-stops",stop{i}}; 410 else 411 pre_args = {"-step", step(i)}; 412 end 413 414 if ! (isscalar (dataLabels{i}) && !dataLabels{i}) 415 pre_args = {pre_args{:}, "-label", dataLabels{i}}; 416 end 417 418 g = g_data (g,pre_args{:}, names{i}, plots{i}); 419 420 else 421 g = g_data (g,"-uint8", names{i}, plots{i}); 422 end 423 endfor 424 ##plotcmds 425 g = g_cmd (g,["plot ",plotcmds(1:end-2)]); 426 endif 427 # EOF Transform args in a gnuplot_object 428 if nargout < 1 || length(filename) || do_display 429 extras = {"-color",do_color}; 430 if do_wait 431 extras = {extras{:}, "-wait"}; 432 endif 433 if ! do_display 434 extras = {extras{:}, "-display", 0}; 435 endif 436 if filename, g = g_plot (g,filename,extras{:}); 437 else g = g_plot (g,extras{:}); 438 endif 439 if struct_contains (g, "double_clicks") 440 printf ("Double-clicked locations:\n"); 441 g.double_clicks 442 end 443 if struct_contains (g, "middle_clicks") 444 printf ("Middle-clicked locations:\n"); 445 g.middle_clicks 446 end 447 filename = ""; 448 if nargout < 1 449 "deleting" 450 g_delete (g); 451 clear g; 452 else 453 "not deleting" 454 endif 455 endif 456endfunction 457 458 459%!demo 460%! printf ("\n\tNote: You may need to resize the window to see the plots\n\n"); 461%! %------------------------------------------------- 462%! im = rand(16,31); 463%! im(3:10,5:25) = linspace(0,0.5,8)'*ones(1,21)+ones(8,1)*linspace(0,0.5,21); 464%! g_ez ("title","A random grey image","plot",im, "img") 465%! %------------------------------------------------- 466%! % a random greylevel image 467 468%!demo 469%! t=linspace(-pi,pi,101); x = sin(t); y = sin (t+pi/3); 470%! g_ez ("title","Some sines","plot",t,x,"-",t,y,"-") 471%! %------------------------------------------------- 472%! % some sines 473 474%!demo 475%! im = rand(16,31,3); 476%! im(3:10,5:25,1) = linspace(0,1,8)'*ones(1,21); 477%! im(3:10,5:25,2) = 0.5; 478%! im(3:10,5:25,3) = 1; 479%! g_ez ("xrange",[-1,1],"plot",im*255, "img") 480%! %------------------------------------------------- 481%! % a random color image 482 483 484 485 486 487 488 489