Menu

#90 plot() arguments not working with 'Property','value' syntax

open
nobody
5
2007-01-25
2007-01-25
Anonymous
No

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

Discussion

  • Shai Ayal

    Shai Ayal - 2007-01-25

    Logged In: YES
    user_id=136223
    Originator: NO

    Thanks for the report

    If you could submit a patch it would speed things along ...
    Shai

     
  • Shai Ayal

    Shai Ayal - 2007-01-25
    • labels: --> matlab incompatibility
     
  • lindnerb

    lindnerb - 2007-01-30

    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

     
  • Shai Ayal

    Shai Ayal - 2007-01-30

    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

     
  • lindnerb

    lindnerb - 2007-02-19

    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

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.