Hi,
Using the plot() command in a Matlab-Like way yields errors when specifying the plotting options as 'property','value' pairs.
system: octplot-0.3.9 on octave-2.1.73 under cygwin
e.g.
gcf(); clf; plot( 0:0.1:10, sin(0:0.1:10), 'LineWidth',2);
works, but
gcf(); clf; plot( 0:0.1:10, sin(0:0.1:10), 'color','b');
fails with:
error: Illegal plot format specifier
error: evaluating if command near line 34, column 5
error: evaluating while command near line 32, column 3
error: called from `__pltopt__' in file `/opt/octplot/0.3.9_octave-2.1.73-gcc-3.2/__pltopt__.m'
error: evaluating if command near line 150, column 7
error: evaluating if command near line 149, column 5
error: evaluating while command near line 148, column 3
error: called from `plot' in file `/opt/octplot/0.3.9_octave-2.1.73-gcc-3.2/plot.m'
Also
gcf(); clf; plot( 0:0.1:10, sin(0:0.1:10), 'c','color','b');
fails with the same error message
Looking into __pltopt__.m this is caused by the order of the parameter checks.
First is tested if one of the colour characters appears in the parameter, but this is also true for the property 'color', where the first character matches a "c" colour specifier. The remaining "olor" string is then treated as a property value which does not exist.
In order to be matlab compatible, the order of flow would need to be reorderd to FIRST check for any of the possible property names and afterwards check for special strings containing colour chars and line specifiers.
(This would have the side-effect benefit of a listing of possible options for the plot command - the help text lacks these)
I know that this causes a lot of additional code, but I see no other way to be reliably support 'parameter','value' syntax.
ben
Logged In: YES
user_id=136223
Originator: NO
Thanks for the report
If you could submit a patch it would speed things along ...
Shai
Logged In: YES
user_id=1590249
Originator: NO
Thanks for the reply,
OK, I will try and provide a patch, It will take some time, as I'm busy at work right away...
Should patches concerning bugs be posted here with the bug report or at the patches tracker list?
ben
Logged In: YES
user_id=136223
Originator: NO
I think it is best to post the patch here, so that we don't need to maintain too many cross-links
Thanks for your time and effort,
Shai
Logged In: YES
user_id=1590249
Originator: NO
Ok, It took a while to get to it
The following patch to __pltopt__.m enables the matlab-like usage of "property","value" pairs.
I added a cell-map of <user-visible-parameter> and <internal-parameter>. This way, the
internal parameter names are encapsuled, and it enables one degree more on compatibility to whomever.
e.g. the possibility to specify a line's label using "DisplayName" (MATLAB R14SP3), "label" (octplot),
or the gnuplot-way.
The listing of properties may not be complete, but it should be easy to add them accordingly
I also shifted code a bit around to make it behave properly.
With this patch, the following now works as expected:
plot( 0:0.1:10, sin(0:0.1:10),"marker","+","colour","g","DisplayName","sin", 0:0.1:10,cos(0:0.1:10),"dg;cos;" );
comments & feedback welcome
benjamin
( I'm pasting the patch, there seems no button to attach files here?)
> svn diff __pltopt__.m
Index: __pltopt__.m
===================================================================
--- __pltopt__.m (revision 426)
+++ __pltopt__.m (working copy)
@@ -18,78 +18,136 @@
function [prop,numarg]=__pltopt__(args)
i = 0;
p = 1;
- ls = 0;
- mk = 0;
-
+ ls = 0; # linestyle
+ lc = []; # line colour
+ mk = 0; # marker
+ mec = 0; # marker edge colour
+
+ # mapping of line properties to internal properties
+ # <user-visible>, <internal>
+ lineopt = { ...
+ "color", "color"; ...
+ "colour", "color"; ...
+ "label", "label"; ...
+ "displayname", "label"; ... # Matlab 7 compatibility
+ "linestyle", "linestyle"; ...
+ "linewidth", "linewidth"; ...
+ "marker", "marker"; ...
+ "markersize", "markersize"; ...
+ "markeredgecolor", "markeredgecolor"; ...
+ "markeredgecolour", "markeredgecolor"; ...
+ "markerfacecolor", "markerfacecolor"; ...
+ "markerfacecolour", "markerfacecolor"; ...
+ };
+
ps = args{1};
- numarg = 1;
+ numarg = 0; # No of arguments processed
+ na = length(args); # No of arguments passed to __pltopt__
+ ca = 1; # current argument
if (length(ps)==0),
prop = [];
return;
endif
- while (i<length(ps))
- i++;
- if(index("rgbcymkw",ps(i)))
- prop(p).name="color";
- prop(p).val=ps(i);
+ # loop over all plot arguments
+ while( ca <= na )
+ ps = args{ca};
+
+ if( ~isstr(ps) )
+ # not a property string
+ break;
+ endif
+
+ n = find(strcmp( lineopt(:,1), lower(ps) ));
+ if( ~isempty(n) )
+ # Found a valid "property","value" pair
+ prop(p).name = lineopt{n,2};
+ prop(p).val = args{ca+1};
p++;
- # keep marker color and line color the same
- prop(p).name = "markeredgecolor";
- prop(p).val = ps(i);
- p++;
- elseif(index("+o*.xsd^v><ph",ps(i)))
- prop(p).name="marker";
- prop(p).val=ps(i);
- p++;
- mk = 1;
- elseif(ps(i)==":")
- prop(p).name="linestyle";
- prop(p).val=":";
- p++;
- ls = 1;
- elseif(ps(i)=="-")
- prop(p).name="linestyle";
- if(i==length(ps))
- prop(p).val="-";
- elseif(index(":-.",ps(i+1)))
- prop(p).val=ps(i:i+1);
- i++;
- else
- prop(p).val="-";
- endif
- p++;
- ls = 1;
- elseif(ps(i)==";")
- is = i+1;
+
+ # postprocessing
+ switch( lineopt{n,2} )
+ case "marker"
+ mk = 1;
+ case "markeredgecolor"
+ mec = 1;
+ case "color"
+ lc = args{ca+1};
+ case "linestyle"
+ ls = 1;
+ endswitch
+
+ numarg += 2;
+ ca += 2;
+
+ else
+
+ # plot format specifier string
while (i<length(ps))
i++;
- if (ps(i)==";")
- break;
+ if(index("rgbcymkw",ps(i)))
+ prop(p).name="color";
+ prop(p).val=ps(i);
+ p++;
+ lc = ps(i);
+ elseif(index("+o*.xsd^v><ph",ps(i)))
+ prop(p).name="marker";
+ prop(p).val=ps(i);
+ p++;
+ mk = 1;
+ elseif(ps(i)==":")
+ prop(p).name="linestyle";
+ prop(p).val=":";
+ p++;
+ ls = 1;
+ elseif(ps(i)=="-")
+ prop(p).name="linestyle";
+ if(i==length(ps))
+ prop(p).val="-";
+ elseif(index(":-.",ps(i+1)))
+ prop(p).val=ps(i:i+1);
+ i++;
+ else
+ prop(p).val="-";
+ endif
+ p++;
+ ls = 1;
+ elseif(ps(i)==";")
+ is = i+1;
+ while (i<length(ps))
+ i++;
+ if (ps(i)==";")
+ break;
+ endif
+ endwhile
+ prop(p).name="label";
+ prop(p).val=ps(is:i-1);
+ p++;
+ else
+ error("Illegal plot format specifier \"%s\"",ps(i));
endif
endwhile
- prop(p).name="label";
- prop(p).val=ps(is:i-1);
- p++;
- elseif(i==1 & length(args)>1)
- ## a "property",value pair was specified explicitly
- prop(p).name = ps;
- prop(p).val = args{2};
- p++;
- i = length(ps);
- numarg = 2;
- else
- error("Illegal plot format specifier");
+
+ ca++;
+ numarg++;
+
endif
endwhile
# specifing marker without linestyle implies
# linestyle==none (default linestyle="-")
- if(mk & ~ls) ,
+ if(mk && ~ls)
prop(p).name = "linestyle";
prop(p).val = "none";
p++;
endif
+ # specifying colour without markeredgecolour implies
+ # markeredgecolour==colour
+ if( ~isempty(lc) && ~mec )
+ prop(p).name = "markeredgecolor";
+ prop(p).val = lc;
+ p++;
+ endif
endfunction