Reputation: 24169
I am trying to make an animation where several datasets are being cycled through in a histogram
plot, and a datatip follows the highest bar in every frame, as demonstrated below:
Here's a code which achieves the desired result using a bar graph:
%% // Initialization
close all force; clear variables; clc;
%% // Generate some data:
indMax = 20; data = randi(indMax,[5,45]);
%% // Generate the 1st values to plot:
edges = 0.5:1:indMax+0.5;
counts = histcounts(data(1,:),edges);
[~,maxInd] = max(counts);
%% // Create the plot and the datatip:
figure(100); hBar = bar(1:indMax,counts);
hDT = makedatatip(hBar,maxInd); hDT = handle(hDT);
grid on; hold on; grid minor; xlim([0,indMax+1]); ylim([0,10]);
%% // Update the figure and the datatip:
for indFrame = 2:size(data,1)
counts = histcounts(data(indFrame,:),edges);
[~,maxInd] = max(counts);
hBar.YData = counts; %// Update bar heights
hDT.Cursor.DataIndex = maxInd; %// Update datatip location
%// Alternatively to the above line: hDT.Position = [newX newY newZ];
java.lang.Thread.sleep(1000);
drawnow;
end
Note that the datatip is created using a modified version of the makedatatip
submission from FEX, as per the comment on the submission page (this is true for the 27/06/2012 version of makedatatip
):
a couple of changes need to be made to the code:
***********CHANGE 1*********
line 122 needs to be: pos = [X(index(n)) Y(index(n)) 0];
***********CHANGE 2*********
lines 135-141 should be commented OUT
And also Change 3: line 84 to Z = [];
Since makedatatip
attempts to acces the 'XData'
and 'YData'
properties of the input handle, which are absent in histogram
plots, it refuses to work. So my question is:
How can datatips be created and updated programmatically in histogram
plots (using matlab-hg2), along with the histogram itself?
Upvotes: 2
Views: 581
Reputation: 24169
Turns out the solution is quite straight-forward, at least when only a single datatip is needed. Here are the required steps:
Replace the bar plot with a histogram:
hHist = histogram(data(1,:),edges);
Create the datatip "manually" instead of using makedatatip
:
hDataCursorMgr = datacursormode(ancestor(hHist,'figure'));
hDT = createDatatip(hDataCursorMgr,hHist);
Update the position as needed:
hDT.Cursor.DataIndex = maxInd;
To update the histogram's bar heights, it is not possible to update the 'Values'
property directly (since it's read-only), so one must update the 'Data'
property (and let MATLAB recompute the bar heights on its own):
hHist.Data = data(indFrame,:);
And everything put together:
%% // Initialization
close all force; clear variables; clc;
%% // Generate some data:
indMax = 20; data = randi(indMax,[5,45]);
%% // Generate the 1st values to plot:
edges = 0.5:1:indMax+0.5;
counts = histcounts(data(1,:),edges);
[~,maxInd] = max(counts);
%% // Create the plot and the datatip:
figure(100); hHist = histogram(data(1,:),edges);
hDataCursorMgr = datacursormode(ancestor(hHist,'figure'));
hDT = createDatatip(hDataCursorMgr,hHist); hDT.Cursor.DataIndex = maxInd;
grid on; hold on; grid minor; xlim([0,indMax+1]); ylim([0,10]);
%% // Update the plot and the datatip:
for indFrame = 2:size(data,1)
[~,maxInd] = max(histcounts(data(indFrame,:),edges));
hHist.Data = data(indFrame,:);
hDT.Cursor.DataIndex = maxInd;
java.lang.Thread.sleep(1000);
drawnow;
end
Which results in:
Some notes \ observations:
double
values (i.e. plotting something other than double doesn't let you add datatips to it, apparently). This is true for MATLAB 2015a. See another discussion about it here.Upvotes: 2