How can I display Index of a data point on the Data Cursor?
71 views (last 30 days)
Show older comments
When I use the Data Cursor option on a plot, I am able to view the X and Y-coordinates on the tool tip. However I wish to see the index of that point. I have tried editing the textUpdate function as follows:
function output_txt = myfunction(obj,event_obj)
% Display the position of the data cursor
% obj Currently not used (empty)
% event_obj Handle to event object
% output_txt Data cursor text string (string or cell array of strings).
pos = get(event_obj,'Position');
x = pos(1);
y = pos(2);
idx = find(xydata == x,y);
[row,~] = ind2sub(size(xydata),idx);
output_txt{end+1} = cell2mat(labels(row));
However this gives an error. Does anyone have any suggestions?
Thanks in advance
Deepa
2 Comments
Adam
on 7 Jul 2017
Edited: Adam
on 7 Jul 2017
You haven't shown what you are doing with that function (how you are calling it) or what the error is so you can't really expect to get too much help if you don't give all relevant information.
dcm = datacursormode( hFig );
dcm.UpdateFcn = @updateDataCursor;
is the kind of thing to use to create a custom data cursor if you put the relevant code in updateDataCursor which may be what your 'myFunction' is, but that would just be a guess since you haven't shown that part of the code.
Accepted Answer
Deepa T
on 12 Jul 2017
Edited: Deepa T
on 12 Jul 2017
3 Comments
Samuli Karvinen
on 15 Jan 2020
Hey,
Oh I see, what data have put in there? The data tip objects?
Thanks in advance!
Samuli
More Answers (3)
Les Beckham
on 8 Jul 2017
Try this (modify the num2str calls as you wish to get the number of digits you desire):
function output_txt = datatip_cb15digits(obj,event_obj)
% datatip_cb15digits.m - datatip callback function - modified to display 15 digits
% Display the position of the data cursor
% obj Currently not used (empty)
% event_obj Handle to event object
% output_txt Data cursor text string (string or cell array of strings).
pos = get(event_obj,'Position');
handles = get(gca, 'Children');
h=handles((handles == event_obj.Target));
dim = 2; % initially assume this is a 2d plot
output_txt = {['X: ',num2str(pos(1),15)],...
['Y: ',num2str(pos(2),15)]};
% If there is a Z-coordinate in the position, display it as well
if length(pos) > 2
output_txt{end+1} = ['Z: ',num2str(pos(3),15)];
dim = 3;
end
% display the index of the currently selected datapoint
if (dim == 2)
i = find(get(h, 'XData') == pos(1) & get(h, 'YData') == pos(2));
else
i = find(get(h, 'XData') == pos(1) & get(h, 'YData') == pos(2) ...
& get(h, 'ZData') == pos(3));
end
output_txt{end+1} = ['i: ', num2str(i)];
5 Comments
Walter Roberson
on 9 Jul 2017
Correct, the data index is specific to the line that was clicked on, and indicates the relative offset into the line, as in XData(index) YData(index) . This need not be sorted by x or y, and is completely independent of every other line or graphics object.
If you have access to all of the data to be plotted, you could always unique() the complete list of y values concatenated together, and request the third output of unique() so you know the index of each of the values relative the list of unique values, and then you could break that list up using mat2cell() according to the length of each original line, and then you could set() the UserData for each line to include the y indices for each point. Then your update handler can use the data index to index the UserData to get the information to display.
Walter Roberson
on 9 Jul 2017
Suppose you have a cell, Xs, of all of the X values, and a cell Ys, of the corresponding Y values, such as might be plotted with
XYs = [Xs(:).'; Ys(:).'];
plot(XYs{:})
Then,
%create a giant column vector of all of the Y values
%and find the unique Y values and the indices of each
%original value into the unique list.
%this code does not assume anything about the orientation
%of the vectors
[uY, ~, uYidx] = unique( cell2mat( cellfun(@(V) V(:), Ys(:), 'Uniform', 0) ) );
Ylens = cellfun(@length, Ys);
Yidxcell = mat2cell(uYidx, Ylens, 1);
XYs = [Xs(:).'; Ys(:).'];
linehandles = plot(XYs{:});
for K = 1 : length(linehandles)
set(linehandles(K), 'UserData', Yidxcell{K});
end
Together with
function txt = myupdatefcn(obj, event_obj)
pos = get(event_obj,'Position');
x = pos(1); y = pos(2);
I = get(event_obj, 'DataIndex');
Yidxs = get(obj, 'UserData');
if isempty(Yidxs) || length(Yidxs) < I;
Yidx = '?';
else
Yidx = Yidxs(I);
end
txt = {['X: ',num2str(x)],...
['Y: ',num2str(y)],...
['I: ', Yidx]};
2 Comments
Les Beckham
on 9 Jul 2017
There are definitely some very clever Matlab tricks and manipulations going on here, but in what legitimate use case would anyone ever create a plot this way? Since the OP never gave us an example of how the data is being plotted or what they are really trying to achieve, I'm skeptical that your very creative answer will really solve the poorly defined problem. OP did comment that "That sounds like what I want to do," so, hopefully I'm wrong.
I would definitely be interested in some sort of real world example where this approach would apply.
Walter Roberson
on 10 Jul 2017
Les, see https://www.mathworks.com/matlabcentral/answers/347916-i-have-an-array-which-is-increasing-at-one-point-it-starts-to-decrease-this-trend-starts-repeatin#comment_467698 where I implemented a plot using exactly this scheme of cells of coordinates.
See Also
Categories
Find more on Data Type Identification in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!