Desperate Help!!! Multiple Legends

  • Follow


Hello,

I am building a gui to plot a lot of data from an experiment. Data was collected from multiple "channels" over a series of "runs."  I am able to plot Channel 1, Channel 2, and Channel 3 for Run#1 and Run#2. But now i'm desperately trying to create a legend for each Run. 

I have gathered from the Newsgroup that only 1 legend is allowed per axes and am attempting the approach of using multiple axes. My sad excuse for a code is below:


if i == 1
            plot(handles.data_axes,xData,yDataMatrix(:,1:i*length(Channel2Analyze_Contents)))
            ax1 = gca;
            hold on
        elseif i > 1
            ax1_position = axes('Position',get(ax1,'Position'),...
                                    'xlim',get(ax1,'xlim'),'ylim',get(ax1,'ylim'),...
                                    'Visible','off','Color','none');
            eval(['ax' num2str(i) '=ax1_position'])
            plot(eval(['ax' num2str(i)]),xData,yData(:,...
                                    1:i*length(Channel2Analyze_Contents)))
        end
        eval(['legend_handle' num2str(i) '= legend(Channel2Analyze_Contents)']);
        set(get(eval(['legend_handle' num2str(i)]),'title'),'string',...
                                    RunNumberPlottedList(i),'fontweight','bold')

I know this is messy (apologies) but if anyone out there can help me figure this out I would REALLY appreciate it. 

- Frustrated
0
Reply John 7/14/2010 1:34:04 PM

"John " <jfishbac@gmail.com> wrote in message 
news:i1kecc$in$1@fred.mathworks.com...
> Hello,
>
> I am building a gui to plot a lot of data from an experiment. Data was 
> collected from multiple "channels" over a series of "runs."  I am able to 
> plot Channel 1, Channel 2, and Channel 3 for Run#1 and Run#2. But now i'm 
> desperately trying to create a legend for each Run.
> I have gathered from the Newsgroup that only 1 legend is allowed per axes 
> and am attempting the approach of using multiple axes. My sad excuse for a 
> code is below:
>
>
> if i == 1
> 
> plot(handles.data_axes,xData,yDataMatrix(:,1:i*length(Channel2Analyze_Contents)))
>            ax1 = gca;
>            hold on
>        elseif i > 1
>            ax1_position = axes('Position',get(ax1,'Position'),...
> 
> 'xlim',get(ax1,'xlim'),'ylim',get(ax1,'ylim'),...
>                                    'Visible','off','Color','none');
>            eval(['ax' num2str(i) '=ax1_position'])

Do NOT, repeat NOT DO THIS.  See Q4.6 in the newsgroup FAQ for why this is a 
BAD IDEA.

>            plot(eval(['ax' num2str(i)]),xData,yData(:,...
>                                    1:i*length(Channel2Analyze_Contents)))
>        end
>        eval(['legend_handle' num2str(i) '= 
> legend(Channel2Analyze_Contents)']);

See above.

>        set(get(eval(['legend_handle' num2str(i)]),'title'),'string',...
> 
> RunNumberPlottedList(i),'fontweight','bold')

Yuck.  This looks awful, doesn't it?  (This isn'treally a comment on your 
code, but just another piece of motivation to move you AWAY from creating 
variables with EVAL.)

> I know this is messy (apologies) but if anyone out there can help me 
> figure this out I would REALLY appreciate it.

Two questions:

Why do you need separate legends for each run?  Why not just create one 
6-element legend for your 3 channels in each of 2 runs?  Or is the problem 
that you want to do this for N channels and M runs where N, M >> 3?  If so, 
consider how "noisy" each axes and each legend will become.

Have you tried calling LEGEND with the first input being the axes handle (as 
documented as the AX input in HELP LEGEND)?

-- 
Steve Lord
slord@mathworks.com
comp.soft-sys.matlab (CSSM) FAQ: http://matlabwiki.mathworks.com/MATLAB_FAQ
To contact Technical Support use the Contact Us link on 
http://www.mathworks.com 


0
Reply slord (13285) 7/14/2010 2:31:24 PM


"Steven Lord" <slord@mathworks.com> wrote in message <i1khns$ehp$1@fred.mathworks.com>...
> 
> "John " <jfishbac@gmail.com> wrote in message 
> news:i1kecc$in$1@fred.mathworks.com...
> > Hello,
> >
> > I am building a gui to plot a lot of data from an experiment. Data was 
> > collected from multiple "channels" over a series of "runs."  I am able to 
> > plot Channel 1, Channel 2, and Channel 3 for Run#1 and Run#2. But now i'm 
> > desperately trying to create a legend for each Run.
> > I have gathered from the Newsgroup that only 1 legend is allowed per axes 
> > and am attempting the approach of using multiple axes. My sad excuse for a 
> > code is below:
> >
> >
> > if i == 1
> > 
> > plot(handles.data_axes,xData,yDataMatrix(:,1:i*length(Channel2Analyze_Contents)))
> >            ax1 = gca;
> >            hold on
> >        elseif i > 1
> >            ax1_position = axes('Position',get(ax1,'Position'),...
> > 
> > 'xlim',get(ax1,'xlim'),'ylim',get(ax1,'ylim'),...
> >                                    'Visible','off','Color','none');
> >            eval(['ax' num2str(i) '=ax1_position'])
> 
> Do NOT, repeat NOT DO THIS.  See Q4.6 in the newsgroup FAQ for why this is a 
> BAD IDEA.
> 
> >            plot(eval(['ax' num2str(i)]),xData,yData(:,...
> >                                    1:i*length(Channel2Analyze_Contents)))
> >        end
> >        eval(['legend_handle' num2str(i) '= 
> > legend(Channel2Analyze_Contents)']);
> 
> See above.
> 
> >        set(get(eval(['legend_handle' num2str(i)]),'title'),'string',...
> > 
> > RunNumberPlottedList(i),'fontweight','bold')
> 
> Yuck.  This looks awful, doesn't it?  (This isn'treally a comment on your 
> code, but just another piece of motivation to move you AWAY from creating 
> variables with EVAL.)
> 
> > I know this is messy (apologies) but if anyone out there can help me 
> > figure this out I would REALLY appreciate it.
> 
> Two questions:
> 
> Why do you need separate legends for each run?  Why not just create one 
> 6-element legend for your 3 channels in each of 2 runs?  Or is the problem 
> that you want to do this for N channels and M runs where N, M >> 3?  If so, 
> consider how "noisy" each axes and each legend will become.
> 
> Have you tried calling LEGEND with the first input being the axes handle (as 
> documented as the AX input in HELP LEGEND)?
> 
> -- 
> Steve Lord
> slord@mathworks.com
> comp.soft-sys.matlab (CSSM) FAQ: http://matlabwiki.mathworks.com/MATLAB_FAQ
> To contact Technical Support use the Contact Us link on 
> http://www.mathworks.com 
> 
Steve,

I need separate legends for each run because the way my gui is set up, I allow the user to pick the Run Numbers they want to plot and the channels they want to look at. I'm leaving it up to the user to determine what they want to observe (regardless of how congested the plot may get). That said, the only way to make sense of the data it to annotate it by Run Number. This allows a user to compare the same set of channels for different runs during the test. If there were 5 (or more) channels for 3 (or more) runs that a user wanted to look at, that'd be 15 lines on the plot where 5 of those lines belong to one run. A legend would indicate which lines belonged with which run. I think this answers both of your questions.

I believe that I have tried calling LEGEND with the first input being the axes handle (as documented as the AX input in HELP LEGEND). This was the reason I used EVAL in the first place because it would generate the handle for the specific axes that I wasnted to put my legend on. However, if no data is plotted to AX (the axes handle), then LEGEND(AX, Chann2AnalyzeList_Contents) is returned as empty []. 

Keep working with me, Steve! You've helped me before. You're a genius!

-John
0
Reply jfishbac (5) 7/14/2010 2:52:06 PM

"John " <jfishbac@gmail.com> wrote in message 
news:i1kium$4lk$1@fred.mathworks.com...
> "Steven Lord" <slord@mathworks.com> wrote in message 
> <i1khns$ehp$1@fred.mathworks.com>...

*snip*

> Steve,
>
> I need separate legends for each run because the way my gui is set up, I 
> allow the user to pick the Run Numbers they want to plot and the channels 
> they want to look at. I'm leaving it up to the user to determine what they 
> want to observe (regardless of how congested the plot may get). That said, 
> the only way to make sense of the data it to annotate it by Run Number. 
> This allows a user to compare the same set of channels for different runs 
> during the test. If there were 5 (or more) channels for 3 (or more) runs 
> that a user wanted to look at, that'd be 15 lines on the plot where 5 of 
> those lines belong to one run. A legend would indicate which lines 
> belonged with which run. I think this answers both of your questions.
>
> I believe that I have tried calling LEGEND with the first input being the 
> axes handle (as documented as the AX input in HELP LEGEND). This was the 
> reason I used EVAL in the first place because it would generate the handle 
> for the specific axes that I wasnted to put my legend on.

There's no need to use EVAL for that purpose.  If you know you have/want six 
axes (for example) then create a vector to store the handles.


n = 6;
axeshandles = zeros(1, n);
leghandles = zeros(1, n);
x = 0:0.1:2*pi;

for k = 1:n
    % if n changes, the following line will need to change
    axeshandles(k) = subplot(2, 3, k);

    % Plot to the specified axes
    plot(axeshandles(k), x, sin(k*x));

    % Create a legend for the specified axes and store its handle in another 
vector
    leghandles(k) = legend(axeshandles(k), sprintf('sin(%d*x)', k));
end


That even lets you do interesting things like:


% Change the value of a property for some of the legends
% I'm using light red and light blue because full red and blue
% obscured the text in the legend somewhat
set(leghandles(2:2:6), 'Color', [1 0.7 0.7])
set(leghandles(1:2:6), 'Color', [0.7 0.7 1])

% Or look for children in any of the legends and change their properties
set(findall(leghandles, 'Type', 'Text'), 'FontWeight', 'bold')


If you don't know how many axes you will have in the end, then overallocate 
(by as small an amount as you can) your handle vector and trim the excess at 
the end or, if you must, grow the (likely small) vector of axes handles in 
the loop.

> However, if no data is plotted to AX (the axes handle), then LEGEND(AX, 
> Chann2AnalyzeList_Contents) is returned as empty [].

And I believe you should receive a warning when you do that?  In that case, 
you will need to decide what to do for that axes anyway.

But you're right, that could cause a problem with the above approach.  You 
can switch to using a cell array of handles instead of a vector of handles 
in this case, and check to see if the legend handle you want to tweak 
ISEMPTY before using it.

-- 
Steve Lord
slord@mathworks.com
comp.soft-sys.matlab (CSSM) FAQ: http://matlabwiki.mathworks.com/MATLAB_FAQ
To contact Technical Support use the Contact Us link on 
http://www.mathworks.com 


0
Reply slord (13285) 7/14/2010 5:17:23 PM

3 Replies
149 Views

(page loaded in 0.266 seconds)

Similiar Articles:




7/24/2012 3:45:56 AM


Reply: