Undocumented Matlab
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT

Legend '-DynamicLegend' semi-documented feature

June 4, 2009 21 Comments

In one of my projects, I had to build a GUI in which users could interactively add and remove plot lines from an axes. The problem was that the legend needed to be kept in constant sync with the currently-displayed plot lines. This can of course be done programmatically, but a much simpler solution was to use legend‘s semi-documented ‘-DynamicLegend’ feature. Here’s a simple example:

x=0:.01:10;
plot(x, sin(x), 'DisplayName','sin');
legend('-DynamicLegend');
hold all;   % add new plot lines on top of previous ones
plot(x, cos(x), 'DisplayName','cos');

x=0:.01:10; plot(x, sin(x), 'DisplayName','sin'); legend('-DynamicLegend'); hold all; % add new plot lines on top of previous ones plot(x, cos(x), 'DisplayName','cos');

We can see how the dynamic legend automatically keeps in sync with its associated axes contents when plot lines are added/removed, even down to the zoom-box lines… The legend automatically uses the plot lines ‘DisplayName’ property where available, or a standard ‘line#’ nametag where not available:


Dynamic legend
Dynamic legend

DynamicLegend works by attaching a listener to the axes child addition/deletion callback (actually, it works on the scribe object, which is a large topic for several future posts). It is sometimes necessary to selectively disable the dynamic behavior. For example, in my GUI I needed to plot several event lines which looked alike, and so I only wanted the first line to be added to the legend. To temporarily disable the DynamicLegend listener, do the following:

% Try to disable this axes's legend plot-addition listener
legendAxListener = [];
try
   legendListeners = get(gca,'ScribeLegendListeners');
   legendAxListener = legendListeners.childadded;
   set(legendAxListener,'Enable','off');
catch
   % never mind...
end
% Update the axes - the legend will not be updated
...
% Re-enable the dynamic legend listener
set(legendAxListener,'Enable','on');

% Try to disable this axes's legend plot-addition listener legendAxListener = []; try legendListeners = get(gca,'ScribeLegendListeners'); legendAxListener = legendListeners.childadded; set(legendAxListener,'Enable','off'); catch % never mind... end % Update the axes - the legend will not be updated ... % Re-enable the dynamic legend listener set(legendAxListener,'Enable','on');

Unfortunately, this otherwise-useful DynamicLegend feature throws errors when zooming-in on bar or stairs graphs. This can be replicated by:

figure;
bar(magic(4));  %or: stairs(magic(3),magic(3));
legend('-DynamicLegend');
zoom on;
% Now zoom-in using the mouse to get the errors on the Command Window

figure; bar(magic(4)); %or: stairs(magic(3),magic(3)); legend('-DynamicLegend'); zoom on; % Now zoom-in using the mouse to get the errors on the Command Window

The fix: modify %MATLABROOT%\toolbox\matlab\scribe\@scribe\@legend\init.m line #528 as follows:

%old:
str = [str(1:insertindex-1);{newstr};str(insertindex:length(str))];
%new:
if size(str,2)>size(str,1)
    str=[str(1:insertindex-1),{newstr},str(insertindex:length(str))];
else
    str=[str(1:insertindex-1);{newstr};str(insertindex:length(str))];
end

%old: str = [str(1:insertindex-1);{newstr};str(insertindex:length(str))]; %new: if size(str,2)>size(str,1) str=[str(1:insertindex-1),{newstr},str(insertindex:length(str))]; else str=[str(1:insertindex-1);{newstr};str(insertindex:length(str))]; end

The origin of the bug is that bar and stairs generate hggroup plot-children, which saves the legend strings column-wise rather than the expected row-wise. My fix solves this, but I do not presume this solves all possible problems in all scenarios (please report if you find anything else).
p.s. – object visibility in the legend can be controlled on an object-by-object basis using the semi-documented hasbehavior function.

Semi-documented

The DynamicLegend feature is semi-documented. This means that the feature is explained in a comment within the function (which can be seen via the edit(‘legend’) command), that is nonetheless not part of the official help or doc sections. It is an unsupported feature originally intended only for internal Matlab use (which of course doesn’t mean we can’t use it). This feature has existed many releases back (Matlab 7.1 for sure, perhaps earlier), so while it may be discontinued in some future Matlab release, it did have a very long life span… The down side is that it is not supported: I reported the bar/stairs issue back in mid-2007 and so far this has not been addressed (perhaps it will never be). Even my reported workaround in January this year went unanswered (no hard feelings…).
DynamicLegend is a good example of a useful semi-documented feature. Some other examples, which I may cover in future posts, include text(…,‘sc’), drawnow(‘discard’), several options in pan and datacursormode etc. etc.
There are also entire semi-documented functions: many of the uitools (e.g., uitree, uiundo), as well as hgfeval and others.
Have you discovered any useful semi-documented feature or function? If so, then please share your finding in the comments section below.

Related posts:

  1. Multi-column (grid) legend – This article explains how to use undocumented axes listeners for implementing multi-column plot legends...
  2. Transparent legend – Matlab chart legends are opaque be default but can be made semi- or fully transparent. ...
  3. Plot legend title – Titles to plot legends are easy to achieve in HG1 (R2014a or earlier), but much more difficult in HG2 (R2014b or newer). ...
  4. Plot legend customization – Matlab plot legends and their internal components can be customized using a variety of undocumented properties that are easily accessible. ...
  5. Undocumented feature list – A list of undocumented MATLAB features can be retrieved. Here's how... ...
  6. The HotLinks feature – feature('HotLinks') can be used to temporarily disable hyperlinks and other markups in the Matlab console. ...
Listener Pure Matlab scribe Semi-documented feature
Print Print
« Previous
Next »
21 Responses
  1. Ustun Ozgur June 5, 2009 at 06:01 Reply

    Thanks for this tip.
    I was in a similar need, and was getting the legend cell via get, appending the new string, and setting the cell back.

    leghandle = findall(gcf, 'tag', 'legend');
    legstr = get(leg,'String');
    % ensure legstr is a cell, not a string
    if ischar(legstr), legstr = mat2cell(legstr); end
    legstr(end+1) = {'New legend string'};

    leghandle = findall(gcf, 'tag', 'legend'); legstr = get(leg,'String'); % ensure legstr is a cell, not a string if ischar(legstr), legstr = mat2cell(legstr); end legstr(end+1) = {'New legend string'};

    This seems much simpler.

  2. Pietro July 2, 2009 at 06:31 Reply

    I was looking for an undocumented matlab feature named ‘feature’ and google luckied me here. Maybe you know something about. I tried

    which feature

    which feature

    and I found out this ‘feature’ is an undocumented built-in function.

    How I got across it?

    I typed configinfo.m M-file attached to Matlab white paper on performance.

    Nice blog, useful even for a beginner in Matlab as I am. 🙂

    • Yair Altman July 2, 2009 at 12:16 Reply

      Thanks Pietro.

      I plan to write a post about some of feature‘s features in the future. Keep a look-out for this on this blog. You can see this in my TODO list.

      So much to do, so little time…

      Yair

  3. uitree | Undocumented Matlab August 11, 2010 at 11:02 Reply

    […] uitools in the %matlabroot%/toolbox/matlab/uitools/ folder, uitree and its companion uitreenode are semi-documented, meaning that they have no support or doc-page, but do have readable help sections within […]

  4. handle2struct, struct2handle & Matlab 8.0 | Undocumented Matlab December 29, 2010 at 11:02 Reply

    […] under the hood, hgsave uses the semi-documented built-in handle2struct function to convert the figure handle into a Matlab struct […]

  5. Uitable sorting | Undocumented Matlab July 26, 2011 at 11:03 Reply

    […] After many years in which the uitable was available but semi-documented and not officially supported in Matlab, it finally became fully documented and supported in R2008a […]

  6. Stephan January 12, 2012 at 06:18 Reply

    I was searching for a way to use a legend’s “refresh” function (that is available when right-clicking on the legend with the mouse) in a script. When I came across this post I first thought this was the way Matlab implemented the “refresh” functionality.
    However, ‘DynamicLegend’ only seems to react to additions or deletions to the axes: switching the ‘Visibility’ of a line to ‘off’ or switching the legend entry off by

    set(get(get(line_handle,'Annotation'),'LegendInformation'),'IconDisplayStyle','off')

    set(get(get(line_handle,'Annotation'),'LegendInformation'),'IconDisplayStyle','off')

    is ignored by the ‘DynamicLegend’ feature. The “refresh” function correctly removes the corresponding legend entry in these cases.
    Do you know how to use “refresh” from the command line?

    • Yair Altman March 21, 2012 at 12:27 Reply

      @Stephan – yes: You can access the Refresh uicontextmenu item (and any other context-menu item) directly from the legend axes, and then run it via the hgfeval function, as follows:

      hLegend = findall(gcf,'tag','legend');
      uic = get(hLegend,'UIContextMenu');
      uimenu_refresh = findall(uic,'Label','Refresh');
      callback = get(uimenu_refresh,'Callback');
      hgfeval(callback,[],[]);

      hLegend = findall(gcf,'tag','legend'); uic = get(hLegend,'UIContextMenu'); uimenu_refresh = findall(uic,'Label','Refresh'); callback = get(uimenu_refresh,'Callback'); hgfeval(callback,[],[]);

      For the record, this invokes the refresh_cb function within %matlabroot%/toolbox/matlab/scribe/@scribe/@legend/methods.m. You can place a breakpoint there to see exactly what it does internally.

  7. Andy February 27, 2012 at 05:41 Reply

    I got the same Problem/Question as Stephan I do plot all data in the Fig however only some data is visible but in the legend all data even the one not visible is listed. Only by right klick an refresh I can get rid of them however I can’t do that with every single file….

    Hope there will be a solution in the future.

    • Yair Altman February 27, 2012 at 16:47 Reply

      @Stephan and @Andy – the Legend’s DynamicLegend functionality only listens to newly-created axes children (in %matlabroot%/toolbox/matlab/scribe/@scribe/@legend/init.m line 102 [for R2012aPR]), and axes children deletions (in %matlabroot%/toolbox/matlab/scribe/@scribe/@legend/methods.m line 1281 [R2012aPR again]).

      It should be relatively easy to modify any of these two places to listen to changes in the Visible property of axes children. I described the mechanism for doing this in several articles (here for example).

  8. sunny March 15, 2012 at 09:40 Reply

    wow, i never knew there was a function like this and i have been thinking on how to program it. thanks, this is gonna save me lots of time

  9. Teodor March 15, 2012 at 13:26 Reply

    Hi. Thank you for this post. At the moment I am a bit stuck as trying to get the ‘ScribeLegendListeners’ throws a ‘MATLAB:class:InvalidProperty’ exception. There seem to be no such property…

    My University is using Matlab-R2011a. Could it be something related to their installation?

    What I am doing is using -DynamicLegend for plotting data in multiple iterations. However, I need to remove from the legend some plotted lines.

    Could you recommend other solutions? Thank you.

    • Yair Altman March 17, 2012 at 11:41 Reply

      @Teodor – try placing a drawnow after plotting the lines and before trying to access the hidden ScribeLegendListeners property. It is also possible that you are trying to access this property on a handle of another object (maybe one of the line plots, or a figure, or another axes), rather than the handle of the axes that holds the plots for the requested legend.

  10. Customizing menu items part 1 | Undocumented Matlab April 25, 2012 at 11:14 Reply

    […] Menu callbacks generally use internal semi-documented functions (i.e., having a readable help section but no doc, online help, or official support) […]

  11. Rafraichir une légende (part II) | MATLAB pour les geeks September 13, 2012 at 07:11 Reply

    […] Yair Altman m’a contacté pour me notifier qu’il avait également écrit un billet sur ce sujet le 4 juin 2009 : Legend ‘-DynamicLegend’ semi-documented feature […]

  12. Handle Graphics Behavior | Undocumented Matlab March 6, 2013 at 11:08 Reply

    […] is not updated directly (although there is absolutely nothing to prevent this), but rather via the semi-documented built-in accessor functions hggetbehavior and hgaddbehavior […]

  13. treeTable | Undocumented Matlab August 6, 2013 at 00:12 Reply

    […] Matlab 7.0 (R14), Matlab has included a built-in GUI table control (uitable), at first as a semi-documented function and in release 7.6 (R2008a) as a fully-documented function. Useful as this control is, it […]

  14. Clark January 11, 2016 at 20:36 Reply

    Thanks for letting the world know about the -DynamicLegend feature. Note that it appears to be limited to at most 50 entries, at least in R2015b. Plots beyond the first 50 simply don’t appear in the legend created by legend(‘-DynamicLegend’)

    • Yair Altman January 11, 2016 at 20:44 Reply

      @Clark – if your plot contains so many dynamic plot lines, then for both visual design and performance reasons I would strongly suggest using some other mechanism…

  15. Sachin Patel January 24, 2016 at 13:16 Reply

    Thanks a lot man for letting us know about -DynamicLegend…i was really needed this kind of function as i was using for loop and in that plotting plot for n times while required to have legends for each plot…Again Thanks a lot

  16. Manuel June 1, 2017 at 14:31 Reply

    Thx for providing DynamicLegend, I really like it!
    One question though: Is it possible, to add new items on the bottom instead of a vertical legend? That would be really great. Or maybe this even works with a general command to flip the legend after it was generated? But I couldn’t find such thing 🙁

    Thx & Best,
    Manuel

Leave a Reply
HTML tags such as <b> or <i> are accepted.
Wrap code fragments inside <pre lang="matlab"> tags, like this:
<pre lang="matlab">
a = magic(3);
disp(sum(a))
</pre>
I reserve the right to edit/delete comments (read the site policies).
Not all comments will be answered. You can always email me (altmany at gmail) for private consulting.

Click here to cancel reply.

Useful links
  •  Email Yair Altman
  •  Subscribe to new posts (feed)
  •  Subscribe to new posts (reader)
  •  Subscribe to comments (feed)
 
Accelerating MATLAB Performance book
Recent Posts

Speeding-up builtin Matlab functions – part 3

Improving graphics interactivity

Interesting Matlab puzzle – analysis

Interesting Matlab puzzle

Undocumented plot marker types

Matlab toolstrip – part 9 (popup figures)

Matlab toolstrip – part 8 (galleries)

Matlab toolstrip – part 7 (selection controls)

Matlab toolstrip – part 6 (complex controls)

Matlab toolstrip – part 5 (icons)

Matlab toolstrip – part 4 (control customization)

Reverting axes controls in figure toolbar

Matlab toolstrip – part 3 (basic customization)

Matlab toolstrip – part 2 (ToolGroup App)

Matlab toolstrip – part 1

Categories
  • Desktop (45)
  • Figure window (59)
  • Guest bloggers (65)
  • GUI (165)
  • Handle graphics (84)
  • Hidden property (42)
  • Icons (15)
  • Java (174)
  • Listeners (22)
  • Memory (16)
  • Mex (13)
  • Presumed future risk (394)
    • High risk of breaking in future versions (100)
    • Low risk of breaking in future versions (160)
    • Medium risk of breaking in future versions (136)
  • Public presentation (6)
  • Semi-documented feature (10)
  • Semi-documented function (35)
  • Stock Matlab function (140)
  • Toolbox (10)
  • UI controls (52)
  • Uncategorized (13)
  • Undocumented feature (217)
  • Undocumented function (37)
Tags
ActiveX (6) AppDesigner (9) Callbacks (31) Compiler (10) Desktop (38) Donn Shull (10) Editor (8) Figure (19) FindJObj (27) GUI (141) GUIDE (8) Handle graphics (78) HG2 (34) Hidden property (51) HTML (26) Icons (9) Internal component (39) Java (178) JavaFrame (20) JIDE (19) JMI (8) Listener (17) Malcolm Lidierth (8) MCOS (11) Memory (13) Menubar (9) Mex (14) Optical illusion (11) Performance (78) Profiler (9) Pure Matlab (187) schema (7) schema.class (8) schema.prop (18) Semi-documented feature (6) Semi-documented function (33) Toolbar (14) Toolstrip (13) uicontrol (37) uifigure (8) UIInspect (12) uitools (20) Undocumented feature (187) Undocumented function (37) Undocumented property (20)
Recent Comments
  • Nicholas (6 days 15 hours ago): Hi Yair, Thanks for the reply. I am on Windows 10. I also forgot to mention that this all works wonderfully out of the editor. It only fails once compiled. So, yes, I have tried a...
  • Nicholas (6 days 15 hours ago): Hi Yair, Thanks for the reply. I am on Windows 10. I also forgot to mention that this all works wonderfully out of the editor. It only fails once compiled. So, yes, I have tried a...
  • Yair Altman (6 days 23 hours ago): Nicholas – yes, I used it in a compiled Windows app using R2022b (no update). You didn’t specify the Matlab code location that threw the error so I can’t help...
  • Nicholas (7 days 19 hours ago): Hi Yair, Have you attempted your displayWebPage utility (or the LightweightHelpPanel in general) within a compiled application? It appears to fail in apps derived from both R2022b...
  • João Neves (11 days 0 hours ago): I am on matlab 2021a, this still works: url = struct(struct(struct(struct(hF ig).Controller).PlatformHost). CEF).URL; but the html document is empty. Is there still a way to do...
  • Yair Altman (13 days 22 hours ago): Perhaps the class() function could assist you. Or maybe just wrap different access methods in a try-catch so that if one method fails you could access the data using another...
  • Jeroen Boschma (14 days 1 hour ago): Never mind, the new UI components have an HTML panel available. Works for me…
  • Alexandre (14 days 2 hours ago): Hi, Is there a way to test if data dictionnatry entry are signal, simulink parameters, variables … I need to access their value, but the access method depends on the data...
  • Nicholas (14 days 16 hours ago): In case anyone is looking for more info on the toolbar: I ran into some problems creating a toolbar with the lightweight panel. Previously, the Browser Panel had an addToolbar...
  • Jeroen Boschma (17 days 23 hours ago): I do not seem to get the scrollbars (horizontal…) working in Matlab 2020b. Snippets of init-code (all based on Yair’s snippets on this site) handles.text_explorer...
  • Yair Altman (46 days 1 hour ago): m_map is a mapping tool, not even created by MathWorks and not part of the basic Matlab system. I have no idea why you think that the customizations to the builtin bar function...
  • chengji chen (46 days 8 hours ago): Hi, I have tried the method, but it didn’t work. I plot figure by m_map toolbox, the xticklabel will add to the yticklabel at the left-down corner, so I want to move down...
  • Yair Altman (54 days 1 hour ago): @Alexander – this is correct. Matlab stopped including sqlite4java in R2021b (it was still included in 21a). You can download the open-source sqlite4java project from...
  • Alexander Eder (59 days 20 hours ago): Unfortunately Matlab stopped shipping sqlite4java starting with R2021(b?)
  • K (66 days 7 hours ago): Is there a way to programmatically manage which figure gets placed where? Let’s say I have 5 figures docked, and I split it into 2 x 1, I want to place 3 specific figures on the...
Contact us
Captcha image for Custom Contact Forms plugin. You must type the numbers shown in the image
Undocumented Matlab © 2009 - Yair Altman
This website and Octahedron Ltd. are not affiliated with The MathWorks Inc.; MATLAB® is a registered trademark of The MathWorks Inc.
Scroll to top