0
votes

I have 20-40 discrete figures to create and save in a Matlab program. I am trying to create a function which will allow me to input elements (images, lines, vectors etc) and create layered plots by passing each element to plot() in a for loop:

function [  ] = constructFigs( figTitle, backgroundClass, varargin )

fig = figure('visible', 'off');

if strcmp(backgroundClass, 'plot') == 1

    plot(varargin{1});

elseif strcmp(backgroundClass, 'image') == 1

    imshow(varargin{1});

end


for i = 1:length(varargin)

    hold on

    if ndims(varargin{i}) == 2

        plot(varargin{i}(:, 1), varargin{i}(:, 2))

    else

        plot(varargin{i});

    end

end

saveas(fig, figTitle);

close(fig);

end

This function works but is very limiting in terms of what can be plotted; you cannot perform certain types of plotting operations (superimposed images for example) and cannot pass in optional arguments to plot(). What I would like to do is pass in a structure of elements to be plotted and then pass these structure elements into plot() as arguments. For example (simplified and with bad syntax):

toBePlotted = struct('arg1', {image}, 'arg2', {vector1, vector2, 'o'})


    plot(toBePlotted.arg1)
    plot(toBePlotted.arg2)

I am able to programmatically construct the structures with argument names, but I am unable to extract the elements from the structure in a way that plot will accept them as arguments.

Any help would be greatly appreciated

1

1 Answers

0
votes

For your use case, you need to use cell expansion {:} to populate the inputs to plot

plot(toBePlotted.arg1{:})
plot(toBePlotted.arg2{:})

This will expand the elements contained in the cell array toBePlotted.arg1 to be separate input arguments to plot.

The other option is to use line rather than plot (a lower-level graphics object) and pass the constructor a more intelligible struct which contains all of the parameters you would like to use for that plot.

s = struct('XData', [1,2,3], 'YData', [4,5,6], 'Marker', 'o', 'LineStyle', 'none');
line(s)

Honestly though, it is likely far easier to do the plotting within your program itself rather than having a separate function because there are not a lot of custom parameters being used in your function.

If you really want some streamlined plotting you could do something like this:

function plotMyStuff(varargin)

    fig = figure();
    hold on;

    for k = 1:numel(varargin)

        params = rmfield(varargin{k}, 'type');

        switch lower(varargin{k}.type)
            case 'line'
                line(params);
            case 'image'
                imagesc(params);
            otherwise
                disp('Not supported')
                return
        end 
    end

    saveas(fig);
    delete(fig);
end

plotMyStuff(struct('XData', [1,2], 'YData', [2,3], 'type', 'line'), ...
            struct('CData', rand(10), 'type', 'image'));