crosshairs or just vertical line across linked axis plots
    조회 수: 24 (최근 30일)
  
       이전 댓글 표시
    
What I have are plots that are linked by the linkaxes() function. I would like to have a vertical line that spans all of the plots so that I can compare the peaks and valleys interactively between plots.
댓글 수: 0
채택된 답변
  Jiro Doke
    
 2011년 2월 22일
        This may get you started:
function vertical_cursors
set(gcf, ...
   'WindowButtonDownFcn', @clickFcn, ...
   'WindowButtonUpFcn', @unclickFcn);
% Set up cursor text
allLines = findobj(gcf, 'type', 'line');
hText = nan(1, length(allLines));
for id = 1:length(allLines)
   hText(id) = text(NaN, NaN, '', ...
      'Parent', get(allLines(id), 'Parent'), ...
      'BackgroundColor', 'yellow', ...
      'Color', get(allLines(id), 'Color'));
end
% Set up cursor lines
allAxes = findobj(gcf, 'Type', 'axes');
hCur = nan(1, length(allAxes));
for id = 1:length(allAxes)
   hCur(id) = line([NaN NaN], ylim(allAxes(id)), ...
      'Color', 'black', 'Parent', allAxes(id));
end
     function clickFcn(varargin)
        % Initiate cursor if clicked anywhere but the figure
        if strcmpi(get(gco, 'type'), 'figure')
           set(hCur, 'XData', [NaN NaN]);                % <-- EDIT
           set(hText, 'Position', [NaN NaN]);            % <-- EDIT
        else
           set(gcf, 'WindowButtonMotionFcn', @dragFcn)
           dragFcn()
        end
     end
     function dragFcn(varargin)
        % Get mouse location
        pt = get(gca, 'CurrentPoint');
        % Update cursor line position
        set(hCur, 'XData', [pt(1), pt(1)]);
        % Update cursor text
        for idx = 1:length(allLines)
           xdata = get(allLines(idx), 'XData');
           ydata = get(allLines(idx), 'YData');
           if pt(1) >= xdata(1) && pt(1) <= xdata(end)
              y = interp1(xdata, ydata, pt(1));
              set(hText(idx), 'Position', [pt(1), y], ...
                 'String', sprintf('(%0.2f, %0.2f)', pt(1), y));
           else
              set(hText(idx), 'Position', [NaN NaN]);
           end
        end
     end
     function unclickFcn(varargin)
        set(gcf, 'WindowButtonMotionFcn', '');
     end
end
Save the above function. Here's an example of how to use it:
subplot(221);
plot(rand(10,1));
subplot(222);
plot(rand(10,2));
subplot(223);
plot([rand(10,1), rand(10,1)+1]);
subplot(224);
plot(rand(10,1));
vertical_cursors;
EDIT: As a response to a request, I added the ability to make the cursor disappear when clicking outside the axes. See the two lines of code with the comment "<-- EDIT".
댓글 수: 10
  Ferd
 2019년 4월 4일
				Hi, 
I tried the example given and it works without issues. Then on another figure with 4 subplots that I've linked their x-axes, I've come across this error below, 
Is there a way to get around this error message?
Error using griddedInterpolant
The grid vectors must contain unique points.
Error in interp1 (line 149)
        F = griddedInterpolant(X,V,method);
Error in vertical_cursors/dragFcn (line 41)
              y = interp1(xdata, ydata, pt(1));
Error in vertical_cursors/clickFcn (line 28)
           dragFcn()
Error while evaluating Figure WindowButtonDownFcn.
Error using griddedInterpolant
The grid vectors must contain unique points.
Error in interp1 (line 149)
        F = griddedInterpolant(X,V,method);
Error in vertical_cursors/dragFcn (line 41)
              y = interp1(xdata, ydata, pt(1));
Error in vertical_cursors/clickFcn (line 28)
           dragFcn()
Error while evaluating Figure WindowButtonDownFcn.
Error using griddedInterpolant
The grid vectors must contain unique points.
Error in interp1 (line 149)
        F = griddedInterpolant(X,V,method);
Error in vertical_cursors/dragFcn (line 41)
              y = interp1(xdata, ydata, pt(1));
Error while evaluating Figure WindowButtonMotionFcn.
Error using griddedInterpolant
The grid vectors must contain unique points.
Error in interp1 (line 149)
        F = griddedInterpolant(X,V,method);
Error in vertical_cursors/dragFcn (line 41)
              y = interp1(xdata, ydata, pt(1));
Error while evaluating Figure WindowButtonMotionFcn.
Error using griddedInterpolant
The grid vectors must contain unique points.
Error in interp1 (line 149)
        F = griddedInterpolant(X,V,method);
Error in vertical_cursors/dragFcn (line 41)
              y = interp1(xdata, ydata, pt(1));
Error while evaluating Figure WindowButtonMotionFcn.
Error using griddedInterpolant
The grid vectors must contain unique points.
Error in interp1 (line 149)
        F = griddedInterpolant(X,V,method);
Error in vertical_cursors/dragFcn (line 41)
              y = interp1(xdata, ydata, pt(1));
Error while evaluating Figure WindowButtonMotionFcn.
Error using griddedInterpolant
The grid vectors must contain unique points.
Error in interp1 (line 149)
        F = griddedInterpolant(X,V,method);
Error in vertical_cursors/dragFcn (line 41)
              y = interp1(xdata, ydata, pt(1));
Error while evaluating Figure WindowButtonMotionFcn.
Error using griddedInterpolant
The grid vectors must contain unique points.
Error in interp1 (line 149)
        F = griddedInterpolant(X,V,method);
Error in vertical_cursors/dragFcn (line 41)
              y = interp1(xdata, ydata, pt(1));
Error while evaluating Figure WindowButtonMotionFcn.
Error using griddedInterpolant
The grid vectors must contain unique points.
Error in interp1 (line 149)
        F = griddedInterpolant(X,V,method);
Error in vertical_cursors/dragFcn (line 41)
              y = interp1(xdata, ydata, pt(1));
Error while evaluating Figure WindowButtonMotionFcn.
  Matthias Luh
 2022년 3월 19일
				
      편집: Matthias Luh
 2022년 3월 19일
  
			Thank you very much for the code!
I extended it for datetime x-axis compatibility:
function vertical_cursors
    set(gcf, ...
       'WindowButtonDownFcn', @clickFcn, ...
       'WindowButtonUpFcn', @unclickFcn);
    % Set up cursor text
    allLines = findobj(gcf, 'type', 'line');
    hText = nan(1, length(allLines));
    for id = 1:length(allLines)
        hText(id) = text(NaN, NaN, '', ...
            'Parent', get(allLines(id), 'Parent'), ...
            'BackgroundColor', 'yellow', ...
            'Color', get(allLines(id), 'Color'));
    end
    % Set up cursor lines
    allAxes = findobj(gcf, 'Type', 'axes');
    hCur = nan(1, length(allAxes));
    for id = 1:length(allAxes)
        if isa(xlim(allAxes(id)), 'datetime') == 1
            x_lims = xlim(allAxes(id));
            %default_time = x_lims(1) + diff(x_lims) / 2; % Option A) use mid
            default_time = NaT('TimeZone',x_lims(1).TimeZone); % Option B) don't display at start
            nan_data = [default_time default_time];
        else
            nan_data = [NaN NaN];
        end
        hCur(id) = line(nan_data, ylim(allAxes(id)), ...
            'Color', 'black', 'Parent', allAxes(id));
    end
    function clickFcn(varargin)
        % Initiate cursor if clicked anywhere but the figure
        if strcmpi(get(gco, 'type'), 'figure')
            if isa(xlim(gca), 'datetime') == 1
                x_lims = xlim(gca);
                nan_time = NaT('TimeZone',x_lims(1).TimeZone);
                nan_data = [nan_time nan_time];
            else
                nan_data = [NaN NaN];
            end
            set(hCur, 'XData', nan_data);
            set(hText, 'Position', [NaN NaN]);
        else
            set(gcf, 'WindowButtonMotionFcn', @dragFcn)
            dragFcn()
        end
    end
    function dragFcn(varargin)
        % Get mouse location
        pt = get(gca, 'CurrentPoint');
        % Update cursor line position
        set(hCur, 'XData', [pt(1), pt(1)]);
        % Update cursor text
        for idx = 1:length(allLines)
            xdata = get(allLines(idx), 'XData');
            ydata = get(allLines(idx), 'YData');
            if isa(xlim(gca), 'datetime') == 1
                if pt(1) >= get_date_xpos(xdata(1)) && pt(1) <= get_date_xpos(xdata(end))
                    x_lims = xlim(gca);
                    x = pt(1) + x_lims(1);
                    data_index = dsearchn(get_date_xpos(xdata'),get_date_xpos(x));
                    x_nearest = xdata(data_index);
                    y_nearest = ydata(data_index);
                    set(hText(idx), 'Position', [pt(1), y_nearest], ...
                        'String', sprintf('(%s, %0.2f)', datestr(x_nearest), y_nearest));
                    % y = interp1(get_date_xpos(xdata), ydata, pt(1));
                    % set(hText(idx), 'Position', [pt(1), y], ...
                    %     'String', sprintf('(%s, %0.2f)', datestr(pt(1)), y));
                else
                    set(hText(idx), 'Position', [NaN NaN]);
                end
            else
                if pt(1) >= xdata(1) && pt(1) <= xdata(end)
                    y = interp1(xdata, ydata, pt(1));
                    set(hText(idx), 'Position', [pt(1), y], ...
                        'String', sprintf('(%0.2f, %0.2f)', pt(1), y));
                else
                    set(hText(idx), 'Position', [NaN NaN]);
                end
            end
        end
    end
    function unclickFcn(varargin)
        set(gcf, 'WindowButtonMotionFcn', '');
    end
    function xpos = get_date_xpos(x_value)
        ax1 = gca;
        % dx_days = diff(ax1.XLim)/24;
        x_min = ax1.XLim(1);
        xpos = datenum(x_value - x_min);
    end
end
추가 답변 (3개)
  Patrick Kalita
    
      
 2011년 2월 22일
        f = figure;
subplot(2,1,1)
plot(rand(5))
subplot(2,1,2);
plot(magic(5))
set(f, 'Pointer', 'fullcrosshair')
댓글 수: 4
  Walter Roberson
      
      
 2011년 2월 22일
				I see what you mean, Patrick. On the other hand, it would cover the entire figure rather than just the plots.
  Jiro Doke
    
 2011년 2월 22일
				It seems that this solution is the easiest and cleanest when the axes are stacked vertically. I'm not entirely sure what the OP meant when he said "compare the peaks and valleys interactively between plots". Is it just visually line things up, or does he want more information like actual numbers.
  claudio
      
 2014년 5월 26일
        Is it possible to display the values in a window (like in datacursormode, "window inside figure" display style)??
댓글 수: 0
참고 항목
카테고리
				Help Center 및 File Exchange에서 Annotations에 대해 자세히 알아보기
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!