Cursor line

80 visualizaciones (últimos 30 días)
Mtlb Usr
Mtlb Usr el 14 de Feb. de 2011
Comentada: Matthias Luh el 19 de Mzo. de 2022
Hi,
I've got a figure with several subplots. These subplots are located one under the other one. Then, that I want to do is create a vertical cursor to across all subplots and when I'm going to move this appear the current values of all subplots.
How can I develop this?
thanks
regards

Respuesta aceptada

Matt Fig
Matt Fig el 14 de Feb. de 2011
This can be done with a little handle graphics. I don't have time right now to make this code perfect (error checking, special cases handling, commenting(!), etc.), but it should give you something of an idea. Run this function then hit the left and right arrow to see what happens.
function [] = data_subplots()
% Link data cursors so that they track accross subplots.
% Create the subplots.
% Alternatively, use GET to create s and L from existing plots.
x = 1:.1:10;
for ii = 1:3
s(ii) = subplot(3,1,ii);
L(ii) = plot(x,sin(x/ii)*ii);
end
% Now start the work.
for ii = 1:length(s)
S.D{ii} = get(L(ii),{'xdata','ydata'});
S.L(ii) = length(S.D{ii}{1});
S.M(ii) = floor(S.L(ii)/2);
S.DF = diff(S.D{ii}{1}(S.M(ii):S.M(ii)+1)); % uniform assum
S.I(ii) = S.M(ii);
S.T(ii) = text(S.D{ii}{1}(S.M(ii)+2),S.D{ii}{2}(S.M(ii)+2),'here');
set(S.T(ii),'string',{['X: ',sprintf('%3.3g',S.D{ii}{1}(S.M(ii)))];...
['Y: ',sprintf('%3.3g',S.D{ii}{2}(S.M(ii)))]},...
'parent',s(ii),'backgroundco',[.8 .8 0]);
set(s(ii),'nextplot','add')
S.F(ii) = plot(s(ii),S.D{ii}{1}(S.M(ii)),S.D{ii}{2}(S.M(ii)),'sk');
set(S.F(ii),'markerfacec','b')
end
set(gcf,'keypressfcn',{@fh_kpfcn,S})
function [] = fh_kpfcn(varargin)
D = varargin{2}.Key;
S = varargin{3};
if strcmp(D,'leftarrow')
for ii = 1:length(S.T)
if S.I(ii)~=1
S.I(ii) = S.I(ii)-1;
set(S.F(ii),'xdata',S.D{ii}{1}(S.I(ii)),...
'ydata',S.D{ii}{2}(S.I(ii)))
set(S.T(ii),'position',...
[S.D{ii}{1}(S.I(ii))+S.DF*2,S.D{ii}{2}(S.I(ii))],...
'string',{['X: ',sprintf('%3.3g',S.D{ii}{1}(S.I(ii)))];...
['Y: ',sprintf('%3.3g',S.D{ii}{2}(S.I(ii)))]})
end
end
elseif strcmp(D,'rightarrow')
for ii = 1:length(S.T)
if S.I(ii)~=S.L(ii)
S.I(ii) = S.I(ii)+1;
set(S.F(ii),'xdata',S.D{ii}{1}(S.I(ii)),...
'ydata',S.D{ii}{2}(S.I(ii)))
set(S.T(ii),'position',...
[S.D{ii}{1}(S.I(ii))+S.DF*2,S.D{ii}{2}(S.I(ii))],...
'string',{['X: ',sprintf('%3.3g',S.D{ii}{1}(S.I(ii)))];...
['Y: ',sprintf('%3.3g',S.D{ii}{2}(S.I(ii)))]})
end
end
end
set(gcf,'keypressfcn',{@fh_kpfcn,S}) % Update the structure.
  3 comentarios
Mtlb Usr
Mtlb Usr el 15 de Feb. de 2011
Hi,
I hadn't realized!!! I can move the datatips with by arrow's key of pc.
I think that with this solution I will resolve my question.
Thank you so much
regards
Matthias Luh
Matthias Luh el 19 de Mzo. de 2022
This is awesome, thank you! I extended the function a bit and tried to make it more readable for me (see below).
For others looking for help: Also have a look the solution jiro posted here: http://www.mathworks.com/matlabcentral/answers/1758-crosshairs-or-just-vertical-line-across-linked-axis-plots
It might be more intuitive because it allows clicking instead of using the arrow keys.
Dear MATLAB team, if you read this: please add a simple and intuitive crosshair function that can be easily used and activated, e.g. also in the GUI. Something like used in Grafana: https://play.grafana.org/
Extension of Matt Fig's code:
  • compatibility with datetime x-axis
  • use "shift" + left/right to move around faster
  • variable to adjust offset of the textbox relative to data point (textbox_dx_offset, 2x)
  • created an own function to generates the text so you only need to adjust it once
function [] = data_subplots_2()
% Link data cursors so that they track accross subplots.
% Create the subplots.
% Alternatively, use GET to create s and L from existing plots.
x = 1:.1:10;
for ii = 1:3
subpl(ii) = subplot(3,1,ii);
pl(ii) = plot(x,sin(x/ii)*ii);
end
% Data tool tip
% https://de.mathworks.com/matlabcentral/answers/1308-cursor-line
textbox_dx_offset = 3;
for ii = 1:length(subpl) % for each subplot
S.data_x{ii} = get(pl(ii), 'xdata');
S.data_y{ii} = get(pl(ii), 'ydata');
S.datalength(ii) = length(S.data_x{ii});
S.startindex(ii) = floor(S.datalength(ii) / 2);
S.delta_x = diff(S.data_x{ii}(S.startindex(ii):(S.startindex(ii) + 1))); % assume uniform x-axis data difference
S.index(ii) = S.startindex(ii);
S.text(ii) = text(S.data_x{ii}(S.startindex(ii) + textbox_dx_offset), S.data_y{ii}(S.startindex(ii) + textbox_dx_offset),'here');
set(S.text(ii), 'string', get_tooltip_text(S, ii), 'parent', subpl(ii), 'BackgroundColor', [1 1 1], 'EdgeColor', [0 0 0]);
set(subpl(ii), 'nextplot', 'add')
S.tooltip_point(ii) = plot(subpl(ii), S.data_x{ii}(S.startindex(ii)), S.data_y{ii}(S.startindex(ii)), 'sk');
set(S.tooltip_point(ii), 'markerfacec', 'b')
end
set(gcf, 'keypressfcn', {@key_press_function, S})
% "on key press" function:
function [] = key_press_function(varargin)
key_id = varargin{2}.Key;
S = varargin{3};
if (size(varargin{2}.Modifier, 2) > 0) && (strcmp(varargin{2}.Modifier{1}, 'shift') == 1)
dx_fac = 12;
else
dx_fac = 1;
end
textbox_dx_offset = 3;
if strcmp(key_id, 'leftarrow')
for ii = 1:length(S.text)
if S.index(ii) ~= 1
S.index(ii) = S.index(ii) - dx_fac;
set(S.tooltip_point(ii), 'xdata', S.data_x{ii}(S.index(ii)),...
'ydata', S.data_y{ii}(S.index(ii)))
set(S.text(ii), 'position',...
[get_text_xpos(S.data_x{ii}(S.index(ii)) + S.delta_x * textbox_dx_offset), S.data_y{ii}(S.index(ii))],...
'string', get_tooltip_text(S, ii))
end
end
elseif strcmp(key_id, 'rightarrow')
for ii = 1:length(S.text)
if S.index(ii) ~= S.datalength(ii)
S.index(ii) = S.index(ii) + dx_fac;
set(S.tooltip_point(ii),'xdata',S.data_x{ii}(S.index(ii)),...
'ydata',S.data_y{ii}(S.index(ii)))
set(S.text(ii),'position',...
[get_text_xpos(S.data_x{ii}(S.index(ii)) + S.delta_x * textbox_dx_offset), S.data_y{ii}(S.index(ii))],...
'string', get_tooltip_text(S, ii))
end
end
end
set(gcf,'keypressfcn',{@key_press_function,S}) % Update the structure.
% end of "on key press" function
% "get tooltip text" function:
function text = get_tooltip_text(S, ii)
if isa(S.data_x{ii}(S.index(ii)), 'datetime') == 1
text = {...
['X: ',sprintf('%s', datestr(S.data_x{ii}(S.index(ii))))];...
['Y: ',sprintf('%3.3g', S.data_y{ii}(S.index(ii)))]...
};
else
text = {...
['X: ',sprintf('%3.3g', S.data_x{ii}(S.index(ii)))];...
['Y: ',sprintf('%3.3g', S.data_y{ii}(S.index(ii)))]...
};
end
% end of "get tooltip text" function
% "get x-position" function:
function xpos = get_text_xpos(x_value)
if isa(x_value, 'datetime') == 1
ax1 = gca;
% dx_days = diff(ax1.XLim)/24;
x_min = ax1.XLim(1);
xpos = datenum(x_value - x_min);
else
xpos = x_value;
end
% end of "get tooltip text" function

Iniciar sesión para comentar.

Más respuestas (3)

Brett Shoelson
Brett Shoelson el 14 de Feb. de 2011
I would create a line object for each axes, and use LINKPROP to move them all (i.e., set their x positions) simultaneously. You might also take a look at Brandon Kuczenski's vline on the File Exchange.
Cheers,
Brett

Jiro Doke
Jiro Doke el 22 de Feb. de 2011
I posted a similar solution here.

Paulo Silva
Paulo Silva el 14 de Feb. de 2011
You might find useful tips inside the ginput function
edit ginput
%this function can be found inside ginput
set(fig,'pointer','fullcrosshair'); %horizontal and vertical cursor lines
  9 comentarios
Paulo Silva
Paulo Silva el 14 de Feb. de 2011
I'm finally understanding but what you want isn't easy, at least for me and my basic matlab skills, maybe someone with more experience might help you.
Here's some websites with info, maybe you can find something useful in them
http://matlab.wikia.com/wiki/MATLAB_Wiki
http://undocumentedmatlab.com
Mtlb Usr
Mtlb Usr el 15 de Feb. de 2011
Hi,
OK, I'm going to visit these web pages.
Thank you
regards

Iniciar sesión para comentar.

Categorías

Más información sobre Specifying Target for Graphics Output en Help Center y File Exchange.

Community Treasure Hunt

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

Start Hunting!

Translated by