How to "highlight" an individual bin in a histogram?

3 views (last 30 days)
Hey MATLAB geniuses. I'm working on a GUI with a table and four plots (and a few other UI elements). When data is loaded into the GUI (by clicking a button) a ranked list of the data headers is populated into the table and the data is plotted on the four plots. Two of the plots are just 2D plots. I've set it up so that when a particular cell is selected in the table, the data related to that cell is "highlighted" (change that individual curve's 'LineWidth') in the 2D plots. The other plots are histograms. I would also like to "highlight" the bin that the selected cell's data falls in.
This is where my problem lies. As far as I know, there is no way to edit the properties of individual bins. I can figure out how to find the bin the data lies in if someone knows a way to edit the properties of just a single bin. Either changing the bin's 'EdgeColor' or 'FaceColor' works for me.
Now, I've attempted a workaround by overlaying another histogram with just that particular bin. It has the exact same 'BinLimits' and 'BinWidth' but a different 'FaceColor'. This gets overlaid when I select a cell in the table. However, I've run into a problem with this solution too. When I try select another cell the overlay remains, and keeps overlaying with each subsequent table cell selection. I can't figure out how to redraw the underlying plot. Here's some sample code to better understand the solution I'm attempting and the problem:
function my_table_CellSelectionCallback(hObject, eventdata, handles)
% Pull the handle for the plot that's already drawn.
h1 = handles.histplot1;
% Pull handle for the axes for which these plots are contained.
ax = handles.fs_axes;
% Data I'm plotting.
fs = handles.fs;
% Hold the axes for the existing histogram so it doesn't get overwritten.
hold(ax,'on');
% Plot the overlaid histogram.
h2 = histogram(ax,fs,'BinLimits',handles.blim,'BinWidth',handles.bwidth,'FaceColor','r');
end
To be clear, what I'm trying to do is when I select another cell in the table it clears the current histogram overlay, keeps the underlying histogram, and plots a new histogram overlay based on the newly selected cell.
Things I've tried that haven't worked:
  • Turn off the hold after the overlaid plot.
  • refreshdata(h1) before plotting overlay.
  • refreshdata(h2) before plotting overlay. This can't work because MATLAB hasn't technically created the h2 object yet when the callback is activated again.
  • cla(h1) & cla(h2) before/after plotting the overlay. This ends up just clearing the whole axes, doesn't replot, and does nothing further.
  • getting the object data from the fs_axes and doing a copyobj() but I can't quite figure how to do it right.
Anyway, I hope this is clear. Any help or guidance on how to achieve my goal is appreciated. Thanks in advance.

Accepted Answer

Thorsten
Thorsten on 12 Jul 2016
You can draw a patch on top of the bar you like to highlight:
Create the histogram
H = histogram(a);
Highlight the ith's bar, e.g. the 3rd:
i = 3;
x = H.BinEdges(i:i+1); x = [x fliplr(x)]; y = [0 0 repmat(H.Values(i), 1, 2)];
h_patch = patch(x, y, 'blue');
Remove highlight
delete(h_patch)
  1 Comment
Matthew Robinson
Matthew Robinson on 13 Jul 2016
Mr. Thorsten, sir, that did the trick! Thanks for the easy, creative solution.
Now, there was still the dilemma of deleting the patch when, according to the callback function, the patch variable (in Thorten's case, is "h_patch") doesn't technically exist yet (next time it's activated). I got around that by using findobj() to create a handle from the existing patch on the axes then used delete() on that.
For any of those interested, here's part of the code I implemented to achieve the solution I needed (which also allows for multiple selections):
function my_table_CellSelectionCallback(hObject, eventdata, handles)
% 'fs' is the data I'm plotting on the histogram.
% Find existing patch and delete.
h_patch = findobj(handles.fs_axes,'Type','Patch');
delete(h_patch);
% Get selected cell indices from table.
indices = eventdata.Indices;
r = indices(:,1);
% Plot patch
for i = 1:size(r,1)
bin = find(handles.hedge < handles.fs(r(i)));
idx = bin(end);
px = handles.hedge(idx:idx+1);
x = [px fliplr(px)];
y = [0 0 repmat(handles.hvals(idx), 1, 2)];
patch(x, y, 'red', 'Parent', handles.fs_axes);
end
end

Sign in to comment.

More Answers (0)

Categories

Find more on Data Distribution Plots in Help Center and File Exchange

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!