将varargs传递给plot()函数

时间:2011-12-13 09:30:58

标签: matlab plot

我正在为plot编写一个包装器,它可以自动完成我经常做的一些任务。

示例代码段可能看起来像

function myplot(x,y,varargin)
    plot(x,y,varargin{:})
    xlabel('x axis')
    ylabel('y axis')
end

我正在使用Matlab的varargin将其他参数传递给plot。但是,我发现我可能想在varargin中传递自己的可选参数。例如,我可能想写类似

的东西
>> myplot(1:10, 1:10, 'r', 'LineWidth', 2, 'legend', {'Series 1'})

让函数自动在图中包含一个图例 - 也就是说,我希望能够将我自己的关键字参数与您可以提供给图表的参数混合。如果没有为我的varargs编写完整的解析器,有没有办法在Matlab中简单地重复使用?

我尝试使用inputParser对象,但这需要我手动添加每个可能的附加参数到绘图(以及它的默认值),这似乎并不理想。

3 个答案:

答案 0 :(得分:6)

inputParser可能仍然是最佳选择。您可以为其他参数构造对象,并将要传递给plot的所有parameterName / parameterValue对转换为Unmatched

function myplot(x,y,varargin)

    parserObj = inputParser;
    parserObj.KeepUnmatched = true;
    parserObj.AddParamValue('legend',false); 
    %# and some more of your special arguments

    parserObj.parse(varargin);

    %# your inputs are in Results
    myArguments = parserObj.Results;

    %# plot's arguments are unmatched
    tmp = [fieldnames(parserObj.Unmatched),struct2cell(parserObj.Unmatched)];
    plotArgs = reshape(tmp',[],1)'; 


    plot(x,y,plotArgs{:})
    xlabel('x axis')
    ylabel('y axis')

    if myArguments.legend
       %# add your legend
    end
end

答案 1 :(得分:1)

为了支持Linespec参数而不干扰名称为4个字符或更少的输入解析器参数(例如,' grid'或' bins'),你应该稍微更复杂的方法来检查Linespec参数的有效性而不是' @(x)ischar(x)&& numel(x)< = 4'。对于' grid'这个检查也会返回true。和' bins',虽然它们不是有效的Linespec参数。

仅当输入了有效的Linespec参数时,以下函数才会返回true:

function isls = islinespec(x)
isls    = false;

if ~ischar(x)
    return;
end

lineStyleSpecifiers     = {'--','-.','-',':'};
markerSpecifiers        = {'square','diamond','pentagram','hexagram','+','o','*','.','x','s','d','^','v','>','<','p','h'};
colorSpecifiers         = {'r','g','b','c','m','y','k','w'};

for oo=1:length(lineStyleSpecifiers)
    k = strfind(x,lineStyleSpecifiers{oo});
    if ~isempty(k)
        x(k:(k+length(lineStyleSpecifiers{oo})-1)) = [];
        break;
    end
end

for oo=1:length(markerSpecifiers)
    k = strfind(x,markerSpecifiers{oo});
    if ~isempty(k)
        x(k:(k+length(markerSpecifiers{oo})-1)) = [];
        break;
    end
end

for oo=1:length(colorSpecifiers)
    k = strfind(x,colorSpecifiers{oo});
    if ~isempty(k)
        x(k:(k+length(colorSpecifiers{oo})-1)) = [];
        break;
    end
end

if isempty(x)
    isls = true;
end

(不可否认,使用正则表达式可以更好地编写函数,但它可以解决问题。)

使用示例:

parserObj = inputParser;
parserObj.KeepUnmatched = true;
parserObj.AddParamValue('legend',false);
parserObj.AddParamValue('grid',true);
parserObj.addOptional('LineSpec','-', @(x) islinespec(x));

答案 2 :(得分:0)

要使用解析器以明确的w / param / val对的方式添加对LineSpec的支持,请执行以下操作:

function myplot(x,y,varargin)
    parserObj = inputParser;
    parserObj.KeepUnmatched = true;
    parserObj.AddParamValue('legend',false);
    parserObj.addOptional('LineSpec','-',@(x) ischar(x) && (numel(x) <= 4));
    %# and some more of your special arguments

    parserObj.parse(varargin{:});

    %# your inputs are in Results
    myArguments = parserObj.Results;

    %# plot's arguments are unmatched
    plotArgs = struct2pv(parserObj.Unmatched); 

    plot(x,y,myArguments.LineSpec,plotArgs{:})
    xlabel('x axis')
    ylabel('y axis')

    if myArguments.legend
       %# add your legend
    end
end

function [pv_list, pv_array] = struct2pv (s)
    p = fieldnames(s);
    v = struct2cell(s);
    pv_array = [p, v];
    pv_list = reshape(pv_array', [],1)';
end