To change data displayed by data cursor in 3d scatter graph.
6 views (last 30 days)
Show older comments
I have a 4 sets of 200x1 (double type) data. say a,b,c,d.
I have plotted a 3d scatter plot using scatter3(a,b,c); the current data cursor shows me the position values (i.e the values of a b and c).
and is using this function
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');
output_txt = {['X: ',num2str(pos(1),4)],...
['Y: ',num2str(pos(2),4)]};
% 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),4)];
end
I want the data cursor in the graph to display the corresponding value from data set d for that point.
eg. a(1) = 2, b(1) = 4 c(1) = 6 and d(1) = 10
for the plotted point (a,b,c) the data cursor should show the corresponding value of d= 10.
2 Comments
Eric Cote
on 31 Jan 2017
Edited: Eric Cote
on 31 Jan 2017
I want to do something similar, and it's not clear if it's possible.
For example, in my case I have a 3D plot, but I want the data cursor to display 2 other datapoints associated with any given point on the 3D plot. So for a given x/y/z pair I may have some other variables providing information about time recorded, and sensor used (arbitrary examples).
The problem increases in complexity when you want to do this for multiple datasets within a single graph. I'd love to hear if someone has an elegant solution for this that doesn't involve passing in the whole darn dataset to the datacursor function.
Walter Roberson
on 31 Jan 2017
Eric Cote:
Make the datacursormode callback a sub-function of a routine that has the data defined, so that it can share the data efficiently.
Answers (2)
Adam
on 19 Jan 2017
dcm_obj = datacursormode(figure_handle);
returns you the object that controls the datacursor. Then when you have this, you can use
dcm_obj.UpdateFcn = @myFunction;
with whatever function handle representation you want, to define the function that will get called to display the data. It isn't something I have ever done, but since you asked the question and I looked it up it may well be something I want to try on my own plots.
You can easily embed whatever other data you want into your function handle.
doc datacursormode
gives the information on this. I'm not exactly sure what form your function needs to take in terms of its body or return arguments without reading up.
0 Comments
Eric Cote
on 31 Jan 2017
Edited: Eric Cote
on 1 Feb 2017
Okay, I think I have an answer, though forgive the lack of coding elegance. Basically I solved this with a brute force approach that passes all of the data into a reference table indexed on my X/Y/Z values.
There are easier ways to do this (see further in my answer), but this approach allows me to look up other data when a given cursor point was selected and across several data sets being displayed on a single figure.
So in my case, I'm plotting in Cartesian coordinates, but I want to display the original spherical coordinate values, Az, El, Gain. This solution works with as many datasets as you care to plot, but it does pass a lot of data to the datacursor update function to accomplish this. In my case, I am also plotting points above a certain threshold a different color as well, further complicating my particular application and necessitating this approach.
To do this, I construct my reference table first. I'll only show doing this for a single dataset, but it's easy to loop and build the table for as many datasets as you care to plot...
% Store reference table with az/el/gain/xs/ys/zs arrays
refTable.az = az;
refTable.el = el;
refTable.gn = gn;
refTable.xs = xs;
refTable.ys = ys;
refTable.zs = zs;
% Plot xs/ys/zs as 3D data
fHandle = figure;
plot3(xs,ys,zs);
% Reference custom datacursor function for custom functionality
dcm_obj = datacursormode(fHandle);
set(dcm_obj,'UpdateFcn',{@display_cursor_fcn,refTable})
And then override the datacursor function to look up the other data and display it instead...
function txt = display_cursor_fcn(~,event_obj,refTable)
% Customizes text of data tips, showing az/el/gain instead of xs/ys/zs
pos = get(event_obj, 'Position');
idx1 = find(refTable.xs == pos(1));
idx2 = find(refTable.ys(idx1) == pos(2));
idx3 = find(refTable.zs(idx1(idx2)) == pos(3));
idx = idx1(idx2(idx3));
txt = {['AZ: ',num2str(refTable.az(idx(1)))],...
['EL: ',num2str(refTable.el(idx(1)))],...
['GN: ',num2str(refTable.gn(idx(1)))]};
end
If you can assume you're only plotting a single set of data, then the problem actually becomes much easier. There are other solutions on Matlab that show how to do that, simply passing in the other array to the datacursor function, and using the position in the index of the data you selected to index into your other array.
In other words...
function txt = display_cursor_fcn(~,event_obj,fourthVariable)
% Customizes text of data tips, showing additional fourth variable
pos = get(event_obj, 'Position');
idx = get(event_obj, 'DataIndex');
txt = {['A: ',num2str(pos(1))],...
['B: ',num2str(pos(2))],...
['C: ',num2str(pos(3))],...
['D: ',num2str(fourthVariable(idx))]};
end
0 Comments
See Also
Categories
Find more on Timetables 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!