Cursor line

조회 수: 71 (최근 30일)
Mtlb Usr
Mtlb Usr 2011년 2월 14일
댓글: Matthias Luh 2022년 3월 19일
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

채택된 답변

Matt Fig
Matt Fig 2011년 2월 14일
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
Mtlb Usr
Mtlb Usr 2011년 2월 15일
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 2022년 3월 19일
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

댓글을 달려면 로그인하십시오.

추가 답변 (3개)

Brett Shoelson
Brett Shoelson 2011년 2월 14일
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 2011년 2월 22일
I posted a similar solution here.

Paulo Silva
Paulo Silva 2011년 2월 14일
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
Paulo Silva
Paulo Silva 2011년 2월 14일
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 2011년 2월 15일
Hi,
OK, I'm going to visit these web pages.
Thank you
regards

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Specifying Target for Graphics Output에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by